ThirdParty/Pygments/pygments/cmdline.py

changeset 4172
4f20dba37ab6
parent 3145
a9de05d4a22f
child 4697
c2e9bf425554
equal deleted inserted replaced
4170:8bc578136279 4172:4f20dba37ab6
3 pygments.cmdline 3 pygments.cmdline
4 ~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~
5 5
6 Command line interface. 6 Command line interface.
7 7
8 :copyright: Copyright 2006-2013 by the Pygments team, see AUTHORS. 8 :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS.
9 :license: BSD, see LICENSE for details. 9 :license: BSD, see LICENSE for details.
10 """ 10 """
11 from __future__ import unicode_literals 11
12 from __future__ import print_function
12 13
13 import sys 14 import sys
14 import getopt 15 import getopt
15 from textwrap import dedent 16 from textwrap import dedent
16 17
17 from pygments import __version__, highlight 18 from pygments import __version__, highlight
18 from pygments.util import ClassNotFound, OptionError, docstring_headline 19 from pygments.util import ClassNotFound, OptionError, docstring_headline, \
19 from pygments.lexers import get_all_lexers, get_lexer_by_name, get_lexer_for_filename, \ 20 guess_decode, guess_decode_from_terminal, terminal_encoding
20 find_lexer_class, guess_lexer, TextLexer 21 from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer, \
22 get_lexer_for_filename, find_lexer_class, TextLexer
23 from pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter
21 from pygments.formatters import get_all_formatters, get_formatter_by_name, \ 24 from pygments.formatters import get_all_formatters, get_formatter_by_name, \
22 get_formatter_for_filename, find_formatter_class, \ 25 get_formatter_for_filename, find_formatter_class, \
23 TerminalFormatter # pylint:disable-msg=E0611 26 TerminalFormatter # pylint:disable-msg=E0611
24 from pygments.filters import get_all_filters, find_filter_class 27 from pygments.filters import get_all_filters, find_filter_class
25 from pygments.styles import get_all_styles, get_style_by_name 28 from pygments.styles import get_all_styles, get_style_by_name
26 29
27 30
28 USAGE = """\ 31 USAGE = """\
29 Usage: %s [-l <lexer> | -g] [-F <filter>[:<options>]] [-f <formatter>] 32 Usage: %s [-l <lexer> | -g] [-F <filter>[:<options>]] [-f <formatter>]
30 [-O <options>] [-P <option=value>] [-o <outfile>] [<infile>] 33 [-O <options>] [-P <option=value>] [-s] [-o <outfile>] [<infile>]
31 34
32 %s -S <style> -f <formatter> [-a <arg>] [-O <options>] [-P <option=value>] 35 %s -S <style> -f <formatter> [-a <arg>] [-O <options>] [-P <option=value>]
33 %s -L [<which> ...] 36 %s -L [<which> ...]
34 %s -N <filename> 37 %s -N <filename>
35 %s -H <type> <name> 38 %s -H <type> <name>
37 40
38 Highlight the input file and write the result to <outfile>. 41 Highlight the input file and write the result to <outfile>.
39 42
40 If no input file is given, use stdin, if -o is not given, use stdout. 43 If no input file is given, use stdin, if -o is not given, use stdout.
41 44
45 If -s is passed, lexing will be done in "streaming" mode, reading and
46 highlighting one line at a time. This will only work properly with
47 lexers that have no constructs spanning multiple lines!
48
42 <lexer> is a lexer name (query all lexer names with -L). If -l is not 49 <lexer> is a lexer name (query all lexer names with -L). If -l is not
43 given, the lexer is guessed from the extension of the input file name 50 given, the lexer is guessed from the extension of the input file name
44 (this obviously doesn't work if the input is stdin). If -g is passed, 51 (this obviously doesn't work if the input is stdin). If -g is passed,
45 attempt to guess the lexer from the file contents, or pass through as 52 attempt to guess the lexer from the file contents, or pass through as
46 plain text if this fails (this can work for stdin). 53 plain text if this fails (this can work for stdin).
75 the given filename. It does not take input or highlight anything. 82 the given filename. It does not take input or highlight anything.
76 If no specific lexer can be determined "text" is returned. 83 If no specific lexer can be determined "text" is returned.
77 84
78 The -H option prints detailed help for the object <name> of type <type>, 85 The -H option prints detailed help for the object <name> of type <type>,
79 where <type> is one of "lexer", "formatter" or "filter". 86 where <type> is one of "lexer", "formatter" or "filter".
87
88 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 is intended for streaming input such as you get from 'tail -f'.
91 Example usage: "tail -f sql.log | pygmentize -s -l sql"
80 92
81 The -h option prints this help. 93 The -h option prints this help.
82 The -V option prints the package version. 94 The -V option prints the package version.
83 """ 95 """
84 96
92 continue 104 continue
93 o_args = o_str.split(',') 105 o_args = o_str.split(',')
94 for o_arg in o_args: 106 for o_arg in o_args:
95 o_arg = o_arg.strip() 107 o_arg = o_arg.strip()
96 try: 108 try:
97 o_key, o_val = o_arg.split('=') 109 o_key, o_val = o_arg.split('=', 1)
98 o_key = o_key.strip() 110 o_key = o_key.strip()
99 o_val = o_val.strip() 111 o_val = o_val.strip()
100 except ValueError: 112 except ValueError:
101 opts[o_arg] = True 113 opts[o_arg] = True
102 else: 114 else:
184 cls = get_style_by_name(name) 196 cls = get_style_by_name(name)
185 print("* " + name + ':') 197 print("* " + name + ':')
186 print(" %s" % docstring_headline(cls)) 198 print(" %s" % docstring_headline(cls))
187 199
188 200
189 def main(args=sys.argv): 201 def main_inner(popts, args, usage):
190 """
191 Main command line entry point.
192 """
193 # pylint: disable-msg=R0911,R0912,R0915
194
195 usage = USAGE % ((args[0],) * 6)
196
197 if sys.platform in ['win32', 'cygwin']:
198 try:
199 # Provide coloring under Windows, if possible
200 import colorama
201 colorama.init()
202 except ImportError:
203 pass
204
205 try:
206 popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHg")
207 except getopt.GetoptError as err:
208 print(usage, file=sys.stderr)
209 return 2
210 opts = {} 202 opts = {}
211 O_opts = [] 203 O_opts = []
212 P_opts = [] 204 P_opts = []
213 F_opts = [] 205 F_opts = []
214 for opt, arg in popts: 206 for opt, arg in popts:
218 P_opts.append(arg) 210 P_opts.append(arg)
219 elif opt == '-F': 211 elif opt == '-F':
220 F_opts.append(arg) 212 F_opts.append(arg)
221 opts[opt] = arg 213 opts[opt] = arg
222 214
223 if not opts and not args:
224 print(usage)
225 return 0
226
227 if opts.pop('-h', None) is not None: 215 if opts.pop('-h', None) is not None:
228 print(usage) 216 print(usage)
229 return 0 217 return 0
230 218
231 if opts.pop('-V', None) is not None: 219 if opts.pop('-V', None) is not None:
232 print('Pygments version %s, (c) 2006-2013 by Georg Brandl.' % __version__) 220 print('Pygments version %s, (c) 2006-2014 by Georg Brandl.' % __version__)
233 return 0 221 return 0
234 222
235 # handle ``pygmentize -L`` 223 # handle ``pygmentize -L``
236 L_opt = opts.pop('-L', None) 224 L_opt = opts.pop('-L', None)
237 if L_opt is not None: 225 if L_opt is not None:
273 except ValueError: 261 except ValueError:
274 parsed_opts[p_opt] = True 262 parsed_opts[p_opt] = True
275 else: 263 else:
276 parsed_opts[name] = value 264 parsed_opts[name] = value
277 opts.pop('-P', None) 265 opts.pop('-P', None)
266
267 # encodings
268 inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding'))
269 outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding'))
278 270
279 # handle ``pygmentize -N`` 271 # handle ``pygmentize -N``
280 infn = opts.pop('-N', None) 272 infn = opts.pop('-N', None)
281 if infn is not None: 273 if infn is not None:
282 try: 274 try:
324 316
325 # parse -F options 317 # parse -F options
326 F_opts = _parse_filters(F_opts) 318 F_opts = _parse_filters(F_opts)
327 opts.pop('-F', None) 319 opts.pop('-F', None)
328 320
329 # select formatter 321 # select lexer
330 outfn = opts.pop('-o', None) 322 lexer = None
331 fmter = opts.pop('-f', None) 323
332 if fmter: 324 # given by name?
333 try: 325 lexername = opts.pop('-l', None)
334 fmter = get_formatter_by_name(fmter, **parsed_opts) 326 if lexername:
327 try:
328 lexer = get_lexer_by_name(lexername, **parsed_opts)
335 except (OptionError, ClassNotFound) as err: 329 except (OptionError, ClassNotFound) as err:
336 print('Error:', err, file=sys.stderr) 330 print('Error:', err, file=sys.stderr)
337 return 1 331 return 1
338 332
339 if outfn: 333 # read input code
340 if not fmter: 334 code = None
341 try:
342 fmter = get_formatter_for_filename(outfn, **parsed_opts)
343 except (OptionError, ClassNotFound) as err:
344 print('Error:', err, file=sys.stderr)
345 return 1
346 try:
347 outfile = open(outfn, 'wb')
348 except Exception as err:
349 print('Error: cannot open outfile:', err, file=sys.stderr)
350 return 1
351 else:
352 if not fmter:
353 fmter = TerminalFormatter(**parsed_opts)
354 outfile = sys.stdout
355
356 # select lexer
357 lexer = opts.pop('-l', None)
358 if lexer:
359 try:
360 lexer = get_lexer_by_name(lexer, **parsed_opts)
361 except (OptionError, ClassNotFound) as err:
362 print('Error:', err, file=sys.stderr)
363 return 1
364 335
365 if args: 336 if args:
366 if len(args) > 1: 337 if len(args) > 1:
367 print(usage, file=sys.stderr) 338 print(usage, file=sys.stderr)
368 return 2 339 return 2
369 340
341 if '-s' in opts:
342 print('Error: -s option not usable when input file specified',
343 file=sys.stderr)
344 return 1
345
370 infn = args[0] 346 infn = args[0]
371 try: 347 try:
372 code = open(infn, 'rb').read() 348 with open(infn, 'rb') as infp:
349 code = infp.read()
373 except Exception as err: 350 except Exception as err:
374 print('Error: cannot read infile:', err, file=sys.stderr) 351 print('Error: cannot read infile:', err, file=sys.stderr)
375 return 1 352 return 1
376 353 if not inencoding:
354 code, inencoding = guess_decode(code)
355
356 # do we have to guess the lexer?
377 if not lexer: 357 if not lexer:
378 try: 358 try:
379 lexer = get_lexer_for_filename(infn, code, **parsed_opts) 359 lexer = get_lexer_for_filename(infn, code, **parsed_opts)
380 except ClassNotFound as err: 360 except ClassNotFound as err:
381 if '-g' in opts: 361 if '-g' in opts:
388 return 1 368 return 1
389 except OptionError as err: 369 except OptionError as err:
390 print('Error:', err, file=sys.stderr) 370 print('Error:', err, file=sys.stderr)
391 return 1 371 return 1
392 372
393 else: 373 elif '-s' not in opts: # treat stdin as full file (-s support is later)
394 if '-g' in opts: 374 # read code from terminal, always in binary mode since we want to
375 # decode ourselves and be tolerant with it
376 if sys.version_info > (3,):
377 # Python 3: we have to use .buffer to get a binary stream
378 code = sys.stdin.buffer.read()
379 else:
395 code = sys.stdin.read() 380 code = sys.stdin.read()
381 if not inencoding:
382 code, inencoding = guess_decode_from_terminal(code, sys.stdin)
383 # else the lexer will do the decoding
384 if not lexer:
396 try: 385 try:
397 lexer = guess_lexer(code, **parsed_opts) 386 lexer = guess_lexer(code, **parsed_opts)
398 except ClassNotFound: 387 except ClassNotFound:
399 lexer = TextLexer(**parsed_opts) 388 lexer = TextLexer(**parsed_opts)
400 elif not lexer: 389
401 print('Error: no lexer name given and reading ' + \ 390 # select formatter
402 'from stdin (try using -g or -l <lexer>)', file=sys.stderr) 391 outfn = opts.pop('-o', None)
403 return 2 392 fmter = opts.pop('-f', None)
393 if fmter:
394 try:
395 fmter = get_formatter_by_name(fmter, **parsed_opts)
396 except (OptionError, ClassNotFound) as err:
397 print('Error:', err, file=sys.stderr)
398 return 1
399
400 if outfn:
401 if not fmter:
402 try:
403 fmter = get_formatter_for_filename(outfn, **parsed_opts)
404 except (OptionError, ClassNotFound) as err:
405 print('Error:', err, file=sys.stderr)
406 return 1
407 try:
408 outfile = open(outfn, 'wb')
409 except Exception as err:
410 print('Error: cannot open outfile:', err, file=sys.stderr)
411 return 1
412 else:
413 if not fmter:
414 fmter = TerminalFormatter(**parsed_opts)
415 if sys.version_info > (3,):
416 # Python 3: we have to use .buffer to get a binary stream
417 outfile = sys.stdout.buffer
404 else: 418 else:
405 code = sys.stdin.read() 419 outfile = sys.stdout
406 420
407 # No encoding given? Use latin1 if output file given, 421 # determine output encoding if not explicitly selected
408 # stdin/stdout encoding otherwise. 422 if not outencoding:
409 # (This is a compromise, I'm not too happy with it...)
410 if 'encoding' not in parsed_opts and 'outencoding' not in parsed_opts:
411 if outfn: 423 if outfn:
412 # encoding pass-through 424 # output file? use lexer encoding for now (can still be None)
413 fmter.encoding = 'latin1' 425 fmter.encoding = inencoding
414 else: 426 else:
415 if sys.version_info < (3,): 427 # else use terminal encoding
416 # use terminal encoding; Python 3's terminals already do that 428 fmter.encoding = terminal_encoding(sys.stdout)
417 lexer.encoding = getattr(sys.stdin, 'encoding', 429
418 None) or 'ascii' 430 # provide coloring under Windows, if possible
419 fmter.encoding = getattr(sys.stdout, 'encoding', 431 if not outfn and sys.platform in ('win32', 'cygwin') and \
420 None) or 'ascii' 432 fmter.name in ('Terminal', 'Terminal256'):
421 elif not outfn and sys.version_info > (3,): 433 # unfortunately colorama doesn't support binary streams on Py3
422 # output to terminal with encoding -> use .buffer 434 if sys.version_info > (3,):
423 outfile = sys.stdout.buffer 435 from pygments.util import UnclosingTextIOWrapper
436 outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding)
437 fmter.encoding = None
438 try:
439 import colorama.initialise
440 except ImportError:
441 pass
442 else:
443 outfile = colorama.initialise.wrap_stream(
444 outfile, convert=None, strip=None, autoreset=False, wrap=True)
445
446 # When using the LaTeX formatter and the option `escapeinside` is
447 # specified, we need a special lexer which collects escaped text
448 # before running the chosen language lexer.
449 escapeinside = parsed_opts.get('escapeinside', '')
450 if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter):
451 left = escapeinside[0]
452 right = escapeinside[1]
453 lexer = LatexEmbeddedLexer(left, right, lexer)
454
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
424 462
425 # ... and do it! 463 # ... and do it!
464 if '-s' not in opts:
465 # process whole input as per normal...
466 highlight(code, lexer, fmter, outfile)
467 return 0
468 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')...
474 try:
475 while 1:
476 if sys.version_info > (3,):
477 # Python 3: we have to use .buffer to get a binary stream
478 line = sys.stdin.buffer.readline()
479 else:
480 line = sys.stdin.readline()
481 if not line:
482 break
483 if not inencoding:
484 line = guess_decode_from_terminal(line, sys.stdin)[0]
485 highlight(line, lexer, fmter, outfile)
486 if hasattr(outfile, 'flush'):
487 outfile.flush()
488 except KeyboardInterrupt:
489 return 0
490
491
492 def main(args=sys.argv):
493 """
494 Main command line entry point.
495 """
496 usage = USAGE % ((args[0],) * 6)
497
426 try: 498 try:
427 # process filters 499 popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHgs")
428 for fname, fopts in F_opts: 500 except getopt.GetoptError:
429 lexer.add_filter(fname, **fopts) 501 print(usage, file=sys.stderr)
430 highlight(code, lexer, fmter, outfile) 502 return 2
431 except Exception as err: 503
504 try:
505 return main_inner(popts, args, usage)
506 except Exception:
432 import traceback 507 import traceback
433 info = traceback.format_exception(*sys.exc_info()) 508 info = traceback.format_exception(*sys.exc_info())
434 msg = info[-1].strip() 509 msg = info[-1].strip()
435 if len(info) >= 3: 510 if len(info) >= 3:
436 # extract relevant file and position info 511 # extract relevant file and position info
437 msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] 512 msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:]
438 print(file=sys.stderr) 513 print(file=sys.stderr)
439 print('*** Error while highlighting:', file=sys.stderr) 514 print('*** Error while highlighting:', file=sys.stderr)
440 print(msg, file=sys.stderr) 515 print(msg, file=sys.stderr)
441 return 1 516 return 1
442
443 return 0

eric ide

mercurial