diff --git a/reporting/markslider.packager.sh b/reporting/markslider.packager.sh new file mode 100644 index 0000000..b3fcaea --- /dev/null +++ b/reporting/markslider.packager.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +set -e +set -x + +rm -rf markslider +mkdir -p markslider/scripts markslider/markslider +cp -v ansi.py md_color.py markslider.py markslider/markslider/ + +echo '#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +import re +import sys + +from markslider import main + +if __name__ == "__main__": + sys.exit(main()) +' > markslider/scripts/markslider + +echo 'from markslider import *' > markslider/markslider/__init__.py + +echo 'Markdown slideshow. Display your markdown file directly in the terminal!' > markslider/README.md +echo '[metadata] +description-file = README.md' > markslider/setup.cfg + +echo "from distutils.core import setup +setup( + name = 'markslider', + packages = ['markslider'], + scripts = ['scripts/markslider'], + version = '$( ./markslider.py -v 2>&1 )', + description = 'Markdown viewer as slides', + author = 'Ville Rantanen', + author_email = 'ville.q.rantanen@gmail.com', + url = 'https://bitbucket.org/MoonQ/tools', + download_url = 'https://bitbucket.org/MoonQ/tools/raw/tip/reporting/markslider.tar.gz', + keywords = ['markdown', 'console'], + classifiers = [], + license = 'MIT', +)" > markslider/setup.py + +tar czf markslider.tar.gz markslider +rm -rf markslider + diff --git a/reporting/markslider.py b/reporting/markslider.py index c71b032..949a608 100755 --- a/reporting/markslider.py +++ b/reporting/markslider.py @@ -23,7 +23,7 @@ __author__ = "Ville Rantanen " __version__ = "0.9" import sys,os,argparse,re,datetime -from argparse import ArgumentParser +from argparse import ArgumentParser import traceback,tty,termios,subprocess,signal sys.path.append(os.path.dirname(os.path.realpath(__file__))) import ansi,md_color @@ -48,7 +48,7 @@ class EndProgram( Exception ): pass class slide_reader: - """ Class for reading files. """ + """ Class for reading files. """ def __init__(self,files,opts): self.filename=files[0] self.files=files @@ -65,9 +65,9 @@ class slide_reader: self.re_image_convert=re.compile("(.*)(!\[.*\])\((.*)\)>") self.re_command=re.compile("(.*)`(.*)`>(.*)") #~ self.control_chars = ''.join(map(unichr, range(0,32) + range(127,160))) - #~ self.control_char_re = re.compile('[%s]' % re.escape(self.control_chars)) + #~ self.control_char_re = re.compile('[%s]' % re.escape(self.control_chars)) self.read() - + def read(self): ''' Read a file, set pages and data ''' @@ -111,7 +111,7 @@ class slide_reader: self.max_height=max(self.max_height, len(page)) for row in page: self.max_width=max(self.max_width, len(row)) - + def get_data(self): return self.data def get_current_filename(self): @@ -127,13 +127,13 @@ class slide_reader: return self.data[page] except IndexError: return None - + def get_pages(self): return self.pages def get_current_page(self): return self.data[self.page] - + def get_page_no(self): return self.page def inc_page_no(self,inc=1,loop=False): @@ -160,7 +160,7 @@ class slide_reader: return self.max_height def get_max_width(self): return self.max_width - + def get_toc(self,display_position=False): title=self.opts.toc if self.opts.toc else "Table of Contents" TOC=["# "+title,""] @@ -186,7 +186,7 @@ class slide_reader: subh=[ subh[0], subh[1], subh[2]+1 ] TOC.append(" %d.%d.%d.%d. %s"%(h1+1,subh[0],subh[1],subh[2],title)) return TOC - + def toc(self): if self.opts.toc: TOC=self.get_toc() @@ -207,7 +207,7 @@ class slide_reader: return [s] def launch(self,command): - """ 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: @@ -230,7 +230,7 @@ class slide_reader: # return [s] def convert_image(self,image): - """ comnvert image using tags ![]()> + """ comnvert image using tags ![]()> Remove empty lines from beginning and end of stdout. """ #~ 2=title @@ -248,9 +248,9 @@ class slide_reader: 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 c list contents (toc) M modify file with VIM @@ -261,7 +261,7 @@ def get_interactive_help_text(): ,/. scroll page up/down move highlight enter execute highlighted line - h help''' + h help''' def setup_options(): ''' Create command line options ''' @@ -274,21 +274,21 @@ Special syntaxes: * Execute shell: ` command -switch `! Beware of malicious code! * Execute and print output: ` command `> Beware of malicious code! * Convert images to ASCII, with jp2a: ![](file.jpg) - + 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__) parser.add_argument("--export",action="store",dest="screenshots",default=False, type=str, help="Take screenshots of the slideshow in the given folder.") - + content = parser.add_argument_group('content') execution = parser.add_argument_group('execution') control = parser.add_argument_group('controls') - + content.add_argument("--center",action="store_true",dest="center",default=False, help="Center slides on screen.") content.add_argument("--dc",action="store_true",dest="dark_colors",default=False, @@ -297,15 +297,15 @@ Keyboard shortcuts: help="Disable color by markdown structure.") content.add_argument("--no-color","-n",action="store_false",dest="color",default=True, help="Disable color.") - + execution.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!") execution.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!") - + control.add_argument("--exit",action="store_true",dest="exit_last",default=False, help="Exit after last slide.") - + control.add_argument("-s",action="store_false",dest="menu",default=True, help="Disable status bar.") control.add_argument("--timer",action="store",dest="slideTimer",default=False, type=int, @@ -315,10 +315,10 @@ Keyboard shortcuts: content.add_argument("--toc",action="store",dest="toc",default=False, const="Table of Contents", type=str, nargs='?', help="Insert table of contents. Define the header, or use default: %(const)s") - content.add_argument("--toc-page",action="store",dest="toc_page",default=2, type=int, + content.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") - content.add_argument("--toc-depth",action="store",dest="toc_depth",default=2, type=int, - choices=xrange(1,5), + content.add_argument("--toc-depth",action="store",dest="toc_depth",default=2, type=int, + choices=list(range(1,5)), help="Table of contents display depth. default: %(const)s") parser.add_argument("files",type=str, nargs='+', help="File(s) to show") @@ -332,7 +332,7 @@ Keyboard shortcuts: def page_print(reader,opts,offset): ''' Print a page ''' - + page=reader.get_current_page() scrsize=opts.size # clear page @@ -351,7 +351,7 @@ def page_print(reader,opts,offset): else: coloring="${U}${Y}" print(align_pad+colorify(coloring+page[0],opts)+bc.Z) - + # Print page rows if not opts.wrap: page=[cut_line(row,scrsize[1]-1) for row in page] @@ -373,12 +373,12 @@ def page_print(reader,opts,offset): row_lines=int(float(len(row))/scrsize[1]) else: row_lines=0 - row_lines=0 + row_lines=0 colored_row=colored[row_i]#=colorify(row,opts) if offset[1]==r+1+offset[0]: colored_row=add_highlight(row,opts) sys.stdout.write(align_pad+colored_row) - + if r>=scrsize[0]-2: break r+=row_lines+1 @@ -387,8 +387,8 @@ def page_print(reader,opts,offset): return def print_menu(reader,opts): - - bc.posprint( opts.size[0], 0, + + bc.posprint( opts.size[0], 0, colorify("${y}%d${Z}/%d %s|%s"%( 1+reader.get_page_no(), reader.get_pages(), @@ -459,7 +459,7 @@ def browser(opts,files): try: reader=slide_reader(files,opts) except: - print "Error in reading the file:" + print("Error in reading the file:") for o in sys.exc_info(): print(o) sys.exit(1) @@ -499,7 +499,7 @@ def browser(opts,files): #~ print(inkey) if inkey in [113,3,120]: #print('Exited in: ') - return + return if inkey in [67,54,32]: # PGDN or space if opts.exit_last: if reader.page+1==reader.pages: @@ -527,7 +527,7 @@ def browser(opts,files): reader.read() offset=offset_change(opts,reader,offset,(0, 0)) if inkey==ord('M'): - modify_file(reader,offset) + modify_file(reader,offset) reader.read() offset=offset_change(opts,reader,offset,(0, 0)) if inkey==ord(','): @@ -541,8 +541,8 @@ def browser(opts,files): if inkey==13: # enter launch(reader,opts,offset) break - - + + except IOError: pass except KeyboardInterrupt: @@ -550,8 +550,8 @@ def browser(opts,files): except EndProgram: pass except: - print "Unexpected error:" - print traceback.format_exc() + print("Unexpected error:") + print(traceback.format_exc()) sys.exit(1) def get_console_size(): @@ -568,9 +568,9 @@ def colorify(s,opts): def cut_line(s,i): """ cut a color tagged string, and remove control chars """ s=s[:i] - s=re.sub("\$$","", - re.sub("\$\{$","", - re.sub("\$\{.$","", + s=re.sub("\$$","", + re.sub("\$\{$","", + re.sub("\$\{.$","", s))) return s def add_highlight(s,opts): @@ -596,7 +596,7 @@ def launch(reader,opts,offset): images = re.findall('!\[[^]]+\]\([^\)]+\)', s) if s.find("`")==-1 and len(urls)==0 and len(images)==0: return - + run_command=re.match("(.*)`(.*)`!(.*)",s) show_command=re.match("(.*)`(.*)`>(.*)",s) if show_command != None: @@ -614,24 +614,24 @@ def launch(reader,opts,offset): inkey=getch.get() return if run_command != None: - subprocess.call(run_command.group(2), + subprocess.call(run_command.group(2), shell=True,executable="/bin/bash") inkey=getch.get() return # Open URLS last if len(urls)>0: # Remove ) at the end of url: [name](link) markdown syntax - subprocess.call("xdg-open '%s' &"%(urls[0].rstrip(")"),), + subprocess.call("xdg-open '%s' &"%(urls[0].rstrip(")"),), stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) return if len(images)>0: image = re.sub('.*\(([^\)]+)\).*', "\\1",images[0]) - subprocess.call("xdg-open '%s' &"%(image,), + subprocess.call("xdg-open '%s' &"%(image,), stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) return - return + return def modify_file(reader,offset): row=1 @@ -642,23 +642,33 @@ def modify_file(reader,offset): row+=len(reader.data[page]) if (page+1) in row_restarts: row=1 - subprocess.call("vim +%d -c 'exe \"normal! zt\"' -c %d %s"%(row,row+offset[1],reader.get_current_filename()), + subprocess.call("vim +%d -c 'exe \"normal! zt\"' -c %d %s"%(row,row+offset[1],reader.get_current_filename()), shell=True) - + def take_screenshot(reader,opts): out_file=os.path.join(opts.screenshots,"slide%03d.png"%(reader.page+1)) if not os.path.exists(opts.screenshots): os.mkdir(opts.screenshots) - subprocess.call("sleep 0.5; import -window $WINDOWID '%s'"%(out_file,), + subprocess.call("sleep 0.5; import -window $WINDOWID '%s'"%(out_file,), stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) -bc=ansi.code() -getch=getch() -opts=setup_options() -browser(opts,opts.files) -if opts.screenshots: - print("\n\nCrop the images for terminal tabs, and PDFize e.g.:\n- mogrify -chop 0x50 %s/*png\n- convert %s/*png %s.pdf"%( - opts.screenshots, - opts.screenshots, - os.path.basename(opts.screenshots), - )) + + +def main(): + global bc + global getch + global opts + bc = ansi.code() + getch = getch() + opts = setup_options() + + browser(opts,opts.files) + if opts.screenshots: + print("\n\nCrop the images for terminal tabs, and PDFize e.g.:\n- mogrify -chop 0x50 %s/*png\n- convert %s/*png %s.pdf"%( + opts.screenshots, + opts.screenshots, + os.path.basename(opts.screenshots), + )) + +if __name__ == "__main__": + main() diff --git a/reporting/markslider.tar.gz b/reporting/markslider.tar.gz new file mode 100644 index 0000000..a73ef92 Binary files /dev/null and b/reporting/markslider.tar.gz differ