ThirdParty/Pygments/pygments/cmdline.py

changeset 4697
c2e9bf425554
parent 4172
4f20dba37ab6
child 5713
6762afd9f963
equal deleted inserted replaced
4696:bf4d19a7cade 4697:c2e9bf425554
3 pygments.cmdline 3 pygments.cmdline
4 ~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~
5 5
6 Command line interface. 6 Command line interface.
7 7
8 :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2015 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11 11
12 from __future__ import print_function 12 from __future__ import print_function
13 13
17 17
18 from pygments import __version__, highlight 18 from pygments import __version__, highlight
19 from pygments.util import ClassNotFound, OptionError, docstring_headline, \ 19 from pygments.util import ClassNotFound, OptionError, docstring_headline, \
20 guess_decode, guess_decode_from_terminal, terminal_encoding 20 guess_decode, guess_decode_from_terminal, terminal_encoding
21 from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer, \ 21 from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer, \
22 get_lexer_for_filename, find_lexer_class, TextLexer 22 get_lexer_for_filename, find_lexer_class_for_filename
23 from pygments.lexers.special import TextLexer
23 from pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter 24 from pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter
24 from pygments.formatters import get_all_formatters, get_formatter_by_name, \ 25 from pygments.formatters import get_all_formatters, get_formatter_by_name, \
25 get_formatter_for_filename, find_formatter_class, \ 26 get_formatter_for_filename, find_formatter_class
26 TerminalFormatter # pylint:disable-msg=E0611 27 from pygments.formatters.terminal import TerminalFormatter
27 from pygments.filters import get_all_filters, find_filter_class 28 from pygments.filters import get_all_filters, find_filter_class
28 from pygments.styles import get_all_styles, get_style_by_name 29 from pygments.styles import get_all_styles, get_style_by_name
29 30
30 31
31 USAGE = """\ 32 USAGE = """\
32 Usage: %s [-l <lexer> | -g] [-F <filter>[:<options>]] [-f <formatter>] 33 Usage: %s [-l <lexer> | -g] [-F <filter>[:<options>]] [-f <formatter>]
33 [-O <options>] [-P <option=value>] [-s] [-o <outfile>] [<infile>] 34 [-O <options>] [-P <option=value>] [-s] [-v] [-o <outfile>] [<infile>]
34 35
35 %s -S <style> -f <formatter> [-a <arg>] [-O <options>] [-P <option=value>] 36 %s -S <style> -f <formatter> [-a <arg>] [-O <options>] [-P <option=value>]
36 %s -L [<which> ...] 37 %s -L [<which> ...]
37 %s -N <filename> 38 %s -N <filename>
38 %s -H <type> <name> 39 %s -H <type> <name>
88 The -s option processes lines one at a time until EOF, rather than 89 The -s option processes lines one at a time until EOF, rather than
89 waiting to process the entire file. This only works for stdin, and 90 waiting to process the entire file. This only works for stdin, and
90 is intended for streaming input such as you get from 'tail -f'. 91 is intended for streaming input such as you get from 'tail -f'.
91 Example usage: "tail -f sql.log | pygmentize -s -l sql" 92 Example usage: "tail -f sql.log | pygmentize -s -l sql"
92 93
94 The -v option prints a detailed traceback on unhandled exceptions,
95 which is useful for debugging and bug reports.
96
93 The -h option prints this help. 97 The -h option prints this help.
94 The -V option prints the package version. 98 The -V option prints the package version.
95 """ 99 """
96 100
97 101
98 def _parse_options(o_strs): 102 def _parse_options(o_strs):
99 opts = {} 103 opts = {}
100 if not o_strs: 104 if not o_strs:
101 return opts 105 return opts
102 for o_str in o_strs: 106 for o_str in o_strs:
103 if not o_str: 107 if not o_str.strip():
104 continue 108 continue
105 o_args = o_str.split(',') 109 o_args = o_str.split(',')
106 for o_arg in o_args: 110 for o_arg in o_args:
107 o_arg = o_arg.strip() 111 o_arg = o_arg.strip()
108 try: 112 try:
130 134
131 135
132 def _print_help(what, name): 136 def _print_help(what, name):
133 try: 137 try:
134 if what == 'lexer': 138 if what == 'lexer':
135 cls = find_lexer_class(name) 139 cls = get_lexer_by_name(name)
136 print("Help on the %s lexer:" % cls.name) 140 print("Help on the %s lexer:" % cls.name)
137 print(dedent(cls.__doc__)) 141 print(dedent(cls.__doc__))
138 elif what == 'formatter': 142 elif what == 'formatter':
139 cls = find_formatter_class(name) 143 cls = find_formatter_class(name)
140 print("Help on the %s formatter:" % cls.name) 144 print("Help on the %s formatter:" % cls.name)
141 print(dedent(cls.__doc__)) 145 print(dedent(cls.__doc__))
142 elif what == 'filter': 146 elif what == 'filter':
143 cls = find_filter_class(name) 147 cls = find_filter_class(name)
144 print("Help on the %s filter:" % name) 148 print("Help on the %s filter:" % name)
145 print(dedent(cls.__doc__)) 149 print(dedent(cls.__doc__))
146 except AttributeError: 150 return 0
151 except (AttributeError, ValueError):
147 print("%s not found!" % what, file=sys.stderr) 152 print("%s not found!" % what, file=sys.stderr)
153 return 1
148 154
149 155
150 def _print_list(what): 156 def _print_list(what):
151 if what == 'lexer': 157 if what == 'lexer':
152 print() 158 print()
215 if opts.pop('-h', None) is not None: 221 if opts.pop('-h', None) is not None:
216 print(usage) 222 print(usage)
217 return 0 223 return 0
218 224
219 if opts.pop('-V', None) is not None: 225 if opts.pop('-V', None) is not None:
220 print('Pygments version %s, (c) 2006-2014 by Georg Brandl.' % __version__) 226 print('Pygments version %s, (c) 2006-2015 by Georg Brandl.' % __version__)
221 return 0 227 return 0
222 228
223 # handle ``pygmentize -L`` 229 # handle ``pygmentize -L``
224 L_opt = opts.pop('-L', None) 230 L_opt = opts.pop('-L', None)
225 if L_opt is not None: 231 if L_opt is not None:
240 if H_opt is not None: 246 if H_opt is not None:
241 if opts or len(args) != 2: 247 if opts or len(args) != 2:
242 print(usage, file=sys.stderr) 248 print(usage, file=sys.stderr)
243 return 2 249 return 2
244 250
245 what, name = args 251 what, name = args # pylint: disable=unbalanced-tuple-unpacking
246 if what not in ('lexer', 'formatter', 'filter'): 252 if what not in ('lexer', 'formatter', 'filter'):
247 print(usage, file=sys.stderr) 253 print(usage, file=sys.stderr)
248 return 2 254 return 2
249 255
250 _print_help(what, name) 256 return _print_help(what, name)
251 return 0
252 257
253 # parse -O options 258 # parse -O options
254 parsed_opts = _parse_options(O_opts) 259 parsed_opts = _parse_options(O_opts)
255 opts.pop('-O', None) 260 opts.pop('-O', None)
256 261
263 else: 268 else:
264 parsed_opts[name] = value 269 parsed_opts[name] = value
265 opts.pop('-P', None) 270 opts.pop('-P', None)
266 271
267 # encodings 272 # encodings
268 inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding')) 273 inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding'))
269 outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding')) 274 outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding'))
270 275
271 # handle ``pygmentize -N`` 276 # handle ``pygmentize -N``
272 infn = opts.pop('-N', None) 277 infn = opts.pop('-N', None)
273 if infn is not None: 278 if infn is not None:
274 try: 279 lexer = find_lexer_class_for_filename(infn)
275 lexer = get_lexer_for_filename(infn, **parsed_opts) 280 if lexer is None:
276 except ClassNotFound as err: 281 lexer = TextLexer
277 lexer = TextLexer()
278 except OptionError as err:
279 print('Error:', err, file=sys.stderr)
280 return 1
281 282
282 print(lexer.aliases[0]) 283 print(lexer.aliases[0])
283 return 0 284 return 0
284 285
285 # handle ``pygmentize -S`` 286 # handle ``pygmentize -S``
299 fmter = get_formatter_by_name(f_opt, **parsed_opts) 300 fmter = get_formatter_by_name(f_opt, **parsed_opts)
300 except ClassNotFound as err: 301 except ClassNotFound as err:
301 print(err, file=sys.stderr) 302 print(err, file=sys.stderr)
302 return 1 303 return 1
303 304
304 arg = a_opt or '' 305 print(fmter.get_style_defs(a_opt or ''))
305 try:
306 print(fmter.get_style_defs(arg))
307 except Exception as err:
308 print('Error:', err, file=sys.stderr)
309 return 1
310 return 0 306 return 0
311 307
312 # if no -S is given, -a is not allowed 308 # if no -S is given, -a is not allowed
313 if a_opt is not None: 309 if a_opt is not None:
314 print(usage, file=sys.stderr) 310 print(usage, file=sys.stderr)
339 return 2 335 return 2
340 336
341 if '-s' in opts: 337 if '-s' in opts:
342 print('Error: -s option not usable when input file specified', 338 print('Error: -s option not usable when input file specified',
343 file=sys.stderr) 339 file=sys.stderr)
344 return 1 340 return 2
345 341
346 infn = args[0] 342 infn = args[0]
347 try: 343 try:
348 with open(infn, 'rb') as infp: 344 with open(infn, 'rb') as infp:
349 code = infp.read() 345 code = infp.read()
385 try: 381 try:
386 lexer = guess_lexer(code, **parsed_opts) 382 lexer = guess_lexer(code, **parsed_opts)
387 except ClassNotFound: 383 except ClassNotFound:
388 lexer = TextLexer(**parsed_opts) 384 lexer = TextLexer(**parsed_opts)
389 385
386 else: # -s option needs a lexer with -l
387 if not lexer:
388 print('Error: when using -s a lexer has to be selected with -l',
389 file=sys.stderr)
390 return 2
391
392 # process filters
393 for fname, fopts in F_opts:
394 try:
395 lexer.add_filter(fname, **fopts)
396 except ClassNotFound as err:
397 print('Error:', err, file=sys.stderr)
398 return 1
399
390 # select formatter 400 # select formatter
391 outfn = opts.pop('-o', None) 401 outfn = opts.pop('-o', None)
392 fmter = opts.pop('-f', None) 402 fmter = opts.pop('-f', None)
393 if fmter: 403 if fmter:
394 try: 404 try:
427 # else use terminal encoding 437 # else use terminal encoding
428 fmter.encoding = terminal_encoding(sys.stdout) 438 fmter.encoding = terminal_encoding(sys.stdout)
429 439
430 # provide coloring under Windows, if possible 440 # provide coloring under Windows, if possible
431 if not outfn and sys.platform in ('win32', 'cygwin') and \ 441 if not outfn and sys.platform in ('win32', 'cygwin') and \
432 fmter.name in ('Terminal', 'Terminal256'): 442 fmter.name in ('Terminal', 'Terminal256'): # pragma: no cover
433 # unfortunately colorama doesn't support binary streams on Py3 443 # unfortunately colorama doesn't support binary streams on Py3
434 if sys.version_info > (3,): 444 if sys.version_info > (3,):
435 from pygments.util import UnclosingTextIOWrapper 445 from pygments.util import UnclosingTextIOWrapper
436 outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding) 446 outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding)
437 fmter.encoding = None 447 fmter.encoding = None
450 if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter): 460 if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter):
451 left = escapeinside[0] 461 left = escapeinside[0]
452 right = escapeinside[1] 462 right = escapeinside[1]
453 lexer = LatexEmbeddedLexer(left, right, lexer) 463 lexer = LatexEmbeddedLexer(left, right, lexer)
454 464
455 # process filters
456 for fname, fopts in F_opts:
457 try:
458 lexer.add_filter(fname, **fopts)
459 except ClassNotFound as err:
460 print('Error:', err, file=sys.stderr)
461 return 1
462
463 # ... and do it! 465 # ... and do it!
464 if '-s' not in opts: 466 if '-s' not in opts:
465 # process whole input as per normal... 467 # process whole input as per normal...
466 highlight(code, lexer, fmter, outfile) 468 highlight(code, lexer, fmter, outfile)
467 return 0 469 return 0
468 else: 470 else:
469 if not lexer:
470 print('Error: when using -s a lexer has to be selected with -l',
471 file=sys.stderr)
472 return 1
473 # line by line processing of stdin (eg: for 'tail -f')... 471 # line by line processing of stdin (eg: for 'tail -f')...
474 try: 472 try:
475 while 1: 473 while 1:
476 if sys.version_info > (3,): 474 if sys.version_info > (3,):
477 # Python 3: we have to use .buffer to get a binary stream 475 # Python 3: we have to use .buffer to get a binary stream
483 if not inencoding: 481 if not inencoding:
484 line = guess_decode_from_terminal(line, sys.stdin)[0] 482 line = guess_decode_from_terminal(line, sys.stdin)[0]
485 highlight(line, lexer, fmter, outfile) 483 highlight(line, lexer, fmter, outfile)
486 if hasattr(outfile, 'flush'): 484 if hasattr(outfile, 'flush'):
487 outfile.flush() 485 outfile.flush()
488 except KeyboardInterrupt: 486 return 0
487 except KeyboardInterrupt: # pragma: no cover
489 return 0 488 return 0
490 489
491 490
492 def main(args=sys.argv): 491 def main(args=sys.argv):
493 """ 492 """
494 Main command line entry point. 493 Main command line entry point.
495 """ 494 """
496 usage = USAGE % ((args[0],) * 6) 495 usage = USAGE % ((args[0],) * 6)
497 496
498 try: 497 try:
499 popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHgs") 498 popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:vhVHgs")
500 except getopt.GetoptError: 499 except getopt.GetoptError:
501 print(usage, file=sys.stderr) 500 print(usage, file=sys.stderr)
502 return 2 501 return 2
503 502
504 try: 503 try:
505 return main_inner(popts, args, usage) 504 return main_inner(popts, args, usage)
506 except Exception: 505 except Exception:
506 if '-v' in dict(popts):
507 print(file=sys.stderr)
508 print('*' * 65, file=sys.stderr)
509 print('An unhandled exception occurred while highlighting.',
510 file=sys.stderr)
511 print('Please report the whole traceback to the issue tracker at',
512 file=sys.stderr)
513 print('<https://bitbucket.org/birkenfeld/pygments-main/issues>.',
514 file=sys.stderr)
515 print('*' * 65, file=sys.stderr)
516 print(file=sys.stderr)
517 raise
507 import traceback 518 import traceback
508 info = traceback.format_exception(*sys.exc_info()) 519 info = traceback.format_exception(*sys.exc_info())
509 msg = info[-1].strip() 520 msg = info[-1].strip()
510 if len(info) >= 3: 521 if len(info) >= 3:
511 # extract relevant file and position info 522 # extract relevant file and position info
512 msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] 523 msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:]
513 print(file=sys.stderr) 524 print(file=sys.stderr)
514 print('*** Error while highlighting:', file=sys.stderr) 525 print('*** Error while highlighting:', file=sys.stderr)
515 print(msg, file=sys.stderr) 526 print(msg, file=sys.stderr)
527 print('*** If this is a bug you want to report, please rerun with -v.',
528 file=sys.stderr)
516 return 1 529 return 1

eric ide

mercurial