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> |
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 |
|