Improve ANSI escape code support in process_wallpaper.py
This commit is contained in:
parent
313453f5b3
commit
5d8d8a3406
|
@ -1,5 +1,9 @@
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
Attribute = namedtuple('Attribute', ['fg', 'bg', 'bold'])
|
||||||
|
|
||||||
WIDTH = 80
|
WIDTH = 80
|
||||||
HEIGHT = 25
|
HEIGHT = 25
|
||||||
# ANSI orders the colours black, red, green, yellow, blue, magenta, cyan, white
|
# ANSI orders the colours black, red, green, yellow, blue, magenta, cyan, white
|
||||||
|
@ -24,7 +28,7 @@ origin_y = int(sys.argv[6])
|
||||||
assert 0 <= origin_y < HEIGHT
|
assert 0 <= origin_y < HEIGHT
|
||||||
|
|
||||||
chars = [bytearray([0]*HEIGHT) for _ in range(WIDTH)]
|
chars = [bytearray([0]*HEIGHT) for _ in range(WIDTH)]
|
||||||
attributes = [[(default_fgcolor, default_bgcolor)]*HEIGHT for _ in range(WIDTH)]
|
attributes = [[(Attribute(default_fgcolor, default_bgcolor, False))]*HEIGHT for _ in range(WIDTH)]
|
||||||
|
|
||||||
with open(infile, 'rb') as f:
|
with open(infile, 'rb') as f:
|
||||||
ansitext = f.read()
|
ansitext = f.read()
|
||||||
|
@ -33,6 +37,9 @@ x = origin_x
|
||||||
y = origin_y
|
y = origin_y
|
||||||
fgcolor = default_fgcolor
|
fgcolor = default_fgcolor
|
||||||
bgcolor = default_bgcolor
|
bgcolor = default_bgcolor
|
||||||
|
bold = False
|
||||||
|
|
||||||
|
error = False
|
||||||
|
|
||||||
line = 1
|
line = 1
|
||||||
line_start = 0
|
line_start = 0
|
||||||
|
@ -40,31 +47,59 @@ index = 0
|
||||||
while index < len(ansitext):
|
while index < len(ansitext):
|
||||||
if ansitext[index:].startswith(b'\x1b['):
|
if ansitext[index:].startswith(b'\x1b['):
|
||||||
index += len(b'\x1b[')
|
index += len(b'\x1b[')
|
||||||
escape_length = ansitext[index:].index(b'm')
|
escape_start = index
|
||||||
escape = ansitext[index:index+escape_length]
|
while index < len(ansitext) and ansitext[index] not in b'CDHJhm':
|
||||||
for color_parameter in escape.split(b';'):
|
index += 1
|
||||||
color_parameter = int(color_parameter)
|
escape_params = ansitext[escape_start:index]
|
||||||
if color_parameter == 39:
|
escape_type = ansitext[index:index+1]
|
||||||
fgcolor = default_fgcolor
|
index += 1
|
||||||
elif color_parameter == 49:
|
if escape_type == b'C':
|
||||||
bgcolor = default_bgcolor
|
x += int(escape_params)
|
||||||
elif 30 <= color_parameter <= 37:
|
elif escape_type == b'D':
|
||||||
fgcolor = color_map[color_parameter - 30]
|
x -= int(escape_params)
|
||||||
elif 40 <= color_parameter <= 47:
|
elif escape_type == b'H':
|
||||||
bgcolor = color_map[color_parameter - 40]
|
row, column = escape_params.split(b';')
|
||||||
elif 90 <= color_parameter <= 97:
|
y = int(row) - 1
|
||||||
fgcolor = color_map[color_parameter - 90] + 8
|
x = int(column) - 1
|
||||||
elif 100 <= color_parameter <= 107:
|
elif escape_type == b'J':
|
||||||
bgcolor = color_map[color_parameter - 100] + 8
|
# Erase display
|
||||||
else:
|
# We just ignore this, because why would you have
|
||||||
print(f'{line},{index-line_start+1}: Unknown colour escape {color_parameter}')
|
# erase command anywhere but at the start
|
||||||
index += escape_length + len(b'm')
|
pass
|
||||||
|
elif escape_type == b'h':
|
||||||
|
# Something nonstandard, ignore
|
||||||
|
pass
|
||||||
|
elif escape_type == b'm':
|
||||||
|
for color_parameter in escape_params.split(b';'):
|
||||||
|
color_parameter = int(color_parameter)
|
||||||
|
if color_parameter == 0:
|
||||||
|
bold = False
|
||||||
|
elif color_parameter == 1:
|
||||||
|
bold = True
|
||||||
|
elif color_parameter == 39:
|
||||||
|
fgcolor = default_fgcolor
|
||||||
|
elif color_parameter == 49:
|
||||||
|
bgcolor = default_bgcolor
|
||||||
|
elif 30 <= color_parameter <= 37:
|
||||||
|
fgcolor = color_map[color_parameter - 30]
|
||||||
|
elif 40 <= color_parameter <= 47:
|
||||||
|
bgcolor = color_map[color_parameter - 40]
|
||||||
|
elif 90 <= color_parameter <= 97:
|
||||||
|
fgcolor = color_map[color_parameter - 90] + 8
|
||||||
|
elif 100 <= color_parameter <= 107:
|
||||||
|
bgcolor = color_map[color_parameter - 100] + 8
|
||||||
|
else:
|
||||||
|
print(f'{line},{escape_start-line_start+1}: Unknown colour escape {color_parameter}')
|
||||||
|
error = True
|
||||||
|
else:
|
||||||
|
print(f'{line},{escape_start-line_start+1}: Unknown escape ^[[{escape_params.decode()}{escape_type.decode()}')
|
||||||
|
error = True
|
||||||
elif ansitext[index] == 13:
|
elif ansitext[index] == 13:
|
||||||
x = origin_x
|
x = origin_x
|
||||||
index += 1
|
index += 1
|
||||||
elif ansitext[index] == 10:
|
elif ansitext[index] == 10:
|
||||||
for i in range(x, WIDTH):
|
for i in range(x, WIDTH):
|
||||||
attributes[i][y] = (fgcolor, bgcolor)
|
attributes[i][y] = Attribute(fgcolor, bgcolor, bold)
|
||||||
x = origin_x
|
x = origin_x
|
||||||
y += 1
|
y += 1
|
||||||
index += 1
|
index += 1
|
||||||
|
@ -72,13 +107,16 @@ while index < len(ansitext):
|
||||||
line_start = index
|
line_start = index
|
||||||
else:
|
else:
|
||||||
chars[x][y] = ansitext[index]
|
chars[x][y] = ansitext[index]
|
||||||
attributes[x][y] = (fgcolor, bgcolor)
|
attributes[x][y] = Attribute(fgcolor, bgcolor, bold)
|
||||||
index += 1
|
index += 1
|
||||||
x += 1
|
x += 1
|
||||||
|
|
||||||
|
if error:
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
with open(outfile, 'wb') as f:
|
with open(outfile, 'wb') as f:
|
||||||
for y in range(HEIGHT):
|
for y in range(HEIGHT):
|
||||||
for x in range(WIDTH):
|
for x in range(WIDTH):
|
||||||
fgcolor, bgcolor = attributes[x][y]
|
fgcolor, bgcolor, bold = attributes[x][y]
|
||||||
char = chars[x][y]
|
char = chars[x][y]
|
||||||
f.write(bytes([char, (bgcolor<<4) | fgcolor]))
|
f.write(bytes([char, (bgcolor<<4) | fgcolor | (8 if bold else 0)]))
|
||||||
|
|
Loading…
Reference in New Issue