summaryrefslogtreecommitdiffstats
path: root/syntax-highlight.py
blob: e7a8ad472162e369d6cd37260c66e44b6c1d173f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/usr/bin/env python3
"""
cgit source-filter: syntax highlighting via Pygments (Catppuccin Macchiato).

cgit passes the filename as argv[1] and the file content on stdin.
Output is HTML written to stdout.
"""

import sys
import os

try:
    from pygments import highlight
    from pygments.lexers import get_lexer_for_filename, TextLexer
    from pygments.formatters import HtmlFormatter
    from pygments.util import ClassNotFound
    PYGMENTS_AVAILABLE = True
except ImportError:
    PYGMENTS_AVAILABLE = False


def get_lexer(filename):
    try:
        return get_lexer_for_filename(filename, stripnl=False, ensurenl=False)
    except ClassNotFound:
        return TextLexer(stripnl=False, ensurenl=False)


def main():
    filename = sys.argv[1] if len(sys.argv) > 1 else ""

    data = sys.stdin.buffer.read()

    # Try UTF-8, fall back to latin-1 to avoid decode errors on binary-ish files
    try:
        text = data.decode("utf-8")
    except UnicodeDecodeError:
        try:
            text = data.decode("latin-1")
        except UnicodeDecodeError:
            # Give up and emit as plain text
            sys.stdout.write("<pre>" + data.decode("ascii", errors="replace") + "</pre>")
            return

    if not PYGMENTS_AVAILABLE or not filename:
        sys.stdout.write("<pre>" + text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;") + "</pre>")
        return

    lexer = get_lexer(filename)

    formatter = HtmlFormatter(
        style="monokai",       # base style; token colors overridden by CSS
        nowrap=True,           # no wrapping <div class="highlight">
        cssclass="highlight",
        noclasses=False,       # use CSS classes, not inline styles
    )

    highlighted = highlight(text, lexer, formatter)

    # Wrap in pre so cgit's blob table renders it correctly
    sys.stdout.write('<pre><code class="highlight">')
    sys.stdout.write(highlighted)
    sys.stdout.write("</code></pre>")


if __name__ == "__main__":
    main()