1
+ import os
1
2
from pathlib import Path
2
3
import queue
4
+ import re
3
5
import subprocess
4
6
import threading
7
+ import traceback
5
8
from typing import Optional
6
9
import sys
7
10
import time
8
11
from watchdog .observers import Observer
9
12
from watchdog .events import FileSystemEvent , FileSystemEventHandler
13
+
14
+ class PrintColor :
15
+ def __init__ (self ) -> None :
16
+ self .ansi = (
17
+ (sys .platform != 'Pocket PC' ) and
18
+ (
19
+ (sys .platform != 'win32' ) or
20
+ ('ANSICON' in os .environ )
21
+ ) and
22
+ (
23
+ sys .stdout .isatty () or
24
+ (sys .platform == 'win32' )
25
+ ) and
26
+ (
27
+ 'TERM' not in os .environ or
28
+ (
29
+ os .environ ['TERM' ].lower () in ('xterm' , 'linux' , 'screen' , 'vt100' , 'cygwin' , 'ansicon' ) and
30
+ os .environ ['TERM' ].lower () not in ('dumb' , 'emacs' , 'emacs-24' , 'xterm-mono' )
31
+ )
32
+ )
33
+ )
34
+ self .colors = {
35
+ 'reset' : '\033 [0m' ,
36
+ 'red' : '\033 [31m' ,
37
+ 'green' : '\033 [32m' ,
38
+ 'yellow' : '\033 [33m' ,
39
+ 'blue' : '\033 [34m' ,
40
+ 'magenta' : '\033 [35m' ,
41
+ 'cyan' : '\033 [36m' ,
42
+ 'white' : '\033 [37m' ,
43
+ 'black' : '\033 [30m' ,
44
+ }
45
+ self .open_tag_pattern = r'<(\w+)>'
46
+ self .close_tag_pattern = r'<(\w+)/>'
47
+
48
+ def parse (self , text : str ):
49
+ current_color = self .colors ['reset' ]
50
+ open_tags = re .findall (self .open_tag_pattern , text )
51
+ for tag in open_tags :
52
+ if tag in self .colors :
53
+ text = text .replace (f'<{ tag } >' , self .colors [tag ], 1 )
54
+ current_color = self .colors [tag ]
55
+ else :
56
+ text = text .replace (f'<{ tag } >' , '' , 1 )
57
+ close_tags = re .findall (self .close_tag_pattern , text )
58
+ for tag in close_tags :
59
+ if tag == tag .lower () and self .colors .get (tag .lower (), '' ) == current_color :
60
+ text = text .replace (f'<{ tag } />' , self .colors ['reset' ], 1 )
61
+ current_color = self .colors ['reset' ]
62
+ return text
63
+
64
+ printColor = PrintColor ()
10
65
encoding = sys .getdefaultencoding ()
11
66
process : Optional [subprocess .Popen ] = None
12
67
stdout = None
@@ -55,10 +110,23 @@ def _err():
55
110
else :
56
111
output .put (line )
57
112
58
- def _parse (params ):
113
+ def _parse (params : str ):
59
114
kwargs = {}
60
- if "flush" in params :
61
- kwargs ["flush" ] = True
115
+ for item in params .split ("," ):
116
+ k , v = item .split (":" , 1 )
117
+ if v == "True" :
118
+ v = True
119
+ elif v == "False" :
120
+ v = False
121
+ else :
122
+ try :
123
+ v = float (v )
124
+ except :
125
+ try :
126
+ v = int (v )
127
+ except :
128
+ ...
129
+ kwargs [k ] = v
62
130
return kwargs
63
131
def _print ():
64
132
global output , last_output_length , last_flush
@@ -71,22 +139,28 @@ def _print():
71
139
msg = msg .decode ("gbk" )
72
140
except :
73
141
msg = repr (msg )
74
- msg = msg .removesuffix ("\n " )
75
- date = time .localtime ()
76
- date = f"[{ date .tm_year :04d} -{ date .tm_mon :02d} -{ date .tm_mday :02d} { date .tm_hour :02d} :{ date .tm_min :02d} :{ date .tm_sec :02d} ]"
77
- kwargs : dict = {}
78
- flush : bool = False
79
- if msg .startswith ("<<<" ) and ">>>" in msg :
80
- kwargs = _parse (msg [3 :msg .find (">>>" )])
81
- msg = msg [msg .find (">>>" ) + 3 :]
82
- flush = kwargs .get ("flush" , False )
83
- text = f"{ date } { msg } "
84
- if flush :
85
- sys .stdout .write ('\r ' + ' ' * (last_output_length + 16 ) + '\r ' )
86
- sys .stdout .flush ()
87
- last_output_length = len (text )
88
- print (text + ('\n ' if not flush else '' ), end = '' , flush = flush )
89
- last_flush = flush
142
+ try :
143
+ msg = msg .removesuffix ("\n " )
144
+ date = time .localtime ()
145
+ kwargs : dict = {}
146
+ flush : bool = False
147
+ if msg .startswith ("<<<" ) and ">>>" in msg :
148
+ kwargs = _parse (msg [3 :msg .find (">>>" )])
149
+ msg = msg [msg .find (">>>" ) + 3 :]
150
+ flush = kwargs .get ("flush" , False )
151
+ if 'time' in kwargs :
152
+ date = time .localtime (kwargs ["time" ])
153
+ date = f"[{ date .tm_year :04d} -{ date .tm_mon :02d} -{ date .tm_mday :02d} { date .tm_hour :02d} :{ date .tm_min :02d} :{ date .tm_sec :02d} ]"
154
+ text = printColor .parse (f"<{ kwargs .get ('color' , 'reset' )} >{ date } { msg } " )
155
+ if flush :
156
+ sys .stdout .write ('\r ' + ' ' * (last_output_length + 16 ) + '\r ' )
157
+ sys .stdout .flush ()
158
+ last_output_length = len (text )
159
+ print (text + ('\n ' if not flush else '' ), end = '' , flush = flush )
160
+ last_flush = flush
161
+ except :
162
+ traceback .print_exc ()
163
+ ...
90
164
91
165
class MyHandler (FileSystemEventHandler ):
92
166
def on_any_event (self , event : FileSystemEvent ) -> None :
0 commit comments