3535from token import *
3636from token import EXACT_TOKEN_TYPES
3737import _tokenize
38+ lazy import _colorize
3839
3940cookie_re = re .compile (br'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)' , re .ASCII )
4041blank_re = re .compile (br'^[ \t\f]*(?:[#\r\n]|$)' , re .ASCII )
@@ -505,6 +506,56 @@ def generate_tokens(readline):
505506 """
506507 return _generate_tokens_from_c_tokenizer (readline , extra_tokens = True )
507508
509+
510+ def _get_token_colors (syntax , tokenize ):
511+ """Map token type numbers to theme colors."""
512+ return frozendict ({
513+ COMMENT : syntax .comment ,
514+ DEDENT : tokenize .whitespace ,
515+ ENCODING : tokenize .whitespace ,
516+ ENDMARKER : tokenize .whitespace ,
517+ ERRORTOKEN : tokenize .error ,
518+ FSTRING_START : syntax .string ,
519+ FSTRING_MIDDLE : syntax .string ,
520+ FSTRING_END : syntax .string ,
521+ INDENT : tokenize .whitespace ,
522+ NAME : syntax .reset ,
523+ NEWLINE : tokenize .whitespace ,
524+ NL : tokenize .whitespace ,
525+ NUMBER : syntax .number ,
526+ OP : syntax .op ,
527+ SOFT_KEYWORD : syntax .soft_keyword ,
528+ STRING : syntax .string ,
529+ TSTRING_START : syntax .string ,
530+ TSTRING_MIDDLE : syntax .string ,
531+ TSTRING_END : syntax .string ,
532+ })
533+
534+
535+ def _format_tokens (tokens , * , color = False , exact = False ):
536+ theme = _colorize .get_theme (force_no_color = not color )
537+ s = theme .syntax
538+ t = theme .tokenize
539+ token_colors = _get_token_colors (s , t )
540+ for token in tokens :
541+ token_range = (
542+ f"{ t .position } { token .start [0 ]} "
543+ f"{ t .delimiter } ,{ t .position } { token .start [1 ]} "
544+ f"{ t .delimiter } -"
545+ f"{ t .position } { token .end [0 ]} "
546+ f"{ t .delimiter } ,{ t .position } { token .end [1 ]} "
547+ f"{ t .delimiter } :"
548+ )
549+ token_color = token_colors .get (token .type , s .reset )
550+ token_name = tok_name [token .exact_type if exact else token .type ]
551+ visible_range = f"{ token .start [0 ]} ,{ token .start [1 ]} -{ token .end [0 ]} ,{ token .end [1 ]} :"
552+ yield (
553+ f"{ token_range } { ' ' * (20 - len (visible_range ))} "
554+ f"{ token_color } { token_name :<15} "
555+ f"{ s .reset } { token .string !r:<15} "
556+ )
557+
558+
508559def _main (args = None ):
509560 import argparse
510561
@@ -524,7 +575,7 @@ def error(message, filename=None, location=None):
524575 sys .exit (1 )
525576
526577 # Parse the arguments and options
527- parser = argparse .ArgumentParser (color = True )
578+ parser = argparse .ArgumentParser ()
528579 parser .add_argument (dest = 'filename' , nargs = '?' ,
529580 metavar = 'filename.py' ,
530581 help = 'the file to tokenize; defaults to stdin' )
@@ -545,13 +596,8 @@ def error(message, filename=None, location=None):
545596
546597
547598 # Output the tokenization
548- for token in tokens :
549- token_type = token .type
550- if args .exact :
551- token_type = token .exact_type
552- token_range = "%d,%d-%d,%d:" % (token .start + token .end )
553- print ("%-20s%-15s%-15r" %
554- (token_range , tok_name [token_type ], token .string ))
599+ for line in _format_tokens (tokens , color = True , exact = args .exact ):
600+ print (line )
555601 except IndentationError as err :
556602 line , column = err .args [1 ][1 :3 ]
557603 error (err .args [0 ], filename , (line , column ))
0 commit comments