💾 Archived View for bbs.geminispace.org › s › Lagrange › 18731 captured on 2024-08-31 at 15:43:43. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-08-19)
-=-=-=-=-=-=-
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.
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 is a Python library for rich text and beautiful formatting in the terminal.
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.
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
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:])
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.
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)
Jul 21 · 6 weeks ago · 👍 gritty, hyperreal, shurizzle · ❤ 1
🕹️ 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.
this would go well with a pastebin-style capsule that I think gemini could use