v2.0
This commit is contained in:
parent
b50b70172a
commit
4bead33ae1
815
dr1p4ns1.py
815
dr1p4ns1.py
|
@ -2,8 +2,12 @@
|
|||
#################################################################################################### #######################
|
||||
from glob import glob
|
||||
from time import sleep
|
||||
from collections import namedtuple
|
||||
import sys,tty,os,termios,shutil
|
||||
#################################################################################################### #######################
|
||||
#################################################################################################### #######################
|
||||
####
|
||||
#################################################################################################### #######################
|
||||
"""MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh+MMMMMMMMMMMMMMhsMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
|
||||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm/ oMMMMMMMMMMMMMMm +NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
|
||||
|
@ -36,10 +40,19 @@ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN+` `+NMMMMMMMMMMMMMMMMMMMMMM
|
|||
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNs. -hMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM #######################
|
||||
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", ###########################################
|
||||
### "08", "09", "10", "11", "12", "13", "14", "15", ###########################################
|
||||
|
||||
#####
|
||||
0xFFFFFF, 0x000000, 0x00007F, 0x009300, 0xFF0000, 0x7F0000, 0x9C009C, 0xFC7F00, ###########################################
|
||||
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:
|
||||
############################################################################################################ LOOKUP TABLE
|
||||
|
@ -137,7 +167,6 @@ class dr1p4ns1:
|
|||
self.height=height
|
||||
self.filename=ansifile
|
||||
self.openansi(ansifile)
|
||||
#self.openascii()
|
||||
self.code='\x1b[0m'
|
||||
self.cmps=[]
|
||||
self.op=[]
|
||||
|
@ -149,7 +178,7 @@ class dr1p4ns1:
|
|||
######################################################################################################### FILE OPERATIONS
|
||||
def fifo(self,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.close()
|
||||
######################################################################################################### FILE OPERATIONS
|
||||
|
@ -157,7 +186,7 @@ class dr1p4ns1:
|
|||
f=open(s,'rb')
|
||||
self.ansifile=f.read().decode('cp437')
|
||||
f.close()
|
||||
############################################################################################# DEBUGGING - FILE OPERATIONS
|
||||
############################################################################################################### DEBUGGING
|
||||
def openascii(self):
|
||||
f=open('ansiscii/work.asc','r')
|
||||
self.reference=f.read()
|
||||
|
@ -250,7 +279,7 @@ class dr1p4ns1:
|
|||
code=self.ansifile[i:]
|
||||
self.codes.append([code,i,len(self.ansifile)])
|
||||
if code[1:6].upper()=="SAUCE":
|
||||
self.getsauce(code[1:])
|
||||
self.getsauce()
|
||||
else:
|
||||
if 64 <= ord(_) <= 126:
|
||||
try:
|
||||
|
@ -352,6 +381,7 @@ class dr1p4ns1:
|
|||
color_bg=_
|
||||
colors=f"{color_set}"
|
||||
processed_colors.append(colors)
|
||||
self.processed = processed
|
||||
irc_processed=[]
|
||||
terminal_processed=[]
|
||||
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))
|
||||
else:
|
||||
bold_before.append(int(fg_color))
|
||||
# else:
|
||||
# print('how are you here')
|
||||
newcode='\x03'
|
||||
bold_before.sort()
|
||||
for _ in bold_before:
|
||||
|
@ -445,17 +473,15 @@ class dr1p4ns1:
|
|||
_line=_line.replace(code_replace,newcode,1)
|
||||
irc_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
|
||||
def getsauce(self,sauce):
|
||||
self.sauce=sauce
|
||||
def getsauce(self):
|
||||
f=open(self.filename,'rb')
|
||||
l=f.read()
|
||||
f.close()
|
||||
self.sauce=l[-128:]
|
||||
self.sauce_found=True
|
||||
self.width=ord(self.sauce[96])
|
||||
self.height=ord(self.sauce[98])
|
||||
self.width=self.sauce[96]
|
||||
self.height=self.sauce[98]
|
||||
offset=len("SAUCE")
|
||||
self.sauce_version=str(int(self.sauce[offset:offset+2].strip()))
|
||||
offset+=2
|
||||
|
@ -533,114 +559,659 @@ class dr1p4ns1:
|
|||
#################################################################################################################### TOOL
|
||||
def invert_dict(self,d):
|
||||
return {v: k for k, v in d.items()}
|
||||
########################################################################################################## CLASS MAIN - 4
|
||||
#################################################################################################################### BOOT
|
||||
def boot(self):
|
||||
if self.DEBUG:
|
||||
print("\n\x1b[1;31m[ HEXDUMP ]\x1b[0m\n")
|
||||
self.printhex()
|
||||
self.codedump()
|
||||
self.processdump()
|
||||
#############################################################################################################################
|
||||
def getkey():
|
||||
old_settings = termios.tcgetattr(sys.stdin)
|
||||
tty.setcbreak(sys.stdin.fileno())
|
||||
try:
|
||||
while True:
|
||||
b = os.read(sys.stdin.fileno(), 3).decode()
|
||||
if len(b) == 3:
|
||||
k = ord(b[2])
|
||||
else:
|
||||
k = ord(b)
|
||||
key_mapping = {
|
||||
112: 'p',
|
||||
27: 'esc',
|
||||
67: 'right',
|
||||
68: 'left',
|
||||
113: 'q',
|
||||
120: 'x',
|
||||
99: 'c',
|
||||
82: 'R'
|
||||
}
|
||||
return key_mapping.get(k, chr(k))
|
||||
finally:
|
||||
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
|
||||
################################################################################################################### ENTRY - 1
|
||||
if __name__ == "__main__":
|
||||
#######################################
|
||||
if len(sys.argv) > 1:
|
||||
PATH=''
|
||||
if sys.argv[1]=='.':
|
||||
PATH=os.getcwd()
|
||||
files=glob(PATH+"/*.ans")
|
||||
files+=glob(PATH+"/*.ANS")
|
||||
else:
|
||||
files=glob(sys.argv[1]+"/*.ans")
|
||||
files+=glob(sys.argv[1]+"/*.ANS")
|
||||
else:
|
||||
files=glob('ansiscii/*.ans')
|
||||
files+=glob('ansiscii/*.ANS')
|
||||
#######################################
|
||||
if len(files)==0:
|
||||
print('ERROR: NO ANSI FILES IN THE PATH SPECIFIED',end='')
|
||||
sys.exit(1)
|
||||
#######################################
|
||||
index=0
|
||||
try:
|
||||
print(f'loading: {files[index]}')
|
||||
d=dr1p4ns1(ansifile=files[index],width=80,debug=False)
|
||||
except:
|
||||
pass
|
||||
#######################################
|
||||
try:
|
||||
while True:
|
||||
B='\x1b[1;94m'; C='\x1b[1;94m'; S='\x1b[1;36m'; M='\x1b[1;92m'; E='\x1b[0m'
|
||||
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}"
|
||||
msg+=f"{d.filename}{E}"
|
||||
print(msg)
|
||||
k = getkey()
|
||||
if k == 'left':
|
||||
index-=1
|
||||
if index < 0: index=len(files)-1
|
||||
try:
|
||||
print(f'{C}loading{B}: {S}{files[index]}')
|
||||
d=dr1p4ns1(ansifile=files[index],width=80,debug=False)
|
||||
except:
|
||||
pass
|
||||
elif k == 'right':
|
||||
index+=1
|
||||
if index >= len(files): index=0
|
||||
try:
|
||||
print(f'{C}loading{B}: {S}{files[index]}')
|
||||
d=dr1p4ns1(ansifile=files[index],width=80,debug=False)
|
||||
except:
|
||||
pass
|
||||
elif k == 'esc' or k == 'q' or k == 'x':
|
||||
quit()
|
||||
elif k == 'R':
|
||||
print('file removed: placed in /tmp directory')
|
||||
sleep(3)
|
||||
shutil.copyfile(d.filename,f'/tmp/{str(d.filename).split("/")[1]}')
|
||||
os.remove(d.filename)
|
||||
elif k == 'p':
|
||||
print('pump') #
|
||||
d=dr1p4ns1(ansifile=files[index],width=80,debug=False,pump=True)
|
||||
sleep(1)
|
||||
elif k == 'c':
|
||||
try:
|
||||
shutil.copyfile(d.filename,f'pump/{str(d.filename).split("/")[1]}')
|
||||
print(f'{C}file copied to pump directory')
|
||||
except:
|
||||
print(f'{M}file was not copied')
|
||||
else:
|
||||
index+=1
|
||||
if index >= len(files): index=0
|
||||
try:
|
||||
d=dr1p4ns1(ansifile=files[index],width=80,debug=False)
|
||||
except:
|
||||
pass
|
||||
#######################################
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
os.system('stty sane')
|
||||
#######################################
|
||||
####################################################################################### HUMAN INTERFACE * * * * * * * * * * *
|
||||
class UI:
|
||||
def __init__(self,files=""):
|
||||
self.REMOVED=False
|
||||
self.files=files
|
||||
self.uis_menu()
|
||||
################################################################################### HUMAN INTERFACE * * * * * * * * * * *
|
||||
def getkey(self):
|
||||
old_settings = termios.tcgetattr(sys.stdin)
|
||||
tty.setcbreak(sys.stdin.fileno())
|
||||
try:
|
||||
while True:
|
||||
b = os.read(sys.stdin.fileno(), 3).decode()
|
||||
if len(b) == 3:
|
||||
k = ord(b[2])
|
||||
else:
|
||||
k = ord(b)
|
||||
key_mapping = {
|
||||
112: 'p',
|
||||
27: 'esc',
|
||||
67: 'right',
|
||||
68: 'left',
|
||||
113: 'q',
|
||||
120: 'x',
|
||||
99: 'c',
|
||||
82: 'R'
|
||||
}
|
||||
return key_mapping.get(k, chr(k))
|
||||
finally:
|
||||
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)
|
||||
################################################################################### HUMAN INTERFACE * * * * * * * * * * *
|
||||
def uis_menu(self):
|
||||
index=0
|
||||
try:
|
||||
print(f'loading: {self.files[index]}')
|
||||
d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
|
||||
decoder=ANSIDecoder(self.files[index],d.width)
|
||||
decoder.as_terminal()
|
||||
except:
|
||||
pass
|
||||
#######################################
|
||||
try:
|
||||
while True:
|
||||
B='\x1b[1;94m'; C='\x1b[1;94m'; S='\x1b[1;36m'; M='\x1b[1;92m'; E='\x1b[0m'; R='\x1b[31m'
|
||||
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}, "
|
||||
msg+=f"{C}left{S}: {M}previous{S}, {C}right{S}: {M}next {B}] {S}- "
|
||||
msg+=f"{C}filename{S}: {M}{d.filename} {S}- {B}[{C}{index+1}{S}/{C}{len(self.files)}{B}]{E}"
|
||||
if self.REMOVED==True: msg+=f'{R} - FILE REMOVED'
|
||||
print(msg)
|
||||
k = self.getkey()
|
||||
if k == 'left':
|
||||
index-=1
|
||||
if index < 0: index=len(self.files)-1
|
||||
try:
|
||||
self.REMOVED=False
|
||||
if len(self.files) == 0:
|
||||
print(f'{B}NO FILES LEFT IN QUEUE - {R} EXITING')
|
||||
sleep(1)
|
||||
break
|
||||
print(f'{C}loading{B}: {S}{self.files[index]}')
|
||||
d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
|
||||
decoder=ANSIDecoder(self.files[index],d.width)
|
||||
decoder.as_terminal()
|
||||
except:
|
||||
pass
|
||||
elif k == 'right':
|
||||
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
|
||||
print(f'{C}loading{B}: {S}{self.files[index]}')
|
||||
d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False)
|
||||
decoder=ANSIDecoder(self.files[index],d.width)
|
||||
decoder.as_terminal()
|
||||
except:
|
||||
pass
|
||||
elif k == 'esc' or k == 'q' or k == 'x':
|
||||
quit()
|
||||
elif k == 'c':
|
||||
try:
|
||||
if not self.files[index].find('/') == -1:
|
||||
FILEPATH=f'{COPY_PATH}/{str(self.files[index]).split("/")[1]}'
|
||||
shutil.copyfile(self.files[index],FILEPATH)
|
||||
print(f'{C}{self.files[index]} copied to {FILEPATH}')
|
||||
else:
|
||||
FILEPATH=f'{COPY_PATH}/{self.files[index]}'
|
||||
shutil.copyfile(self.files[index],FILEPATH)
|
||||
print(f'{C}{self.files[index]} {M}copied to {C}{FILEPATH}')
|
||||
except:
|
||||
print(f'{C}{self.files[index]} {M}was not copied')
|
||||
sleep(1)
|
||||
decoder.as_terminal()
|
||||
elif k == 'p':
|
||||
try:
|
||||
if FIFO_ENABLED:
|
||||
decoder=ANSIDecoder(self.files[index],d.width)
|
||||
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()
|
Loading…
Reference in New Issue