Skip to content

Commit bd3c18b

Browse files
committed
Revert using consolekit for terminal_colours and coloured_diff
1 parent bee3a16 commit bd3c18b

File tree

3 files changed

+325
-40
lines changed

3 files changed

+325
-40
lines changed

domdf_python_tools/terminal_colours.py

Lines changed: 290 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,14 @@
6464
# Distributed under the BSD 3-Clause license.
6565
#
6666

67+
# stdlib
68+
import re
69+
from abc import ABC
70+
from typing import List, Pattern
71+
6772
# 3rd party
68-
from consolekit.terminal_colours import (
69-
BEL,
70-
CSI,
71-
OSC,
72-
AnsiBack,
73-
AnsiCodes,
74-
AnsiCursor,
75-
AnsiFore,
76-
AnsiStyle,
77-
Back,
78-
Colour,
79-
Cursor,
80-
Fore,
81-
Style,
82-
back_stack,
83-
clear_line,
84-
code_to_chars,
85-
fore_stack,
86-
set_title,
87-
strip_ansi,
88-
style_stack
89-
)
73+
from colorama import init # type: ignore
74+
from typing_extensions import Final
9075

9176
__all__ = [
9277
"CSI",
@@ -109,6 +94,289 @@
10994
"strip_ansi",
11095
]
11196

97+
init()
98+
99+
CSI: Final[str] = "\u001b["
100+
OSC: Final[str] = "\u001b]"
101+
BEL: Final[str] = '\x07'
102+
103+
fore_stack: List[str] = []
104+
back_stack: List[str] = []
105+
style_stack: List[str] = []
106+
107+
108+
def code_to_chars(code) -> str:
109+
return CSI + str(code) + 'm'
110+
111+
112+
def set_title(title: str) -> str:
113+
return OSC + "2;" + title + BEL
114+
112115

