xulbux 1.6.1__py3-none-any.whl → 1.6.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xulbux might be problematic. Click here for more details.
- xulbux/__init__.py +1 -1
- xulbux/_consts_.py +18 -18
- xulbux/xx_color.py +102 -92
- xulbux/xx_console.py +0 -12
- xulbux/xx_env_path.py +1 -1
- xulbux/xx_format_codes.py +219 -95
- xulbux/xx_regex.py +41 -30
- xulbux/xx_system.py +53 -1
- {xulbux-1.6.1.dist-info → xulbux-1.6.3.dist-info}/METADATA +15 -15
- xulbux-1.6.3.dist-info/RECORD +21 -0
- xulbux-1.6.1.dist-info/RECORD +0 -21
- {xulbux-1.6.1.dist-info → xulbux-1.6.3.dist-info}/LICENSE +0 -0
- {xulbux-1.6.1.dist-info → xulbux-1.6.3.dist-info}/WHEEL +0 -0
- {xulbux-1.6.1.dist-info → xulbux-1.6.3.dist-info}/entry_points.txt +0 -0
- {xulbux-1.6.1.dist-info → xulbux-1.6.3.dist-info}/top_level.txt +0 -0
xulbux/xx_format_codes.py
CHANGED
|
@@ -1,39 +1,78 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
These codes, when used within following functions, will change the look of log within the console:
|
|
2
|
+
Methods to transform formatting codes to ANSI and use them for pretty console output:
|
|
4
3
|
- `FormatCodes.print()` (print a special format-codes containing string)
|
|
5
4
|
- `FormatCodes.input()` (input with a special format-codes containing prompt)
|
|
6
5
|
- `FormatCodes.to_ansi()` (transform all special format-codes into ANSI codes in a string)\n
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
------------------------------------------------------------------------------------------------------------------------------------
|
|
7
|
+
### The Easy Formatting
|
|
8
|
+
|
|
9
|
+
First, let's take a look at a small example of what a highly styled print string with formatting could look like using this module:
|
|
10
|
+
```regex
|
|
11
|
+
This here is just unformatted text. [b|u|br:blue](Next we have text that is bright blue + bold + underlined.)\\n
|
|
12
|
+
[#000|bg:#F67](Then there's also black text with a red background.) And finally the ([i](boring)) plain text again.
|
|
13
13
|
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
|
|
15
|
+
How all of this exactly works is explained in the sections below. 🠫
|
|
16
|
+
|
|
17
|
+
------------------------------------------------------------------------------------------------------------------------------------
|
|
18
|
+
#### Formatting Codes and Keys
|
|
19
|
+
|
|
20
|
+
In this module, you can apply styles and colors using simple formatting codes.
|
|
21
|
+
These formatting codes consist of one or multiple different formatting keys in between square brackets.
|
|
22
|
+
|
|
23
|
+
If a formatting code is placed in a print-string, the formatting of that code will be applied to everything behind it until its
|
|
24
|
+
formatting is reset. If applying multiple styles and colors in the same place, instead of writing the formatting keys all into
|
|
25
|
+
separate brackets (e.g. `[x][y][z]`), they can also be put in a single pair of brackets, separated by pipes (e.g. `[x|y|z]`).
|
|
26
|
+
|
|
27
|
+
A list of all possible formatting keys can be found under all possible formatting keys.
|
|
28
|
+
|
|
29
|
+
------------------------------------------------------------------------------------------------------------------------------------
|
|
30
|
+
#### Auto Resetting Formatting Codes
|
|
31
|
+
|
|
32
|
+
Certain formatting can automatically be reset, behind a certain amount of text, just like shown in the following example:
|
|
33
|
+
```regex
|
|
34
|
+
This is plain text, [br:blue](which is bright blue now.) Now it was automatically reset to plain again.
|
|
19
35
|
```
|
|
20
|
-
|
|
21
|
-
This
|
|
22
|
-
|
|
23
|
-
|
|
36
|
+
|
|
37
|
+
This will only reset formatting codes, that have a specific reset listed below.
|
|
38
|
+
That means if you use it where another formatting is already applied, that formatting is still there after the automatic reset:
|
|
39
|
+
```regex
|
|
40
|
+
[cyan]This is cyan text, [dim](which is dimmed now.) Now it's not dimmed any more but still cyan.
|
|
24
41
|
```
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
|
|
43
|
+
If you want to ignore the auto-reset functionality of `()` brackets, you can put a `\\` or `/` between them and
|
|
44
|
+
the formatting code:
|
|
45
|
+
```regex
|
|
46
|
+
[cyan]This is cyan text, [u]/(which is underlined now.) And now it is still underlined and cyan.
|
|
28
47
|
```
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
All possible
|
|
32
|
-
|
|
33
|
-
- RGB colors:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
48
|
+
|
|
49
|
+
------------------------------------------------------------------------------------------------------------------------------------
|
|
50
|
+
#### All possible Formatting Keys
|
|
51
|
+
|
|
52
|
+
- RGB colors:
|
|
53
|
+
Change the text color directly with an RGB color inside the square brackets. (With or without `rgb()` brackets doesn't matter.)
|
|
54
|
+
Examples:
|
|
55
|
+
- `[rgb(115, 117, 255)]`
|
|
56
|
+
- `[(255, 0, 136)]`
|
|
57
|
+
- `[255, 0, 136]`
|
|
58
|
+
- HEX colors:
|
|
59
|
+
Change the text color directly with a HEX color inside the square brackets. (If `RGB` or `RRGGBB` formatting code is used,
|
|
60
|
+
and if there's a `#` or `0x` prefix, doesn't matter.)
|
|
61
|
+
Examples:
|
|
62
|
+
- `[#7788FF]`
|
|
63
|
+
- `[7788FF]`
|
|
64
|
+
- `[#78F]`
|
|
65
|
+
- `[78F]`
|
|
66
|
+
- background RGB / HEX colors:
|
|
67
|
+
Change the background color directly with an RGB or HEX color inside the square brackets, using the `background:` `BG:` prefix.
|
|
68
|
+
(Same RGB / HEX formatting code rules as for text color.)
|
|
69
|
+
Examples:
|
|
70
|
+
- `[background:rgb(115, 117, 255)]`
|
|
71
|
+
- `[BG:(255, 0, 136)]`
|
|
72
|
+
- `[background:#7788FF]`
|
|
73
|
+
- `[BG:#78F]`
|
|
74
|
+
- standard console colors:
|
|
75
|
+
Change the text color to one of the standard console colors by just writing the color name in the square brackets.
|
|
37
76
|
- `[black]`
|
|
38
77
|
- `[red]`
|
|
39
78
|
- `[green]`
|
|
@@ -42,28 +81,64 @@ All possible formatting codes:
|
|
|
42
81
|
- `[magenta]`
|
|
43
82
|
- `[cyan]`
|
|
44
83
|
- `[white]`
|
|
45
|
-
- bright
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
84
|
+
- bright console colors:
|
|
85
|
+
Use the prefix `bright:` `BR:` to use the bright variant of the standard console color.
|
|
86
|
+
Examples:
|
|
87
|
+
- `[bright:black]` `[BR:black]`
|
|
88
|
+
- `[bright:red]` `[BR:red]`
|
|
89
|
+
- ...
|
|
90
|
+
- Background console colors:
|
|
91
|
+
Use the prefix `background:` `BG:` to set the background to a standard console color. (Not all consoles support bright
|
|
92
|
+
standard colors.)
|
|
93
|
+
Examples:
|
|
94
|
+
- `[background:black]` `[BG:black]`
|
|
95
|
+
- `[background:red]` `[BG:red]`
|
|
96
|
+
- ...
|
|
97
|
+
- Bright background console colors:
|
|
98
|
+
Combine the prefixes `background:` / `BG:` and `bright:` / `BR:` to set the background to a bright console color.
|
|
99
|
+
(The order of the prefixes doesn't matter.)
|
|
100
|
+
Examples:
|
|
101
|
+
- `[background:bright:black]` `[BG:BR:black]`
|
|
102
|
+
- `[background:bright:red]` `[BG:BR:red]`
|
|
103
|
+
- ...
|
|
104
|
+
- Text styles:
|
|
105
|
+
Use the built-in text formatting to change the style of the text. There are long and short forms for each formatting code.
|
|
106
|
+
(Not all consoles support all text styles.)
|
|
107
|
+
- `[bold]` `[b]`
|
|
51
108
|
- `[dim]`
|
|
52
|
-
- `[italic]`
|
|
53
|
-
- `[underline]`
|
|
54
|
-
- `[inverse]
|
|
55
|
-
- `[hidden]
|
|
56
|
-
- `[strikethrough]`
|
|
57
|
-
- `[double-underline]`
|
|
58
|
-
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
- `[
|
|
63
|
-
- `[
|
|
64
|
-
- `[
|
|
65
|
-
- `[
|
|
66
|
-
|
|
109
|
+
- `[italic]` `[i]`
|
|
110
|
+
- `[underline]` `[u]`
|
|
111
|
+
- `[inverse]` `[invert]` `[in]`
|
|
112
|
+
- `[hidden]` `[hide]` `[h]`
|
|
113
|
+
- `[strikethrough]` `[s]`
|
|
114
|
+
- `[double-underline]` `[du]`
|
|
115
|
+
- Specific reset:
|
|
116
|
+
Use these reset codes to remove a specific style, color or background. Again, there are long and
|
|
117
|
+
short forms for each reset code.
|
|
118
|
+
- `[_bold]` `[_b]`
|
|
119
|
+
- `[_dim]`
|
|
120
|
+
- `[_italic]` `[_i]`
|
|
121
|
+
- `[_underline]` `[_u]`
|
|
122
|
+
- `[_inverse]` `[_invert]` `[_in]`
|
|
123
|
+
- `[_hidden]` `[_hide]` `[_h]`
|
|
124
|
+
- `[_strikethrough]` `[_s]`
|
|
125
|
+
- `[_double-underline]` `[_du]`
|
|
126
|
+
- `[_color]` `[_c]`
|
|
127
|
+
- `[_background]` `[_bg]`
|
|
128
|
+
- Total reset:
|
|
129
|
+
This will reset all previously applied formatting codes.
|
|
130
|
+
- `[_]`
|
|
131
|
+
|
|
132
|
+
------------------------------------------------------------------------------------------------------------------------------------
|
|
133
|
+
#### Additional Formatting Codes when a `default_color` is set
|
|
134
|
+
|
|
135
|
+
1. `[*]` resets everything, just like `[_]`, but the text color will remain in `default_color`
|
|
136
|
+
2. `[*color]` will reset the text color, just like `[_color]`, but then also make it `default_color`
|
|
137
|
+
3. `[default]` will just color the text in `default_color`
|
|
138
|
+
4. `[background:default]` `[BG:default]` will color the background in `default_color`
|
|
139
|
+
|
|
140
|
+
Unlike the standard console colors, the default color can be changed by using the following modifiers:
|
|
141
|
+
|
|
67
142
|
- `[l]` will lighten the `default_color` text by `brightness_steps`%
|
|
68
143
|
- `[ll]` will lighten the `default_color` text by `2 × brightness_steps`%
|
|
69
144
|
- `[lll]` will lighten the `default_color` text by `3 × brightness_steps`%
|
|
@@ -71,7 +146,7 @@ Unlike the standard cmd colors, the default color can be changed by using the fo
|
|
|
71
146
|
- `[d]` will darken the `default_color` text by `brightness_steps`%
|
|
72
147
|
- `[dd]` will darken the `default_color` text by `2 × brightness_steps`%
|
|
73
148
|
- `[ddd]` will darken the `default_color` text by `3 × brightness_steps`%
|
|
74
|
-
- ... etc
|
|
149
|
+
- ... etc.
|
|
75
150
|
Per default, you can also use `+` and `-` to get lighter and darker `default_color` versions.
|
|
76
151
|
"""
|
|
77
152
|
|
|
@@ -80,26 +155,43 @@ from .xx_string import String
|
|
|
80
155
|
from .xx_regex import Regex
|
|
81
156
|
from .xx_color import *
|
|
82
157
|
|
|
83
|
-
from functools import lru_cache
|
|
84
158
|
import ctypes as _ctypes
|
|
85
159
|
import regex as _rx
|
|
86
160
|
import sys as _sys
|
|
87
161
|
import re as _re
|
|
88
162
|
|
|
163
|
+
_CONSOLE_ANSI_CONFIGURED = False
|
|
89
164
|
|
|
90
|
-
|
|
165
|
+
_PREFIX = {
|
|
166
|
+
"BG": {"background", "bg"},
|
|
167
|
+
"BR": {"bright", "br"},
|
|
168
|
+
}
|
|
169
|
+
_PREFIX_RX = {
|
|
170
|
+
"BG": rf"(?:{'|'.join(_PREFIX['BG'])})\s*:",
|
|
171
|
+
"BR": rf"(?:{'|'.join(_PREFIX['BR'])})\s*:",
|
|
172
|
+
}
|
|
173
|
+
_COMPILED = { # PRECOMPILE REGULAR EXPRESSIONS
|
|
91
174
|
"*": _re.compile(r"\[\s*([^]_]*?)\s*\*\s*([^]_]*?)\]"),
|
|
92
175
|
"*color": _re.compile(r"\[\s*([^]_]*?)\s*\*color\s*([^]_]*?)\]"),
|
|
93
|
-
"
|
|
94
|
-
Regex.brackets("[", "]", is_group=True)
|
|
176
|
+
"formatting": _rx.compile(
|
|
177
|
+
Regex.brackets("[", "]", is_group=True)
|
|
178
|
+
+ r"(?:\s*([/\\]?)\s*"
|
|
179
|
+
+ Regex.brackets("(", ")", is_group=True, ignore_in_strings=False)
|
|
180
|
+
+ r")?"
|
|
95
181
|
),
|
|
96
|
-
"bg?_default": _re.compile(r"(?i)((?:BG
|
|
97
|
-
"bg_default": _re.compile(r"(?i)BG\s
|
|
182
|
+
"bg?_default": _re.compile(r"(?i)((?:" + _PREFIX_RX["BG"] + r")?)\s*default"),
|
|
183
|
+
"bg_default": _re.compile(r"(?i)" + _PREFIX_RX["BG"] + r"\s*default"),
|
|
98
184
|
"modifier": _re.compile(
|
|
99
|
-
|
|
185
|
+
r"(?i)((?:BG\s*:)?)\s*("
|
|
186
|
+
+ "|".join(
|
|
187
|
+
[f"{_re.escape(m)}+" for m in ANSI.default_color_modifiers["lighten"] + ANSI.default_color_modifiers["darken"]]
|
|
188
|
+
)
|
|
189
|
+
+ r")$"
|
|
190
|
+
),
|
|
191
|
+
"rgb": _re.compile(
|
|
192
|
+
r"(?i)^\s*(" + _PREFIX_RX["BG"] + r")?\s*(?:rgb|rgba)?\s*\(?\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)?\s*$"
|
|
100
193
|
),
|
|
101
|
-
"
|
|
102
|
-
"hex": _re.compile(r"(?i)^\s*(BG\s*:)?\s*(?:#|0x)?([0-9A-F]{6}|[0-9A-F]{3})\s*$"),
|
|
194
|
+
"hex": _re.compile(r"(?i)^\s*(" + _PREFIX_RX["BG"] + r")?\s*(?:#|0x)?([0-9A-F]{6}|[0-9A-F]{3})\s*$"),
|
|
103
195
|
}
|
|
104
196
|
|
|
105
197
|
|
|
@@ -108,12 +200,16 @@ class FormatCodes:
|
|
|
108
200
|
@staticmethod
|
|
109
201
|
def print(
|
|
110
202
|
*values: object,
|
|
111
|
-
default_color:
|
|
203
|
+
default_color: rgba | hexa = None,
|
|
112
204
|
brightness_steps: int = 20,
|
|
113
205
|
sep: str = " ",
|
|
114
206
|
end: str = "\n",
|
|
115
207
|
flush: bool = True,
|
|
116
208
|
) -> None:
|
|
209
|
+
"""A print function, whose print values can be formatted using formatting codes.\n
|
|
210
|
+
-----------------------------------------------------------------------------------
|
|
211
|
+
For exact information about how to use special formatting codes, see the
|
|
212
|
+
`xx_format_codes` module documentation."""
|
|
117
213
|
FormatCodes.__config_console()
|
|
118
214
|
_sys.stdout.write(FormatCodes.to_ansi(sep.join(map(str, values)) + end, default_color, brightness_steps))
|
|
119
215
|
if flush:
|
|
@@ -122,18 +218,34 @@ class FormatCodes:
|
|
|
122
218
|
@staticmethod
|
|
123
219
|
def input(
|
|
124
220
|
prompt: object = "",
|
|
125
|
-
default_color:
|
|
221
|
+
default_color: rgba | hexa = None,
|
|
126
222
|
brightness_steps: int = 20,
|
|
223
|
+
reset_ansi: bool = False,
|
|
127
224
|
) -> str:
|
|
225
|
+
"""An input, whose prompt can be formatted using formatting codes.\n
|
|
226
|
+
-------------------------------------------------------------------------
|
|
227
|
+
If `reset_ansi` is true, all ANSI formatting will be reset, after the
|
|
228
|
+
user confirms the input and the program continues to run.\n
|
|
229
|
+
-------------------------------------------------------------------------
|
|
230
|
+
For exact information about how to use special formatting codes, see the
|
|
231
|
+
`xx_format_codes` module documentation."""
|
|
128
232
|
FormatCodes.__config_console()
|
|
129
|
-
|
|
233
|
+
user_input = input(FormatCodes.to_ansi(str(prompt), default_color, brightness_steps))
|
|
234
|
+
if reset_ansi:
|
|
235
|
+
_sys.stdout.write("\x1b[0m")
|
|
236
|
+
return user_input
|
|
130
237
|
|
|
131
238
|
@staticmethod
|
|
132
239
|
def to_ansi(
|
|
133
|
-
string: str,
|
|
240
|
+
string: str,
|
|
241
|
+
default_color: rgba | hexa = None,
|
|
242
|
+
brightness_steps: int = 20,
|
|
243
|
+
_default_start: bool = True,
|
|
134
244
|
) -> str:
|
|
135
|
-
|
|
136
|
-
|
|
245
|
+
"""Convert the formatting codes inside a string to ANSI formatting.\n
|
|
246
|
+
-------------------------------------------------------------------------
|
|
247
|
+
For exact information about how to use special formatting codes, see the
|
|
248
|
+
`xx_format_codes` module documentation."""
|
|
137
249
|
if Color.is_valid_rgba(default_color, False):
|
|
138
250
|
use_default = True
|
|
139
251
|
elif Color.is_valid_hexa(default_color, False):
|
|
@@ -141,8 +253,8 @@ class FormatCodes:
|
|
|
141
253
|
else:
|
|
142
254
|
use_default = False
|
|
143
255
|
if use_default:
|
|
144
|
-
string =
|
|
145
|
-
string =
|
|
256
|
+
string = _COMPILED["*"].sub(r"[\1_|default\2]", string) # REPLACE `[…|*|…]` WITH `[…|_|default|…]`
|
|
257
|
+
string = _COMPILED["*color"].sub(r"[\1default\2]", string) # REPLACE `[…|*color|…]` WITH `[…|default|…]`
|
|
146
258
|
|
|
147
259
|
def is_valid_color(color: str) -> bool:
|
|
148
260
|
return color in ANSI.color_map or Color.is_valid_rgba(color) or Color.is_valid_hexa(color)
|
|
@@ -166,10 +278,9 @@ class FormatCodes:
|
|
|
166
278
|
reset_keys = []
|
|
167
279
|
for k in format_keys:
|
|
168
280
|
k_lower = k.lower()
|
|
169
|
-
|
|
170
|
-
k_set
|
|
171
|
-
|
|
172
|
-
if k_set & color_pref:
|
|
281
|
+
k_set = set(k_lower.split(":"))
|
|
282
|
+
if _PREFIX["BG"] & k_set and len(k_set) <= 3:
|
|
283
|
+
if k_set & _PREFIX["BR"]:
|
|
173
284
|
for i in range(len(k)):
|
|
174
285
|
if is_valid_color(k[i:]):
|
|
175
286
|
reset_keys.extend(["_bg", "_color"])
|
|
@@ -181,7 +292,7 @@ class FormatCodes:
|
|
|
181
292
|
break
|
|
182
293
|
elif is_valid_color(k) or any(
|
|
183
294
|
k_lower.startswith(pref_colon := f"{prefix}:") and is_valid_color(k[len(pref_colon) :])
|
|
184
|
-
for prefix in
|
|
295
|
+
for prefix in _PREFIX["BR"]
|
|
185
296
|
):
|
|
186
297
|
reset_keys.append("_color")
|
|
187
298
|
else:
|
|
@@ -209,38 +320,42 @@ class FormatCodes:
|
|
|
209
320
|
+ ("" if escaped else "".join(ansi_resets))
|
|
210
321
|
)
|
|
211
322
|
|
|
212
|
-
|
|
213
|
-
return (FormatCodes.__get_default_ansi(default_color) if _default_start else "") +
|
|
323
|
+
string = "\n".join(_COMPILED["formatting"].sub(replace_keys, line) for line in string.split("\n"))
|
|
324
|
+
return (FormatCodes.__get_default_ansi(default_color) if _default_start else "") + string if use_default else string
|
|
214
325
|
|
|
215
326
|
@staticmethod
|
|
216
|
-
def escape_ansi(ansi_string: str
|
|
217
|
-
"""
|
|
218
|
-
return ansi_string.replace(ANSI.char, escaped_char)
|
|
327
|
+
def escape_ansi(ansi_string: str) -> str:
|
|
328
|
+
"""Escapes all ANSI codes in a string, so they are visible when output to the console."""
|
|
329
|
+
return ansi_string.replace(ANSI.char, ANSI.escaped_char)
|
|
219
330
|
|
|
220
331
|
@staticmethod
|
|
221
|
-
@lru_cache(maxsize=64)
|
|
222
332
|
def __config_console() -> None:
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
333
|
+
"""Configure the console to be able to interpret ANSI formatting."""
|
|
334
|
+
if not _CONSOLE_ANSI_CONFIGURED:
|
|
335
|
+
_sys.stdout.flush()
|
|
336
|
+
kernel32 = _ctypes.windll.kernel32
|
|
337
|
+
h = kernel32.GetStdHandle(-11)
|
|
338
|
+
mode = _ctypes.c_ulong()
|
|
339
|
+
kernel32.GetConsoleMode(h, _ctypes.byref(mode))
|
|
340
|
+
kernel32.SetConsoleMode(h, mode.value | 0x0004)
|
|
341
|
+
global _CONSOLE_ANSI_CONFIGURED
|
|
342
|
+
_CONSOLE_ANSI_CONFIGURED = True
|
|
229
343
|
|
|
230
344
|
@staticmethod
|
|
231
345
|
def __get_default_ansi(
|
|
232
346
|
default_color: tuple,
|
|
233
347
|
format_key: str = None,
|
|
234
348
|
brightness_steps: int = None,
|
|
235
|
-
_modifiers: tuple[str, str] = (ANSI.
|
|
349
|
+
_modifiers: tuple[str, str] = (ANSI.default_color_modifiers["lighten"], ANSI.default_color_modifiers["darken"]),
|
|
236
350
|
) -> str | None:
|
|
237
|
-
|
|
238
|
-
|
|
351
|
+
"""Get the `default_color` and lighter/darker versions of it as ANSI code."""
|
|
352
|
+
if not brightness_steps or (format_key and _COMPILED["bg?_default"].search(format_key)):
|
|
353
|
+
return (ANSI.seq_bg_color if format_key and _COMPILED["bg_default"].search(format_key) else ANSI.seq_color).format(
|
|
239
354
|
*default_color[:3]
|
|
240
355
|
)
|
|
241
356
|
if not (format_key in _modifiers[0] or format_key in _modifiers[1]):
|
|
242
357
|
return None
|
|
243
|
-
match =
|
|
358
|
+
match = _COMPILED["modifier"].match(format_key)
|
|
244
359
|
if not match:
|
|
245
360
|
return None
|
|
246
361
|
is_bg, modifiers = match.groups()
|
|
@@ -264,11 +379,7 @@ class FormatCodes:
|
|
|
264
379
|
If `default_color` is not `None`, the text color will be `default_color` if all formats
|
|
265
380
|
are reset or you can get lighter or darker version of `default_color` (also as BG)"""
|
|
266
381
|
use_default = default_color and Color.is_valid_rgba(default_color, False)
|
|
267
|
-
_format_key, format_key = format_key, ( # NORMALIZE
|
|
268
|
-
"bg:" if "bg" in (parts := format_key.replace(" ", "").lower().split(":")) else ""
|
|
269
|
-
) + ("bright:" if any(x in parts for x in ("bright", "br")) else "") + ":".join(
|
|
270
|
-
p for p in parts if p not in ("bg", "bright", "br")
|
|
271
|
-
)
|
|
382
|
+
_format_key, format_key = format_key, FormatCodes.__normalize_key(format_key) # NORMALIZE KEY AND SAVE ORIGINAL
|
|
272
383
|
if use_default:
|
|
273
384
|
if new_default_color := FormatCodes.__get_default_ansi(default_color, format_key, brightness_steps):
|
|
274
385
|
return new_default_color
|
|
@@ -284,8 +395,8 @@ class FormatCodes:
|
|
|
284
395
|
None,
|
|
285
396
|
)
|
|
286
397
|
)
|
|
287
|
-
rgb_match = _re.match(
|
|
288
|
-
hex_match = _re.match(
|
|
398
|
+
rgb_match = _re.match(_COMPILED["rgb"], format_key)
|
|
399
|
+
hex_match = _re.match(_COMPILED["hex"], format_key)
|
|
289
400
|
try:
|
|
290
401
|
if rgb_match:
|
|
291
402
|
is_bg = rgb_match.group(1)
|
|
@@ -303,3 +414,16 @@ class FormatCodes:
|
|
|
303
414
|
except Exception:
|
|
304
415
|
pass
|
|
305
416
|
return _format_key
|
|
417
|
+
|
|
418
|
+
@staticmethod
|
|
419
|
+
def __normalize_key(format_key: str) -> str:
|
|
420
|
+
"""Normalizes the given format key."""
|
|
421
|
+
k_parts = format_key.replace(" ", "").lower().split(":")
|
|
422
|
+
prefix_str = "".join(
|
|
423
|
+
f"{prefix_key.lower()}:"
|
|
424
|
+
for prefix_key, prefix_values in _PREFIX.items()
|
|
425
|
+
if any(k_part in prefix_values for k_part in k_parts)
|
|
426
|
+
)
|
|
427
|
+
return prefix_str + ":".join(
|
|
428
|
+
part for part in k_parts if part not in {val for values in _PREFIX.values() for val in values}
|
|
429
|
+
)
|
xulbux/xx_regex.py
CHANGED
|
@@ -9,6 +9,7 @@ Really long regex code presets:
|
|
|
9
9
|
`hsla_str` match a HSLA color
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
|
+
import regex as _rx
|
|
12
13
|
import re as _re
|
|
13
14
|
|
|
14
15
|
|
|
@@ -17,25 +18,33 @@ class Regex:
|
|
|
17
18
|
@staticmethod
|
|
18
19
|
def quotes() -> str:
|
|
19
20
|
"""Matches everything inside quotes. (strings)\n
|
|
20
|
-
|
|
21
|
+
--------------------------------------------------------------------------------
|
|
21
22
|
Will create two named groups:
|
|
22
23
|
- `quote` the quote type (single or double)
|
|
23
24
|
- `string` everything inside the found quote pair\n
|
|
24
|
-
|
|
25
|
+
--------------------------------------------------------------------------------
|
|
25
26
|
Attention: Requires non standard library `regex` not standard library `re`!"""
|
|
26
27
|
return r'(?P<quote>[\'"])(?P<string>(?:\\.|(?!\g<quote>).)*?)\g<quote>'
|
|
27
28
|
|
|
28
29
|
@staticmethod
|
|
29
|
-
def brackets(bracket1: str = "(", bracket2: str = ")", is_group: bool = False) -> str:
|
|
30
|
+
def brackets(bracket1: str = "(", bracket2: str = ")", is_group: bool = False, ignore_in_strings: bool = True) -> str:
|
|
30
31
|
"""Matches everything inside brackets, including other nested brackets.\n
|
|
31
|
-
|
|
32
|
+
--------------------------------------------------------------------------------
|
|
33
|
+
If `is_group` is true, you will be able to reference the matched content as a
|
|
34
|
+
group (e.g. `match.group(…)` or `r'\\…'`).
|
|
35
|
+
If `ignore_in_strings` is true and a bracket is inside a string (e.g. `'...'`
|
|
36
|
+
or `"..."`), it will not be counted as the matching closing bracket.\n
|
|
37
|
+
--------------------------------------------------------------------------------
|
|
32
38
|
Attention: Requires non standard library `regex` not standard library `re`!"""
|
|
33
39
|
g, b1, b2 = (
|
|
34
40
|
"" if is_group else "?:",
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
_rx.escape(bracket1) if len(bracket1) == 1 else bracket1,
|
|
42
|
+
_rx.escape(bracket2) if len(bracket2) == 1 else bracket2,
|
|
37
43
|
)
|
|
38
|
-
|
|
44
|
+
if ignore_in_strings:
|
|
45
|
+
return rf'{b1}\s*({g}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|{b1}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|(?R))*{b2})*)\s*{b2}'
|
|
46
|
+
else:
|
|
47
|
+
return rf"{b1}\s*({g}(?:[^{b1}{b2}]|{b1}(?:[^{b1}{b2}]|(?R))*{b2})*)\s*{b2}"
|
|
39
48
|
|
|
40
49
|
@staticmethod
|
|
41
50
|
def outside_strings(pattern: str = r".*") -> str:
|
|
@@ -48,22 +57,27 @@ class Regex:
|
|
|
48
57
|
ignore_pattern: str = "",
|
|
49
58
|
is_group: bool = False,
|
|
50
59
|
) -> str:
|
|
51
|
-
"""Matches everything except `disallowed_pattern`, unless the `disallowed_pattern`
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
"""Matches everything except `disallowed_pattern`, unless the `disallowed_pattern`
|
|
61
|
+
is found inside a string (`'...'` or `"..."`).\n
|
|
62
|
+
------------------------------------------------------------------------------------
|
|
63
|
+
The `ignore_pattern` is just always ignored. For example if `disallowed_pattern` is
|
|
64
|
+
`>` and `ignore_pattern` is `->`, the `->`-arrows will be allowed, even though they
|
|
65
|
+
have `>` in them.
|
|
66
|
+
If `is_group` is true, you will be able to reference the matched content as a group
|
|
67
|
+
(e.g. `match.group(…)` or `r'\\…'`)."""
|
|
56
68
|
return rf'({"" if is_group else "?:"}(?:(?!{ignore_pattern}).)*(?:(?!{Regex.outside_strings(disallowed_pattern)}).)*)'
|
|
57
69
|
|
|
58
70
|
@staticmethod
|
|
59
71
|
def func_call(func_name: str = None) -> str:
|
|
60
|
-
"""Match a function call
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
"""Match a function call, and get back two groups:
|
|
73
|
+
1. function name
|
|
74
|
+
2. the function's arguments\n
|
|
63
75
|
If no `func_name` is given, it will match any function call.\n
|
|
64
|
-
|
|
76
|
+
--------------------------------------------------------------------------------
|
|
65
77
|
Attention: Requires non standard library `regex` not standard library `re`!"""
|
|
66
|
-
return
|
|
78
|
+
return (
|
|
79
|
+
r"(?<=\b)(" + (r"[\w_]+" if func_name is None else func_name) + r")\s*" + Regex.brackets("(", ")", is_group=True)
|
|
80
|
+
)
|
|
67
81
|
|
|
68
82
|
@staticmethod
|
|
69
83
|
def rgba_str(fix_sep: str = ",", allow_alpha: bool = True) -> str:
|
|
@@ -76,11 +90,10 @@ class Regex:
|
|
|
76
90
|
- `(r, g, b, a)` (if `allow_alpha=True`)
|
|
77
91
|
- `r, g, b`
|
|
78
92
|
- `r, g, b, a` (if `allow_alpha=True`)\n
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- `
|
|
82
|
-
- `
|
|
83
|
-
- `b` 0-255 (amount: blue)
|
|
93
|
+
#### Valid ranges:
|
|
94
|
+
- `r` 0-255 (int: red)
|
|
95
|
+
- `g` 0-255 (int: green)
|
|
96
|
+
- `b` 0-255 (int: blue)
|
|
84
97
|
- `a` 0-1 (float: opacity)\n
|
|
85
98
|
----------------------------------------------------------------------------
|
|
86
99
|
If the `fix_sep` is set to nothing, any char that is not a letter or number
|
|
@@ -112,11 +125,10 @@ class Regex:
|
|
|
112
125
|
- `(h, s, l, a)` (if `allow_alpha=True`)
|
|
113
126
|
- `h, s, l`
|
|
114
127
|
- `h, s, l, a` (if `allow_alpha=True`)\n
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
- `
|
|
118
|
-
- `
|
|
119
|
-
- `l` 0-100 (percentage: lightness)
|
|
128
|
+
#### Valid ranges:
|
|
129
|
+
- `h` 0-360 (int: hue)
|
|
130
|
+
- `s` 0-100 (int: saturation)
|
|
131
|
+
- `l` 0-100 (int: lightness)
|
|
120
132
|
- `a` 0-1 (float: opacity)\n
|
|
121
133
|
----------------------------------------------------------------------------
|
|
122
134
|
If the `fix_sep` is set to nothing, any char that is not a letter or number
|
|
@@ -146,9 +158,8 @@ class Regex:
|
|
|
146
158
|
- `RGBA` (if `allow_alpha=True`)
|
|
147
159
|
- `RRGGBB`
|
|
148
160
|
- `RRGGBBAA` (if `allow_alpha=True`)\n
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
each channel from 0-9 and A-F (case insensitive)"""
|
|
161
|
+
#### Valid ranges:
|
|
162
|
+
every channel from 0-9 and A-F (case insensitive)"""
|
|
152
163
|
return (
|
|
153
164
|
r"(?i)^(?:#|0x)?[0-9A-F]{8}|[0-9A-F]{6}|[0-9A-F]{4}|[0-9A-F]{3}$"
|
|
154
165
|
if allow_alpha
|