diff options
Diffstat (limited to 'pygments/cmdline.py')
-rw-r--r-- | pygments/cmdline.py | 225 |
1 files changed, 166 insertions, 59 deletions
diff --git a/pygments/cmdline.py b/pygments/cmdline.py index b782dc97..53f47206 100644 --- a/pygments/cmdline.py +++ b/pygments/cmdline.py @@ -10,18 +10,26 @@ """ import sys import getopt +from textwrap import dedent from pygments import __version__, __author__, highlight -from pygments.lexers import LEXERS, get_lexer_by_name, get_lexer_for_filename -from pygments.util import OptionError -from pygments.formatters import FORMATTERS, get_formatter_by_name, \ - get_formatter_for_filename, TerminalFormatter +from pygments.util import ClassNotFound, OptionError, docstring_headline +from pygments.lexers import get_all_lexers, get_lexer_by_name, get_lexer_for_filename, \ + find_lexer_class +from pygments.formatters import get_all_formatters, get_formatter_by_name, \ + get_formatter_for_filename, TerminalFormatter, find_formatter_class +from pygments.filters import get_all_filters, find_filter_class +from pygments.styles import get_all_styles, get_style_by_name USAGE = """\ -Usage: %s [-l <lexer>] [-f <formatter>] [-O <options>] [-o <outfile>] [<infile>] +Usage: %s [-l <lexer>] [-F <filter>[:<options]] [-f <formatter>] + [-O <options>] [-o <outfile>] [<infile>] + %s -S <style> -f <formatter> [-a <arg>] [-O <options>] - %s -L | -h | -V + %s -L [<which> ...] + %s -H <type> <name> + %s -h | -V Highlight the input file and write the result to <outfile>. @@ -38,77 +46,151 @@ the terminal formatter will be used by default. With the -O option, you can give the lexer and formatter a comma- separated list of options, e.g. ``-O bg=light,python=cool``. +With the -F option, you can add filters to the token stream, you can +give options in the same way as for -O after a colon (note: there must +not be spaces around the colon). + +The -O and -F options can be given multiple times. + With the -S option, print out style definitions for style <style> for formatter <formatter>. The argument given by -a is formatter dependent. -The -L option lists all available lexers and formatters. +The -L option lists lexers, formatters, styles or filters -- set +`which` to the thing you want to list (e.g. "styles"), or omit it to +list everything. + +The -H option prints detailed help for the object <name> of type <type>, +where <type> is one of "lexer", "formatter" or "filter". + The -h option prints this help. The -V option prints the package version. """ -def _parse_options(o_str): +def _parse_options(o_strs): opts = {} - if not o_str: + if not o_strs: return opts - o_args = o_str.split(',') - for o_arg in o_args: - o_arg = o_arg.strip() - try: - o_key, o_val = o_arg.split('=') - o_key = o_key.strip() - o_val = o_val.strip() - except ValueError: - opts[o_arg] = True - else: - opts[o_key] = o_val + for o_str in o_strs: + if not o_str: + continue + o_args = o_str.split(',') + for o_arg in o_args: + o_arg = o_arg.strip() + try: + o_key, o_val = o_arg.split('=') + o_key = o_key.strip() + o_val = o_val.strip() + except ValueError: + opts[o_arg] = True + else: + opts[o_key] = o_val return opts -def _print_lflist(): - # print version - main(['', '-V']) - - print - print "Lexers:" - print "~~~~~~~" - - info = [] - for _, fullname, names, exts, _ in LEXERS.itervalues(): - tup = (', '.join(names)+':', fullname, - exts and '(extensions ' + ', '.join(exts) + ')' or '') - info.append(tup) - info.sort() - for i in info: - print ('%s\n %s %s') % i +def _parse_filters(f_strs): + filters = [] + if not f_strs: + return filters + for f_str in f_strs: + if ':' in f_str: + fname, fopts = f_str.split(':', 1) + filters.append((fname, _parse_options([fopts]))) + else: + filters.append((f_str, {})) + return filters - print - print "Formatters:" - print "~~~~~~~~~~~" - info = [] - for fullname, names, exts, doc in FORMATTERS.itervalues(): - tup = (', '.join(names)+':', doc, - exts and '(extensions ' + ', '.join(exts) + ')' or '') - info.append(tup) - info.sort() - for i in info: - print ('%s\n %s %s') % i +def _print_help(type, name): + try: + if type == 'lexer': + cls = find_lexer_class(name) + print "Help on the %s lexer:" % cls.name + print dedent(cls.__doc__) + elif type == 'formatter': + cls = find_formatter_class(name) + print "Help on the %s formatter:" % cls.name + print dedent(cls.__doc__) + elif type == 'filter': + cls = find_filter_class(name) + print "Help on the %s filter:" % name + print dedent(cls.__doc__) + except ClassNotFound: + print >>sys.stderr, "%s not found!" % type + + +def _print_list(what): + if what == 'lexer': + print + print "Lexers:" + print "~~~~~~~" + + info = [] + for fullname, names, exts, _ in get_all_lexers(): + tup = (', '.join(names)+':', fullname, + exts and '(filenames ' + ', '.join(exts) + ')' or '') + info.append(tup) + info.sort() + for i in info: + print ('* %s\n %s %s') % i + + elif what == 'formatter': + print + print "Formatters:" + print "~~~~~~~~~~~" + + info = [] + for cls in get_all_formatters(): + doc = docstring_headline(cls) + tup = (', '.join(cls.aliases) + ':', doc, + cls.filenames and '(filenames ' + ', '.join(cls.filenames) + ')' or '') + info.append(tup) + info.sort() + for i in info: + print ('* %s\n %s %s') % i + + elif what == 'filter': + print + print "Filters:" + print "~~~~~~~~" + + for name in get_all_filters(): + cls = find_filter_class(name) + print "* " + name + ':' + print " %s" % docstring_headline(cls) + + elif what == 'style': + print + print "Styles:" + print "~~~~~~~" + + for name in get_all_styles(): + cls = get_style_by_name(name) + print "* " + name + ':' + print " %s" % docstring_headline(cls) def main(args): """ Main command line entry point. """ - usage = USAGE % ((args[0],) * 3) + usage = USAGE % ((args[0],) * 5) try: - opts, args = getopt.getopt(args[1:], "l:f:o:O:LhVS:a:") - except getopt.GetoptError: + popts, args = getopt.getopt(args[1:], "l:f:F:o:O:LS:a:hVH") + except getopt.GetoptError, err: print >>sys.stderr, usage return 2 - opts = dict(opts) + opts = {} + O_opts = [] + F_opts = [] + for opt, arg in popts: + if opt == '-O': + O_opts.append(arg) + elif opt == '-F': + F_opts.append(arg) + opts[opt] = arg if not opts and not args: print usage @@ -125,15 +207,37 @@ def main(args): # handle ``pygmentize -L`` L_opt = opts.pop('-L', None) if L_opt is not None: - if opts or args: + if opts: + print >>sys.stderr, usage + return 2 + + # print version + main(['', '-V']) + if not args: + args = ['lexer', 'formatter', 'filter', 'style'] + for arg in args: + _print_list(arg.rstrip('s')) + return 0 + + # handle ``pygmentize -H`` + H_opt = opts.pop('-H', None) + if H_opt is not None: + if opts or len(args) != 2: + print >>sys.stderr, usage + return 2 + + type, name = args + if type not in ('lexer', 'formatter', 'filter'): print >>sys.stderr, usage return 2 - _print_lflist() + _print_help(type, name) return 0 # parse -O options - O_opts = _parse_options(opts.pop('-O', None)) + O_opts = _parse_options(O_opts) + # parse -F options + F_opts = _parse_filters(F_opts) # handle ``pygmentize -S`` S_opt = opts.pop('-S', None) @@ -150,7 +254,7 @@ def main(args): try: O_opts['style'] = S_opt fmter = get_formatter_by_name(f_opt, **O_opts) - except ValueError, err: + except ClassNotFound, err: print >>sys.stderr, err return 1 @@ -169,7 +273,7 @@ def main(args): if fmter: try: fmter = get_formatter_by_name(fmter, **O_opts) - except (OptionError, ValueError), err: + except (OptionError, ClassNotFound), err: print >>sys.stderr, 'Error:', err return 1 @@ -177,7 +281,7 @@ def main(args): if not fmter: try: fmter = get_formatter_for_filename(outfn, **O_opts) - except (OptionError, ValueError), err: + except (OptionError, ClassNotFound), err: print >>sys.stderr, 'Error:', err return 1 try: @@ -195,7 +299,7 @@ def main(args): if lexer: try: lexer = get_lexer_by_name(lexer, **O_opts) - except (OptionError, ValueError), err: + except (OptionError, ClassNotFound), err: print >>sys.stderr, 'Error:', err return 1 @@ -208,7 +312,7 @@ def main(args): if not lexer: try: lexer = get_lexer_for_filename(infn, **O_opts) - except (OptionError, ValueError), err: + except (OptionError, ClassNotFound), err: print >>sys.stderr, 'Error:', err return 1 @@ -225,6 +329,9 @@ def main(args): # ... and do it! try: + # process filters + for fname, fopts in F_opts: + lexer.add_filter(fname, **fopts) highlight(code, lexer, fmter, outfile) except Exception, err: import traceback |