########################################################################################### dr1p4ns1 version 2.700 ##### SOF #################################################################################################### ####################### import os import random import shutil import sys import termios import threading import tty from collections import namedtuple from glob import glob from time import sleep #################################################################################################### ####################### #################################################################################################### ####################### ##### #################################################################################################### ####################### """MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMh+MMMMMMMMMMMMMMhsMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMm/ oMMMMMMMMMMMMMMm +NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy` yMMMMMMMMMMMMMMM- -mMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMs+dMMMMMMMMMM+ sMMMMMMMMMMMMMMM- `dMMMMMMMMMMms/NMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMM+ .omMMMMMM: -MMMMMMMMMMMMMMo `yMMMMMMMy: `dMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMM- /dMMM+ sMMMMMMMMMMMMh `hMMMNo` sMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMd :dm `mMMMMMMMMMMN. .NNo` .MMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMM: - :MMMMMMMMMMs :` sMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMs ymNMMMMMNm. NMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMy `-/-` .MMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMo .NMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMNh+. :sdMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMhso+:. `-/+syMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMM- dMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMM` `.:+/. `/s+:. sMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMNo -oms. .//-` `:/:` `+md+` .hMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMNs` .odNdo. .ohmd+` :dMMMMMMMMMMMMM ####################### MMMMMMMMMMMNo` .. .- :hMMMMMMMMMMM ####################### MMMMMMMMMd+` -sNMMMMMMMM ####################### ###MMMNs- `.. `/-. `+dMMMMMM ####################### ###Ny: ./sdNMMMh: `sNMMMNds/. .odMMM ####################### MM+ :ymMMMMMMMMMMh. +NMMMMMMMMMMmo- /NM ####################### MMMh: .sNMMMMMMMMMMMMMMN- `hMMMMMMMMMMMMMMMm+` :hMMM ####################### MMMMMd:` ``-:+shmMMMMMMMMMMMMMMMMMMN. hMMMMMMMMMMMMMMMMMMMmhs+/-..``````./dMMMMM ####################### MMMMMMMMMNNNNNNMMMMMMMMMMMMMMMMMMMMMMMMMMMo .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMy .MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN. /MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN+` `+NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ####################### 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" ##### FLOODRATE_INTERVAL_SECONDS = 0.125 ##### global SHOW_FILENAME ##### SHOW_FILENAME=True ##### DR1P_VERSION="2.700 - last updated: 03/26/23 - https://git.tcp.direct/decoded/dr1p4ns1" ##### #################################################################################################### ####################### #################################################################################################### ####################### ##### ### "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, ########################################### ##### ############################################################################################################################# ############################################################################################################################# ### ##### ### "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", ##### ### "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", ##### ### "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", ##### ### "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", ##### ### "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", ##### ### "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", ##### ### "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98" ''' ##### 0x470000, 0x472100, 0x474700, 0x324700, 0x004700, 0x00472C, 0x004747, 0x002747, 0x000047, 0x2E0047, 0x470047, 0x47002A, ##### 0x740000, 0x743a00, 0x747400, 0x517400, 0x007400, 0x007449, 0x007474, 0x004074, 0x000074, 0x4b0074, 0x740074, 0x740045, ##### 0xb50000, 0xb56300, 0xb5b500, 0x7db500, 0x00b500, 0x00b571, 0x00b5b5, 0x0063b5, 0x0000b5, 0x7500b5, 0xb500b5, 0xb5006b, ##### 0xff0000, 0xff8c00, 0xffff00, 0xb2ff00, 0x00ff00, 0x00ffa0, 0x00ffff, 0x008cff, 0x0000ff, 0xa500ff, 0xff00ff, 0xff0098, ##### 0xff5959, 0xffb459, 0xffff71, 0xcfff60, 0x6fff6f, 0x65ffc9, 0x6dffff, 0x59b4ff, 0x5959ff, 0xc459ff, 0xff66ff, 0xff59bc, ##### 0xff9c9c, 0xffd39c, 0xffff9c, 0xe2ff9c, 0x9cff9c, 0x9cffdb, 0x9cffff, 0x9cd3ff, 0x9c9cff, 0xdc9cff, 0xff9cff, 0xff94d3, ##### 0x000000, 0x131313, 0x282828, 0x363636, 0x4d4d4d, 0x656565, 0x818181, 0x9f9f9f, 0xbcbcbc, 0xe2e2e2, 0xffffff ##### ##### ############################################################################################################################# ############################################################################################################################# 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 D: def __init__(self): self.delay=FLOODRATE_INTERVAL_SECONDS self.correct=0 ########################################################################################################## CLASS DR1P4NS1 - 2 class dr1p4ns1: ############################################################################################################ LOOKUP TABLE commands = { 'A': 'up', 'B': 'down', 'C': 'forward', 'D': 'back', 'H': 'position', 'f': 'position', 'J': 'erase', 'K': 'erase_line', 's': 'save_cursor', 'u': 'restore_cursor', 'm': 'color', 'R': 'report_cursor_position', 't': 'nfi'} ############################################################################################################ LOOKUP TABLE asc_table="""\ ╟ⁿΘΓΣαστΩδΦ∩ε∞─┼╔µ╞⌠÷≥√∙ ╓▄óúÑ₧ƒ\ ßφ≤·±╤¬║┐⌐¼╜╝í½╗░▒▓│┤╡╢╖╕╣║╗╝╜╛┐\ └┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀\ α▀ΓπΣσ╡τΦΘΩδ∞φε∩≡▒≥≤⌠⌡≈≈░∙╖√ⁿ▓■á""" ##################################################################################################### ASCII TABLE CLEANUP for r in (('\n',''),(' ','')): asc_table=asc_table.replace(*r) ############################################################################################################ LOOKUP TABLE asc_table_full="""\ \x00☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼\ \_!"#$%&\'()*+,-./0123456789:;<=>\ ?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^\ _`abcdefghijklmnopqrstuvwxyz{|}~\ ⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧\ ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛\ ┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐\ ▀ɑϐᴦᴨ∑ơµᴛɸϴΩẟ∞∅∈∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■\ ÿ""" ##################################################################################################### ASCII TABLE CLEANUP for r in ((' ',''),('\_',' ')): asc_table_full=asc_table_full.replace(*r) ########################################################################################## RGB TERMINAL ESCAPE COLORCODES def _rgb(r=0,g=0,b=0):return f"\033[38;2;{r};{g};{b}m" ############################################################################################################ LOOKUP TABLE asc2uni=dict(zip([i for i in range(128,256)],[ord(c) for c in asc_table])) ############################################################################################################ LOOKUP TABLE asc2chr=dict(zip([i for i in range(128,256)],[c for c in asc_table])) ############################################################################################################ LOOKUP TABLE rgb2irc = { 52: '16', 94: '17', 100: '18', 58: '19', 22: '20', 29: '21', 23: '22', 24: '23', 17: '24', 54: '25', 53: '26', 89: '27', 88: '28', 130: '29', 142: '30', 64: '31', 28: '32', 35: '33', 30: '34', 25: '35', 18: '36', 91: '37', 90: '38', 125: '39', 124: '40', 166: '41', 184: '42', 106: '43', 34: '44', 49: '45', 37: '46', 33: '47', 19: '48', 129: '49', 127: '50', 161: '51', 196: '52', 208: '53', 226: '54', 154: '55', 46: '56', 86: '57', 51: '58', 75: '59', 21: '60', 171: '61', 201: '62', 198: '63', 203: '64', 215: '65', 227: '66', 191: '67', 83: '68', 122: '69', 87: '70', 111: '71', 63: '72', 177: '73', 207: '74', 205: '75', 217: '76', 223: '77', 229: '78', 193: '79', 157: '80', 158: '81', 159: '82', 153: '83', 147: '84', 183: '85', 219: '86', 212: '87', 16: '88', 233: '89', 235: '90', 237: '91', 239: '92', 241: '93', 244: '94', 247: '95', 250: '96', 254: '97', 231: '98', } ########################################################################################################## CLASS INIT - 3 def __init__(self,ansifile="",width=80,height=25,debug=False,pump=False): self.DEBUG=debug self.width=width self.height=height self.filename=ansifile self.openansi(ansifile) self.code='\x1b[0m' self.cmps=[] self.op=[] self.optype=[] self.sauce_found=False print('\x1bc') self.pump=pump self.boot() ######################################################################################################### FILE OPERATIONS def fifo(self,s): s=[s] f=open(FIFO_PATH,"w") [f.write("*{}\n".format(x)) for x in s] f.close() ######################################################################################################### FILE OPERATIONS def openansi(self,s): f=open('log','w') f.write(f'{s}\n') f.close() f=open(s,'rb') self.ansifile=f.read().decode('cp437') f.close() ############################################################################################################### DEBUGGING def openascii(self): f=open('ansiscii/work.asc','r') self.reference=f.read() f.close() #################################################################################################################### TOOL def printascii(self): for i,_ in enumerate(self.asc_table): _int=str(i+128).zfill(3) _hex=hex(i+128)[2:].upper().zfill(2) _ord=str(ord(_)).zfill(4) print(f'{_} - {_int} - {_hex} - {_ord}') ############################################################################################################### DEBUGGING def printrange(self,n,nn): for index,_ in enumerate(self.ansifile): h=hex(_)[2:].upper() i=str(_).zfill(3) s='' if _>47 and _<127: s=chr(_) else: s='.' l=str(index).zfill(len(str(len(self.ansifile)))) if index >=n and index <=nn: print(f"{l} {i} {h} {s}") if index==nn: break ############################################################################################################### DEBUGGING def printhex(self): theasc=[] thehex=[] buffer='' for _ in self.ansifile: buffer+=hex(ord(_)).upper()[2:].zfill(2) for _ in self.chunk(buffer,32): subchunks='' for i,__ in enumerate(self.chunk(_,2)): if i>0 and i%4==0: subchunks+=" " subchunks+=f'{__} ' thehex.append(subchunks.strip()) for __ in thehex: buffer='' for _ in __.split(): i=int(_,16) if i>47 and i<127: buffer+=chr(i) else: buffer+='.' theasc.append(buffer) for _ in range(len(thehex)): old=buffer buffer={thehex[_]} if not buffer == old: print(f"{hex(16 * _)[2:].zfill(8)} {thehex[_]} {theasc[_]}") ############################################################################################################### DEBUGGING def hexdump(self): self.codes=[] code_start=0 code_end=0 code_state=False for i,_ in enumerate(self.ansifile): if code_state==False: if _ == '\x1b': code_state=True code_start=i elif _ == '\x1a': code=self.ansifile[i:] self.codes.append([code,i,len(self.ansifile)]) else: if 64 <= ord(_) <= 126: if _ in self.commands: code_state=False code_end=i+1 code=self.ansifile[code_start:code_end] self.codes.append([code,code_start,code_end]) ############################################################################################################### DEBUGGING def codedump(self): xpos_old=0 xpos_new=0 self.codes=[] code_start=0 code_end=0 code_state=False for i,_ in enumerate(self.ansifile): if code_state==False: if _ == '\x1b': code_state=True code_start=i elif _ == '\x1a': self.op.append(self.ansifile[code_end:i]) code=self.ansifile[i:] self.codes.append([code,i,len(self.ansifile)]) if code[1:6].upper()=="SAUCE": self.getsauce() else: if 64 <= ord(_) <= 126: try: if _ in self.commands: code_state=False code_end=i+1 code=self.ansifile[code_start:code_end] self.codes.append([code,code_start,code_end]) xpos_new=code_start distance=xpos_new-xpos_old if not distance == 0: nonop=self.ansifile[xpos_old:xpos_old+distance] self.op.append(nonop) self.optype.append(1) self.op.append(code) xpos_old=code_end if self.commands[_] == 'color': self.optype.append(2) elif self.commands[_] == 'forward': self.optype.append(3) else: self.optype.append(0) except Exception as e: print(f'error: {e}') if not self.sauce_found: code=self.ansifile[i:] #################################################################################################################### TOOL def processdump(self): offset=0 offsets=[] processed=[] uniqued=[] uniques=[] codes=[] processing='' try: for i,_optype in enumerate(self.optype): if _optype==2: processing+=self.op[i] offset+=len(self.op[i]) elif _optype==3: count=int(self.op[i].split('[')[1].split('C')[0]) processing+=' '*count elif _optype==1: processing+=self.op[i] _bseq='\r\n' _xpos=processing.find(_bseq) distance=0 while not processing.find(_bseq) == -1: _xpos=processing.find(_bseq) if not _xpos == -1: uniques.append(_bseq) uniques.append(_xpos) if len(self.stripcodes(processing[:_xpos])) >= 80: distance=80 gaps=self.width-len(self.stripcodes(processing)[distance:].split('\r\n')[0]) processing=processing.replace(_bseq,chr(32)*gaps,1) if len(processing)-offset > self.width: trailing_size=0 while len(processing)-offset > self.width: deconcatenate=processing[0:self.width+offset] if deconcatenate.endswith('m'): if not deconcatenate.rfind('\x1b')==-1: trailing_size=len(deconcatenate[deconcatenate.rfind('\x1b'):]) deconcatenate=deconcatenate[:deconcatenate.rfind('\x1b')] processed.append(deconcatenate) if len(uniques) < 2: uniqued.append('') else: uniqued.append(uniques) uniqued.append(uniques) uniques=[] offsets.append(offset) processing=processing.replace(deconcatenate,'',1) offset=0+trailing_size if len(processing) > 0: gaps=int(80-len(self.stripcodes(processing))) processing+=chr(32)*gaps processed.append(processing) processed_colors=[]; last_colors=''; color_fg=''; color_bg=''; color_set=''; for y,__ in enumerate(processed): code_start=0; code_end=0; code_state=False; codes=[]; for x,_ in enumerate(__): if not code_state: if _ =='\x1b': code_start = x code_state = True else: if _ in self.commands: if self.commands[_] == 'color': code_end = x+1 code_state = False codes.append(__[code_start:code_end]) for code in codes: for _ in code.replace('m','').split('[')[1].split(';'): try: if 0 <= int(_) <= 9: color_set=_ if 30 <= int(_) <= 39: color_fg=_ if 40 <= int(_) <= 49: color_bg=_ except: print('error') pass 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]; default_fg_color=7 default_bg_color=0 codes=[] for _ in processed: line=_ for r in (('\x16',chr(9644)),('\x15','\u00A7')): line=line.replace(*r) _line=line bold_offset=0 bold_before=[] bold_init=False codes_root_popped=False fg_color=color_table[default_fg_color] bg_color=color_table[default_bg_color] color_set='0' for _ in [line[x[0]:x[1]+1] for x in zip([x for x in self.findall(line,'\x1b')],[line.find('m',x) for x in self.findall(line,'\x1b')])]: codes.append(_) code_values=_.split('[')[1].split(';') code_replace=_ newcode='' for __ in code_values: __=__.replace('m','') if 0 <= int(__) <= 9: color_set=int(__) if color_set==1: bold_offset=8 bold_before=[] else: bold_offset=0 elif 40 <= int(__) <= 49: if bold_init and bold_offset==0: bg_color=color_table[default_bg_color] else: bg_color=__ if not bold_offset==0 and not bold_init: bold_before.append(int(bg_color)) elif 30 <= int(__) <= 39: if bold_init and bold_offset==0: fg_color=color_table[default_fg_color] else: fg_color=__ if not bold_offset==0 and not bold_init: bold_before.append(int(fg_color)) if bold_init and bold_offset==0: bold_init=False newcode='\x03' bold_before.sort() for _ in bold_before: if 30 <= int(_) <= 39: newcode += str(color_table[default_fg_color]) if 40 <= int(_) <= 49: newcode += "," + str(color_table[default_bg_color]) elif not bold_offset == 0 and not bold_init: newcode='\x03' bold_before.sort() for _ in bold_before: if 30 <= int(_) <= 39: newcode+=str(color_table[int(fg_color)-30+bold_offset]) if 40 <= int(_) <= 49: newcode+=","+str(color_table[int(bg_color)-40]) bold_init=True elif not bold_offset == 0 and bold_init: for _ in bold_before: if len(bold_before)==1: if 30 <= int(_) <= 39: bold_before.append(int(bg_color)) else: bold_before.append(int(fg_color)) newcode='\x03' bold_before.sort() for _ in bold_before: if 30 <= int(_) <= 39: newcode+=str(color_table[int(fg_color)-30+bold_offset]) if 40 <= int(_) <= 49: newcode+=","+str(color_table[int(bg_color)-40]) else: pass #non-bold-operations if len(codes) == 1 and not codes_root_popped: if color_set == 0: _line=_line.replace(codes[-1],"",1) codes_root_popped=True else: _line=_line.replace(code_replace,newcode,1) irc_processed.append(_line) terminal_processed.append(line) except Exception as e: print(f'bp error: {e}') #################################################################################################################### TOOL def getsauce(self): f=open(self.filename,'rb') l=f.read() f.close() self.sauce=l[-128:] self.sauce_found=True self.width=self.sauce[96] self.height=self.sauce[98] if self.width==0: print("ERROR: sauce.width has 0 value, defaulting to 80 width") self.width=80 offset=len("SAUCE") self.sauce_version=str(int(self.sauce[offset:offset+2].strip())) offset+=2 self.sauce_title=self.sauce[offset:offset+35].strip() offset+=35 self.sauce_title=self.sauce[offset:offset+20].strip() offset+=20 self.sauce_group=self.sauce[offset:offset+20].strip() offset+=20 self.sauce_date=self.sauce[offset:offset+8].strip() offset+=8 #################################################################################################################### TOOL def findall(self,s,w): return [i for i in range(len(s)) if s.startswith(w, i)] ############################################################################################################### DEBUGGING def cmpans(self,s1,s2,n1=0,n2=0): _s1=''; _s2=''; _sn1=''; _sn2='' _s1=self.stripcodes(s1) _s2=self.stripcodes(s2) if not n1 == n2: _sn1=_s1[n1:n2] _sn2=_s2[n1:n2] _sn3='' for i in range(self.width): try: if ord(_sn1[i]) == ord(_sn2[i]): _sn3+='\x1b[32m0\x1b[0m' else: _sn3+='\x1b[31m1\x1b[0m' except Exception as e: print(e) self.cmps.append(f'{_sn1}\n{_sn2}\n{_sn3}') n1+=self.width n2+=self.width #################################################################################################################### TOOL def chunk(self,s,n): return [s[i:i+n] for i in range(0,len(s),n)] #################################################################################################################### TOOL def stripcodes(self,s): buffer=s code_start=0 code_end=0 code_state=False for i,_ in enumerate(s): if code_state==False: if _ == '\x1b': code_state=True code_start=i else: if 64 <= ord(_) <= 126: if _ in self.commands: code_state=False code_end=i+1 code=s[code_start:code_end] buffer=buffer.replace(code,'') return buffer #################################################################################################################### TOOL def rgb(self,t='',r=0,g=0,b=0): """colorize text with rgb values""" return f"\033[38;2;{r};{g};{b}m{t}\033[38;2;255;255;255m" #################################################################################################################### TOOL def vga(self,t='',i=0): """colorize text using vga color set""" vga = [ '#000000','#aa0000','#00aa00','#aa5500', '#0000aa','#aa00aa','#00aaaa','#aaaaaa', '#555555','#ff5555','#55ff55','#ffff55', '#5555ff','#ff55ff','#55ffff','#ffffff', ] try: r=int(vga[i][1:][0:2],16) g=int(vga[i][1:][2:4],16) b=int(vga[i][1:][4:6],16) except: r,g,b=0,0,0 return f"\033[38;2;{r};{g};{b}m{t}\033[38;2;255;255;255m" #################################################################################################################### TOOL def invert_dict(self,d): return {v: k for k, v in d.items()} #################################################################################################################### BOOT def boot(self): if self.DEBUG: print("\n\x1b[1;31m[ HEXDUMP ]\x1b[0m\n") self.printhex() self.codedump() self.processdump() ####################################################################################### HUMAN INTERFACE * * * * * * * * * * * class UI: def __init__(self,files=""): self.REMOVED=False self.QUEUE=[] 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', 100: 'd', 82: 'R' } return key_mapping.get(k, chr(k)) finally: termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) ################################################################################### HUMAN INTERFACE * * * * * * * * * * * def uis_menu(self): global SHOW_FILENAME 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;95m'; S='\x1b[1;36m'; M='\x1b[1;92m'; E='\x1b[0m'; R='\x1b[31m' msg=f"{B}[ {C}DR1P {B}] {B}- {B}[ {M}x{B}: {M}exit{B}, {M}c{B}: {M}copy{B}, {M}R{B}: {M}remove{B}, {M}f{B}: {M}show_filename{B}:{C}{SHOW_FILENAME}{B}, {M}q{B}: {M}pumpqueue{B}, {M}z{B}/{M}p{B}: {M}auto{B}/{M}pump{B}, " msg+=f"{M}left{B}/{M}right{B}: {M}browse {B}]\n[ {M}d{B}: {M}delay{B} - {M}{dr1p.delay}{B} ] {B}- " msg+=f"{B}[ {S}pumpqueue{B}: {C}{len(self.QUEUE)} {B}- {S}index{B}: {C}{index+1}{B}/{C}{len(self.files)} {B}- {S}filename{B}: {C}{d.filename} {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]}') try: d=dr1p4ns1(ansifile=self.files[index],width=80,debug=False) except: pass decoder=ANSIDecoder(self.files[index],d.width) print('\x1bc') 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) print('\x1bc') decoder.as_terminal() except: pass elif k == 'esc' 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) print('\x1bc') decoder.as_terminal() elif k == 'q': self.QUEUE.append((self.files[index],d.width)) print(f'{C}{self.files[index]} {B}added to pumpqueue') sleep(1) print('\x1bc') decoder.as_terminal() elif k == 'f': if SHOW_FILENAME: SHOW_FILENAME=False else: SHOW_FILENAME=True elif k == 'd': while True: print(f'{C}input floodrate delay{B}: {C}',end='') USER_INPUT=input() TRAPFLAG=-1 try: TRAPFLAG=int(USER_INPUT) except: try: TRAPFLAG=float(USER_INPUT) except: print(f'{S}accepted floodrate delay range is between 0 and 10.0 seconds') try: if TRAPFLAG>=0 and TRAPFLAG<=10: dr1p.delay=TRAPFLAG break except: print(f'{S}accepted floodrate delay range is between 0 and 10.0 seconds') print(f'{M}floodrate delay set to{B}: {C}{dr1p.delay}') sleep(1) print('\x1bc') decoder.as_terminal() elif k == 'z': flag_done=False if len(self.QUEUE)==0: self.QUEUE=self.files print(f'\n{dr1p4ns1._rgb(55,55,55)}pumpqueue empty{dr1p4ns1._rgb(155,155,155)}:{dr1p4ns1._rgb(55,55,55)} autopumping from directory index{dr1p4ns1._rgb(155,155,155)}: {dr1p4ns1._rgb(55,55,55)}{sys.argv[1]}') sleep(1) else: print(f'{R} autopumping from pump queue') while not flag_done: if len(self.QUEUE) > 0: print('\x1bc') dr1p4ns1.filename=self.QUEUE[-1]; dr1p4ns1.getsauce(dr1p4ns1) d=dr1p4ns1(ansifile=self.QUEUE[0],width=dr1p4ns1.width,debug=False) decoder=ANSIDecoder(self.QUEUE[0],d.width) decoder.as_terminal() self.QUEUE.reverse() buffer_filename=self.QUEUE[-1] buffer_width=dr1p4ns1.width self.QUEUE.pop() self.QUEUE.reverse() decoder=ANSIDecoder(buffer_filename,buffer_width) decoder.as_irc() N=random.randint(5,10) try: print(f'{dr1p4ns1._rgb(155,155,155)}<<<{dr1p4ns1._rgb(55,55,55)} sleeping {dr1p4ns1._rgb(155,155,155)}{N}{dr1p4ns1._rgb(55,55,55)} seconds before next autopump {dr1p4ns1._rgb(155,155,155)}>>> {dr1p4ns1._rgb(200,200,200)} {self.QUEUE[0]}') except: break sleep(N) else: flag_done=True print(f'{B}NO FILES LEFT IN QUEUE - {R} EXITING') sleep(1) break elif k == 'p': print(f'{C}p.u.m.p.i.n.g ', end = "") PMSG="" try: if FIFO_ENABLED: if len(self.QUEUE) > 0: self.QUEUE.reverse() buffer_filename, buffer_width=self.QUEUE[-1] self.QUEUE.pop() self.QUEUE.reverse() decoder=ANSIDecoder(buffer_filename,buffer_width) PMSG=f'{M}pump: pumped from pumpqueue {C}{self.files[index]} {M}to fifo - {C}{FIFO_PATH}' else: decoder=ANSIDecoder(self.files[index],d.width) PMSG=f'{M}pump: nothing in pumpqueue, pumping from screen {C}{self.files[index]} {M}to fifo - {C}{FIFO_PATH}' decoder.as_irc() else: PMSG=f'{M}pumping disabled - fifo not detected in path: {C}{FIFO_PATH}' except Exception as e: PMSG=f'{M}pumping failed - {e}' decoder.as_terminal() print(PMSG) 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) print('\x1bc') decoder.as_terminal() 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) print('\x1bc') decoder.as_terminal() except: pass ####################################### except (KeyboardInterrupt, SystemExit): os.system('stty sane') ############################################################################################################################# class ANSIDecodeError(ValueError): pass ############################################################################################################################# class ANSIDecoder: ############################################################################################################################# ################# ESCAPE_PUMP=False ################# 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 print(self.filename) try: stream=open(self.filename,'rt',encoding='cp437') if stream: self.play(stream) except: pass ######################################################################################################################### 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='' 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 getkeythreaded(self): tty.setcbreak(sys.stdin.fileno()) print(f'{dr1p4ns1._rgb(55,55,55)}<<<{dr1p4ns1._rgb(155,155,155)} press any key to abort pump {dr1p4ns1._rgb(55,55,55)}>>> {dr1p4ns1._rgb(155,155,155)}-{dr1p4ns1._rgb(200,200,200)} {self.filename}') b = os.read(sys.stdin.fileno(), 3).decode() if len(b) == 3: k = ord(b[2]) else: k = ord(b) self.ESCAPE_PUMP=True ######################################################################################################################### def as_irc(self): DID_I_ABORT=False self.output_lines=[] self.as_irc_lines() x=threading.Thread(target=self.getkeythreaded) x.start() for _ in self.output_lines: self.fifo(_) sleep(dr1p.delay) if self.ESCAPE_PUMP: DID_I_ABORT=True break if SHOW_FILENAME: self.fifo(f"\x0315FILENAME\x0314: \x0315{self.filename.split('/')[-1]} \x0314- \x0315DR1P4NS1\x0314:\x0315 {DR1P_VERSION}") try: x._stop() except: pass self.ESCAPE_PUMP=False if DID_I_ABORT: print(f'\x1b[31m<<< ABORTED PUMP >>>') self.fifo("\x035<<< ABORTED PUMP >>>") sleep(3) ################################################################################################### 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 if len(self.buffer[i]) == 0: self.output_lines.append(f"{'█'*self.width}") else: distance=int(self.width)-len(line) processing+=f"{'█'*distance}" self.output_lines.append(processing) # 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(_) ################################################################################################################### ENTRY - 1 if __name__=="__main__": dr1p=D() FIFO_ENABLED = os.path.exists(FIFO_PATH) dr1p.files = getfiles(sys.argv) ui = UI(dr1p.files) #################################################################################################### ####################### ########################################################################################### dr1p4ns1 version 2.667 ##### EOF