3 pygments.cmdline |
3 pygments.cmdline |
4 ~~~~~~~~~~~~~~~~ |
4 ~~~~~~~~~~~~~~~~ |
5 |
5 |
6 Command line interface. |
6 Command line interface. |
7 |
7 |
8 :copyright: Copyright 2006-2017 by the Pygments team, see AUTHORS. |
8 :copyright: Copyright 2006-2019 by the Pygments team, see AUTHORS. |
9 :license: BSD, see LICENSE for details. |
9 :license: BSD, see LICENSE for details. |
10 """ |
10 """ |
11 |
|
12 from __future__ import print_function |
|
13 |
11 |
14 import os |
12 import os |
15 import sys |
13 import sys |
16 import getopt |
14 import getopt |
17 from textwrap import dedent |
15 from textwrap import dedent |
18 |
16 |
19 from pygments import __version__, highlight |
17 from pygments import __version__, highlight |
20 from pygments.util import ClassNotFound, OptionError, docstring_headline, \ |
18 from pygments.util import ClassNotFound, OptionError, docstring_headline, \ |
21 guess_decode, guess_decode_from_terminal, terminal_encoding |
19 guess_decode, guess_decode_from_terminal, terminal_encoding, \ |
|
20 UnclosingTextIOWrapper |
22 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, \ |
23 load_lexer_from_file, get_lexer_for_filename, find_lexer_class_for_filename |
22 load_lexer_from_file, get_lexer_for_filename, find_lexer_class_for_filename |
24 from pygments.lexers.special import TextLexer |
23 from pygments.lexers.special import TextLexer |
25 from pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter |
24 from pygments.formatters.latex import LatexEmbeddedLexer, LatexFormatter |
26 from pygments.formatters import get_all_formatters, get_formatter_by_name, \ |
25 from pygments.formatters import get_all_formatters, get_formatter_by_name, \ |
231 if opts.pop('-h', None) is not None: |
230 if opts.pop('-h', None) is not None: |
232 print(usage) |
231 print(usage) |
233 return 0 |
232 return 0 |
234 |
233 |
235 if opts.pop('-V', None) is not None: |
234 if opts.pop('-V', None) is not None: |
236 print('Pygments version %s, (c) 2006-2017 by Georg Brandl.' % __version__) |
235 print('Pygments version %s, (c) 2006-2019 by Georg Brandl.' % __version__) |
237 return 0 |
236 return 0 |
238 |
237 |
239 # handle ``pygmentize -L`` |
238 # handle ``pygmentize -L`` |
240 L_opt = opts.pop('-L', None) |
239 L_opt = opts.pop('-L', None) |
241 if L_opt is not None: |
240 if L_opt is not None: |
336 lexername = opts.pop('-l', None) |
335 lexername = opts.pop('-l', None) |
337 if lexername: |
336 if lexername: |
338 # custom lexer, located relative to user's cwd |
337 # custom lexer, located relative to user's cwd |
339 if allow_custom_lexer_formatter and '.py' in lexername: |
338 if allow_custom_lexer_formatter and '.py' in lexername: |
340 try: |
339 try: |
|
340 filename = None |
|
341 name = None |
341 if ':' in lexername: |
342 if ':' in lexername: |
342 filename, name = lexername.rsplit(':', 1) |
343 filename, name = lexername.rsplit(':', 1) |
|
344 |
|
345 if '.py' in name: |
|
346 # This can happen on Windows: If the lexername is |
|
347 # C:\lexer.py -- return to normal load path in that case |
|
348 name = None |
|
349 |
|
350 if filename and name: |
343 lexer = load_lexer_from_file(filename, name, |
351 lexer = load_lexer_from_file(filename, name, |
344 **parsed_opts) |
352 **parsed_opts) |
345 else: |
353 else: |
346 lexer = load_lexer_from_file(lexername, **parsed_opts) |
354 lexer = load_lexer_from_file(lexername, **parsed_opts) |
347 except ClassNotFound as err: |
355 except ClassNotFound as err: |
395 return 1 |
403 return 1 |
396 |
404 |
397 elif '-s' not in opts: # treat stdin as full file (-s support is later) |
405 elif '-s' not in opts: # treat stdin as full file (-s support is later) |
398 # read code from terminal, always in binary mode since we want to |
406 # read code from terminal, always in binary mode since we want to |
399 # decode ourselves and be tolerant with it |
407 # decode ourselves and be tolerant with it |
400 if sys.version_info > (3,): |
408 code = sys.stdin.buffer.read() # use .buffer to get a binary stream |
401 # Python 3: we have to use .buffer to get a binary stream |
|
402 code = sys.stdin.buffer.read() |
|
403 else: |
|
404 code = sys.stdin.read() |
|
405 if not inencoding: |
409 if not inencoding: |
406 code, inencoding = guess_decode_from_terminal(code, sys.stdin) |
410 code, inencoding = guess_decode_from_terminal(code, sys.stdin) |
407 # else the lexer will do the decoding |
411 # else the lexer will do the decoding |
408 if not lexer: |
412 if not lexer: |
409 try: |
413 try: |
430 fmter = opts.pop('-f', None) |
434 fmter = opts.pop('-f', None) |
431 if fmter: |
435 if fmter: |
432 # custom formatter, located relative to user's cwd |
436 # custom formatter, located relative to user's cwd |
433 if allow_custom_lexer_formatter and '.py' in fmter: |
437 if allow_custom_lexer_formatter and '.py' in fmter: |
434 try: |
438 try: |
|
439 filename = None |
|
440 name = None |
435 if ':' in fmter: |
441 if ':' in fmter: |
436 file, fmtername = fmter.rsplit(':', 1) |
442 # Same logic as above for custom lexer |
437 fmter = load_formatter_from_file(file, fmtername, |
443 filename, name = fmter.rsplit(':', 1) |
438 **parsed_opts) |
444 |
|
445 if '.py' in name: |
|
446 name = None |
|
447 |
|
448 if filename and name: |
|
449 fmter = load_formatter_from_file(filename, name, |
|
450 **parsed_opts) |
439 else: |
451 else: |
440 fmter = load_formatter_from_file(fmter, **parsed_opts) |
452 fmter = load_formatter_from_file(fmter, **parsed_opts) |
441 except ClassNotFound as err: |
453 except ClassNotFound as err: |
442 print('Error:', err, file=sys.stderr) |
454 print('Error:', err, file=sys.stderr) |
443 return 1 |
455 return 1 |
464 if not fmter: |
476 if not fmter: |
465 if '256' in os.environ.get('TERM', ''): |
477 if '256' in os.environ.get('TERM', ''): |
466 fmter = Terminal256Formatter(**parsed_opts) |
478 fmter = Terminal256Formatter(**parsed_opts) |
467 else: |
479 else: |
468 fmter = TerminalFormatter(**parsed_opts) |
480 fmter = TerminalFormatter(**parsed_opts) |
469 if sys.version_info > (3,): |
481 outfile = sys.stdout.buffer |
470 # Python 3: we have to use .buffer to get a binary stream |
|
471 outfile = sys.stdout.buffer |
|
472 else: |
|
473 outfile = sys.stdout |
|
474 |
482 |
475 # determine output encoding if not explicitly selected |
483 # determine output encoding if not explicitly selected |
476 if not outencoding: |
484 if not outencoding: |
477 if outfn: |
485 if outfn: |
478 # output file? use lexer encoding for now (can still be None) |
486 # output file? use lexer encoding for now (can still be None) |
483 |
491 |
484 # provide coloring under Windows, if possible |
492 # provide coloring under Windows, if possible |
485 if not outfn and sys.platform in ('win32', 'cygwin') and \ |
493 if not outfn and sys.platform in ('win32', 'cygwin') and \ |
486 fmter.name in ('Terminal', 'Terminal256'): # pragma: no cover |
494 fmter.name in ('Terminal', 'Terminal256'): # pragma: no cover |
487 # unfortunately colorama doesn't support binary streams on Py3 |
495 # unfortunately colorama doesn't support binary streams on Py3 |
488 if sys.version_info > (3,): |
496 outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding) |
489 from pygments.util import UnclosingTextIOWrapper |
497 fmter.encoding = None |
490 outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding) |
|
491 fmter.encoding = None |
|
492 try: |
498 try: |
493 import colorama.initialise |
499 import colorama.initialise |
494 except ImportError: |
500 except ImportError: |
495 pass |
501 pass |
496 else: |
502 else: |
513 return 0 |
519 return 0 |
514 else: |
520 else: |
515 # line by line processing of stdin (eg: for 'tail -f')... |
521 # line by line processing of stdin (eg: for 'tail -f')... |
516 try: |
522 try: |
517 while 1: |
523 while 1: |
518 if sys.version_info > (3,): |
524 line = sys.stdin.buffer.readline() |
519 # Python 3: we have to use .buffer to get a binary stream |
|
520 line = sys.stdin.buffer.readline() |
|
521 else: |
|
522 line = sys.stdin.readline() |
|
523 if not line: |
525 if not line: |
524 break |
526 break |
525 if not inencoding: |
527 if not inencoding: |
526 line = guess_decode_from_terminal(line, sys.stdin)[0] |
528 line = guess_decode_from_terminal(line, sys.stdin)[0] |
527 highlight(line, lexer, fmter, outfile) |
529 highlight(line, lexer, fmter, outfile) |
552 print('*' * 65, file=sys.stderr) |
554 print('*' * 65, file=sys.stderr) |
553 print('An unhandled exception occurred while highlighting.', |
555 print('An unhandled exception occurred while highlighting.', |
554 file=sys.stderr) |
556 file=sys.stderr) |
555 print('Please report the whole traceback to the issue tracker at', |
557 print('Please report the whole traceback to the issue tracker at', |
556 file=sys.stderr) |
558 file=sys.stderr) |
557 print('<https://bitbucket.org/birkenfeld/pygments-main/issues>.', |
559 print('<https://github.com/pygments/pygments/issues>.', |
558 file=sys.stderr) |
560 file=sys.stderr) |
559 print('*' * 65, file=sys.stderr) |
561 print('*' * 65, file=sys.stderr) |
560 print(file=sys.stderr) |
562 print(file=sys.stderr) |
561 raise |
563 raise |
562 import traceback |
564 import traceback |