diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-07-31 15:09:24 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-07-31 15:09:24 +0200 |
commit | 4b3b73da8ba5f31ec6a89cefe4737ffdfe6236e4 (patch) | |
tree | 260aa945aab66718ec0f88cc96ac6e530f110e27 | |
parent | 171e7a112b85c103358bf9e45f60a35c71d298c3 (diff) | |
download | groff-tools-4b3b73da8ba5f31ec6a89cefe4737ffdfe6236e4.tar.gz |
added pygments-groff.py - a syntax highlighting preprocessor based on Pygments
-rw-r--r-- | README.md | 40 | ||||
-rwxr-xr-x | pygments-groff.py | 43 |
2 files changed, 83 insertions, 0 deletions
@@ -23,6 +23,46 @@ To build the sample `select-from.ebnf`, type something like: cat samples/select-from.ebnf | ./ebnf.sno | pic | groff -Tps >select-from.ps +## HIGHLIGHT (Python) + +`pygments-groff.py` is a syntax highlighting preprocessor based on [Pygments](https://pygments.org/) and +consequently written in Python 3. +It is the most powerful (and probably fastest) of the syntax highlighting preprocessors presented here. +It should also be more portable as it does not rely on stdout redirection magic. +It should work with all Groff macro suites and even preserves the line numbering +in Groff error messages. + +You can process embedded blocks of code as in the following ms-based example: + +```groff +.LD +.CW +.lg 0 +.HIGHLIGHT c +#include <stdio.h> + +int main(int argc, char **argv) +{ + printf("Hello world!\n"); + return 0; +} +.HIGHLIGHT +.DE +``` + +Note that you may have to do more before `.HIGHLIGHT` - for instance redefine chars - +depending on your use case. + +The `default` language identifier is useful to include code without highlighting, +but still benefit from Pygment's preprocessing in order to achieve verbatim text. +A list of language identifiers (short names) can be found on the [Pygments website](https://pygments.org/languages/). + +Just like `highlight.lua`, you can specify a file name directly after the language identifier: + +```groff +.HIGHLIGHT c hello.c +``` + ## HIGHLIGHT (SNOBOL4) `highlight.sno` is a small preprocessor written in [CSNOBOL4](http://www.snobol4.org/csnobol4/) diff --git a/pygments-groff.py b/pygments-groff.py new file mode 100755 index 0000000..49637eb --- /dev/null +++ b/pygments-groff.py @@ -0,0 +1,43 @@ +#!/usr/local/bin/python3.9 +from pygments.lexers import get_lexer_by_name, RawTokenLexer +from pygments.formatters import GroffFormatter +from pygments import highlight +import re +from sys import stdin, stdout, stderr + +formatter = GroffFormatter(style="sas") + +start_pattern = re.compile(r"\. *HIGHLIGHT +([^ ]+)( +(.*))?\n") +end_pattern = re.compile(r"\. *HIGHLIGHT *\n") + +while True: + for line in stdin: + stdout.write(line) + params = start_pattern.match(line) + if params: + break + if not params: # EOF + break + + lang, filename = params.group(1, 3) + + lexer = RawTokenLexer() if lang == "default" else get_lexer_by_name(lang) + # NOTE: This option is broken and will result in a bogus empty line with the GroffFormatter + lexer.ensurenl = False + + contents = [] + if filename: + contents.append(open(filename).read()) + stdout.write(".ds HIGHLIGHT-LF \\n[.c] \\n[.F]\n") + stdout.write(".lf 1 "+filename+"\n") + else: + for line in stdin: + if end_pattern.match(line): + stdout.write(line) + break + contents.append(line) + + formatted = highlight("".join(contents), lexer, formatter) + stdout.write(formatted.replace("\n\n", "\n\\&\n")+"\n") + if filename: + stdout.write(".lf \\*[HIGHLIGHT-LF]\n") |