113116
def clear_screen(mode: int = 2) -> str:
114117
return CSI + str(mode) + 'J'
118+
119+
120+
def clear_line(mode: int = 2) -> str:
121+
return CSI + str(mode) + 'K'
122+
123+
124+
_ansi_re: Pattern[str] = re.compile(r"\033\[[;?0-9]*[a-zA-Z]")
125+
126+
127+
def strip_ansi(value: str) -> str:
128+
"""
129+
Strip ANSI colour codes from the given string to return a plaintext output.
130+
131+
:param value:
132+
133+
:rtype:
134+
135+
.. versionadded:: 1.1.0
136+
"""
137+
138+
return _ansi_re.sub('', value)
139+
140+
141+
class Colour(str):
142+
r"""
143+
An ANSI escape sequence representing a colour.
144+
145+
The colour can be used as a context manager, a string, or a function.
146+
147+
:param style: Escape sequence representing the style.
148+
:type style: :class:`str`
149+
:param stack: The stack to place the escape sequence on.
150+
:type stack: :class:`~typing.List`\[:class:`str`\]
151+
:param reset: The escape sequence to reset the style.
152+
:type reset: :class:`str`
153+
"""
154+
155+
style: str
156+
reset: str
157+
stack: List[str]
158+
159+
def __new__(cls, style: str, stack: List[str], reset: str) -> "Colour": # noqa D102
160+
color = super().__new__(cls, style) # type: ignore
161+
color.style = style
162+
color.stack = stack
163+
color.reset = reset
164+
165+
return color
166+
167+
def __enter__(self) -> None:
168+
print(self.style, end='')
169+
self.stack.append(self.style)
170+
171+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
172+
if self.style == self.stack[-1]:
173+
self.stack.pop()
174+
print(self.stack[-1], end='')
175+
176+
def __call__(self, text) -> str:
177+
"""
178+
Returns the given text in this colour.
179+
"""
180+
181+
return f"{self}{text}{self.reset}"
182+
183+
184+
class AnsiCodes(ABC):
185+
"""
186+
Abstract base class for ANSI Codes.
187+
"""
188+
189+
_stack: List[str]
190+
_reset: str
191+
192+
def __init__(self) -> None:
193+
"""
194+
The subclasses declare class attributes which are numbers.
195+
196+
Upon instantiation we define instance attributes, which are the same
197+
as the class attributes but wrapped with the ANSI escape sequence.
198+
"""
199+
200+
for name in dir(self):
201+
if not name.startswith('_'):
202+
value = getattr(self, name)
203+
setattr(self, name, Colour(code_to_chars(value), self._stack, self._reset))
204+
205+
206+
class AnsiCursor:
207+
208+
def UP(self, n: int = 1) -> str:
209+
"""
210+
211+
:param n:
212+
"""
213+
214+
return f"{CSI}{str(n)}A"
215+
216+
def DOWN(self, n: int = 1) -> str:
217+
"""
218+
219+
:param n:
220+
"""
221+
222+
return f"{CSI}{str(n)}B"
223+
224+
def FORWARD(self, n: int = 1) -> str:
225+
"""
226+
227+
:param n:
228+
"""
229+
230+
return f"{CSI}{str(n)}C"
231+
232+
def BACK(self, n: int = 1) -> str:
233+
"""
234+
235+
:param n:
236+
"""
237+
238+
return f"{CSI}{str(n)}D"
239+
240+
def POS(self, x: int = 1, y: int = 1) -> str:
241+
"""
242+
243+
:param x:
244+
:param y:
245+
"""
246+
247+
return f"{CSI}{str(y)};{str(x)}H"
248+
249+
250+
class AnsiFore(AnsiCodes):
251+
"""
252+
ANSI Colour Codes for foreground colour.
253+
254+
The colours can be used as a context manager, a string, or a function.
255+
256+
Valid values are:
257+
258+
* BLACK
259+
* RED
260+
* GREEN
261+
* YELLOW
262+
* BLUE
263+
* MAGENTA
264+
* CYAN
265+
* WHITE
266+
* RESET
267+
* LIGHTBLACK_EX
268+
* LIGHTRED_EX
269+
* LIGHTGREEN_EX
270+
* LIGHTYELLOW_EX
271+
* LIGHTBLUE_EX
272+
* LIGHTMAGENTA_EX
273+
* LIGHTCYAN_EX
274+
* LIGHTWHITE_EX
275+
"""
276+
277+
_stack = fore_stack
278+
_reset = "\u001b[39m"
279+
280+
BLACK = 30
281+
RED = 31
282+
GREEN = 32
283+
YELLOW = 33
284+
BLUE = 34
285+
MAGENTA = 35
286+
CYAN = 36
287+
WHITE = 37
288+
RESET = 39
289+
290+
# These are fairly well supported, but not part of the standard.
291+
LIGHTBLACK_EX = 90
292+
LIGHTRED_EX = 91
293+
LIGHTGREEN_EX = 92
294+
LIGHTYELLOW_EX = 93
295+
LIGHTBLUE_EX = 94
296+
LIGHTMAGENTA_EX = 95
297+
LIGHTCYAN_EX = 96
298+
LIGHTWHITE_EX = 97
299+
300+
301+
class AnsiBack(AnsiCodes):
302+
"""
303+
ANSI Colour Codes for background colour.
304+
305+
The colours can be used as a context manager, a string, or a function.
306+
307+
Valid values are:
308+
309+
* BLACK
310+
* RED
311+
* GREEN
312+
* YELLOW
313+
* BLUE
314+
* MAGENTA
315+
* CYAN
316+
* WHITE
317+
* RESET
318+
* LIGHTBLACK_EX
319+
* LIGHTRED_EX
320+
* LIGHTGREEN_EX
321+
* LIGHTYELLOW_EX
322+
* LIGHTBLUE_EX
323+
* LIGHTMAGENTA_EX
324+
* LIGHTCYAN_EX
325+
* LIGHTWHITE_EX
326+
"""
327+
328+
_stack = back_stack
329+
_reset = "\u001b[49m"
330+
331+
BLACK = 40
332+
RED = 41
333+
GREEN = 42
334+
YELLOW = 43
335+
BLUE = 44
336+
MAGENTA = 45
337+
CYAN = 46
338+
WHITE = 47
339+
RESET = 49
340+
341+
# These are fairly well supported, but not part of the standard.
342+
LIGHTBLACK_EX = 100
343+
LIGHTRED_EX = 101
344+
LIGHTGREEN_EX = 102
345+
LIGHTYELLOW_EX = 103
346+
LIGHTBLUE_EX = 104
347+
LIGHTMAGENTA_EX = 105
348+
LIGHTCYAN_EX = 106
349+
LIGHTWHITE_EX = 107
350+
351+
352+
class AnsiStyle(AnsiCodes):
353+
"""
354+
ANSI Colour Codes for text style.
355+
356+
Valid values are:
357+
358+
* BRIGHT
359+
* DIM
360+
* NORMAL
361+
362+
Additionally, ``AnsiStyle.RESET_ALL`` can be used to reset the
363+
foreground and background colours as well as the text style.
364+
"""
365+
366+
_stack = style_stack
367+
_reset = "\u001b[22m"
368+
369+
BRIGHT = 1
370+
DIM = 2
371+
NORMAL = 22
372+
RESET_ALL = 0
373+
374+
375+
Fore = AnsiFore()
376+
Back = AnsiBack()
377+
Style = AnsiStyle()
378+
Cursor = AnsiCursor()
379+
380+
fore_stack.append(Fore.RESET)
381+
back_stack.append(Back.RESET)
382+
style_stack.append(Style.NORMAL)

0 commit comments

Comments
 (0)