Syntax Highlighting in Code Blocks

Syntax Highlighting (png, ~82 Kb)

DISCLAIMER. Do not do this! It's impossible to copy-paste highlighted text, tons of the ANSI-escapes will be on your conscience!

We'll use Lagrange MIME-hooks and Python script with "rich" and "pygments" modules.

Lagrange (git.skyjake.fi)

Hooks are configured using the file "mimehooks.txt" in Lagrange's config directory. Each hook has a regexp that is matched against the response MIME type and parameters, and each matching hook is offered the response body via stdin. The called external programs are free to rewrite the entire response, including the MIME type. If one of the hooks returns a valid response, it is used as the final response of the Gemini request.

Rich (github.com)

Rich is a Python library for rich text and beautiful formatting in the terminal.

Pygments (github.com)

It is a generic syntax highlighter written in Python that supports over 500 languages and text formats, for use in code hosting, forums, wikis or other applications that need to prettify source code.

Preparation

First of all, we need Python Virtual Environment with installed "rich" and "pygments" modules:

mkdir /opt/lagrange-pygments

cd /opt/lagrange-pygments

python3 -m venv .venv

source .venv/bin/activate

pip install rich pygments

touch lagrange-pygments.py

Scripting

And let's write a function in "/opt/lagrange-pygments.py" to pygmentize any code blocks! This function will accept a text and lexer name to tokenize text and print out syntax highlighted text to console.

from rich.console import Console
from rich.syntax import Syntax

def print_code(code: str, lexer: str, code_width: int, line_numbers: bool):
    syntax = Syntax(code, lexer, theme="solarized-dark",
                    line_numbers=line_numbers, code_width=code_width + 1)
    console = Console(color_system="truecolor",
                      width=code_width + (6 if line_numbers else 1))
    console.print(syntax)

You can set color theme in 'Syntax(..., theme="xxx",...)' parameter.

Pygments :: Styles (pygments.org)

Next we'll do:





import re
import sys

LEXERS_NAMES = ['sql', 'python', 'c#', 'c++', 'java', 'json', 'xml']


def readline():
    while line := sys.stdin.readline():
        yield line


def read_code_block():
    code = ''
    max_len = 0
    for code_line in readline():
        if re.match(r'^```', code_line):
            break
        code += code_line
        max_len = max(len(code_line.rstrip('\r\n')), max_len)
    return code.rstrip('\r\n'), max_len


def rich_pygments(meta: list[str]):
    print(f'20 {"; ".join(meta)}', end='\r\n')
    for line in readline():
        if match := re.match(r'^```?([/#+\-\dA-z]*)?($|\s)', line):
            lexer = match.groups()[0]
            if lexer not in LEXERS_NAMES:
                print(line.rstrip('\r\n'))
                continue  #

            print(line.rstrip('\r\n'))
            code, max_len = read_code_block()
            print_code(code, lexer, max_len, line_numbers=True)
            print('```')
        else:
            print(line.rstrip('\r\n'))


if __name__ == '__main__':
    rich_pygments(sys.argv[1:])

Hook them all

The final step is setup our hook in Lagrange. You can find "mimehooks.txt" in:

   Windows : C:\Users\Name\AppData\Roaming\fi.skyjake.Lagrange
     macOS : ~/Library/Application Support/fi.skyjake.Lagrange/
Other Unix : ~/.config/lagrange/

Insert into this file a title, 'text/gemini' mime-type, hook command:

Syntax Highlight
text/gemini
/opt/lagrange-pygments/.venv/bin/python3;/opt/lagrange-pygments/lagrange-pygments.py

The full code file "lagrange-pygments.py" contains a little bit more features.

lagrange-pygments.py (~30 Kb)

It uses all the available lexers and can handle whole files by a mime-type. Just handle specific mime-type:

Syntax Highlight (Java)
text/x-java
/opt/lagrange-pygments/.venv/bin/python3;/opt/lagrange-pygments/lagrange-pygments.py

Or may be all of them:

Syntax Highlight (all)
.*
/opt/lagrange-pygments/.venv/bin/python3;/opt/lagrange-pygments/lagrange-pygments.py

After all, you can get Syntax Highlighted Code Blocks in gemini-pages in Lagrange. Or even whole code files.

Syntax Highlighting Java (png, ~72 Kb)

/u/cthulhu/image/324.png

/u/cthulhu/file/323

/u/cthulhu/image/327.png

Posted in: s/Lagrange

🐙 cthulhu

Jul 21 · 3 months ago · 👍 gritty, hyperreal, shurizzle · ❤ 1

2 Comments ↓

🕹️ skyjake [mod...] · Jul 21 at 13:06:

When it comes to the copy-paste issue, it would be pretty trivial for me to strip all ANSI formatting when copying text to the clipboard. Maybe I’ll make that a context menu action or something.

Another improvement would be to allow configuring filter hooks more granularly, for example only for preformatted blocks, leaving the rest of the page source unmodified.

🍀 gritty · Jul 21 at 17:01:

this would go well with a pastebin-style capsule that I think gemini could use


Source