more functions and documentation

This commit is contained in:
filip 2021-03-12 22:33:18 +01:00
parent 8ddd20203d
commit 6f2547eb1f
21 changed files with 582 additions and 117 deletions

View File

@ -1,40 +1,311 @@
def bell():
print("\u0007")
"""
Name: ansi_escape
By: Filip Nilsen
Website: filip-nilsen.com
Sources:
https://en.wikipedia.org/wiki/ANSI_escape_code
https://terminalguide.namepad.de/seq/
https://man7.org/linux/man-pages/man4/console_codes.4.html
"""
def cursor_position(**coordinates):
def set_title(title, *args):
"""
Set title of the terminal emulator:
\u001b]{n};{t}\u001b\\
Where {t} is the title of the window and/or icon
Values of {n}
|0|Makes {t} title of window and minimized desktop icon
|1|Makes {t} title of just the minimized desktop icon
|2|Makes {t} title of just the terminal emulator window
"""
if len(args) == 0:
return "\u001b]0;" + title + "\u001b\\"
elif args[0] == "window":
return "\u001b]2;" + title + "\u001b\\"
elif args[0] == "icon":
return "\u001b]1;" + title + "\u001b\\"
else:
return "\u001b]" + str(args[0]) + ";" + title + "\u001b\\"
def bell_frequency(Hz):
return "\u001b[10;" + str(Hz) + "]"
bell_freq = bell_frequency
bell_f = bell_frequency
bell_hz = bell_frequency
def bell_duration(ms):
return "\u001b[11;" + str(ms) + "]"
def blink_interval(ms):
return "\u001b[16;" + str(ms) + "]"
def erase_character(*amount):
"""
Deletes from left to right -->
Does not change cursor position.
"""
try:
return "\u001b[" + str(amount[0]) + "X"
except:
return "\u001bX"
def delete_character(*amount):
"""
Deletes from left to right -->
Characters to the left ar shifted to the right by {amout}.
Does not change cursor position.
"""
try:
return "\u001b[" + str(amount[0]) + "P"
except:
return "\u001bP"
def line(a, *amount):
return_string = "\u001b["
try:
return_string += coordinates["row"]
return_string += str(amount[0])
except:
pass
if a == "insert":
return return_string + "L"
elif a == "delete":
return return_string + "M"
def set_leds(led):
a = {
"reset": "0",
"clear": "0",
"none": "0",
"scroll lock": "1",
"num lock": "2",
"caps lock": "3"
}
try:
return "\u001b[" + a[led] + "q"
except:
return "\u001b" + str(led) + "q"
def set(attr):
a = {
"bold": "1",
"faint": "2",
"italic": "3",
"underline": "4",
"blink": "5",
"overline": "53",
"inverse": "7",
"invisible": "8",
"strike": "9"
}
try:
return "\u001b[" + a[attr] + "m"
except:
return "\u001b[" + str(attr) + "m"
def unset(attr):
a = {
"all": "0",
"bold": "22",
"faint": "22",
"italic": "23",
"underline": "24",
"blink": "25",
"overline": "55",
"inverse": "27",
"invisible": "28",
"strike": "29",
"fg": "39",
"bg": "49"
}
try:
return "\u001b[" + a[attr] + "m"
except:
return "\u001b[" + str(attr) + "m"
def set_top_and_bottom_margins(**args):
return_string = "\u001b["
try:
return_string += args["top"]
except:
pass
return_string += ";"
try:
return_string += coordinates["column"]
return_string += args["bottom"]
except:
pass
return_string += "r"
return return_string
decstbm = set_top_and_bottom_margins
set_scrolling_region = set_top_and_bottom_margins
def select_cursor_style(a, b):
return_string = "\u001b["
if a == "blinking":
if b == "block":
return_string += "1"
elif b == "underline":
return_string += "3"
elif b == "bar":
return_string += "5"
elif a == "steady":
if b == "block":
return_string += "2"
elif b == "underline":
return_string += "4"
elif b == "bar":
return_string += "6"
return_string += " q"
return return_string
decscusr = select_cursor_style
def scroll(direction, *lines):
"""
\u001b[{n}{d}
Scrolls the display up or down by {n} lines. {n} defaults to 1.
{d} is the direction to scroll in.
Values for {d}:
|S|up
|T|down
"""
return_string = "\u001b["
try:
return_string += str(lines[0])
except:
pass
if direction == "up":
return_string += "S"
elif direction == "down":
return_string += "T"
return return_string
def cursor_horisontal_absolute(*column):
"""
\u001b[{n}G
Wil move the cursor to column {n}.
{n} defaults to 1
"""
return_string = "\u001b["
try:
return_string += str(column[0]) #optional; therefore it is in a try:
except:
pass #defaults to 1
return_string += "G"
return return_string
cha = cursor_horisontal_absolute
def cursor_line(direction, *lines):
"""
\u001b[{n}E
Will move the cursor {n} lines down and put the cursor at the beginning of that line.
If {n} is not supplied it defaults to 1.
\u001b[{n}F
The same as above, just that the cursor wil go up.
"""
return_string = "\u001b[" #csi
try:
return_string += str(lines[0]) #try to add the optinal lines variable to the control sequence
except:
pass #lines are optional the standard defaults to 1
a = {
"next": "E", #indicates wanting to scroll down
"down": "E",
"previous": "F", #scroll up
"up": "F"
}
try:
return_string += a[direction] #replace human readable name with variable in a{}
except:
return_string += str(direction) #makes it possible to pass E or F directly to the function
return return_string
def cursor_position(**coordinates):
"""
\u001b[{r};{c}H
Will move the cursor to row {r} and column {c}.
If {c} and/or {r} is not provided they will default to 1.
\u001b;H
Will therefore move the cursor to 1,1.
"""
return_string = "\u001b["
try:
return_string += str(coordinates["row"])
except:
pass
return_string += ";"
try:
return_string += str(coordinates["column"])
except:
pass
return_string += "H"
return return_string
set_cursor = cursor_position
#set_cursor = cursor_position
cup = cursor_position
def move_cursor(direction, *cells):
return_string = "\u001b["
"""
\u001b[{c}{d}
Moves the cursor {c} cells in direction {d}.
{d} can be A, B, C, or D which means up, down, forward/right, and backward/left respectivley.
{c} can be omitted and defaults to 1.
Examples:
\u001b[3A #moves the cursor 3 cells up
\u001b[B #moves the cursor 1 cell down
"""
return_string = "\u001b[" #csi
try:
return_string += cells[0]
return_string += str(cells[0]) #cells is optional therefore it is in a try statement
except:
pass
a = {
pass #if no argument is supplied it defaults to 1
a = { #human redable names for directions to move the cursor
"up": "A",
"down": "B",
"forward": "C",
"backward": "D"
"right": "C",
"backward": "D",
"left": "D"
}
return_string += a[direction]
try:
return_string += a[direction] #allows human redable names to be used
except:
return_string += direction #allows the function to take A-D as parameters directly
return return_string
def erase_in_display(direction):
"""
\u001b[{d}J
Erases cells on the display from the cursor to direction {d}.
{d} can be:
|0|Erases from the cursor to the end of the display.
|1|Erases from the cursor to the top of the display.
|2|Does both.
|3|On some terminals this will do both and erase the history. Since it is not supported in all terminals I do not recomend using this.
"""
return_string = "\u001b["
a = {
"forward": "0",
@ -53,92 +324,136 @@ erase_in_display_from_cursor = erase_in_display
ed = erase_in_display
def erase_in_line(direction):
"""
\u001b[{n}K
Deletes characters on the same line as the cursor in direction {n} from the cursor.
{n} can be:
|0|Deletes from the cursor to the end of the line.
|1|Deletes from the cursor to the beginning of the line.
|2|Deletes in both directions. (Clears the line)
"""
return_string = "\u001b["
a = {
a = { #human readable names
"forward": "0",
"right": "0",
"backward": "1",
"left": "1",
"both": "2"
}
try:
return_string += a[direction]
return_string += a[direction] #replaces the human readable name with mthe machine readable number
except:
return_string += direction
return_string += str(direction) #makes it posible to use numbers 0-2 instead
return_string += "K"
return return_string
erase_in_line_from_cursor = erase_in_line
el = erase_in_line
def color(mode, ground, *args):
return_string = "\u001b["
if mode == "bright":
return_string += "1;"
mode = "normal"
def color(ground, *args):
"""
Color is complicated:
See: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
if ground == "fg":
3-bit 8 colors support:
\u001b[{g}{c}m
Where {g} can be 3 or 4 and represents if the foreground color (aka text color) or background color should be changed.
|3|Change foreground color (aka text color)
|4|Change background color
{c} is a number between 0-7 that represents the color itself
Example:
\u001b[46m #makes the text background color cyan
Brighter/lighter/"more intense" variants of the 3-bit colors (4-bit color):
\u001b[{g}{c}m
Here the values of {g} are different:
|9 |Foreground color
|10|Background color
{c} is the same as 3-bit
Example:
\u001b[100m #sets background color to bright black (esentially grey)
8-bit 256 color support:
See: https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit for list of colors
\u001b[{g}8;5;{c}m
{g} uses the same values as 3-bit color.
{c} is a number between 0-255 that represent the color.
Values for {c}:
|0-7 |Same numbers as those used for 3-bit colors
|8-15 |Brighter 3-bit colors
|16-231 |Colors
|232-255|Grayscale
Example:
\001b[48;5;34m #sets a light green background color
24-bit True color:
\u001b[8;2;{r};{g};{b}m
Variables {r}, {g}, and {b} are rgb values
"""
return_string = "\u001b[" #csi
if ground == "fg": #sets text color aka foreground color
return_string += "3"
elif ground == "bg":
elif ground == "bg": #sets background color
return_string += "4"
if mode == "256":
return_string += "8;5;"
return_string += args[0]
return_string += "m"
return return_string
elif mode == "rgb":
return_string += "8;2;"
return_string = return_string + args[0] + ";" + args[1] + ";" +args[2]
return_string += "m"
return return_string
elif mode == "normal":
color_chart = {
"black": "0",
"red": "1",
"green": "2",
"yellow": "3",
"blue": "4",
"magenta": "5",
"cyan": "6",
"white": "7"
if len(args) == 1:
return_string += "8;5;" #SGR code for 8-bit 256 color support
color_chart = { #human readable color names instead of 0-7
"black": 0,
"red": 1,
"green": 2,
"yellow": 3,
"blue": 4,
"magenta": 5,
"cyan": 6,
"white": 7
}
a = color_chart[args[0]]
return_string += a
color = args[0]
if type(color) == str: #human readable name
if "bright-" in color:
color = color.replace("bright-", "")
color = color_chart[color] + 8
else:
color = color_chart[color]
return_string += str(color)
return_string += "m"
return return_string
elif len(args) == 3:
return_string += "8;2;" #SGR code for 24-bit RGB
return_string = return_string + str(args[0]) + ";" + str(args[1]) + ";" + str(args[2]) #r;g;b
return_string += "m"
return return_string
bell = "\u0007"
backspace = "\u0008"
bs = backspace
escape = "\u001b"
esc = escape
csi = escape + "["
reset = csi + "0m"
normal = reset
reset_formatting = reset
"""
Device Status Report (DSR)
Returns cursor position to the application
\u001b[{r};{c}R
{r} is the row
{c} is the column
"""
device_status_report = csi + "6n"
dsr = device_status_report
bold = csi + "1m"
faint = csi +"2m"
underline = csi + "4m"
blink = csi + "5m"
decaln = esc + "#8" #fills screen with E
decid = esc + "Z"
invert = csi + "7m"
reverse_video = invert
save_cursor = esc + "7"
decsc = save_cursor
strike = csi + "9m"
crossed_out = strike
normal_intensity = csi + "22m"
#no_italic = csi + "23m" #not vidley supported
no_blink = csi + "25m"
no_strike = csi + "29m"
reset_fg = csi + "39m"
reset_bg = csi + "49m"
overline = csi + "53m"
no_overline = csi + "55m"
frame = csi + "51m"
encircle = csi + "52m"
no_frame = csi + "54m"
restore_cursor = esc + "8"
decrc = restore_cursor

49
doc/color.md Normal file
View File

@ -0,0 +1,49 @@
Color
=====
256 8-bit colors
----------------
```python
print(ansi_escape.color("fg", "red") + "red text")
```
Makes the color of the text itself (aka the foreground color) red.
```python
print(ansi_escape.color("bg", "bright-cyan") + "bright cyan text background")
```
This will make the background color bright cyan.
ansi_escape.color() also supports the numbers 0-255 [here is a list explaining each number.](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit)
```python
print(ansi_escape.color("bg", 33) + "text")
```
You can also use the following human readable names insteead of 0-16:
| Instead of | Use |
| ---------: | :------------- |
| 0|"black" |
| 1|"red" |
| 2|"green" |
| 3|"yellow" |
| 4|"blue" |
| 5|"magenta" |
| 6|"cyan" |
| 7|"white" |
| 8|"bright-black" |
| 9|"bright-red" |
| 10|"bright-green" |
| 11|"bright-yellow" |
| 12|"bright-blue" |
| 13|"bright-magenta"|
| 14|"bright-cyan" |
| 15|"bright-white" |
24-bit True Color
-----------------
To do this provide ansi_escape.color() with "fg" or "bg" + 3 comma reperated values for r, g, and b respectivley, each rgb value can be a number between 0-255.
```python
print(ansi_escape.color("bg", 128, 0, 255) + "bg for background color")
print(ansi_escape.color("fg", 255, 69, 128) + "fg for foreground color")
```

49
doc/cursor.md Normal file
View File

@ -0,0 +1,49 @@
Cursor control
==============
Move to spesific coordinates
----------------------------
To move the terminal cursor using positional coordinates use the following function:
```python
ansi_escape.cursor_position()
```
If the function name is to long you can use:
```python
ansi_escape.cup()
```
instead.
```python
ansi_escape.cup() #sets position to 1,1
ansi_escape.cursor_position(row=5) #sets cursor position to row 5 and column 1
ansi_escape.cup(column=16) #sets cursor position to column 16 and row 1
ansi_escape.cursor_position(row=30, column=3) #sets cursor position to row 30 and column 3
```
Move cursor from current position
---------------------------------
For relative movements use:
```python
ansi_escape(direction, cells)
```
direction can be:
- "up"
- "down"
- "forward"
- "backward"
It is the direction the cursor moves towards.
cells is an optional argumant which specifies how many character cells you want to move the cursor.
Move cursor to spesific horisontal position
-------------------------------------------
Use:
```python
ansi_escape.cursor_horisontal_absolute(column)
#or
ansi_escape.cha(column)
```
column can be omitted and will then default to 1.
This will not affect the vertical coordinates of the cursor.

38
doc/delete.md Normal file
View File

@ -0,0 +1,38 @@
Character deletion
==================
Erase character
---------------
```python
ansi_escape.erase_character(n)
```
Will erase n amount of characters from the cursor to the right of the cursor.
amount defaults to 1.
<!---Example:
0|1|2|3|4|5|6|7|8|9|10
:---|:---|:---|:---|:---|:---|:---|:---|:---|:---|:--
h|e|l|l|o|{cursor}|w|o|r|l|d
Here the cursor is on cell 5, if you where to run--->
Delete character
----------------
```python
ansi_escape.delete_character(n)
```
Works just like erase_character(), but after deleting the characters it wil shift any remaining characters to the left of the cursor by n amount.
If n is omitted it defaults to 1.
Erase in display
----------------
```python
ansi_escape.erase_in_display(n)
#or
ansi_escape.ed(n)
```
Will erase in the display from the cursor.
n is the direction from the cursor to erase in and can be : forward, backward, or both. n can also be "history" which works like "both", but will also include the buffered history of the terminal. I do not reccomend using history since it is not widley supported.
Erase in line
-------------
```python
ansi_escape.erase_in_line(n)
#or
ansi_escape.el(n)
```
Like erase in display, but limited to one line. The n variable works the same way, minus the history option.

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
/home/filip/Documents/python3/ansi_escape/ansi_escape.py

7
examples/backspace.py Normal file
View File

@ -0,0 +1,7 @@
import ansi_escape, sys, time
print("Hello World!!", end='')
time.sleep(1)
a = 0
while a < 5:
a += 1
sys.stdout.write(ansi_escape.backspace)

5
examples/bell.py Normal file
View File

@ -0,0 +1,5 @@
import ansi_escape
print(ansi_escape.bell_f(10000))
a = 10
while a < 10:
print(ansi_escape.bell)

View File

@ -1,8 +0,0 @@
import ansi_escape
a = 0
while a < 10:
a += 1
print("Hello World!!")
a = input()
print(ansi_escape.move_cursor("up", str(a)) + ansi_escape.el("both"))

2
examples/dsr.py Normal file
View File

@ -0,0 +1,2 @@
import ansi_escape, sys
print(ansi_escape.cup(column=23, row=22) + ansi_escape.dsr)

View File

@ -1,2 +0,0 @@
import ansi_escape, os
print(ansi_escape.erase_from_cursor("2"))

View File

@ -0,0 +1,7 @@
import ansi_escape
from random import randint as randint
while 1:
print(ansi_escape.cup(column=randint(1, 80), row=randint(1, 30)) +
ansi_escape.color("bg", randint(0, 255), randint(0, 255), randint(0, 255)) +
" " +
ansi_escape.unset("all"))

3
examples/keyboard.py Normal file
View File

@ -0,0 +1,3 @@
import ansi_escape
print(ansi_escape.set_leds("reset"))
input()

View File

@ -1,7 +0,0 @@
import keyboard, ansi_escape
print(ansi_escape.erase_from_cursor("both"))
keyboard.add_hotkey('up', ansi_escape.cursor, args=('up'))
keyboard.add_hotkey('down', ansi_escape.cursor, args=('down'))
keyboard.add_hotkey('left', ansi_escape.cursor, args=('backward'))
keyboard.add_hotkey('right', ansi_escape.cursor, args=('forward'))
keyboard.wait()

View File

@ -2,8 +2,6 @@ import ansi_escape
color = 0
print(ansi_escape.escape + "]0;256 Color Terminal Palette" + ansi_escape.bell)
while color <= 255:
color = str(color)
print(ansi_escape.color("256", "bg", color) + " " + " " * ( len(color) - 2 ) + color + " ", end="")
color = int(color)
print(ansi_escape.color("bg", color) + " " + " " * ( len(str(color)) - 2 ) + str(color) + " ", end="")
color += 1
input()

View File

@ -1,4 +0,0 @@
import ansi_escape, random
while 1:
print(ansi_escape.set_cursor(row=str(random.randint(1,20)), column=str(random.randint(1,20))) + ansi_escape.color("normal", "bg", "red") + " " + ansi_escape.reset)
input()

10
examples/simple_colors.py Normal file
View File

@ -0,0 +1,10 @@
import ansi_escape
print(ansi_escape.set("underline"))
print(ansi_escape.color("ul", "bright-black") + "aa")
print(ansi_escape.color("bg", "bright-red") + " ")
print(ansi_escape.color("bg", "bright-green") + " ")
print(ansi_escape.color("bg", "bright-yellow") + " ")
print(ansi_escape.color("bg", "bright-blue") + " ")
print(ansi_escape.color("bg", "bright-magenta") + " ")
print(ansi_escape.color("bg", "bright-cyan") + " ")
print(ansi_escape.color("bg", "bright-white") + " ")

2
examples/size.py Normal file
View File

@ -0,0 +1,2 @@
import ansi_escape
print(ansi_escape.esc + "[18t")

View File

@ -1,13 +0,0 @@
import ansi_escape
a = 0
while a < 256:
b = str(a)
print(ansi_escape.color("256", "bg", b) + " " + b + " " + ansi_escape.reset, end='')
a += 1
print(ansi_escape.escape + "]0;Demo" + ansi_escape.escape + "\\")
input()
print("hello" + ansi_escape.move_cursor("up", "2"))
input()
print(ansi_escape.erase_from_cursor("forward"))
input()

3
examples/title.py Normal file
View File

@ -0,0 +1,3 @@
import ansi_escape
print(ansi_escape.set_title("hello"))
input()

View File

@ -1,9 +1,23 @@
# ansi_escape
## A pure python3 library for ansi VT-100 escape codes
ansi_escape
===========
A pure python3 library for ansi VT-100 escape codes
---------------------------------------------------
See the doc/ folder and ansi_escape.py for documentation (WIP)
See the examples directory for examples/ You need to copy the ansi_escape.py file to the example/ directory to run the examples.
Since this library wraps around text sent to the terminal it only returns strings that need to be put inside a print() statement, example:
```python
print(ansi_escape.color("fg", "red") + "Hello")
```
On the positive side that means that you easily can send
output to a file using .write() or write it to the terminal using sys.stdout.write().
You are not limited by the limitations of print().
Features:
---------
SGR (Select Graphic Rendition)
SGR foreground and background color in 4-bit color, 8-bit color and 24-bit color
SGR foreground and background color support with support for 256 8-bit colors and 24-bit true color
SGR text formating like; underline, overline and bold text
Easy way to use the bell character
Move cursor
Use the bell character
Free cursor movement
Clear parts of screen or line
Toggle keyboard leds