Skip to content

Commit 91364b3

Browse files
committed
temporary add ascii_escape_code.py
(this should live in its own library)
1 parent 07b3c39 commit 91364b3

File tree

1 file changed

+357
-0
lines changed

1 file changed

+357
-0
lines changed

ascii_escape_code.py

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
#!/usr/bin/env python3
2+
# coding=utf-8
3+
4+
# SPDX-FileCopyrightText: Copyright (c) 2021 Stefan Krüger s-light.eu
5+
#
6+
# SPDX-License-Identifier: MIT
7+
"""
8+
`ASCII_escape_code`
9+
================================================================================
10+
11+
simple helper library for common ASCII escape codes
12+
13+
inspired / based on information from
14+
- https://en.wikipedia.org/wiki/ANSI_escape_code
15+
- https://www.geeksforgeeks.org/print-colors-python-terminal/
16+
17+
18+
* Author(s): Stefan Krüger
19+
20+
Implementation Notes
21+
--------------------
22+
23+
**Hardware:**
24+
25+
**Software and Dependencies:**
26+
27+
* Adafruit CircuitPython firmware `>= 7.0.0 for the supported boards.
28+
<https://github.com/adafruit/circuitpython/releases>`_
29+
"""
30+
31+
# pylint: disable=invalid-name, too-few-public-methods
32+
33+
import time
34+
35+
##########################################
36+
# helper functions
37+
38+
39+
def create_seq(control, esc="\033["):
40+
"""
41+
Control sequences function generator.
42+
43+
:param string control: control characters.
44+
:param string esc: escape character. Default: ``\033[``
45+
:return lambda: function generator with predefined control sequences.
46+
"""
47+
return lambda value="": "{esc}{value}{control}".format(
48+
esc=esc, value=value, control=control
49+
)
50+
51+
52+
def create_color(color):
53+
"""
54+
Create color sequences.
55+
56+
:param string color: color number (as string).
57+
:return string: ready to use color control character string.
58+
"""
59+
return create_seq("m")(color)
60+
61+
62+
##########################################
63+
# ASCIIControllsBase Class
64+
65+
66+
class ASCIIControllsBase:
67+
"""
68+
Base Class for ASCII Color and Control Characters.
69+
"""
70+
71+
esc = "\033["
72+
73+
# @staticmethod
74+
# def create_seq(control, esc=esc):
75+
# return lambda value: "{esc}{value}{control}".format(
76+
# esc=esc, value=value, control=control
77+
# )
78+
79+
@classmethod
80+
def get_flat_list(cls, obj_dict=None):
81+
"""Get a flattend list of all control characters in dict."""
82+
result = []
83+
if obj_dict is None:
84+
obj_dict = cls.__dict__
85+
# print("*"*42)
86+
# print("obj_dict", obj_dict)
87+
# print("*"*42)
88+
for attr_name, attr_value in obj_dict.items():
89+
if not attr_name.startswith("__"):
90+
# if type(attr_value) is str:
91+
# value_str = attr_value.replace("\x1b", "\\x1b")
92+
# else:
93+
# value_str = attr_value
94+
# print(
95+
# "'{}' '{}': {} "
96+
# "".format(
97+
# attr_name,
98+
# type(attr_value),
99+
# value_str,
100+
# ),
101+
# end=""
102+
# )
103+
if isinstance(attr_value, str):
104+
# print(" STRING ")
105+
result.append(attr_value)
106+
elif isinstance(attr_value, type):
107+
# print(" TYPE ")
108+
result.extend(cls.get_flat_list(attr_value.__dict__))
109+
else:
110+
# print(" UNKNOWN ")
111+
pass
112+
# print("*"*42)
113+
return result
114+
115+
116+
class ASCIIColors(ASCIIControllsBase):
117+
"""
118+
ASCII Color and Font-Effects Control Characters.
119+
120+
reset all colors with ASCIIColors.reset;
121+
two sub classes
122+
* ``fg`` for foreground
123+
* ``bg`` for background;
124+
use as ASCIIColors.subclass.colorname:
125+
```
126+
ASCIIColors.fg.red
127+
ASCIIColors.bg.green
128+
```
129+
130+
the generic formatings
131+
* bold
132+
* disable
133+
* underline
134+
* reverse
135+
* strike through
136+
* invisible
137+
work with the main class:
138+
``ASCIIColors.bold``
139+
"""
140+
141+
# reset = ASCIIControllsBase.esc + "0m"
142+
"""
143+
reset
144+
145+
:return string: ready to use sequences.
146+
"""
147+
reset = create_color("0")
148+
"""
149+
bold
150+
151+
:return string: ready to use sequences.
152+
"""
153+
bold = create_color("01")
154+
"""
155+
disable
156+
157+
:return string: ready to use sequences.
158+
"""
159+
disable = create_color("02")
160+
"""
161+
underline
162+
163+
:return string: ready to use sequences.
164+
"""
165+
underline = create_color("04")
166+
"""
167+
reverse
168+
169+
:return string: ready to use sequences.
170+
"""
171+
reverse = create_color("07")
172+
"""
173+
strikethrough
174+
175+
:return string: ready to use sequences.
176+
"""
177+
strikethrough = create_color("09")
178+
"""
179+
invisible
180+
181+
:return string: ready to use sequences.
182+
"""
183+
invisible = create_color("08")
184+
185+
# class fg:
186+
# """Forderground Colors."""
187+
#
188+
# black = create_color("30m")
189+
# red = create_color("31m")
190+
# green = create_color("32m")
191+
# orange = create_color("33m")
192+
# blue = create_color("34m")
193+
# purple = create_color("35m")
194+
# cyan = create_color("36m")
195+
# lightgrey = create_color("37m")
196+
# darkgrey = create_color("90m")
197+
# lightred = create_color("91m")
198+
# lightgreen = create_color("92m")
199+
# yellow = create_color("93m")
200+
# lightblue = create_color("94m")
201+
# pink = create_color("95m")
202+
# lightcyan = create_color("96m")
203+
#
204+
# class bg:
205+
# """Background Colors."""
206+
#
207+
# black = create_color("40m")
208+
# red = create_color("41m")
209+
# green = create_color("42m")
210+
# orange = create_color("43m")
211+
# blue = create_color("44m")
212+
# purple = create_color("45m")
213+
# cyan = create_color("46m")
214+
# lightgrey = create_color("47m")
215+
216+
class fg:
217+
"""Forderground Colors."""
218+
219+
"""
220+
Forderground black
221+
222+
:return string: ready to use sequences.
223+
"""
224+
black = ASCIIControllsBase.esc + "30m"
225+
red = ASCIIControllsBase.esc + "31m"
226+
green = ASCIIControllsBase.esc + "32m"
227+
orange = ASCIIControllsBase.esc + "33m"
228+
blue = ASCIIControllsBase.esc + "34m"
229+
purple = ASCIIControllsBase.esc + "35m"
230+
cyan = ASCIIControllsBase.esc + "36m"
231+
lightgrey = ASCIIControllsBase.esc + "37m"
232+
darkgrey = ASCIIControllsBase.esc + "90m"
233+
lightred = ASCIIControllsBase.esc + "91m"
234+
lightgreen = ASCIIControllsBase.esc + "92m"
235+
yellow = ASCIIControllsBase.esc + "93m"
236+
lightblue = ASCIIControllsBase.esc + "94m"
237+
pink = ASCIIControllsBase.esc + "95m"
238+
lightcyan = ASCIIControllsBase.esc + "96m"
239+
240+
class bg:
241+
"""Background Colors."""
242+
243+
black = ASCIIControllsBase.esc + "40m"
244+
red = ASCIIControllsBase.esc + "41m"
245+
green = ASCIIControllsBase.esc + "42m"
246+
orange = ASCIIControllsBase.esc + "43m"
247+
blue = ASCIIControllsBase.esc + "44m"
248+
purple = ASCIIControllsBase.esc + "45m"
249+
cyan = ASCIIControllsBase.esc + "46m"
250+
lightgrey = ASCIIControllsBase.esc + "47m"
251+
252+
253+
class ASCIIControl(ASCIIControllsBase):
254+
"""
255+
ASCII Cursor movement.
256+
257+
please make sure your terminal supports these...
258+
tested with `GTKTerm:
259+
<https://circuitpython.readthedocs.io/en/latest/shared-bindings/usb_cdc/index.html>`_
260+
261+
usage example:
262+
.. code-block:: python
263+
ASCIIControl.erease_line()
264+
ASCIIControl.cursor.up(5)
265+
"""
266+
267+
ED = erase_display = create_seq("J")
268+
EL = erase_line = create_seq("K")
269+
SU = scroll_up = create_seq("S")
270+
SD = scroll_down = create_seq("T")
271+
DSR = device_status_report = create_seq("n")("6")
272+
273+
class cursor:
274+
"""Cursor Movement."""
275+
276+
"""
277+
CUU - CUrsor Up
278+
279+
:param string value: Lines to move up.
280+
:return string: ready to use sequences.
281+
"""
282+
CUU = up = create_seq("A")
283+
CUD = down = create_seq("B")
284+
CUF = forward = create_seq("C")
285+
CUB = back = create_seq("D")
286+
CNL = next_line = create_seq("E")
287+
CPL = previous_line = create_seq("F")
288+
CHA = horizontal_absolute = create_seq("G")
289+
CUP = position = create_seq("H")
290+
291+
292+
##########################################
293+
294+
295+
def filter_ascii_controlls(data):
296+
"""
297+
Remove ASCII controll characters.
298+
299+
:param string data: input data to filter.
300+
:return string: filtered result.
301+
"""
302+
code_list = []
303+
code_list.extend(ASCIIColors.get_flat_list())
304+
code_list.extend(ASCIIControl.get_flat_list())
305+
for list_entry in code_list:
306+
data = data.replace(list_entry, "")
307+
return data
308+
309+
310+
def test_filtering():
311+
"""
312+
Test for filter_ascii_controlls.
313+
314+
print some test cases.
315+
"""
316+
test_string = (
317+
ASCIIColors.fg.lightblue
318+
+ "Hello "
319+
+ ASCIIColors.fg.green
320+
+ "World "
321+
+ ASCIIColors.fg.orange
322+
+ ":-)"
323+
+ ASCIIColors.reset
324+
)
325+
print("test_string", test_string)
326+
test_filtered = filter_ascii_controlls(test_string)
327+
print("test_filtered", test_filtered)
328+
329+
330+
def test_control():
331+
"""
332+
Test for control sequences.
333+
334+
print some test cases.
335+
"""
336+
337+
test_string = (
338+
ASCIIColors.fg.lightblue
339+
+ "Hello "
340+
+ ASCIIColors.fg.green
341+
+ "World "
342+
+ ASCIIColors.fg.orange
343+
+ ":-)"
344+
+ ASCIIColors.reset
345+
)
346+
print("test_string", test_string)
347+
print("test_string", test_string)
348+
print("test_string", test_string)
349+
time.sleep(1)
350+
test_string = (
351+
ASCIIControl.cursor.previous_line(2)
352+
+ "WOOO"
353+
+ ASCIIControl.cursor.next_line(1)
354+
+ ASCIIControl.erase_line()
355+
+ ":-)"
356+
)
357+
print(test_string)

0 commit comments

Comments
 (0)