Pygments¶
This package ships a set of Pygments components that make terminal-style content first-class in any Pygments pipeline:
A lexer (
ansi-color) that parses raw ANSI/ECMA-48 escape sequences: text attributes (bold, faint, italic, underline, blink, reverse, strikethrough, overline), the standard 16 named colors, the 256-color indexed palette, 24-bit RGB, and OSC 8 hyperlinks.An HTML formatter (
ansi-html) that renders those tokens as styled<span>elements and OSC 8 hyperlinks as<a>tags. Works in CSS-class mode ornoclasses=Trueinline-style mode.ANSI-aware variants of every shell-session and REPL lexer Pygments ships (
ansi-shell-session,ansi-pycon,ansi-rb, …) so terminal output embedded in code blocks renders with its colors instead of as raw escape codes.A filter (
ansi-filter) that interceptsGeneric.Outputtokens from any session lexer and re-lexes them throughansi-color. This is the seam used by the ANSI session lexers, but you can also attach it to your own lexer.
These are plain Pygments entry points: once installed, they are usable from pygmentize, pygments.highlight(), and any tool that consumes Pygments (Sphinx, MkDocs, Hexo, mdBook, Jekyll, GitHub-flavored Markdown renderers that use Pygments, …).
Install¶
The Pygments components ship as an optional extra to keep the base install lean:
$ pip install click_extra[pygments]
You do not need to use Click, the Click Extra CLI, or the Sphinx/MkDocs integrations to use any of these components: the pygments extra pulls in only Pygments and its prerequisites. The package name (click_extra) is a historical artifact of where these components first lived; the Pygments components are stable, independent, and have no Click dependency at runtime.
Integration¶
Installing the package automatically registers all components with Pygments through standard pygments.lexers, pygments.filters, and pygments.formatters entry points.
Quick check that the new plugins are visible to Pygments’ regular API:
Formatter:
>>> from pygments.formatters import get_formatter_by_name >>> get_formatter_by_name("ansi-html") <click_extra.pygments.AnsiHtmlFormatter object at 0x1011ff1d0>
Filter:
>>> from pygments.filters import get_filter_by_name >>> get_filter_by_name("ansi-filter") <click_extra.pygments.AnsiFilter object at 0x103aaa790>
Lexers:
>>> from pygments.lexers import get_lexer_by_name >>> get_lexer_by_name("ansi-shell-session") <pygments.lexers.AnsiBashSessionLexer>
Tip
If click-extra is installed but you don’t see these new components, you are probably running the snippets above in the wrong Python interpreter.
For instance, you may be running them in a virtual environment. In that case, make sure the virtual environment is activated, and you can import click_extra from it.
ANSI HTML formatter¶
The new ansi-html formatter interpret ANSI Pygments tokens and renders them into HTML. It is also responsible for producing the corresponding CSS style to color the HTML elements.
Warning
This ansi-html formatter is designed to only work with the ansi-color lexer. These two components are the only one capable of producing ANSI tokens (ansi-color) and rendering them in HTML (ansi-html).
After Click Extra installation, ansi-color will be available to Pygments:
>>> from pygments.lexers import get_lexer_by_name
>>> get_lexer_by_name("ansi-color")
<pygments.lexers.AnsiColorLexer>
Formatter usage¶
To test it, let’s generate a cowsay.ans file that is full of ANSI colors:
$ fortune | cowsay | lolcat --force > ./cowsay.ans
$ cat ./cowsay.ans
________________________________
/ Reality is for people who lack \
\ imagination. /
--------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
We can run our formatter on that file. The demo below uses a 4-line lolcat-style input rather than the full cowsay output to keep the rendered HTML readable, but the same call works against the file:
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import get_formatter_by_name
lexer = get_lexer_by_name("ansi-color")
formatter = get_formatter_by_name("ansi-html")
ansi_content = (
"\x1b[38;5;154mh\x1b[38;5;184me\x1b[38;5;214ml\x1b[38;5;208ml"
"\x1b[38;5;203mo\x1b[0m, "
"\x1b[38;5;33mw\x1b[38;5;39mo\x1b[38;5;45mr\x1b[38;5;51ml\x1b[38;5;87md"
"\x1b[0m!\n"
)
print(highlight(ansi_content, lexer, formatter))
<div class="highlight"><pre><span></span><span class=" -Ansi -Ansi-C154 -Ansi-C154">h</span><span class=" -Ansi -Ansi-C184 -Ansi-C184">e</span><span class=" -Ansi -Ansi-C214 -Ansi-C214">l</span><span class=" -Ansi -Ansi-C208 -Ansi-C208">l</span><span class=" -Ansi -Ansi-C203 -Ansi-C203">o</span>, <span class=" -Ansi -Ansi-C33 -Ansi-C33">w</span><span class=" -Ansi -Ansi-C39 -Ansi-C39">o</span><span class=" -Ansi -Ansi-C45 -Ansi-C45">r</span><span class=" -Ansi -Ansi-C51 -Ansi-C51">l</span><span class=" -Ansi -Ansi-C87 -Ansi-C87">d</span>!
</pre></div>
For a real file, swap the inline string for Path("./cowsay.ans").read_text().
Hint
The ansi-color lexer parse raw ANSI codes and transform them into custom Pygments tokens, for the formatter to render.
Pygments’ highlight() is the utility method tying the lexer and formatter together to generate the final output.
And here is how to obtain the corresponding CSS style. The full output is several hundred lines (one rule per Pygments token plus 16 named ANSI colors and 256 palette indices), so this demo prints just the first 30 lines:
from pygments.formatters import get_formatter_by_name
formatter = get_formatter_by_name("ansi-html")
defs = formatter.get_style_defs(".highlight")
print("\n".join(defs.splitlines()[:30]))
print("...")
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f8f8f8; }
.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #F00 } /* Error */
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
.highlight .o { color: #666 } /* Operator */
.highlight .-Ansi-BGBlack { background-color: #000 } /* Ansi.BGBlack */
.highlight .-Ansi-BGBlue { background-color: #3465A4 } /* Ansi.BGBlue */
.highlight .-Ansi-BGBrightBlack { background-color: #676767 } /* Ansi.BGBrightBlack */
.highlight .-Ansi-BGBrightBlue { background-color: #6871FF } /* Ansi.BGBrightBlue */
.highlight .-Ansi-BGBrightCyan { background-color: #5FFDFF } /* Ansi.BGBrightCyan */
.highlight .-Ansi-BGBrightGreen { background-color: #5FF967 } /* Ansi.BGBrightGreen */
.highlight .-Ansi-BGBrightMagenta { background-color: #FF76FF } /* Ansi.BGBrightMagenta */
.highlight .-Ansi-BGBrightRed { background-color: #FF6D67 } /* Ansi.BGBrightRed */
.highlight .-Ansi-BGBrightWhite { background-color: #FEFFFF } /* Ansi.BGBrightWhite */
.highlight .-Ansi-BGBrightYellow { background-color: #FEFB67 } /* Ansi.BGBrightYellow */
.highlight .-Ansi-BGC0 { background-color: #000 } /* Ansi.BGC0 */
.highlight .-Ansi-BGC1 { background-color: #800000 } /* Ansi.BGC1 */
.highlight .-Ansi-BGC10 { background-color: #0F0 } /* Ansi.BGC10 */
.highlight .-Ansi-BGC100 { background-color: #878700 } /* Ansi.BGC100 */
.highlight .-Ansi-BGC101 { background-color: #87875F } /* Ansi.BGC101 */
.highlight .-Ansi-BGC102 { background-color: #878787 } /* Ansi.BGC102 */
.highlight .-Ansi-BGC103 { background-color: #8787AF } /* Ansi.BGC103 */
.highlight .-Ansi-BGC104 { background-color: #8787D7 } /* Ansi.BGC104 */
.highlight .-Ansi-BGC105 { background-color: #8787FF } /* Ansi.BGC105 */
...
Caution
The ansi-color lexer/ansi-html formatter combo can only render pure ANSI content. It cannot interpret the regular Pygments tokens produced by the usual language lexers.
That’s why we also maintain a collection of ANSI-capable lexers for numerous languages, as detailed below.
Inline styles (self-contained HTML)¶
For HTML output that does not depend on an external stylesheet, pass noclasses=True to the formatter. Pygments then converts every token’s CSS class into an inline style="..." attribute:
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import get_formatter_by_name
lexer = get_lexer_by_name("ansi-color")
formatter = get_formatter_by_name("ansi-html", noclasses=True)
print(highlight("\x1b[1;31mError:\x1b[0m file not found\n", lexer, formatter))
<div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%;"><span></span>Error: file not found
</pre></div>
This mode is the right pick when embedding output in emails, static reports, or any context where shipping a separate stylesheet is impractical. It pairs naturally with the 24-bit true-color mode, which is itself inline-style based.
ANSI filter¶
The AnsiFilter is a Pygments filter that intercepts tokens of a specific type (by default Generic.Output) and re-lexes their content through AnsiColorLexer. This is the glue that makes the ANSI language lexers work: a session lexer like BashSessionLexer splits input into prompts (Generic.Prompt) and output (Generic.Output), then the AnsiFilter transforms the output tokens into colored Token.Ansi.* tokens.
A short example showing how the filter transforms a token stream. The source highlight points to the filter() call; the result highlight points to the line where the styled Token.Ansi.Bold.Red token replaces the original Generic.Output:
from pygments.token import Generic
from click_extra.pygments import AnsiFilter
filt = AnsiFilter()
# Simulate what a session lexer produces: a prompt token and an output
# token containing ANSI escape codes.
stream = [
(Generic.Prompt, "$ "),
(Generic.Output, "\x1b[1;31mError:\x1b[0m file not found\n"),
]
for token_type, value in filt.filter(None, stream):
print(f" {token_type!s:30} {value!r}")
Token.Generic.Prompt '$ '
Token.Ansi.Bold.Red 'Error:'
Token.Text ' file not found\n'
The prompt token passes through unchanged, the output token is split into styled Token.Ansi.* tokens, which AnsiHtmlFormatter then renders with CSS classes (or inline styles, see below).
You can attach AnsiFilter to any custom lexer that emits Generic.Output:
from pygments.lexers import get_lexer_by_name
from click_extra.pygments import AnsiFilter
lexer = get_lexer_by_name("docker") # or any lexer of yours
lexer.add_filter(AnsiFilter())
Pass token_type="Generic.Error" (or any other token type) to redirect the filter at a different stream.
ANSI language lexers¶
Some languages supported by Pygments are command lines or code, mixed with generic output.
For example, the console lexer can be used to highlight shell sessions. The general structure of the shell session will be highlighted by the console lexer, including the leading prompt. But the ANSI codes in the output will not be interpreted by console and will be rendered as plain text.
To fix that, this package implements ANSI-capable lexers. These can parse both the language syntax and the ANSI codes in the output. So you can use the ansi-console lexer instead of console, and this ansi--prefixed variant will highlight shell sessions with ANSI codes.
Lexer variants¶
Here is the list of new ANSI-capable lexers and the original lexers they are based on:
Original Lexer |
Original IDs |
ANSI variants |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Lexers usage¶
Let’s test one of these lexers. We are familiar with Python so we’ll focus on the pycon Python console lexer.
First, we will generate some random art in an interactive Python shell:
>>> import itertools
>>> colors = [f"\033[3{i}m{{}}\033[0m" for i in range(1, 7)]
>>> rainbow = itertools.cycle(colors)
>>> letters = [next(rainbow).format(c) for c in "║▌█║ ANSI Art ▌│║▌"]
>>> art = "".join(letters)
>>> art
'\x1b[35m║\x1b[0m\x1b[36m▌\x1b[0m\x1b[31m█\x1b[0m\x1b[32m║\x1b[0m\x1b[33m \x1b[0m\x1b[34mA\x1b[0m\x1b[35mN\x1b[0m\x1b[36mS\x1b[0m\x1b[31mI\x1b[0m\x1b[32m \x1b[0m\x1b[33mA\x1b[0m\x1b[34mr\x1b[0m\x1b[35mt\x1b[0m\x1b[36m \x1b[0m\x1b[31m▌\x1b[0m\x1b[32m│\x1b[0m\x1b[33m║\x1b[0m\x1b[34m▌\x1b[0m'
The code block above is a typical Python console session. You have interactive prompt (>>>), pure Python code, and the output of these invocations. It is rendered here with Pygments’ original pycon lexer.
You can see that the raw Python string art contain ANSI escape sequences (\x1b[XXm). When we print this string and give the results to Pygments, the ANSI codes are not interpreted and the output is rendered as-is:
>>> print(art)
[35m║[0m[36m▌[0m[31m█[0m[32m║[0m[33m [0m[34mA[0m[35mN[0m[36mS[0m[31mI[0m[32m [0m[33mA[0m[34mr[0m[35mt[0m[36m [0m[31m▌[0m[32m│[0m[33m║[0m[34m▌[0m
If you try to run the snippet above in your own Python console, you will see that the result of the print(art) is colored.
That’s why you need Click Extra’s lexers. If we switch to the new ansi-pycon lexer, the output is colored, replicating exactly what you are expecting in your console:
>>> print(art)
║▌█║ ANSI Art ▌│║▌
Lexer design¶
We can check how the ansi-color lexer transforms a raw string into ANSI tokens:
>>> from pygments.lexers import get_lexer_by_name
>>> ansi_lexer = get_lexer_by_name("ansi-color")
>>> tokens = ansi_lexer.get_tokens(art)
>>> tuple(tokens)
((Token.Ansi.Magenta, '║'), (Token.Text, ''), (Token.Ansi.Cyan, '▌'), (Token.Text, ''), (Token.Ansi.Red, '█'), (Token.Text, ''), (Token.Ansi.Green, '║'), (Token.Text, ''), (Token.Ansi.Yellow, ' '), (Token.Text, ''), (Token.Ansi.Blue, 'A'), (Token.Text, ''), (Token.Ansi.Magenta, 'N'), (Token.Text, ''), (Token.Ansi.Cyan, 'S'), (Token.Text, ''), (Token.Ansi.Red, 'I'), (Token.Text, ''), (Token.Ansi.Green, ' '), (Token.Text, ''), (Token.Ansi.Yellow, 'A'), (Token.Text, ''), (Token.Ansi.Blue, 'r'), (Token.Text, ''), (Token.Ansi.Magenta, 't'), (Token.Text, ''), (Token.Ansi.Cyan, ' '), (Token.Text, ''), (Token.Ansi.Red, '▌'), (Token.Text, ''), (Token.Ansi.Green, '│'), (Token.Text, ''), (Token.Ansi.Yellow, '║'), (Token.Text, ''), (Token.Ansi.Blue, '▌'), (Token.Text, '\n'))
See how the raw string is split into Pygments tokens, including the Token.Ansi tokens. These tokens are then ready to be rendered by our own ansi-html formatter.
pygmentize command line¶
Because they’re properly registered to Pygments, all these new components can be invoked with the pygmentize CLI.
For example, here is how we can render the cowsay.ans file from the example above into a standalone HTML file:
$ pygmentize -f ansi-html -O full -o cowsay.html ./cowsay.ans
$ cat cowsay.html
cowsay.html file generated by pygmentize CLI¶<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<style type="text/css">
pre { line-height: 125%; }
body { background: #f8f8f8; }
body .-Ansi-BGBlack { background-color: #000000 } /* Ansi.BGBlack */
body .-Ansi-BGBlue { background-color: #3465a4 } /* Ansi.BGBlue */
body .-Ansi-Red { color: #ef2929 } /* Ansi.Red */
body .-Ansi-Bold { font-weight: bold } /* Ansi.Bold */
/* … */
</style>
</head>
<body>
<div class="highlight">
<pre>
<span></span>
<span class="-Ansi-C154 -Ansi -Ansi-C154"> __</span>
<span class="-Ansi-C148 -Ansi -Ansi-C148">_</span>
<span class="-Ansi-C184 -Ansi -Ansi-C184">___________</span>
…
</pre>
</div>
</body>
</html>
24-bit true color¶
The ansi-color lexer accepts SGR 38;2;r;g;b and 48;2;r;g;b (24-bit RGB) sequences and renders them as raw RGB inline styles by default. Pass true_color=False to fall back to lossy quantization onto the 256-color palette. The difference is most visible on a smooth gradient:
Default (quantized to 256 colors):
████████████████████████████████████████████████████████████████
Opt-in 24-bit true color:
████████████████████████████████████████████████████████████████
The first row bands visibly where adjacent gradient steps collapse onto the same 256-color palette entry. The second row preserves all 64 distinct hex values.
How it renders¶
True-color tokens reach AnsiHtmlFormatter as Token.Ansi.FG_{rrggbb} / Token.Ansi.BG_{rrggbb} and emit inline <span style="color: #rrggbb"> / <span style="background-color: #rrggbb"> tags. Other token components on the same span (bold, italic, named colors, palette indices) keep their CSS-class rendering, so a bold-orange-on-blue span ends up as nested <span class="-Ansi-Bold"><span style="color: #ffa500"><span style="background-color: #004488">…</span></span></span>.
The 16 named colors and 256-palette indices still resolve through the Pygments stylesheet; only the 24-bit codes carry their colors inline (CSS classes can’t enumerate 16.7M colors).
from click_extra.pygments import AnsiColorLexer
print(list(AnsiColorLexer().get_tokens("\x1b[38;2;255;165;0morange\x1b[0m")))
[(Token.Ansi.FG_ffa500, 'orange'), (Token.Text, '\n')]
Falling back to 256-color quantization¶
There are two cases where you might prefer the lossy quantization mode: a Furo dark-mode stylesheet that you want to recolor at theme-swap time (inline styles can’t be overridden), or a downstream renderer that breaks on inline style="…" attributes. Pass true_color=False to opt out:
from click_extra.pygments import AnsiColorLexer
text = "\x1b[38;2;255;165;0morange\x1b[0m"
# Default: preserve raw RGB hex.
truecolor = list(AnsiColorLexer().get_tokens(text))
# Opt-out: quantize to nearest 256-color palette entry.
quantized = list(AnsiColorLexer(true_color=False).get_tokens(text))
print(f"truecolor: {truecolor}")
print(f"quantized: {quantized}")
truecolor: [(Token.Ansi.FG_ffa500, 'orange'), (Token.Text, '\n')]
quantized: [(Token.Ansi.C214, 'orange'), (Token.Text, '\n')]
The flag also flows through AnsiFilter and the ANSI language lexers:
from pygments.lexers import get_lexer_by_name
lexer = get_lexer_by_name("ansi-shell-session", true_color=False)
Warning
Inline styles bypass the Pygments stylesheet entirely. Furo’s dark-mode CSS swap cannot recolor them, but this matches how the 256-color palette already works (its hex values are baked into the stylesheet at generation time). ANSI colors are absolute by design: a red \e[31m should look red regardless of theme.
See also
Pygments has tracked 24-bit terminal rendering for years without a built-in HTML path: see pygments/pygments#849 (closed without a 24-bit formatter) and pygments/pygments#1644 (subclassing the HTML formatter to add ANSI inline styles is fragile across releases). The pygments-ansi-color project hits the same architectural wall: see chriskuehl/pygments-ansi-color#5 (256-color rendering breaks with noclasses=True, the inline-style mode), chriskuehl/pygments-ansi-color#31, and chriskuehl/pygments-ansi-color#33.
OSC 8 hyperlinks¶
Terminal hyperlinks (OSC 8) in CLI output are rendered as clickable HTML <a> tags.
Tools like Rich and modern CLI frameworks emit these sequences to make URLs clickable in terminals that support them.
The AnsiColorLexer parses the OSC 8 escape sequences and the AnsiHtmlFormatter converts them into proper HTML links, preserving any ANSI color styling on the link text.
Only URLs with safe schemes (http, https, mailto, ftp, ftps) are rendered as links.
All other OSC sequences (like window title changes) are silently stripped.
256-color palette swatch¶
A live proof that the full 256-color indexed palette renders correctly through the pipeline. Each cell sets foreground and background to the same index, producing a solid color block; the second column of each pair is bold.
$ export FORCE_COLOR=1
$ click-extra palette
+ 0 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435
0 ████████████████████████████████
16 ████████████████████████████████████████████████████████████████████████
52 ████████████████████████████████████████████████████████████████████████
88 ████████████████████████████████████████████████████████████████████████
124 ████████████████████████████████████████████████████████████████████████
160 ████████████████████████████████████████████████████████████████████████
196 ████████████████████████████████████████████████████████████████████████
232 ████████████████████████████████████████████████
The same swatch can be reproduced from any Python script — the output above is captured from click-extra palette, but the underlying ANSI text is what pygmentize -l ansi-color -f ansi-html consumes:
swatch = "\x1b[38;5;{0};48;5;{0}m\u2588\x1b[1m\u2588\x1b[m"
ansi_text = "".join(swatch.format(i) for i in range(256))
See also
This package’s own CLI ships several other demo subcommands (colors, styles, 8color, gradient) under Colors and styles: they are useful as ready-made ANSI fixtures even if you do not use the CLI itself.
click_extra.pygments API¶
classDiagram
Filter <|-- AnsiFilter
HtmlFormatter <|-- AnsiHtmlFormatter
Lexer <|-- AnsiColorLexer
Lexer <|-- _AnsiFilterMixin
LexerMeta <|-- _AnsiSessionMeta
Pygments lexers, filters, and formatters for ANSI escape sequences.
Parses ANSI SGR escape sequences (ECMA-48 / ISO 6429) from terminal output and renders them as colored HTML with CSS classes. Supports the standard 8/16 named colors, the 256-color indexed palette, and 24-bit RGB.
SGR text attributes: bold, faint, italic, underline, blink, reverse video, strikethrough, and overline.
OSC 8 hyperlinks are rendered as HTML <a> tags. Other OSC sequences are silently
stripped.
Note
24-bit RGB colors (SGR 38;2;r;g;b and 48;2;r;g;b) are preserved by default
and rendered by AnsiHtmlFormatter as inline style="color: #rrggbb" /
style="background-color: #rrggbb" spans (CSS classes cannot enumerate 16.7M
colors). Other token components (bold, named colors, palette indices) keep their
CSS-class rendering. Pass true_color=False to AnsiColorLexer, AnsiFilter,
or any session lexer (via get_lexer_by_name(..., true_color=False)) to opt into
quantization to the nearest entry in the 256-color palette instead.
- click_extra.pygments.Ansi = ('Ansi',)¶
Unified token namespace for ANSI styling.
Compound tokens from the lexer (like
Token.Ansi.Bold.Red) and individual style components (likeToken.Ansi.Red) share this single namespace. The formatter decomposes compound tokens into individual CSS classes at render time.
- click_extra.pygments.DEFAULT_TOKEN_TYPE = ('Generic', 'Output')¶
Default Pygments token type to render with ANSI support.
Defaults to
Generic.Outputtokens, as this is the token type used by all REPL-like and terminal session lexers.
- class click_extra.pygments.AnsiColorLexer(*args, **kwargs)[source]¶
Bases:
LexerLexer for text containing ANSI escape sequences.
Parses Select Graphic Rendition (SGR) codes and emits compound
Token.Ansi.*tokens representing the active styling state. OSC 8 hyperlinks emitToken.AnsiLinkStart/Token.AnsiLinkEndstructural tokens. All other escape sequences are silently stripped.Supported SGR codes:
Text attributes: bold (1), faint (2), italic (3), underline (4), blink (5), reverse video (7), strikethrough (9), overline (53), and their resets.
Named colors: standard (30-37, 40-47) and bright (90-97, 100-107).
256-color indexed palette (38;5;n, 48;5;n).
24-bit RGB (38;2;r;g;b, 48;2;r;g;b), quantized to the nearest 256-color entry.
Supported OSC sequences:
OSC 8 hyperlinks: rendered as
<a>tags byAnsiHtmlFormatter. Only URLs with safe schemes (http, https, mailto, ftp, ftps) are emitted; others are stripped.
Initialize the lexer.
- Parameters:
true_color – Default
True. 24-bit RGB sequences are preserved asToken.Ansi.FG_{rrggbb}/Token.Ansi.BG_{rrggbb}tokens, whichAnsiHtmlFormatterrenders as inlinestyle="color: #rrggbb"/style="background-color: #rrggbb"attributes (CSS classes cannot enumerate 16.7M colors). PassFalseto quantize 24-bit RGB to the nearest entry in the 256-color palette and emitToken.Ansi.C{n}/Token.Ansi.BGC{n}tokens that map to CSS classes via the style dict.
- name = 'ANSI Color'¶
Full name of the lexer, in human-readable form
- aliases = ('ansi-color', 'ansi', 'ansi-terminal')¶
A list of short, unique identifiers that can be used to look up the lexer from a list, e.g., using get_lexer_by_name().
- class click_extra.pygments.AnsiFilter(**options)[source]¶
Bases:
FilterCustom filter transforming a particular kind of token (
Generic.Outputby default) into ANSI tokens.Initialize an
AnsiColorLexerand configure thetoken_typeto be colorized.- Parameters:
true_color – Forwarded to the inner
AnsiColorLexerto control whether 24-bit RGB sequences are preserved asFG_/BG_hex tokens for inline-style rendering (defaultTrue) or quantized to the 256-color palette. SeeAnsiColorLexerfor details.
Note
Only one
token_typeis supported. All Pygments session lexers (ShellSessionBaseLexerand the manually-maintained list incollect_session_lexers) emit terminal output exclusively asGeneric.Output. No upstream issue or PR proposes splitting output into additional token types (likeGeneric.Errorfor stderr). If that changes, this filter would need to accept a set of token types instead of a single one. See pygments#1148 and pygments#2499 for the closest related discussions.
- click_extra.pygments.collect_session_lexers()[source]¶
Retrieve all lexers producing shell-like sessions in Pygments.
This function contains a manually-maintained list of lexers, to which we dynamically add lexers inheriting from
ShellSessionBaseLexer.Hint
To help maintain this list, there is a test that will fail if a new REPL/terminal-like lexer is added to Pygments but not referenced here.
- click_extra.pygments.LEXER_MAP: dict[type[Lexer], type[Lexer]] = {<class 'pygments.lexers.algebra.GAPConsoleLexer'>: <class 'pygments.lexer.AnsiGAPConsoleLexer'>, <class 'pygments.lexers.dylan.DylanConsoleLexer'>: <class 'pygments.lexer.AnsiDylanConsoleLexer'>, <class 'pygments.lexers.erlang.ElixirConsoleLexer'>: <class 'pygments.lexer.AnsiElixirConsoleLexer'>, <class 'pygments.lexers.erlang.ErlangShellLexer'>: <class 'pygments.lexer.AnsiErlangShellLexer'>, <class 'pygments.lexers.julia.JuliaConsoleLexer'>: <class 'pygments.lexer.AnsiJuliaConsoleLexer'>, <class 'pygments.lexers.matlab.MatlabSessionLexer'>: <class 'pygments.lexer.AnsiMatlabSessionLexer'>, <class 'pygments.lexers.php.PsyshConsoleLexer'>: <class 'pygments.lexer.AnsiPsyshConsoleLexer'>, <class 'pygments.lexers.python.PythonConsoleLexer'>: <class 'pygments.lexer.AnsiPythonConsoleLexer'>, <class 'pygments.lexers.r.RConsoleLexer'>: <class 'pygments.lexer.AnsiRConsoleLexer'>, <class 'pygments.lexers.ruby.RubyConsoleLexer'>: <class 'pygments.lexer.AnsiRubyConsoleLexer'>, <class 'pygments.lexers.shell.BashSessionLexer'>: <class 'pygments.lexer.AnsiBashSessionLexer'>, <class 'pygments.lexers.shell.MSDOSSessionLexer'>: <class 'pygments.lexer.AnsiMSDOSSessionLexer'>, <class 'pygments.lexers.shell.PowerShellSessionLexer'>: <class 'pygments.lexer.AnsiPowerShellSessionLexer'>, <class 'pygments.lexers.shell.TcshSessionLexer'>: <class 'pygments.lexer.AnsiTcshSessionLexer'>, <class 'pygments.lexers.special.OutputLexer'>: <class 'pygments.lexer.AnsiOutputLexer'>, <class 'pygments.lexers.sql.PostgresConsoleLexer'>: <class 'pygments.lexer.AnsiPostgresConsoleLexer'>, <class 'pygments.lexers.sql.SqliteConsoleLexer'>: <class 'pygments.lexer.AnsiSqliteConsoleLexer'>}¶
Map original session lexers to their ANSI-capable variants.
- click_extra.pygments.EXTRA_ANSI_CSS: dict[str, str] = {'Blink': 'animation: ansi-blink 1s step-end infinite', 'Bold': 'font-weight: bold', 'Faint': 'opacity: 0.5', 'Italic': 'font-style: italic', 'Overline': 'text-decoration: overline', 'Reverse': 'filter: invert(1)', 'Strikethrough': 'text-decoration: line-through', 'Underline': 'text-decoration: underline'}¶
All SGR text attribute CSS declarations.
Maps
Token.Ansicomponent names to CSS declarations. These are kept out of the Pygments style dict (_ANSI_STYLES) to prevent Furo’s dark-mode CSS generator from injectingcolor: #D0D0D0fallbacks that conflict with foreground color tokens.Used by
AnsiHtmlFormatter.get_token_style_defsto inject CSS rules that both standalonepygmentizeand Furo’s dark-mode CSS generator pick up.
- class click_extra.pygments.AnsiHtmlFormatter(**kwargs)[source]¶
Bases:
HtmlFormatterHTML formatter with ANSI color and hyperlink support.
Extends Pygments’
HtmlFormatterto handle compoundToken.Ansi.*tokens by decomposing them into individual CSS classes, augments the base style with ANSI color definitions for the 256-color indexed palette, and renders OSC 8 hyperlinks as HTML<a>tags.Intercept the
styleargument to augment it with ANSI color support.Creates a new style instance that inherits from the one provided by the user, but updates its
stylesattribute with ANSI token definitions from_ANSI_STYLES.- name = 'ANSI HTML'¶
Full name for the formatter, in human-readable form.
- aliases: ClassVar[list[str]] = ['ansi-html']¶
A list of short, unique identifiers that can be used to lookup the formatter from a list, e.g. using
get_formatter_by_name().
- format_unencoded(tokensource, outfile)[source]¶
Render tokens to HTML, converting OSC 8 link and 24-bit RGB markers to tags.
Replaces
Token.AnsiLinkStart/Token.AnsiLinkEndwith Unicode Private Use Area markers, stripsFG_/BG_24-bit RGB components from compound tokens and replaces them with PUA markers carrying the hex value, delegates to Pygments’ HTML rendering, then post-processes the output to swap markers for<a>and inline-styled<span>tags.- Return type:
- get_token_style_defs(arg=None)[source]¶
Extend Pygments’ token CSS with rules for SGR attributes it cannot express.
Pygments’ style strings support
bold,italic, andunderline, but have no keywords for faint, blink, reverse, strikethrough, or overline. This override appends dedicated CSS rules fromEXTRA_ANSI_CSSafter the standard Pygments token CSS output.Overriding
get_token_style_defs(rather thanget_style_defs) ensures that Furo’s dark-mode CSS generator, which calls this method directly, also picks up the extra rules.