diff --git a/bin/md-color b/bin/md-color index a846c88..8700fce 120000 --- a/bin/md-color +++ b/bin/md-color @@ -1 +1 @@ -../reporting/md-color.py \ No newline at end of file +../reporting/md_color.py \ No newline at end of file diff --git a/reporting/bc.py b/reporting/ansi.py similarity index 97% rename from reporting/bc.py rename to reporting/ansi.py index 543f922..841ccb9 100644 --- a/reporting/bc.py +++ b/reporting/ansi.py @@ -1,7 +1,7 @@ # Python library for ansi colorization -import re +import re,sys -class ansi: +class code: K="\033[1;30m" R="\033[1;31m" G="\033[1;32m" @@ -59,7 +59,7 @@ class ansi: sys.stdout.write( self.pos(y,x) + str(s) ) def clear(self): - sys.stdout.write( self.CLR+self.pos(0,0) ) + sys.stdout.write( self.CLRSCR+self.pos(0,0) ) def clear_to_end(self): sys.stdout.write( self.CLREND ) def clear_to_beginning(self): diff --git a/reporting/markslider.py b/reporting/markslider.py index 42b1a5b..e68cb5f 100755 --- a/reporting/markslider.py +++ b/reporting/markslider.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # coding=utf-8 # -# Copyright 2015 Ville Rantanen +# Copyright 2016 Ville Rantanen # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published @@ -20,84 +20,17 @@ '''Markslider: a slideshow engine based on markdown.''' __author__ = "Ville Rantanen " -__version__ = "0.6" +__version__ = "0.7" import sys,os,argparse,re from argparse import ArgumentParser import traceback,tty,termios,subprocess,signal +sys.path.append(os.path.dirname(os.path.realpath(__file__))) +import ansi,md_color HL=">" EOS="# End of Slides" -class bc: - K="\033[1;30m" - R="\033[1;31m" - G="\033[1;32m" - B="\033[1;34m" - Y="\033[1;33m" - M="\033[1;35m" - C="\033[1;36m" - W="\033[1;37m" - k="\033[30m" - r="\033[31m" - g="\033[32m" - b="\033[34m" - y="\033[33m" - m="\033[35m" - c="\033[36m" - w="\033[37m" - S = '\033[1m' - U = '\033[4m' - Z = '\033[0m' - CLR = '\033[2J' - CLREND = '\033[K' - CLRBEG = '\033[1K' - - color_keys="KRGBYMCWkrgbymcwSUZ" - color_list=[K,R,G,B,Y,M,C,W,k,r,g,b,y,m,c,w,S,U,Z] - - def pos(self,y,x): - return "\033["+str(y)+";"+str(x)+"H" - def column(self,x): - return "\033["+str(x)+"G" - - def posprint(self, y,x,s): - sys.stdout.write( self.pos(y,x) + str(s) ) - - def clear(self): - sys.stdout.write( self.CLR+self.pos(0,0) ) - def clear_to_end(self): - sys.stdout.write( self.CLREND ) - def clear_to_beginning(self): - sys.stdout.write( self.CLRBEG ) - - def up(self,n=1): - sys.stdout.write( "\033["+str(n)+"A" ) - def down(self,n=1): - sys.stdout.write( "\033["+str(n)+"B" ) - def right(self,n=1): - sys.stdout.write( "\033["+str(n)+"C" ) - def left(self,n=1): - sys.stdout.write( "\033["+str(n)+"D" ) - def up_line(self,n=1): - sys.stdout.write( "\033["+str(n)+"F" ) - def down_line(self,n=1): - sys.stdout.write( "\033["+str(n)+"E" ) - - def save(self): - sys.stdout.write( "\033[s" ) - def restore(self): - sys.stdout.write( "\033[u" ) - - def color_string(self,s): - for i,c in enumerate(self.color_keys): - s=s.replace("${"+c+"}",self.color_list[i]) - return s - def nocolor_string(self,s): - for i,c in enumerate(self.color_keys): - s=s.replace("${"+c+"}","") - return s - class getch: def get(self): fd = sys.stdin.fileno() @@ -226,14 +159,14 @@ class slide_reader: self.data.insert(self.opts.toc_page-1,TOC) def launch(self,s): - """ Launch in a string using tags $!command$! + """ Launch in a string using tags `command`> Remove empty lines from beginning and end of stdout. """ if not self.opts.execute_read: return [s] - if s.find("$>")==-1: + if s.find("`>")==-1: return [s] - command=re.match("(.*)\$>(.*)\$>(.*)",s) + command=re.match("(.*)`(.*)`>(.*)",s) if command != None: output = subprocess.check_output(command.group(2).strip(),shell=True).split("\n") while len(output[0].strip())==0: @@ -267,8 +200,8 @@ Special syntaxes: * Colors: insert string ${C}, where C is one of KRGBYMCWkrgbymcwSUZ * Text before first "# header" is not shown * Text after a "# End of Slides" is not shown - * Execute shell: "$! command -switch $!" Beware of malicious code! - * Execute and print output: "$> command $>" Beware of malicious code! + * Execute shell: "` command -switch `!" Beware of malicious code! + * Execute and print output: "` command `>" Beware of malicious code! Keyboard shortcuts: '''+get_interactive_help_text() @@ -282,7 +215,7 @@ Keyboard shortcuts: parser.add_argument("--dc",action="store_true",dest="dark_colors",default=False, help="Use dark colorscheme, better for white background terminals.") parser.add_argument("-e",action="store_true",dest="execute",default=False, - help="Execute commands in $! or $> tags at show time with Enter key. WARNING: Potentially very dangerous to run others' slides with this switch!") + help="Execute commands in `! or `> tags at show time with Enter key. WARNING: Potentially very dangerous to run others' slides with this switch!") parser.add_argument("-E",action="store_true",dest="execute_read",default=False, help="Execute commands in $> tags at file read time. WARNING: Potentially very dangerous to run others' slides with this switch!") parser.add_argument("-m",action="store_true",dest="autocolor",default=False, @@ -324,23 +257,28 @@ def page_print(reader,opts,offset): print(colorify(coloring+page[0],opts)) # Print page rows + parsed=md_color.parse(page) + colored=md_color.colorize(parsed,not opts.color,opts.dark_colors) r=0 - for row in page[1+offset[0]:]: + for row_i in range(len(page)): + if row_i==0: continue + if row_i=scrsize[0]-2: break r+=row_lines+1 sys.stdout.write("\n") - return def menu_print(reader,opts): @@ -466,46 +404,9 @@ def colorify(s,opts): """ Add colors to string """ if not opts.color: return bc.nocolor_string(s) - if opts.autocolor and not s.startswith("${"): - rules=["(^\s*\*.*)", # * bullets - "(^\s*[0-9]+\..*)", # 1. ordered - "(^#.*)", ## Header - "(^\s\s\s\s[^\*0-9\s].*)", # code block - "(\`[^\s]*[^\`]+\`)", # code inline - "(\$[>!].*\$[>!])", # code tags - "(\[[^]]+\]\([^\)]+\))", # [link](url) - "(\*{1,2}[^\s]*[^\*\s]+\*{1,2})", # *bold* - "(_[^\s]*[^_\s]+_)", # _bold_ - "(<[^>]+>)"] # - if opts.dark_colors: - colors=["${r}\\1", # * bullets - "${r}\\1", # 1. ordered - "${U}${b}\\1", ## Header - "${m}\\1", # code block - "${m}\\1${Z}", # code inline - "${m}\\1${Z}", # code tags - "${B}${U}\\1${Z}", # [link](url) - "${W}\\1${Z}", # *bold* - "${W}\\1${Z}", # _bold_ - "${K}\\1${Z}"] # - else: - colors=["${y}\\1", # * bullets - "${y}\\1", # 1. ordered - "${U}${Y}\\1", ## Header - "${c}\\1", # code block - "${c}\\1${Z}", # code inline - "${c}\\1${Z}", # code tags - "${B}${U}\\1${Z}", # [link](url) - "${W}\\1${Z}", # *bold* - "${W}\\1${Z}", # _bold_ - "${K}\\1${Z}"] # - for r in zip(rules,colors): - s=re.sub(r[0],r[1],s) - # Replace executable commands with $ only in the beginning - s=re.sub("\$[>!]","$",s,1) - s=re.sub("\$[>!]","",s) c=bc.color_string(s)+bc.Z return c + def cut_line(s,i): """ cut a color tagged string, and remove control chars """ s=s[:i] @@ -533,11 +434,11 @@ def launch(reader,opts,offset): s=reader.get_current_page()[offset[1]] urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', s) images = re.findall('!\[[^]]+\]\([^\)]+\)', s) - if s.find("$!")==-1 and s.find("$>")==-1 and len(urls)==0 and len(images)==0: + if s.find("`")==-1 and len(urls)==0 and len(images)==0: return - run_command=re.match("(.*)\$!(.*)\$!(.*)",s) - show_command=re.match("(.*)\$>(.*)\$>(.*)",s) + run_command=re.match("(.*)`(.*)`!(.*)",s) + show_command=re.match("(.*)`(.*)`>(.*)",s) if show_command != None: output = subprocess.check_output(show_command.group(2).strip(),shell=True).split("\n") while len(output[0].strip())==0: @@ -571,7 +472,7 @@ def launch(reader,opts,offset): shell=True) return return -bc=bc() +bc=ansi.code() getch=getch() opts=setup_options() browser(opts,opts.filename) diff --git a/reporting/md-color.py b/reporting/md-color.py deleted file mode 100755 index 9317391..0000000 --- a/reporting/md-color.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python - -import sys,os,re -from argparse import ArgumentParser -sys.path.append(os.path.dirname(os.path.realpath(__file__))) -import bc - -__author__ = "Ville Rantanen " -__version__ = "0.1" - -''' Rules modified from mistune project ''' - -def setup_options(): - ''' Create command line options ''' - usage=''' -Color notation renderer in ANSI codes -Special syntaxes: - * Colors: insert string ${C}, where C is one of KRGBYMCWkrgbymcwSUZ - -''' - - parser=ArgumentParser(description=usage, - epilog=__author__) - - parser.add_argument("-v","--version",action="version",version=__version__) - parser.add_argument("-D",action="store_true",dest="debug",default=False, - help="Debug mode") - parser.add_argument("--no-color","-n",action="store_false",dest="color",default=True, - help="Disable color.") - parser.add_argument("-z",action="store_true",dest="zero",default=False, - help="Reset coloring at the end of each line.") - parser.add_argument("filename",type=str, - help="File to show, - for stdin") - opts=parser.parse_args() - return opts - -block_match={ - 'block_code': (re.compile(r'^( {4}[^*])(.*)$'),'${c}\\1\\2','${Z}${c}'), - 'multiline_code' : (re.compile(r'^ *(`{3,}|~{3,}) *(\S*)'),'${c}\\1\\2','${Z}${c}'), # ```lang - 'block_quote': (re.compile(r'^(>[ >]* )'),'${K}\\1${Z}','${Z}'), - - 'hrule': (re.compile(r'^ {0,3}[-*_]([-*_]){2,}$'),False,'${Z}'), - 'heading' : (re.compile(r'^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)'),'${W}\\1 ${U}\\2','${W}${U}'), - 'lheading' : (re.compile(r'^(=+|-+)$'),'${W}\\1','${W}',(-1,re.compile(r'^([^\n]+)'),'${W}\\1')), - 'list_bullet':(re.compile(r'^( *)([*+-]|[\d\.]+)( +)'),'\\1${y}\\2${Z}\\3','${Z}'), - 'list_loose': (None,False,'${Z}'), - 'text': (re.compile(r'^[^\n]+'),False,'${Z}'), - 'empty': (re.compile(r'^$'),False,'${Z}'), -} -blocks=['block_quote', 'multiline_code','hrule', 'heading','lheading','list_bullet', 'block_code', 'text', 'empty'] - -inline_match={ - 'bold1': (re.compile(r'(^| )(_[^_]+_)'), '${W}\\1\\2'), # _bold_ - 'bold2': (re.compile(r'(^| )(\*{1,2}[^\*]+\*{1,2})'), '${W}\\1\\2'), # **bold** - 'code': (re.compile(r'([`]+[^`]+[`]+)'),'${c}\\1'), # `code` - 'link': (re.compile(r'(\[[^\]]+\]\([^\)]+\))'),'${B}${U}\\1'), # [text](link) - 'image': (re.compile(r'(!\[[^\]]+\]\([^\)]+\))'),'${r}\\1'), # ![text](image) - 'underline': (re.compile(r'(^|\W)(__)([^_]+)(__)'), '\\1\\2${U}\\3${Z}\\4'), # __underline__ - 'strikethrough': (re.compile(r'(~~)([^~]+)(~~)'),'\\1${st}\\2${so}\\3'), # ~~strike~~ -} -inlines=['bold1','bold2','code','image','link','underline','strikethrough'] - - -bc=bc.ansi() -opts=setup_options() -if opts.filename=="-": - f=sys.stdin -else: - f=open(opts.filename,'r') -data=[] -# Read data -for row in f: - if not row: - continue - row=row.decode('utf-8').rstrip("\n\r ") - data.append([None,row]) - -block='text' -new_block='text' -multiline_block=False -# Parse styles -for i,line in enumerate(data): - row=line[1] - if line[0] is not None: - # Previous lines have set the style already - continue - for match in blocks: - if block_match[match][0].match(row): - new_block=match - if match.startswith('multiline'): - if multiline_block: - multiline_block=False - else: - multiline_block=match - break - if multiline_block: - new_block=multiline_block - # Lists must end with empty line - if new_block not in ('empty','list_bullet') and block.startswith('list_'): - new_block='list_loose' - - if len(block_match[match])>3: - # Style sets block in previous or next lines - data[i+block_match[match][3][0]][0]=new_block - data[i+block_match[match][3][0]][1]=block_match[match][3][1].sub( - block_match[match][3][2], data[i+block_match[match][3][0]][1]) - data[i][0]=new_block - if new_block!=block: - block=new_block - -# Start inserting colors, and printing -for i,line in enumerate(data): - row=line[1] - block=line[0] - multiline_block=block.startswith('multiline') - if not multiline_block: - sys.stdout.write(bc.Z) - #print(multiline_block) - if block_match[block][1]: - row=block_match[block][0].sub(block_match[block][1],row) - if not (multiline_block or match=='block_code'): - for match in inlines: - if inline_match[match][0].search(row): - row=inline_match[match][0].sub(inline_match[match][1]+block_match[block][2],row) - if opts.color: - colored=bc.color_string(row) - else: - colored=bc.nocolor_string(row) - if opts.debug: - multistr="*" if multiline_block else " " - colored="{:<18}{:}:".format(data[i][0],multistr)+colored - sys.stdout.write(colored.encode('utf-8')) - if opts.zero: - sys.stdout.write(bc.Z) - sys.stdout.write("\n") - - diff --git a/reporting/md_color.py b/reporting/md_color.py new file mode 100755 index 0000000..b01af96 --- /dev/null +++ b/reporting/md_color.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python + +import sys,os,re +from argparse import ArgumentParser +sys.path.append(os.path.dirname(os.path.realpath(__file__))) +import ansi + +__author__ = "Ville Rantanen " +__version__ = "0.2" + +''' Rules modified from mistune project ''' + +def setup_options(): + ''' Create command line options ''' + usage=''' +Markdown syntax color in ansi codes. +Special syntaxes: + * Colors: insert string ${C}, where C is one of KRGBYMCWkrgbymcwSUZ + * Any ANSI control code: ${3A}, ${1;34;42m}, etc.. + +''' + + parser=ArgumentParser(description=usage, + epilog=__author__) + + parser.add_argument("-v","--version",action="version",version=__version__) + parser.add_argument("-D",action="store_true",dest="debug",default=False, + help="Debug mode") + parser.add_argument("--dc",action="store_true",dest="dark_colors",default=False, + help="Use dark colorscheme, better for white background terminals.") + parser.add_argument("--no-color","-n",action="store_false",dest="color",default=True, + help="Disable color.") + parser.add_argument("-z",action="store_true",dest="zero",default=False, + help="Reset coloring at the end of each line.") + parser.add_argument("filename",type=str, + help="File to show, - for stdin") + opts=parser.parse_args() + return opts + +def parse(data): + data=[[None,row] for row in data] + block='text' + new_block='text' + multiline_block=False + # Parse styles + for i,line in enumerate(data): + row=line[1] + if line[0] is not None: + # Previous lines have set the style already + continue + for match in blocks: + if block_match[match]['re'].match(row): + new_block=match + if match.startswith('multiline'): + if multiline_block: + multiline_block=False + else: + multiline_block=match + break + if multiline_block: + new_block=multiline_block + # Lists must end with empty line + if new_block not in ('empty','list_bullet') and block.startswith('list_'): + new_block='list_loose' + + if 'mod' in block_match[match]: + # Style sets block in previous or next lines + data[i+block_match[match]['mod']['pos']][0]=block_match[match]['mod']['name'] + data[i][0]=new_block + if new_block!=block: + block=new_block + return data + +def colorize(data,remove_colors=False,dark_colors=False,debug=False): + # Start inserting colors, and printing + bc=ansi.code() + colorized=[] + cs='dc' if dark_colors else 'bc' + csc=cs+'c' + for i,line in enumerate(data): + row=line[1] + block=line[0] + multiline_block=block.startswith('multiline') + if multiline_block: + row=block_match[block][csc]+row + if block_match[block][cs]: + row=block_match[block]['re'].sub(block_match[block][cs],row) + # No coloring inside block_code, nor multiline + if not (multiline_block or block=='block_code'): + for match in inlines: + if inline_match[match]['re'].search(row): + row=inline_match[match]['re'].sub(inline_match[match][cs]+block_match[block][csc],row) + if remove_colors: + colored=bc.nocolor_string(row) + else: + colored=bc.color_string(row) + if debug: + multistr="*" if multiline_block else " " + colored="{:<18}{:}:".format(data[i][0],multistr)+colored + colorized.append(colored) + return colorized + +# re: regular expression, bc: subract value bright colors, bcc: continue with this color after inline +block_match={ + 'block_code': {'re':re.compile(r'^( {4}[^*])(.*)$'), + 'bc' :'${Z}${c}\\1\\2', 'bcc':'${Z}${c}', + 'dc' :'${Z}${m}\\1\\2', 'dcc':'${Z}${m}'}, # code + 'multiline_code' : {'re':re.compile(r'^ *(`{3,}|~{3,}) *(\S*)'), + 'bc' :'${Z}${c}\\1\\2', 'bcc':'${Z}${c}', + 'dc' :'${Z}${m}\\1\\2', 'dcc':'${Z}${m}'}, # ```lang + 'block_quote': {'re':re.compile(r'^(>[ >]* )'), + 'bc':'${K}\\1${Z}','bcc':'${Z}', + 'dc':'${Y}\\1${Z}','dcc':'${Z}'}, # > > quote + 'hrule': {'re':re.compile(r'^ {0,3}[-*_]([-*_]){2,}$'), + 'bc':False,'bcc':'${Z}', + 'dc':False,'dcc':'${Z}'}, # ---- + 'heading' : {'re':re.compile(r'^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)'), + 'bc':'${W}\\1 ${U}\\2','bcc':'${W}${U}', + 'dc':'${B}\\1 ${U}\\2','dcc':'${B}${U}'}, # # heading + 'lheading' : {'re':re.compile(r'^(=+|-+)$'), + 'bc':'${W}\\1', 'bcc':'${W}', + 'dc':'${B}\\1', 'dcc':'${B}', + 'mod':{'pos':-1,'name':'lheading.mod'}}, # ======= under header + 'lheading.mod' : {'re':re.compile(r'^([^\n]+)'), + 'bc':'${W}\\1', 'bcc':'${W}', + 'dc':'${B}\\1', 'dcc':'${B}'}, # over the ======= under header + 'list_bullet': {'re':re.compile(r'^( *)([*+-]|[\d\.]+)( +)'), + 'bc':'\\1${y}\\2${Z}\\3','bcc':'${Z}', + 'dc':'\\1${r}\\2${Z}\\3','dcc':'${Z}'}, # * or 1. + 'list_loose': {'re':None, + 'bc':False,'bcc':'${Z}', + 'dc':False,'dcc':'${Z}'}, + 'text': {'re':re.compile(r'^([^\n]+)'), + 'bc':'${Z}\\1','bcc':'${Z}', + 'dc':'${Z}\\1','dcc':'${Z}'}, + 'empty': {'re':re.compile(r'(^$)'), + 'bc':'${Z}\\1','bcc':'${Z}', + 'dc':'${Z}\\1','dcc':'${Z}'}, +} +blocks=['block_quote', 'multiline_code','hrule', 'heading','lheading','list_bullet', 'block_code', 'text', 'empty'] + +inline_match={ + 'bold1': {'re':re.compile(r'(^| )(_[^_]+_)'), + 'bc':'${W}\\1\\2','dc':'${W}\\1\\2'}, # _bold_ + 'bold2': {'re':re.compile(r'(^| )(\*{1,2}[^\*]+\*{1,2})'), + 'bc':'${W}\\1\\2','dc':'${W}\\1\\2'}, # **bold** + 'code': {'re':re.compile(r'([`]+[^`]+[`]+)'), + 'bc':'${c}\\1','dc':'${m}\\1'}, # `code` + 'code_special': {'re':re.compile(r'([`]+[^`]+[`]+)([!>])'), + 'bc':'${c}\\1${g}\\2','dc':'${m}\\1${r}\\2'}, # `code`! or `code`> for markslider + 'link': {'re':re.compile(r'(\[)([^\]]+)(\])(\([^\)]+\))'), + 'bc':'${b}\\1${Z}\\2${b}\\3${U}\\4', + 'dc':'${b}\\1${Z}\\2${b}\\3${U}\\4'}, # [text](link) + 'image': {'re':re.compile(r'(!\[[^\]]+\]\([^\)]+\))'), + 'bc':'${r}\\1','dc':'${g}\\1'}, # ![text](image) + 'underline': {'re':re.compile(r'(^|\W)(__)([^_]+)(__)'), + 'bc':'\\1\\2${U}\\3${Z}\\4','dc':'\\1\\2${U}\\3${Z}\\4'}, # __underline__ + 'strikethrough': {'re':re.compile(r'(~~)([^~]+)(~~)'), + 'bc':'\\1${st}\\2${so}\\3','dc':'\\1${st}\\2${so}\\3'}, # ~~strike~~ +} +inlines=['bold1','bold2','code_special','code','image','link','underline','strikethrough'] + +if __name__ == "__main__": + opts=setup_options() + if opts.filename=="-": + f=sys.stdin + else: + f=open(opts.filename,'r') + data=[] + # Read data + for row in f: + if not row: + continue + row=row.decode('utf-8').rstrip("\n\r ") + data.append(row) + + data=parse(data) + colored=colorize(data,not opts.color,opts.dark_colors,opts.debug) + for c in colored: + sys.stdout.write(c.encode('utf-8')) + if opts.zero: + sys.stdout.write(bc.Z) + sys.stdout.write("\n") + + diff --git a/reporting/srcframes2ans b/reporting/srcframes2ans new file mode 100755 index 0000000..0857f38 --- /dev/null +++ b/reporting/srcframes2ans @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright 2016 Ville Rantanen +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# + +'''Color by notation.''' + +__author__ = "Ville Rantanen " +__version__ = "0.2" + +NEWCHAR="====CHAR" +NEWCOLOR="====COLOR" +NEWIMAGE="====EOI" +ENDOFFILE="====EOF" +PAUSE="====PAUSE" + +import sys,os,argparse,re,time +from argparse import ArgumentParser +class bc: + K="\033[1;30m" + R="\033[1;31m" + G="\033[1;32m" + Y="\033[1;33m" + B="\033[1;34m" + M="\033[1;35m" + C="\033[1;36m" + W="\033[1;37m" + + k="\033[0;30m" + r="\033[0;31m" + g="\033[0;32m" + y="\033[0;33m" + b="\033[0;34m" + m="\033[0;35m" + c="\033[0;36m" + w="\033[0;37m" + + nk="\033[30m" + nr="\033[31m" + ng="\033[32m" + ny="\033[33m" + nb="\033[34m" + nm="\033[35m" + nc="\033[36m" + nw="\033[37m" + + bk="\033[40m" + br="\033[41m" + bg="\033[42m" + by="\033[43m" + bb="\033[44m" + bm="\033[45m" + bc="\033[46m" + bw="\033[47m" + + S = '\033[1m' + U = '\033[4m' + Z = '\033[0m' + CLR = '\033[2J' + CLREND = '\033[K' + CLRSCR = CLR+"\033[0;0H" + + color_keys="PQWERTYU01234567XCZV;asdfghj)!@#$%^&" + color_list=[K, R, G, Y, B, M, C, W, k, r, g, y, b, m, c, w, + S,CLRSCR,Z,U,bk,br,bg,by,bb,bm,bc,bw,nk,nr,ng,ny,nb,nm,nc,nw ] + + def pos(self,y,x): + return "\033["+str(y)+";"+str(x)+"H" + + def posprint(self, y,x,s): + sys.stdout.write( (self.pos(y,x) + str(s)).encode('utf-8') ) + + def clear(self): + sys.stdout.write( (self.CLR+self.pos(0,0)).encode('utf-8') ) + def clear_to_end(self): + sys.stdout.write( self.CLREND.encode('utf-8') ) + + def color_char(self,s): + for i,c in enumerate(self.color_keys): + if c in s: + s=s.replace(c,self.color_list[i]) + return s + return "" + def nocolor_string(self,s): + return "" + + + + +def setup_options(): + ''' Create command line options ''' + usage=''' +Color notation renderer in ANSI codes +Special syntaxes: + * Colors: insert string ${C}, where C is one of KRGBYMCWkrgbymcwSUZ + +''' + + parser=ArgumentParser(description=usage, + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__author__) + + parser.add_argument("-v","--version",action="version",version=__version__) + parser.add_argument("--no-color","-n",action="store_false",dest="color",default=True, + help="Disable color.") + parser.add_argument("-z",action="store_true",dest="zero",default=False, + help="Reset coloring at the end of each line.") + parser.add_argument("-c",action="store_true",dest="clear",default=False, + help="Clear screen first") + parser.add_argument("filename",type=str, + help="File to show") + opts=parser.parse_args() + return opts + +bc=bc() +opts=setup_options() +if opts.filename=='-': + f=sys.stdin +else: + f=open(opts.filename,'r') + +if opts.clear: + bc.clear() +while True: + pause=0 + gray=[] + gray.append([]) + colors=[] + colorFrame=0 + grayFrame=0 + maxRow=0 + for row in f: + if not row: + sys.exit(0) + row=row.decode('utf-8').rstrip("\n\r") + if row.startswith(NEWIMAGE): + break + if row.startswith(PAUSE): + try: + new_value=row[len(PAUSE):].strip() + pause=float(new_value) + except: + pause=0 + continue + if row.startswith(NEWCOLOR): + colorFrame+=1 + colors.append([]) + continue + if colorFrame==0: + if row.startswith(NEWCHAR): + grayFrame+=1 + gray.append([]) + continue + gray[grayFrame].append(row) + maxRow=max(maxRow, len(row)) + else: + colors[colorFrame-1].append(row) + if len(gray[0])==0: + sys.exit(0) + for i in range(len(gray[0])): + while maxRow>len(gray[0][i]): + gray[0][i]=gray[0][i]+" " + + for i in range(len(gray[0])): + for frame in colors: + if len(frame)len(frame[i]): + frame[i]=frame[i]+" " + if len(gray)>1: + for layer in gray[1:]: + if len(layer)len(layer[i]): + layer[i]=layer[i]+" " + + + for i in range(len(gray[0])): + for c in range(len(gray[0][i])): + if opts.color: + for frame in colors: + try: + if frame[i][c]!=" ": + sys.stdout.write(bc.color_char(frame[i][c]).encode('utf-8')) + except IndexError: + pass + char=" " + for layer in gray: + if layer[i][c]==" ": continue + char=layer[i][c] + + sys.stdout.write(char.encode('utf-8')) + if opts.color and opts.zero: + sys.stdout.write(bc.Z.encode('utf-8')) + sys.stdout.write("\n") + if pause>0: + time.sleep(pause) +