This commit is contained in:
decoded
2022-02-28 14:43:08 -06:00
parent b50b70172a
commit 4bead33ae1

View File

@@ -2,8 +2,12 @@
#################################################################################################### ####################### #################################################################################################### #######################
from glob import glob from glob import glob
from time import sleep from time import sleep
from collections import namedtuple
import sys,tty,os,termios,shutil import sys,tty,os,termios,shutil
#################################################################################################### ####################### #################################################################################################### #######################
#################################################################################################### #######################
####
#################################################################################################### #######################
"""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### """MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh+MMMMMMMMMMMMMMhsMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh+MMMMMMMMMMMMMMhsMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm/ oMMMMMMMMMMMMMMm +NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm/ oMMMMMMMMMMMMMMm +NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
@@ -36,10 +40,19 @@ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN+` `+NMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs. -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs. -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMdyymMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM""" ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMdyymMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM""" #######################
#################################################################################################### ####################### #################################################################################################### #######################
#####
#################################################################################################### #######################
#################################################################################################### #######################
FIFO_PATH = f"{os.path.expanduser('~')}/.weechat/weechat_fifo" #####
FIFO_ENABLED = True #####
COPY_PATH = f"{os.path.expanduser('~')}/Pictures" #####
DELETE_PATH = "/tmp" #####
#################################################################################################### #######################
#################################################################################################### #######################
#####
### "00", "01", "02", "03", "04", "05", "06", "07", ########################################### ### "00", "01", "02", "03", "04", "05", "06", "07", ###########################################
### "08", "09", "10", "11", "12", "13", "14", "15", ########################################### ### "08", "09", "10", "11", "12", "13", "14", "15", ###########################################
#####
0xFFFFFF, 0x000000, 0x00007F, 0x009300, 0xFF0000, 0x7F0000, 0x9C009C, 0xFC7F00, ########################################### 0xFFFFFF, 0x000000, 0x00007F, 0x009300, 0xFF0000, 0x7F0000, 0x9C009C, 0xFC7F00, ###########################################
0xFFFF00, 0x00FC00, 0x009393, 0x00FFFF, 0x0000FC, 0xFF00FF, 0x7F7F7F, 0xD2D2D2, ########################################### 0xFFFF00, 0x00FC00, 0x009393, 0x00FFFF, 0x0000FC, 0xFF00FF, 0x7F7F7F, 0xD2D2D2, ###########################################
##### #####
@@ -64,7 +77,24 @@ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMdyymMMMMMMMMMMMMMMMMMMMMMMMMMMM
##### #####
############################################################################################################################# #############################################################################################################################
############################################################################################################################# #############################################################################################################################
def getfiles(argv=""):
PATH=""
if len(argv) > 1:
if argv[1] == ".":
PATH=""
else:
PATH=f'{argv[1]}/'
if len(argv) == 1:
PATH=""
files=glob(PATH+"*")
FILES=[]
for _ in files:
if _.lower()[-4:]==".ans":
FILES.append(_)
if len(FILES)==0:
print('ERROR: NO ANSI FILES IN THE PATH SPECIFIED',end='')
sys.exit(1)
return FILES
########################################################################################################## CLASS DR1P4NS1 - 2 ########################################################################################################## CLASS DR1P4NS1 - 2
class dr1p4ns1: class dr1p4ns1:
############################################################################################################ LOOKUP TABLE ############################################################################################################ LOOKUP TABLE
@@ -137,7 +167,6 @@ class dr1p4ns1:
self.height=height self.height=height
self.filename=ansifile self.filename=ansifile
self.openansi(ansifile) self.openansi(ansifile)
#self.openascii()
self.code='\x1b[0m' self.code='\x1b[0m'
self.cmps=[] self.cmps=[]
self.op=[] self.op=[]
@@ -149,7 +178,7 @@ class dr1p4ns1:
######################################################################################################### FILE OPERATIONS ######################################################################################################### FILE OPERATIONS
def fifo(self,s): def fifo(self,s):
s=[s] s=[s]
f=open(f"{os.path.expanduser('~')}/.weechat/weechat_fifo","w") f=open(FIFO_PATH,"w")
[f.write("*{}\n".format(x)) for x in s] [f.write("*{}\n".format(x)) for x in s]
f.close() f.close()
######################################################################################################### FILE OPERATIONS ######################################################################################################### FILE OPERATIONS
@@ -157,7 +186,7 @@ class dr1p4ns1:
f=open(s,'rb') f=open(s,'rb')
self.ansifile=f.read().decode('cp437') self.ansifile=f.read().decode('cp437')
f.close() f.close()
############################################################################################# DEBUGGING - FILE OPERATIONS ############################################################################################################### DEBUGGING
def openascii(self): def openascii(self):
f=open('ansiscii/work.asc','r') f=open('ansiscii/work.asc','r')
self.reference=f.read() self.reference=f.read()
@@ -250,7 +279,7 @@ class dr1p4ns1:
code=self.ansifile[i:] code=self.ansifile[i:]
self.codes.append([code,i,len(self.ansifile)]) self.codes.append([code,i,len(self.ansifile)])
if code[1:6].upper()=="SAUCE": if code[1:6].upper()=="SAUCE":
self.getsauce(code[1:]) self.getsauce()
else: else:
if 64 <= ord(_) <= 126: if 64 <= ord(_) <= 126:
try: try:
@@ -352,6 +381,7 @@ class dr1p4ns1:
color_bg=_ color_bg=_
colors=f"{color_set}" colors=f"{color_set}"
processed_colors.append(colors) processed_colors.append(colors)
self.processed = processed
irc_processed=[] irc_processed=[]
terminal_processed=[] terminal_processed=[]
color_table=[1,5,3,7,2,6,10,15,14,4,9,8,12,13,11,0]; color_table=[1,5,3,7,2,6,10,15,14,4,9,8,12,13,11,0];
@@ -425,8 +455,6 @@ class dr1p4ns1:
bold_before.append(int(bg_color)) bold_before.append(int(bg_color))
else: else:
bold_before.append(int(fg_color)) bold_before.append(int(fg_color))
# else:
# print('how are you here')
newcode='\x03' newcode='\x03'
bold_before.sort() bold_before.sort()
for _ in bold_before: for _ in bold_before:
@@ -445,17 +473,15 @@ class dr1p4ns1:
_line=_line.replace(code_replace,newcode,1) _line=_line.replace(code_replace,newcode,1)
irc_processed.append(_line) irc_processed.append(_line)
terminal_processed.append(line) terminal_processed.append(line)
for _ in terminal_processed:
print(_)
if self.pump:
for i,theline in enumerate(irc_processed):
self.fifo(theline)
#################################################################################################################### TOOL #################################################################################################################### TOOL
def getsauce(self,sauce): def getsauce(self):
self.sauce=sauce f=open(self.filename,'rb')
l=f.read()
f.close()
self.sauce=l[-128:]
self.sauce_found=True self.sauce_found=True
self.width=ord(self.sauce[96]) self.width=self.sauce[96]
self.height=ord(self.sauce[98]) self.height=self.sauce[98]
offset=len("SAUCE") offset=len("SAUCE")
self.sauce_version=str(int(self.sauce[offset:offset+2].strip())) self.sauce_version=str(int(self.sauce[offset:offset+2].strip()))
offset+=2 offset+=2
@@ -533,114 +559,659 @@ class dr1p4ns1:
#################################################################################################################### TOOL #################################################################################################################### TOOL
def invert_dict(self,d): def invert_dict(self,d):
return {v: k for k, v in d.items()} return {v: k for k, v in d.items()}
########################################################################################################## CLASS MAIN - 4 #################################################################################################################### BOOT
def boot(self): def boot(self):
if self.DEBUG: if self.DEBUG:
print("\n\x1b[1;31m[ HEXDUMP ]\x1b[0m\n") print("\n\x1b[1;31m[ HEXDUMP ]\x1b[0m\n")
self.printhex() self.printhex()
self.codedump() self.codedump()
self.processdump() self.processdump()
############################################################################################################################# ####################################################################################### HUMAN INTERFACE * * * * * * * * * * *
def getkey(): class UI:
old_settings = termios.tcgetattr(sys.stdin) def __init__(self,files=""):
tty.setcbreak(sys.stdin.fileno()) self.REMOVED=False
try: self.files=files
while True: self.uis_menu()
b = os.read(sys.stdin.fileno(), 3).decode() ################################################################################### HUMAN INTERFACE * * * * * * * * * * *
if len(b) == 3: def getkey(self):
k = ord(b[2]) old_settings = termios.tcgetattr(sys.stdin)
else: tty.setcbreak(sys.stdin.fileno())
k = ord(b) try:
key_mapping = { while True:
112: 'p', b = os.read(sys.stdin.fileno(), 3).decode()
27: 'esc', if len(b) == 3:
67: 'right', k = ord(b[2])
68: 'left', else:
113: 'q', k = ord(b)
120: 'x', key_mapping = {
99: 'c', 112: 'p',
82: 'R' 27: 'esc',
} 67: 'right',
return key_mapping.get(k, chr(k)) 68: 'left',
finally: 113: 'q',
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) 120: 'x',
################################################################################################################### ENTRY - 1 99: 'c',
if __name__ == "__main__": 82: 'R'
####################################### }
if len(sys.argv) > 1: return key_mapping.get(k, chr(k))
PATH='' finally:
if sys.argv[1]=='.': termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
PATH=os.getcwd() ################################################################################### HUMAN INTERFACE * * * * * * * * * * *
files=glob(PATH+"/*.ans") def uis_menu(self):
files+=glob(PATH+"/*.ANS") index=0
else: try:
files=glob(sys.argv[1]+"/*.ans") print(f'loading: {self.files[index]}')
files+=glob(sys.argv[1]+"/*.ANS") d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
else: decoder=ANSIDecoder(self.files[index],d.width)
files=glob('ansiscii/*.ans') decoder.as_terminal()
files+=glob('ansiscii/*.ANS') except:
####################################### pass
if len(files)==0: #######################################
print('ERROR: NO ANSI FILES IN THE PATH SPECIFIED',end='') try:
sys.exit(1) while True:
####################################### B='\x1b[1;94m'; C='\x1b[1;94m'; S='\x1b[1;36m'; M='\x1b[1;92m'; E='\x1b[0m'; R='\x1b[31m'
index=0 msg=f"{B}[ {C}DR1P {B}] {S}- {B}[ {C}q{S}: {M}quit{S}, {C}c{S}: {M}copy{S}, {C}R{S}: {M}remove{S}, {C}p{S}: {M}pump{S}, "
try: msg+=f"{C}left{S}: {M}previous{S}, {C}right{S}: {M}next {B}] {S}- "
print(f'loading: {files[index]}') msg+=f"{C}filename{S}: {M}{d.filename} {S}- {B}[{C}{index+1}{S}/{C}{len(self.files)}{B}]{E}"
d=dr1p4ns1(ansifile=files[index],width=80,debug=False) if self.REMOVED==True: msg+=f'{R} - FILE REMOVED'
except: print(msg)
pass k = self.getkey()
####################################### if k == 'left':
try: index-=1
while True: if index < 0: index=len(self.files)-1
B='\x1b[1;94m'; C='\x1b[1;94m'; S='\x1b[1;36m'; M='\x1b[1;92m'; E='\x1b[0m' try:
msg=f"{B}[ {C}DR1P {B}] {S}- {B}[ {C}q{S}: {M}quit{S}, {C}c{S}: {M}copy{S}, {C}R{S}: {M}remove{S}, {C}p{S}: {M}pump{S}, {C}left{S}: {M}previous{S}, {C}right{S}: {M}next {B}] {S}- {C}filename{S}: {M}" self.REMOVED=False
msg+=f"{d.filename}{E}" if len(self.files) == 0:
print(msg) print(f'{B}NO FILES LEFT IN QUEUE - {R} EXITING')
k = getkey() sleep(1)
if k == 'left': break
index-=1 print(f'{C}loading{B}: {S}{self.files[index]}')
if index < 0: index=len(files)-1 d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
try: decoder=ANSIDecoder(self.files[index],d.width)
print(f'{C}loading{B}: {S}{files[index]}') decoder.as_terminal()
d=dr1p4ns1(ansifile=files[index],width=80,debug=False) except:
except: pass
pass elif k == 'right':
elif k == 'right': index+=1
index+=1 if index >= len(self.files): index=0
if index >= len(files): index=0 try:
try: self.REMOVED=False
print(f'{C}loading{B}: {S}{files[index]}') if len(self.files) == 0:
d=dr1p4ns1(ansifile=files[index],width=80,debug=False) print(f'{B}NO FILES LEFT IN QUEUE - {R} EXITING')
except: sleep(1)
pass break
elif k == 'esc' or k == 'q' or k == 'x': print(f'{C}loading{B}: {S}{self.files[index]}')
quit() d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
elif k == 'R': decoder=ANSIDecoder(self.files[index],d.width)
print('file removed: placed in /tmp directory') decoder.as_terminal()
sleep(3) except:
shutil.copyfile(d.filename,f'/tmp/{str(d.filename).split("/")[1]}') pass
os.remove(d.filename) elif k == 'esc' or k == 'q' or k == 'x':
elif k == 'p': quit()
print('pump') # elif k == 'c':
d=dr1p4ns1(ansifile=files[index],width=80,debug=False,pump=True) try:
sleep(1) if not self.files[index].find('/') == -1:
elif k == 'c': FILEPATH=f'{COPY_PATH}/{str(self.files[index]).split("/")[1]}'
try: shutil.copyfile(self.files[index],FILEPATH)
shutil.copyfile(d.filename,f'pump/{str(d.filename).split("/")[1]}') print(f'{C}{self.files[index]} copied to {FILEPATH}')
print(f'{C}file copied to pump directory') else:
except: FILEPATH=f'{COPY_PATH}/{self.files[index]}'
print(f'{M}file was not copied') shutil.copyfile(self.files[index],FILEPATH)
else: print(f'{C}{self.files[index]} {M}copied to {C}{FILEPATH}')
index+=1 except:
if index >= len(files): index=0 print(f'{C}{self.files[index]} {M}was not copied')
try: sleep(1)
d=dr1p4ns1(ansifile=files[index],width=80,debug=False) decoder.as_terminal()
except: elif k == 'p':
pass try:
####################################### if FIFO_ENABLED:
except (KeyboardInterrupt, SystemExit): decoder=ANSIDecoder(self.files[index],d.width)
os.system('stty sane') decoder.as_irc()
####################################### print(f'{M}pumping: pumping {C}{self.files[index]} {M}to fifo - {C}{FIFO_PATH}')
else:
print(f'{M}pumping disabled - fifo not detected in path: {C}{FIFO_PATH}')
except Exception as e:
print(f'{M}pumping failed - {e}')
sleep(3)
decoder.as_terminal()
elif k == 'R':
try:
if not self.files[index].find('/') == -1:
FILEPATH=f'{DELETE_PATH}/{str(self.files[index]).split("/")[1]}'
shutil.copyfile(self.files[index],FILEPATH)
else:
FILEPATH=f'{DELETE_PATH}/{self.files[index]}'
shutil.copyfile(self.files[index],FILEPATH)
os.remove(self.files[index])
self.REMOVED=True
buffer=self.files[index]
self.files.remove(self.files[index])
print(f'{R}{buffer} removed: placed in {DELETE_PATH} directory')
except:
print(f'{C}{self.files[index]} {M}was not removed')
sleep(3)
decoder.as_terminal()
######################################################################################################################### EOF else:
index+=1
if index >= len(self.files): index=0
try:
self.REMOVED=False
if len(self.files) == 0:
print(f'{B}NO FILES LEFT IN QUEUE - {R} EXITING')
sleep(1)
break
d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
decoder=ANSIDecoder(self.files[index],d.width)
decoder.as_terminal()
except:
pass
#######################################
except (KeyboardInterrupt, SystemExit):
os.system('stty sane')
#############################################################################################################################
class ANSIDecodeError(ValueError):
pass
#############################################################################################################################
class ANSIDecoder:
#############################################################################################################################
PALETTES = {
'vga': {
False: ['000', 'a00', '0a0', 'a50', '00a', 'a0a', '0aa', 'aaa'],
True: ['555', 'f55', '5f5', 'ff5', '55f', 'f5f', '5ff', 'fff'],
},
'workbench': {
False: ['aaa', '000', 'fff', '68b', '00f', 'f0f', '0ff', 'fff'],
True: ['aaa', '000', 'fff', '68b', '00f', 'f0f', '0ff', 'fff'],
}
}
#########################################################################################################################
PALETTE_NAMES = PALETTES.keys()
REMAPPED_CHARS = {
'\x00': ' ',
'\x01': '\u263a',
'\x02': '\u263b',
'\x03': '\u2665',
'\x04': '\u2666',
'\x05': '\u2663',
'\x06': '\u2660',
'\x10': '\u25ba',
'\x11': '\u25c4',
'\x16': '\u25ac',
'\x1d': '\u2194',
'\x1e': '\u25b2',
'\x1f': '\u25bc',
}
#########################################################################################################################
DEFAULT_FG = 7
DEFAULT_BG = 0
#########################################################################################################################
Attribute = namedtuple('Attribute', ['fg', 'bg', 'bright', 'underline'])
#########################################################################################################################
DEFAULT_ATTR = Attribute(fg=DEFAULT_FG, bg=DEFAULT_BG, bright=False, underline=False)
def __init__(self,files="",width=80):
#stream=None, palette='vga', width=80, strict=False
self.current_line = []
self.buffer = [self.current_line]
self.palette = self.PALETTES['vga']
self.x = 0
self.y = 0
self.saved_x = 0
self.saved_y = 0
self.current_attr = self.DEFAULT_ATTR
self.width = width
self.strict = False
self.filename=files
stream=open(self.filename,'rt',encoding='cp437')
if stream:
self.play(stream)
#########################################################################################################################
def write_char(self, char):
# Handle an ordinary character
try:
self.current_line[self.x] = (self.current_attr, char)
except IndexError:
# X position is out of range; append to current line
while len(self.current_line) < self.x:
self.current_line.append((self.DEFAULT_ATTR, ' '))
self.current_line.append((self.current_attr, char))
self.x += 1
if self.x >= self.width:
self.write_newline()
#########################################################################################################################
def set_cursor(self, x=None, y=None):
if x is not None:
self.x = max(x, 0)
if y is not None:
self.y = max(y, 0)
try:
self.current_line = self.buffer[self.y]
except IndexError:
while len(self.buffer) <= self.y:
self.current_line = []
self.buffer.append(self.current_line)
#########################################################################################################################
def write_newline(self):
# Handle a line break
self.set_cursor(x=0, y=(self.y + 1))
#########################################################################################################################
def set_attr(self, fg=None, bg=None, bright=None, underline=None):
if fg is None:
fg = self.current_attr.fg
if bg is None:
bg = self.current_attr.bg
if bright is None:
bright = self.current_attr.bright
if underline is None:
underline = self.current_attr.underline
self.current_attr = self.Attribute(fg=fg, bg=bg, bright=bright, underline=underline)
#########################################################################################################################
def write_escape(self, code, params):
if code == 'm':
for param in params:
if param == 0:
self.current_attr = self.DEFAULT_ATTR
elif param == 1:
self.set_attr(bright=True)
elif param == 2 or param == 22:
self.set_attr(bright=False)
elif param == 4:
self.set_attr(underline=True)
elif param == 24:
self.set_attr(underline=False)
elif 30 <= param <= 37:
self.set_attr(fg=(param - 30))
elif 40 <= param <= 47:
self.set_attr(bg=(param - 40))
else:
if self.strict:
raise ANSIDecodeError("Unsupported parameter to 'm' escape sequence: %r" % param)
elif code == 'J':
if params == [] or params == [0]:
# erase from cursor to end of screen
del self.current_line[self.x:]
del self.buffer[(self.y + 1):]
elif params == [1]:
# erase up to cursor
for i in range(0, self.y):
del self.buffer[i][:]
try:
for i in range(0, self.x + 1):
self.current_line[i] = (self.DEFAULT_ATTR, ' ')
except IndexError:
del self.current_line[:]
elif params == [2]:
# erase entire screen
for i in range(0, self.y):
del self.buffer[i][:]
del self.buffer[(self.y + 1):]
else:
if self.strict:
raise ANSIDecodeError("Unrecognised parameters to 'J' escape sequence: %r" % params)
elif code == 'K':
if params == [] or params == [0]:
# erase from cursor to end of line
del self.current_line[self.x:]
elif params == [1]:
# erase up to cursor
try:
for i in range(0, self.x + 1):
self.current_line[i] = (self.DEFAULT_ATTR, ' ')
except IndexError:
del self.current_line[:]
elif params == [2]:
# erase entire line
del self.current_line[:]
else:
if self.strict:
raise ANSIDecodeError("Unrecognised parameters to 'K' escape sequence: %r" % params)
elif code == 'A':
# move cursor up N lines
if not params:
self.set_cursor(y=(self.y - 1))
elif len(params) == 1:
self.set_cursor(y=(self.y - params[0]))
elif self.strict:
raise ANSIDecodeError("Expected 0 or 1 param to 'A' escape sequence, got %d" % len(params))
elif code == 'B':
# move cursor down N lines
if not params:
self.set_cursor(y=(self.y + 1))
elif len(params) == 1:
self.set_cursor(y=(self.y + params[0]))
elif self.strict:
raise ANSIDecodeError("Expected 0 or 1 param to 'B' escape sequence, got %d" % len(params))
elif code == 'C':
# move cursor right N cols
if not params:
self.set_cursor(x=(self.x + 1))
elif len(params) == 1:
self.set_cursor(x=(self.x + params[0]))
elif self.strict:
raise ANSIDecodeError("Expected 0 or 1 param to 'C' escape sequence, got %d" % len(params))
elif code == 'D':
# move cursor left N cols
if not params:
self.set_cursor(x=(self.x - 1))
elif len(params) == 1:
self.set_cursor(x=(self.x - params[0]))
elif self.strict:
raise ANSIDecodeError("Expected 0 or 1 param to 'D' escape sequence, got %d" % len(params))
elif code == 'E':
# move cursor to beginning of next line, N lines down
if not params:
self.set_cursor(x=0, y=(self.y + 1))
elif len(params) == 1:
self.set_cursor(x=0, y=(self.y + params[0]))
elif self.strict:
raise ANSIDecodeError("Expected 0 or 1 param to 'E' escape sequence, got %d" % len(params))
elif code == 'F':
# move cursor to beginning of previous line, N lines up
if not params:
self.set_cursor(x=0, y=(self.y - 1))
elif len(params) == 1:
self.set_cursor(x=0, y=(self.y - params[0]))
elif self.strict:
raise ANSIDecodeError("Expected 0 or 1 param to 'F' escape sequence, got %d" % len(params))
elif code == 'G':
# move cursor to column N
if len(params) == 1:
self.set_cursor(x=params[0])
elif self.strict:
raise ANSIDecodeError("Expected 1 param to 'G' escape sequence, got %d" % len(params))
elif code == 'H' or code == 'f':
# move cursor to (line, col)
if not params:
self.set_cursor(x=0, y=0)
elif len(params) == 2:
self.set_cursor(x=params[1] - 1, y=params[0] - 1)
elif self.strict:
raise ANSIDecodeError("Expected 0 or 2 param to '%s' escape sequence, got %d" % (code, len(params)))
elif code == 'h':
if params == [7]:
# enable line wrapping
pass
elif self.strict:
raise ANSIDecodeError("Unrecognised params to 'h' - got %r" % params)
elif code == 's':
# save cursor position
if params and self.strict:
raise ANSIDecodeError("Unrecognised params to 's' - got %r" % params)
self.saved_x = self.x
self.saved_y = self.y
elif code == 'u':
# restore cursor position
if params and self.strict:
raise ANSIDecodeError("Unrecognised params to 'u' - got %r" % params)
self.set_cursor(x=self.saved_x, y=self.saved_y)
else:
if self.strict:
raise ANSIDecodeError("Unrecognised escape code: %r" % code)
#########################################################################################################################
def play(self, f):
while True:
# Read file a character at a time
char = f.read(1)
if not char:
# End of file
break
elif char >= ' ':
self.write_char(char)
elif char == '\x0a': # LF
self.write_newline()
elif char == '\x0d': # CR
continue
elif char in self.REMAPPED_CHARS:
self.write_char(self.REMAPPED_CHARS[char])
elif char == '\x1a':
# EOF when using SAUCE records
break
elif char == '\x1b':
# Handle an escape sequence
char = f.read(1)
# Next character is expected to be '['
if char != '[':
if self.strict:
raise ANSIDecodeError("Unrecognised character after ESC: %r" % char)
continue
params = []
param = None
private = False
while True:
char = f.read(1)
if '0' <= char <= '9':
if param is None:
param = int(char)
else:
param = param * 10 + int(char)
elif char == ';':
if param is None:
if self.strict:
raise ANSIDecodeError("Encountered ';' character without parameter")
else:
params.append(param)
param = None
elif char == ' ':
pass
elif char == '?':
private = True
else:
if param is not None:
params.append(param)
if not private:
self.write_escape(char, params)
break
elif self.strict:
raise ANSIDecodeError("Unrecognised character: %r" % char)
#########################################################################################################################
def fifo(self,s):
s=[s]
f=open(FIFO_PATH,"w")
[f.write("*{}\n".format(x)) for x in s]
f.close()
################################################################################################### RE-ENCODING ENCODINGS
def as_irc_lines(self):
default_fg=7
default_bg=0
color_table=[1,5,3,7,2,6,10,15,14,4,9,8,12,13,11,0]
color_fg=color_table[default_fg]
color_bg=color_table[default_bg]
offset_bold=0
reset_bold=False
last_attr = None
processing=''
self.fifo(f"filename: {self.filename}")
for i,line in enumerate(self.buffer):
for n,(attr, char) in enumerate(line):
####################################################################################### FOR LINE
if attr[2]:
offset_bold=8
else:
offset_bold=0
color_fg=color_table[attr[0]+offset_bold]
color_bg=color_table[attr[1]]
if attr != last_attr:
if last_attr==None:
processing+=f'\x03{color_table[attr[0]]},{color_table[attr[1]]}'
color_fg=color_table[attr[0]]
color_bg=color_table[attr[1]]
else:
if n==0 and not attr[0]==default_fg:
if attr[2]:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=color_table[attr[0]+offset_bold]
color_bg=color_table[attr[1]]
else:
processing+=f'\x03{color_table[attr[0]]},{color_table[attr[1]]}'
color_fg=color_table[attr[0]]
color_bg=color_table[attr[1]]
elif n==0 and attr[2]:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=attr[0]+offset_bold
color_bg=attr[1]
if not attr[2]==last_attr[2] and not n==0:
if attr[0] == last_attr[0] and not attr[1] == last_attr[1]:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=attr[0]+offset_bold
color_bg=attr[1]
elif attr[0] == last_attr[0] and attr[1] == last_attr[1]:
processing+=f'\x03{color_table[attr[0]+offset_bold]}'
color_fg=attr[0]+offset_bold
elif not attr[0] == last_attr[0] and attr[1] == last_attr[1]:
processing+=f'\x03{color_table[attr[0]+offset_bold]}'
color_fg=attr[0]+offset_bold
elif not attr[0] == last_attr[0] and not attr[1] == last_attr[1]:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=attr[0]+offset_bold
color_bg=attr[1]
elif not attr[0]==last_attr[0] and not attr[1]==last_attr[1] and not n==0:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=attr[0]+offset_bold
color_bg=attr[1]
elif not attr[0]==last_attr[0] and not n==0:
if attr[2]:
processing+=f'\x03{color_table[attr[0]+offset_bold]}'
color_fg=attr[0]+offset_bold
else:
if not '\x30' <= char <= '\x39':
processing+=f'\x03{color_table[attr[0]]},{color_table[attr[1]]}'
else:
processing+=f'\x03{color_table[attr[0]]},{str(color_table[attr[1]]).zfill(2)}'
color_fg=attr[0]
elif not attr[1]==last_attr[1] and not n==0:
if attr[2]:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=attr[0]+offset_bold
color_bg=attr[1]
else:
processing+=f'\x03{color_table[attr[0]]},{color_table[attr[1]]}'
color_fg=attr[0]
color_bg=attr[1]
else:
if n==0 and not attr[0]==default_fg:
if attr[2]:
processing+=f'\x03{color_table[attr[0]+offset_bold]},{color_table[attr[1]]}'
color_fg=color_table[attr[0]+offset_bold]
color_bg=color_table[attr[1]]
else:
processing+=f'\x03{color_table[attr[0]]},{color_table[attr[1]]}'
color_fg=color_table[attr[0]]
color_bg=color_table[attr[1]]
if len(processing) == 0:
processing+=f"\x0315,1"
processing+=char
last_attr=attr
if len(self.buffer[i]) == 0:
self.output_lines.append(f"\x031,1{''*self.width}")
else:
distance=int(self.width)-len(line)
processing+=f"\x031,1{''*distance}"
self.output_lines.append(processing)
processing=''
#########################################################################################################################
def as_irc(self):
self.output_lines=[]
self.as_irc_lines()
for _ in self.output_lines:
self.fifo(_)
pass
################################################################################################### RE-ENCODING ENCODINGS
def as_terminal_lines(self):
default_fg=7
default_bg=0
last_attr = None
processing=''
for i,line in enumerate(self.buffer):
for n,(attr, char) in enumerate(line):
if attr != last_attr:
if last_attr == None:
processing+=f'\x1b[{attr[0]+30};{attr[1]+40}m'
else:
if n==0 and not attr[0]==default_fg:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
else:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
elif n==0 and attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
elif n==0 and not attr[2]:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
if not attr[2]==last_attr[2] and not n==0:
if attr[0] == last_attr[0] and not attr[1] == last_attr[1]:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
else:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
elif attr[0] == last_attr[0] and attr[1] == last_attr[1]:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30}m'
else:
processing+=f'\x1b[0;{attr[0]+30}m'
elif not attr[0] == last_attr[0] and attr[1] == last_attr[1]:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30}m'
else:
processing+=f'\x1b[0;{attr[0]+30}m'
elif not attr[0] == last_attr[0] and not attr[1] == last_attr[1]:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
else:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
elif not attr[0]==last_attr[0] and not attr[1]==last_attr[1] and not n==0:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
else:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
elif not attr[0]==last_attr[0] and not n==0:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30}m'
else:
processing+=f'\x1b[{attr[0]+30};{attr[1]+40}m'
elif not attr[1]==last_attr[1] and not n==0:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
else:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
else:
if n==0 and not attr[0]==default_fg:
if attr[2]:
processing+=f'\x1b[1;{attr[0]+30};{attr[1]+40}m'
else:
processing+=f'\x1b[0;{attr[0]+30};{attr[1]+40}m'
processing+=char
last_attr=attr
self.output_lines.append(processing + '\x1b[40;37m')
processing=''
#########################################################################################################################
def as_terminal(self):
self.output_lines=[]
self.as_terminal_lines()
for _ in self.output_lines:
print(_)
pass
################################################################################################################### ENTRY - 1
if __name__=="__main__":
FIFO_ENABLED = os.path.exists(FIFO_PATH)
files = getfiles(sys.argv)
ui = UI(files)
# for _ in files:
# d=dr1p4ns1(ansifile=_,width=80,debug=False)
# decoder=ANSIDecoder(_,d.width)
# # decoder.as_irc()
# decoder.as_terminal()