Pygments highlights source code in HTML and terminal output. pip install pygments. Basic: from pygments import highlight; from pygments.lexers import get_lexer_by_name; from pygments.formatters import HtmlFormatter. highlight(code, get_lexer_by_name("python"), HtmlFormatter()). Lexer: get_lexer_by_name("python", stripall=True). get_lexer_by_name("javascript"). get_lexer_by_name("sql"). guess_lexer(code) — auto-detect language. get_lexer_for_filename("app.py"). get_lexer_for_mimetype("text/x-python"). HtmlFormatter: HtmlFormatter(style="monokai", full=True, linenos=True, cssclass="highlight"). full=True produces standalone HTML with <html>. full=False (default) produces <div class="highlight">. linenos="table" — line numbers in table cells. linenos="inline". CSS: HtmlFormatter(style="monokai").get_style_defs(".highlight"). Styles: from pygments.styles import get_all_styles; list(get_all_styles()) — monokai, solarized-dark, dracula, github-dark, nord, vs, emacs, friendly. Terminal: from pygments.formatters import TerminalFormatter, Terminal256Formatter. highlight(code, lexer, TerminalFormatter()). highlight(code, lexer, Terminal256Formatter(style="monokai")). Token inspection: from pygments.formatters import RawTokenFormatter. lex(code, lexer) → token stream. list(lexer.get_tokens(code)). Custom lexer: subclass RegexLexer, define tokens dict with regex rules. Claude Code generates Pygments highlight pipelines, HTML renderers, and terminal colorizers.
CLAUDE.md for Pygments
## Pygments Stack
- Version: Pygments >= 2.17 | pip install pygments
- One-shot: highlight(code, get_lexer_by_name("python", stripall=True), HtmlFormatter(style="monokai"))
- CSS: HtmlFormatter(style="monokai").get_style_defs(".highlight") — inject into <style>
- Linenos: HtmlFormatter(linenos="table", anchorlinenos=True, lineanchors="line")
- Terminal: Terminal256Formatter(style="monokai") — needs 256-color terminal
- Guess: guess_lexer(code) for auto-detection | get_lexer_for_filename("file.py")
- Full HTML: HtmlFormatter(full=True, style="monokai") — standalone page
Pygments Syntax Highlighting Pipeline
# app/highlight.py — Pygments HTML and terminal syntax highlighting
from __future__ import annotations
import textwrap
from pathlib import Path
from typing import Any
from pygments import highlight, lex
from pygments.formatter import Formatter
from pygments.formatters import (
HtmlFormatter,
RawTokenFormatter,
Terminal256Formatter,
TerminalFormatter,
)
from pygments.lexer import RegexLexer
from pygments.lexers import (
get_lexer_by_name,
get_lexer_for_filename,
get_lexer_for_mimetype,
guess_lexer,
)
from pygments.styles import get_all_styles
from pygments.token import Comment, Keyword, Name, Number, Operator, String, Token
from pygments.util import ClassNotFound
# ─────────────────────────────────────────────────────────────────────────────
# 1. HTML highlighting
# ─────────────────────────────────────────────────────────────────────────────
def highlight_html(
code: str,
language: str = "python",
style: str = "monokai",
linenos: bool = False,
cssclass: str = "highlight",
) -> str:
"""
Render code as an HTML <div class="highlight"> block.
Pair with get_css() to inject the stylesheet once per page.
linenos=True → "table" style (line numbers in a separate column).
"""
try:
lexer = get_lexer_by_name(language, stripall=True)
except ClassNotFound:
lexer = get_lexer_by_name("text")
formatter = HtmlFormatter(
style=style,
linenos="table" if linenos else False,
cssclass=cssclass,
nowrap=False,
)
return highlight(code, lexer, formatter)
def get_css(style: str = "monokai", cssclass: str = "highlight") -> str:
"""
Return the CSS rules for the given style.
Inject once into the page <style> tag; reuse the same cssclass across snippets.
"""
return HtmlFormatter(style=style, cssclass=cssclass).get_style_defs(f".{cssclass}")
def highlight_html_full(
code: str,
language: str = "python",
style: str = "monokai",
title: str = "",
) -> str:
"""
Produce a standalone HTML page (with <html>, <head>, <body>).
HtmlFormatter(full=True) embeds all CSS inline.
"""
lexer = get_lexer_by_name(language, stripall=True)
formatter = HtmlFormatter(
style=style,
full=True,
linenos="table",
title=title or f"{language} code",
)
return highlight(code, lexer, formatter)
def highlight_with_anchors(
code: str,
language: str = "python",
style: str = "friendly",
) -> str:
"""
Line numbers with anchor links — e.g. #line-15 links to line 15.
Useful for documentation pages where you want to deep-link to lines.
"""
lexer = get_lexer_by_name(language, stripall=True)
formatter = HtmlFormatter(
style=style,
linenos="table",
anchorlinenos=True,
lineanchors="line",
cssclass="highlight",
)
return highlight(code, lexer, formatter)
# ─────────────────────────────────────────────────────────────────────────────
# 2. Terminal (ANSI) highlighting
# ─────────────────────────────────────────────────────────────────────────────
def highlight_terminal(code: str, language: str = "python") -> str:
"""
Highlight for terminal output using 16-color ANSI escape codes.
TerminalFormatter works on all UNIX terminals; no style choice.
"""
lexer = get_lexer_by_name(language, stripall=True)
return highlight(code, lexer, TerminalFormatter())
def highlight_terminal_256(
code: str,
language: str = "python",
style: str = "monokai",
) -> str:
"""
256-color terminal highlighting — richer palette.
Terminal256Formatter accepts full Pygments style names.
"""
lexer = get_lexer_by_name(language, stripall=True)
return highlight(code, lexer, Terminal256Formatter(style=style))
# ─────────────────────────────────────────────────────────────────────────────
# 3. Language detection
# ─────────────────────────────────────────────────────────────────────────────
def detect_and_highlight(code: str, filename: str | None = None) -> dict[str, str]:
"""
Auto-detect language from filename or source content, then highlight.
Returns {"language", "html", "detected"}.
"""
if filename:
try:
lexer = get_lexer_for_filename(filename, stripall=True)
except ClassNotFound:
lexer = guess_lexer(code)
else:
try:
lexer = guess_lexer(code)
except ClassNotFound:
lexer = get_lexer_by_name("text")
html = highlight(
code,
lexer,
HtmlFormatter(style="github-dark", cssclass="highlight"),
)
return {
"language": lexer.name,
"html": html,
"aliases": lexer.aliases[:3] if lexer.aliases else [],
}
# ─────────────────────────────────────────────────────────────────────────────
# 4. Token stream inspection
# ─────────────────────────────────────────────────────────────────────────────
def get_token_types(code: str, language: str = "python") -> list[dict[str, str]]:
"""
Expose the Pygments token stream — each (token_type, value) pair.
Useful for building custom renderers or for analysis tools.
"""
lexer = get_lexer_by_name(language, stripall=True)
return [
{"type": str(ttype), "value": repr(value)}
for ttype, value in lex(code, lexer)
if value.strip()
]
# ─────────────────────────────────────────────────────────────────────────────
# 5. Custom lexer — minimal example (INI-style config)
# ─────────────────────────────────────────────────────────────────────────────
class EnvFileLexer(RegexLexer):
"""
Simple .env file lexer.
RegexLexer maps regex patterns to token types.
"""
name = "Env"
aliases = ["env", "dotenv"]
filenames = [".env", "*.env"]
tokens = {
"root": [
(r"#.*\n", Comment), # # comment
(r"export\s+", Keyword), # export
(r"[A-Z_][A-Z0-9_]*(?==)", Name.Variable), # KEY
(r"=", Operator), # =
(r'"[^"]*"', String.Double), # "value"
(r"'[^']*'", String.Single), # 'value'
(r"[^\s\n]+", String), # unquoted value
(r"\n", Token.Text),
],
}
def highlight_env(env_text: str) -> str:
"""Highlight a .env file using the custom EnvFileLexer."""
return highlight(
env_text,
EnvFileLexer(stripall=True),
HtmlFormatter(style="friendly", cssclass="highlight"),
)
# ─────────────────────────────────────────────────────────────────────────────
# 6. Available styles
# ─────────────────────────────────────────────────────────────────────────────
def list_styles() -> list[str]:
return sorted(get_all_styles())
# ─────────────────────────────────────────────────────────────────────────────
# 7. Jinja2 / Flask integration
# ─────────────────────────────────────────────────────────────────────────────
def register_pygments_filter(env, style: str = "monokai") -> None:
"""
Register a Jinja2 filter so templates can do:
{{ post.code_snippet | highlight("python") | safe }}
"""
def _filter(code: str, language: str = "python") -> str:
return highlight_html(code, language=language, style=style)
env.filters["highlight"] = _filter
def highlight_file(path: Path, style: str = "monokai") -> str:
"""Highlight a source file by detecting its language from the extension."""
code = path.read_text(encoding="utf-8", errors="replace")
return detect_and_highlight(code, filename=path.name)["html"]
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
PYTHON_SAMPLE = textwrap.dedent("""\
def fibonacci(n: int) -> list[int]:
\"\"\"Return the first n Fibonacci numbers.\"\"\"
a, b = 0, 1
result = []
for _ in range(n):
result.append(a)
a, b = b, a + b
return result
if __name__ == "__main__":
print(fibonacci(10))
""")
ENV_SAMPLE = textwrap.dedent("""\
# Application settings
export DEBUG=false
DATABASE_URL="postgresql://user:pass@localhost/mydb"
SECRET_KEY='my-secret-key-here'
PORT=8000
""")
if __name__ == "__main__":
print("=== Available styles (first 10) ===")
print(list_styles()[:10])
print("\n=== Terminal (16-color) ===")
print(highlight_terminal(PYTHON_SAMPLE))
print("\n=== Language detection ===")
detected = detect_and_highlight(PYTHON_SAMPLE)
print(f" Detected: {detected['language']}")
print("\n=== Token stream (first 8 tokens) ===")
tokens = get_token_types(PYTHON_SAMPLE)[:8]
for t in tokens:
print(f" {t['type']:40} {t['value']}")
print("\n=== CSS snippet (first 3 lines) ===")
css = get_css()
print("\n".join(css.splitlines()[:3]))
print("\n=== .env file (custom lexer — HTML) ===")
env_html = highlight_env(ENV_SAMPLE)
print(f" HTML length: {len(env_html)} chars")
For the highlight.js (client-side) alternative — highlight.js runs in the browser, requires JavaScript, and rehighlights on every page load; Pygments runs on the server at build time, embeds static HTML with <span class="..."> tags, and the page renders pre-highlighted with no client-side JavaScript at all — the output is indexable by search engines and works without JS. For the rich.Syntax alternative — rich.Syntax(code, "python") is excellent for terminal output using Rich’s rendering pipeline (Live, Panel, Table), while Pygments is the correct tool when you need HTML output for a web application — HtmlFormatter(style="monokai").get_style_defs() produces a CSS file you inject once, and then every highlight(code, lexer, formatter) call returns a <div class="highlight"> block compatible with any HTML page. The Claude Skills 360 bundle includes Pygments skill sets covering highlight() with HtmlFormatter and TerminalFormatter, get_lexer_by_name / guess_lexer / get_lexer_for_filename, HtmlFormatter options including linenos/anchorlinenos/cssclass/full/style, get_style_defs() CSS extraction, Terminal256Formatter for 256-color ANSI output, lex() token stream inspection, RegexLexer subclassing for custom file formats, detect_and_highlight auto-detection, Jinja2 highlight filter registration, and highlight_file for per-extension language detection. Start with the free tier to try syntax highlighting pipeline code generation.