Skip to content

Commit f30d9fe

Browse files
committed
WIP
1 parent 5a3f479 commit f30d9fe

3 files changed

Lines changed: 61 additions & 4 deletions

File tree

Doc/library/tokenize.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ Example of tokenizing from the command line. The script::
227227

228228
will be tokenized to the following output where the first column is the range
229229
of the line/column coordinates where the token is found, the second column is
230-
the name of the token, and the final column is the value of the token (if any)
230+
the name of the token, and the final column is the value of the token (if any):
231231

232232
.. code-block:: shell-session
233233

Lib/_colorize.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,14 @@ class Timeit(ThemeSection):
375375
reset: str = ANSIColors.RESET
376376

377377

378+
@dataclass(frozen=True, kw_only=True)
379+
class Tokenize(ThemeSection):
380+
whitespace: str = ANSIColors.GREY
381+
error: str = ANSIColors.BOLD_RED
382+
position: str = ANSIColors.GREY
383+
delimiter: str = ANSIColors.RESET
384+
385+
378386
@dataclass(frozen=True, kw_only=True)
379387
class Traceback(ThemeSection):
380388
type: str = ANSIColors.BOLD_MAGENTA
@@ -411,6 +419,7 @@ class Theme:
411419
live_profiler: LiveProfiler = field(default_factory=LiveProfiler)
412420
syntax: Syntax = field(default_factory=Syntax)
413421
timeit: Timeit = field(default_factory=Timeit)
422+
tokenize: Tokenize = field(default_factory=Tokenize)
414423
traceback: Traceback = field(default_factory=Traceback)
415424
unittest: Unittest = field(default_factory=Unittest)
416425

@@ -424,6 +433,7 @@ def copy_with(
424433
live_profiler: LiveProfiler | None = None,
425434
syntax: Syntax | None = None,
426435
timeit: Timeit | None = None,
436+
tokenize: Tokenize | None = None,
427437
traceback: Traceback | None = None,
428438
unittest: Unittest | None = None,
429439
) -> Self:
@@ -440,6 +450,7 @@ def copy_with(
440450
live_profiler=live_profiler or self.live_profiler,
441451
syntax=syntax or self.syntax,
442452
timeit=timeit or self.timeit,
453+
tokenize=tokenize or self.tokenize,
443454
traceback=traceback or self.traceback,
444455
unittest=unittest or self.unittest,
445456
)
@@ -460,6 +471,7 @@ def no_colors(cls) -> Self:
460471
live_profiler=LiveProfiler.no_colors(),
461472
syntax=Syntax.no_colors(),
462473
timeit=Timeit.no_colors(),
474+
tokenize=Tokenize.no_colors(),
463475
traceback=Traceback.no_colors(),
464476
unittest=Unittest.no_colors(),
465477
)

Lib/tokenize.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,32 @@ def generate_tokens(readline):
505505
"""
506506
return _generate_tokens_from_c_tokenizer(readline, extra_tokens=True)
507507

508+
509+
def _get_token_colors(syntax, tokenize):
510+
"""Map token type numbers to theme colors."""
511+
return frozendict({
512+
COMMENT: syntax.comment,
513+
DEDENT: tokenize.whitespace,
514+
ENCODING: tokenize.whitespace,
515+
ENDMARKER: tokenize.whitespace,
516+
ERRORTOKEN: tokenize.error,
517+
FSTRING_START: syntax.string,
518+
FSTRING_MIDDLE: syntax.string,
519+
FSTRING_END: syntax.string,
520+
INDENT: tokenize.whitespace,
521+
NAME: syntax.reset,
522+
NEWLINE: tokenize.whitespace,
523+
NL: tokenize.whitespace,
524+
NUMBER: syntax.number,
525+
OP: syntax.op,
526+
SOFT_KEYWORD: syntax.soft_keyword,
527+
STRING: syntax.string,
528+
TSTRING_START: syntax.string,
529+
TSTRING_MIDDLE: syntax.string,
530+
TSTRING_END: syntax.string,
531+
})
532+
533+
508534
def _main(args=None):
509535
import argparse
510536

@@ -545,13 +571,32 @@ def error(message, filename=None, location=None):
545571

546572

547573
# Output the tokenization
574+
import _colorize
575+
576+
_theme = _colorize.get_theme()
577+
s = _theme.syntax
578+
t = _theme.tokenize
579+
_token_colors = _get_token_colors(s, t)
548580
for token in tokens:
549581
token_type = token.type
550582
if args.exact:
551583
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))
584+
token_range = (
585+
f"{t.position}{token.start[0]}"
586+
f"{t.delimiter},{t.position}{token.start[1]}"
587+
f"{t.delimiter}-"
588+
f"{t.position}{token.end[0]}"
589+
f"{t.delimiter},{t.position}{token.end[1]}"
590+
f"{t.delimiter}:"
591+
)
592+
color = _token_colors.get(token_type, s.reset)
593+
token_name = tok_name[token_type]
594+
visible_range = f"{token.start[0]},{token.start[1]}-{token.end[0]},{token.end[1]}:"
595+
print(
596+
f"{token_range}{' ' * (20 - len(visible_range))}"
597+
f"{color}{token_name:<15}"
598+
f"{s.reset}{token.string!r:<15}"
599+
)
555600
except IndentationError as err:
556601
line, column = err.args[1][1:3]
557602
error(err.args[0], filename, (line, column))

0 commit comments

Comments
 (0)