markdown launch code

This commit is contained in:
ville rantanen
2015-06-22 15:03:58 +03:00
parent 70196411b2
commit 57f924d94c
2 changed files with 140 additions and 33 deletions

View File

@@ -27,10 +27,12 @@ Underline: $U
Usage: highbeam [-c] [-h] [-f config]
-c Be case sensitive
-D Print current rules, not the input
-h Help
-f Define config file (default ~/.highbeamrc)
-r Define rules with a string, replaces the other rules
-r '\''"land[^[:space:]]\+" "$G" "sky" "$B"'\''
'
}
@@ -72,7 +74,8 @@ U="${E}4m"
CONF_FILE=~/.highbeamrc
CONF_LINE=""
FLAGS="ig"
while getopts chf:r: opt
PRINT=0
while getopts chf:r:D opt
do case "$opt" in
c)
FLAGS="g"
@@ -87,6 +90,9 @@ do case "$opt" in
r)
CONF_LINE=( $( eval echo $OPTARG ) )
;;
D)
PRINT=1
;;
esac
done
@@ -118,9 +124,28 @@ done
rIndex=$(( $rIndex + 1 ))
done
}
[[ $PRINT -eq 1 ]] && {
echo "From $CONF_FILE:"
for (( rIndex=0; rIndex<${#RULES[@]}; rIndex++ ));
do printf "%s\\t%s" "${RULES[$rIndex]}" "${RULES[$(( $rIndex + 1 ))]}"
rIndex=$(( $rIndex + 1 ))
done
echo "From argument switches:"
for (( rIndex=0; rIndex<${#CONF_LINE[@]}; rIndex++ ));
do printf "%s\\t%s" "${CONF_LINE[$rIndex]}" "${CONF_LINE[$(( $rIndex + 1 ))]}"
rIndex=$(( $rIndex + 1 ))
done
echo "From HB_RULES environment:"
for (( rIndex=0; rIndex<${#CONF_ENV[@]}; rIndex++ ));
do printf "%s\\t%s" "${CONF_ENV[$rIndex]}" "${CONF_ENV[$(( $rIndex + 1 ))]}"
rIndex=$(( $rIndex + 1 ))
done
#~ echo ${CONF_ENV[@]}
#~ echo $HB_RULES
#~ echo $REGEX
exit
}
[[ -z "$REGEX" ]] && {
cat -
} || {

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python
# coding=utf-8
#
# Copyright 2015 Ville Rantanen
#
@@ -19,12 +20,14 @@
'''Markslider: a slideshow engine based on markdown.'''
__author__ = "Ville Rantanen <ville.q.rantanen@gmail.com>"
__version__ = "0.1"
__version__ = "0.6"
import sys,os,argparse,re
from argparse import ArgumentParser
import traceback,tty,termios
import traceback,tty,termios,subprocess
HL=">"
EOS="# End of Slides"
class bc:
K="\033[1;30m"
@@ -47,6 +50,7 @@ class bc:
U = '\033[4m'
Z = '\033[0m'
CLR = '\033[2J'
CLREND = '\033[K'
color_keys="KRGBYMCWkrgbymcwSUZ"
color_list=[K,R,G,B,Y,M,C,W,k,r,g,b,y,m,c,w,S,U,Z]
@@ -59,6 +63,8 @@ class bc:
def clear(self):
sys.stdout.write( self.CLR+self.pos(0,0) )
def clear_to_end(self):
sys.stdout.write( self.CLREND )
def color_string(self,s):
for i,c in enumerate(self.color_keys):
@@ -68,7 +74,6 @@ class bc:
for i,c in enumerate(self.color_keys):
s=s.replace("${"+c+"}","")
return s
class getch:
def get(self):
@@ -83,7 +88,7 @@ class getch:
class EndProgram( Exception ):
''' Nice way of exiting the program '''
''' Nice exit '''
pass
class slide_reader:
@@ -108,17 +113,27 @@ class slide_reader:
self.pages=0
self.data=[]
new_page=[]
first_slide_found=False
for row in f:
if not row:
continue
row=row.decode('utf-8').rstrip("\n\r ")
# find end of show
if row==EOS:
break
# find header to start a new page
if row.startswith("#") and not row.startswith("##"):
first_slide_found=True
if len(new_page)>0:
self.data.append(new_page)
new_page=[]
new_page.append(row)
# if first slide havent been found yet:
if not first_slide_found:
continue
new_page.extend(self.launch(row))
if len(new_page)>0:
self.data.append(new_page)
self.toc()
self.pages=len(self.data)
self.inc_page_no(0)
@@ -180,15 +195,36 @@ class slide_reader:
if self.opts.toc_depth==3: continue
if re.search("^####[^#]", line):
subh=[ subh[0], subh[1], subh[2]+1 ]
TOC.append(" %d.%d.%d.%d. %s"%(h1+1,subh[0],subh[1],subh[2],title))
TOC.append(" %d.%d.%d.%d. %s"%(h1+1,subh[0],subh[1],subh[2],title))
self.data.insert(self.opts.toc_page-1,TOC)
def launch(self,s):
""" 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:
return [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:
if len(output)==1: return [""]
del output[0]
while len(output[-1].strip())==0:
if len(output)==1: return [""]
del output[-1]
return_value=[command.group(1)]
return_value.extend(output)
return_value.append(command.group(3))
return return_value
return [s]
def get_interactive_help_text():
return ''' left/right,page up/down,home,end
return ''' left/right,page up/down,home,end
change page
m toggle page numbers
s toggle status bar
q exit browser
r reload the file
,/. scroll page
@@ -198,14 +234,20 @@ def get_interactive_help_text():
def setup_options():
''' Create command line options '''
usage='''
Interactive mode keymap:
MarkSlider: a markdown based slideshow engine
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!
Keyboard shortcuts:
'''+get_interactive_help_text()
parser=ArgumentParser(description=usage,
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__author__)
parser.add_argument("-v","--version",action="version",version=__version__)
@@ -219,8 +261,12 @@ def setup_options():
help="Disable status bar.")
parser.add_argument("-w",action="store_false",dest="wrap",default=True,
help="Disable line wrapping. Cuts long lines.")
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!")
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("--toc",action="store",dest="toc",default=False,
const="Table of contents", type=str, nargs='?',
const="Table of Contents", type=str, nargs='?',
help="Insert table of contents. Define the header, or use default: %(const)s")
parser.add_argument("--toc-page",action="store",dest="toc_page",default=2, type=int,
help="Insert table of contents on a chosen page. default: %(const)s")
@@ -232,7 +278,6 @@ def setup_options():
opts=parser.parse_args()
return opts
def page_print(reader,opts,offset):
''' Print a page '''
@@ -256,8 +301,8 @@ def page_print(reader,opts,offset):
else:
row_lines=int(float(len(row))/scrsize[1])
colored=colorify(row,opts)
if offset[1]==r+1:
colored=colorify("${Y}>"+bc.nocolor_string(row),opts)
if offset[1]==r+1+offset[0]:
colored=add_highlight(row,opts)
sys.stdout.write(colored)
if r>=scrsize[0]-2:
@@ -292,13 +337,8 @@ def offset_change(opts,reader,offset,new_offset):
''' Change the display position of page '''
new_offset=(offset[0]+new_offset[0], offset[1]+new_offset[1])
offsety=min(reader.get_page_height()-1,new_offset[0])
offsety=max(0,offsety)
if offsety==0 and new_offset[0]!=0:
return (offsety,offset[1])
offseth=min(opts.size[0]-1,new_offset[1])
offseth=min(reader.get_page_height(),offseth)
offseth=max(0,offseth)
return (offsety, offseth)
offseth=min(reader.get_page_height(),new_offset[1])
return [max(0,o) for o in (offsety,offseth)]
def browser(opts,filename):
''' Main function for printing '''
@@ -338,32 +378,30 @@ def browser(opts,filename):
offset=(0, 0)
if inkey==ord('h'):
print_help(reader,opts)
if inkey==ord('m'):
if inkey==ord('s'):
opts.menu=not opts.menu
if inkey==ord('r'):
reader.read()
offset=(0, 0)
offset=offset_change(opts,reader,offset,(0, 0))
if inkey==ord(','):
offset=offset_change(opts,reader,offset,(-1, 1))
offset=offset_change(opts,reader,offset,(-1, 0))
if inkey==ord('.'):
offset=offset_change(opts,reader,offset,(1, -1))
offset=offset_change(opts,reader,offset,(1, 0))
if inkey==65:
offset=offset_change(opts,reader,offset,(0, -1))
if inkey==66:
offset=offset_change(opts,reader,offset,(0, 1))
if inkey==13:
launch(reader,opts,offset)
break
#~ stdscr.refresh()
except IOError:
pass
except KeyboardInterrupt:
#~ reset_curses(stdscr)
sys.exit(0)
except EndProgram:
pass
except:
#~ reset_curses(stdscr)
print "Unexpected error:"
print traceback.format_exc()
sys.exit(1)
@@ -382,6 +420,7 @@ def colorify(s,opts):
"(^#.*)", ## 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_
@@ -392,6 +431,7 @@ def colorify(s,opts):
"${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_
@@ -402,6 +442,7 @@ def colorify(s,opts):
"${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_
@@ -419,7 +460,48 @@ def cut_line(s,i):
re.sub("\$\{.$","",
s)))
return s
def add_highlight(s,opts):
if len(s.strip())==0:
cleaned=HL
else:
cleaned=bc.nocolor_string(s)
tagged="${Y}"+cleaned
return colorify(tagged,opts)
def launch(reader,opts,offset):
""" Launch in a string using tags $!command$!
Used with highlight
Remove empty lines from beginning and end of stdout.
"""
if not opts.execute:
return
s=reader.get_current_page()[offset[1]]
if s.find("$!")+s.find("$>")==-2:
return
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:
if len(output)==1: return [""]
del output[0]
while len(output[-1].strip())==0:
if len(output)==1: return [""]
del output[-1]
for y,l in enumerate(output):
bc.posprint(y+offset[1]-offset[0]+2,0,l)
bc.clear_to_end()
inkey=getch.get()
return
if run_command != None:
subprocess.call(run_command.group(2),
#~ stdout=subprocess.PIPE,
#~ stderr=subprocess.PIPE,
shell=True,executable="/bin/bash")
inkey=getch.get()
return
return
bc=bc()
getch=getch()
opts=setup_options()