#!/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")