File size: 4,812 Bytes
82e7b5b
deab47c
82e7b5b
 
e5902c3
 
82e7b5b
 
 
 
e5902c3
 
 
 
 
 
 
82e7b5b
 
 
 
 
 
 
 
db9d435
e5902c3
 
 
 
 
 
 
 
 
 
 
 
82e7b5b
e5902c3
82e7b5b
e5902c3
82e7b5b
e5902c3
 
 
 
 
 
 
 
 
 
82e7b5b
 
 
 
e5902c3
 
82e7b5b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e5902c3
 
82e7b5b
 
 
e5902c3
82e7b5b
 
 
 
 
 
 
 
 
db9d435
82e7b5b
e5902c3
 
82e7b5b
e5902c3
 
 
bc3177e
 
 
82e7b5b
 
 
 
e5902c3
 
 
 
82e7b5b
 
 
 
 
 
deab47c
 
 
 
82e7b5b
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import os, webcolors, html
import sys
from datetime import datetime
from . import files

class PrintStyle:
    last_endline = True
    log_file_path = None

    def __init__(self, bold=False, italic=False, underline=False, font_color="default", background_color="default", padding=False, log_only=False):
        self.bold = bold
        self.italic = italic
        self.underline = underline
        self.font_color = font_color
        self.background_color = background_color
        self.padding = padding
        self.padding_added = False  # Flag to track if padding was added
        self.log_only = log_only

        if PrintStyle.log_file_path is None:
            logs_dir = files.get_abs_path("logs")
            os.makedirs(logs_dir, exist_ok=True)
            log_filename = datetime.now().strftime("log_%Y%m%d_%H%M%S.html")
            PrintStyle.log_file_path = os.path.join(logs_dir, log_filename)
            with open(PrintStyle.log_file_path, "w") as f:
                f.write("<html><body style='background-color:black;font-family: Arial, Helvetica, sans-serif;'><pre>\n")

    def _get_rgb_color_code(self, color, is_background=False):
        try:
            if color.startswith("#") and len(color) == 7:
                r = int(color[1:3], 16)
                g = int(color[3:5], 16)
                b = int(color[5:7], 16)
            else:
                rgb_color = webcolors.name_to_rgb(color)
                r, g, b = rgb_color.red, rgb_color.green, rgb_color.blue
            
            if is_background:
                return f"\033[48;2;{r};{g};{b}m", f"background-color: rgb({r}, {g}, {b});"
            else:
                return f"\033[38;2;{r};{g};{b}m", f"color: rgb({r}, {g}, {b});"
        except ValueError:
            return "", ""

    def _get_styled_text(self, text):
        start = ""
        end = "\033[0m"  # Reset ANSI code
        if self.bold:
            start += "\033[1m"
        if self.italic:
            start += "\033[3m"
        if self.underline:
            start += "\033[4m"
        font_color_code, _ = self._get_rgb_color_code(self.font_color)
        background_color_code, _ = self._get_rgb_color_code(self.background_color, True)
        start += font_color_code
        start += background_color_code
        return start + text + end

    def _get_html_styled_text(self, text):
        styles = []
        if self.bold:
            styles.append("font-weight: bold;")
        if self.italic:
            styles.append("font-style: italic;")
        if self.underline:
            styles.append("text-decoration: underline;")
        _, font_color_code = self._get_rgb_color_code(self.font_color)
        _, background_color_code = self._get_rgb_color_code(self.background_color, True)
        styles.append(font_color_code)
        styles.append(background_color_code)
        style_attr = " ".join(styles)
        escaped_text = html.escape(text).replace("\n", "<br>")  # Escape HTML special characters
        return f'<span style="{style_attr}">{escaped_text}</span>'

    def _add_padding_if_needed(self):
        if self.padding and not self.padding_added:
            if not self.log_only:
                print()  # Print an empty line for padding
            self._log_html("<br>")
            self.padding_added = True

    def _log_html(self, html):
        with open(PrintStyle.log_file_path, "a") as f: # type: ignore
            f.write(html)

    @staticmethod
    def _close_html_log():
        if PrintStyle.log_file_path:
            with open(PrintStyle.log_file_path, "a") as f:
                f.write("</pre></body></html>")            

    def get(self, *args, sep=' ', **kwargs):
        text = sep.join(map(str, args))
        return text, self._get_styled_text(text), self._get_html_styled_text(text)
        
    def print(self, *args, sep=' ', **kwargs):
        self._add_padding_if_needed()
        if not PrintStyle.last_endline: 
            print()
            self._log_html("<br>")
        plain_text, styled_text, html_text = self.get(*args, sep=sep, **kwargs)
        if not self.log_only:
            print(styled_text, end='\n', flush=True)
        self._log_html(html_text+"<br>\n")
        PrintStyle.last_endline = True

    def stream(self, *args, sep=' ', **kwargs):
        self._add_padding_if_needed()
        plain_text, styled_text, html_text = self.get(*args, sep=sep, **kwargs)
        if not self.log_only:
            print(styled_text, end='', flush=True)
        self._log_html(html_text)
        PrintStyle.last_endline = False

    def is_last_line_empty(self):
        lines = sys.stdin.readlines()
        return bool(lines) and not lines[-1].strip()

# Ensure HTML file is closed properly when the program exits
import atexit
atexit.register(PrintStyle._close_html_log)