From 7f91cb500e1a16d3701014deddf5d6b4618beed3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 29 Apr 2019 19:27:02 +0200 Subject: [PATCH] m.code: rudimentary support for 24bit console colors. MVP I need for an upcoming article (and docs). --- doc/css/components.rst | 5 ++-- doc/plugins/math-and-code-console-colors.ansi | 3 ++ doc/plugins/math-and-code.rst | 10 +++++++ documentation/doxygen.py | 5 +++- .../contents_code_language/ansi.html | 4 ++- .../console-colors.ansi | 1 + .../contents_code_language/input.dox | 2 ++ plugins/ansilexer.py | 30 +++++++++++++++++++ plugins/m/code.py | 5 +++- plugins/m/test/code/console-colors.ansi | 5 ++++ plugins/m/test/code/page.html | 6 ++++ plugins/m/test/code/page.rst | 5 ++++ 12 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 doc/plugins/math-and-code-console-colors.ansi create mode 120000 documentation/test_doxygen/contents_code_language/console-colors.ansi create mode 100644 plugins/m/test/code/console-colors.ansi diff --git a/doc/css/components.rst b/doc/css/components.rst index f099aeb5..968fd0f6 100644 --- a/doc/css/components.rst +++ b/doc/css/components.rst @@ -898,8 +898,9 @@ Besides code, it's also possible to "highlight" ANSI-colored terminal output. For that, m.css provides a custom Pygments lexer that's together with `pygments-console.css <{filename}/css.rst>`_ able to detect and highlight the basic 4-bit color codes (8 foreground colors in either normal or bright -version). Download the :gh:`ansilexer.py ` -file or use it directly from your Git clone of m.css. Example usage: +version) and a tiny subset of the 24-bit color scheme as well. Download the +:gh:`ansilexer.py ` file or use it +directly from your Git clone of m.css. Example usage: .. code:: sh diff --git a/doc/plugins/math-and-code-console-colors.ansi b/doc/plugins/math-and-code-console-colors.ansi new file mode 100644 index 00000000..a3fa91a1 --- /dev/null +++ b/doc/plugins/math-and-code-console-colors.ansi @@ -0,0 +1,3 @@ +██ ██ ██ ██ ██ ▓▓ ▒▒ + +    ░░ ▒▒ ▓▓ ██ diff --git a/doc/plugins/math-and-code.rst b/doc/plugins/math-and-code.rst index 2287aa2b..01497aac 100644 --- a/doc/plugins/math-and-code.rst +++ b/doc/plugins/math-and-code.rst @@ -419,6 +419,16 @@ terminal, it's best to have the listings in external files and use .. include:: math-and-code-console.ansi :code: ansi + :class: m-nopad + +Apart from the basic color set there's also a very rudimentary support for +24bit colors using the ``\033[{?};2;{r};{g};{b}m`` color sequence --- currently +either just the foreground (the ``\033[38;2;`` prefix) or foreground +immediately followed by background color specification (the +``\033[48;2;`` prefix): + +.. include:: math-and-code-console-colors.ansi + :code: ansi `Code figure`_ -------------- diff --git a/documentation/doxygen.py b/documentation/doxygen.py index e8d98f82..f610d196 100755 --- a/documentation/doxygen.py +++ b/documentation/doxygen.py @@ -1428,7 +1428,10 @@ def parse_desc_internal(state: State, element: ET.Element, immediate_parent: ET. else: class_ = 'm-code' - formatter = HtmlFormatter(nowrap=True) + if isinstance(lexer, ansilexer.AnsiLexer): + formatter = ansilexer.HtmlAnsiFormatter() + else: + formatter = HtmlFormatter(nowrap=True) highlighted = highlight(code, lexer, formatter) # Strip whitespace around if inline code, strip only trailing # whitespace if a block diff --git a/documentation/test_doxygen/contents_code_language/ansi.html b/documentation/test_doxygen/contents_code_language/ansi.html index afc5348b..4457075d 100644 --- a/documentation/test_doxygen/contents_code_language/ansi.html +++ b/documentation/test_doxygen/contents_code_language/ansi.html @@ -22,7 +22,9 @@

ANSI color escape code highlighting

-
![mosra@don-perverzo m.css]$ 
+
![mosra@don-perverzo m.css]$ 
██ ██ ██ ██ ██ ▓▓ ▒▒
+
+      ░░ ▒▒ ▓▓ ██
diff --git a/documentation/test_doxygen/contents_code_language/console-colors.ansi b/documentation/test_doxygen/contents_code_language/console-colors.ansi new file mode 120000 index 00000000..f10d6d62 --- /dev/null +++ b/documentation/test_doxygen/contents_code_language/console-colors.ansi @@ -0,0 +1 @@ +../../../plugins/m/test/code/console-colors.ansi \ No newline at end of file diff --git a/documentation/test_doxygen/contents_code_language/input.dox b/documentation/test_doxygen/contents_code_language/input.dox index c8550a97..6a2033fa 100644 --- a/documentation/test_doxygen/contents_code_language/input.dox +++ b/documentation/test_doxygen/contents_code_language/input.dox @@ -36,6 +36,8 @@ Another paragraph. ![mosra@don-perverzo m.css]$  @endcode +@include console-colors.ansi + */ /** @page warnings Code that produces warnings diff --git a/plugins/ansilexer.py b/plugins/ansilexer.py index dd11d5ca..d9d12e39 100644 --- a/plugins/ansilexer.py +++ b/plugins/ansilexer.py @@ -22,7 +22,10 @@ # DEALINGS IN THE SOFTWARE. # +import re + from pygments.lexer import RegexLexer +from pygments.formatters import HtmlFormatter from pygments.token import * class AnsiLexer(RegexLexer): @@ -65,8 +68,35 @@ class AnsiLexer(RegexLexer): yield (match.start(), string_to_tokentype(token), text) + def callback_fg_color(lexer, match): + token = 'Generic.AnsiForegroundColor{:02x}{:02x}{:02x}'.format( + int(match.group(1)), int(match.group(2)), int(match.group(3))) + yield (match.start, string_to_tokentype(token), match.group(4)) + + def callback_fg_bg_color(lexer, match): + token = 'Generic.AnsiForegroundBackgroundColor{:02x}{:02x}{:02x}'.format( + int(match.group(1)), int(match.group(2)), int(match.group(3))) + yield (match.start, string_to_tokentype(token), match.group(4)) + tokens = { 'root': [ ('[^\x1b]+', Text), + ('\x1b\\[38;2;(\\d+);(\\d+);(\\d+)m\x1b\\[48;2;\\d+;\\d+;\\d+m([^\x1b]+)\x1b\\[0m', callback_fg_bg_color), + ('\x1b\\[38;2;(\\d+);(\\d+);(\\d+)m([^\x1b]+)\x1b\\[0m', callback_fg_color), ('\x1b\\[(\\d+)(;\\d+)?m([^\x1b]*)', callback)] } + +_ansi_fg_color_re = re.compile('class="g g-AnsiForegroundColor([0-9a-f]{6})"') +_ansi_fg_bg_color_re = re.compile('class="g g-AnsiForegroundBackgroundColor([0-9a-f]{6})"') + +class HtmlAnsiFormatter(HtmlFormatter): + def wrap(self, source, outfile): + return self._wrap_code(source) + + def _wrap_code(self, source): + for i, t in source: + if i == 1: # it's a line of formatted code + t = _ansi_fg_bg_color_re.sub('style="color: #\\1; background-color: #\\1"', t) + t = _ansi_fg_color_re.sub('style="color: #\\1"', t) + #t += 'H' + yield i, t diff --git a/plugins/m/code.py b/plugins/m/code.py index 4290e01b..4bb42740 100644 --- a/plugins/m/code.py +++ b/plugins/m/code.py @@ -59,7 +59,10 @@ def _highlight(code, language, options, is_block): else: class_ = 'm-code' - formatter = HtmlFormatter(nowrap=True, **options) + if isinstance(lexer, ansilexer.AnsiLexer): + formatter = ansilexer.HtmlAnsiFormatter(**options) + else: + formatter = HtmlFormatter(nowrap=True, **options) parsed = highlight(code, lexer, formatter).rstrip() if not is_block: parsed.lstrip() diff --git a/plugins/m/test/code/console-colors.ansi b/plugins/m/test/code/console-colors.ansi new file mode 100644 index 00000000..ccd327f6 --- /dev/null +++ b/plugins/m/test/code/console-colors.ansi @@ -0,0 +1,5 @@ +██ ██ ██ ██ ██ ▓▓ ▒▒ + +Leading zeros: ▒▒ ▒▒ + +    ░░ ▒▒ ▓▓ ██ diff --git a/plugins/m/test/code/page.html b/plugins/m/test/code/page.html index 27374967..7d50e386 100644 --- a/plugins/m/test/code/page.html +++ b/plugins/m/test/code/page.html @@ -34,6 +34,12 @@ rendered as plain monospace text: code.

![mosra@don-perverzo m.css]$ ls
 CONTRIBUTING.rst  CREDITS.rst  doc            plugins        README.rst
 COPYING           css          documentation  pelican-theme  site
+

Console colors:

+
██ ██ ██ ██ ██ ▓▓ ▒▒
+
+Leading zeros: ▒▒ ▒▒
+
+      ░░ ▒▒ ▓▓ ██
// this language is not highlighted

Properly preserve backslashes: \frac{a}{b}

Don't trim leading spaces in blocks:

diff --git a/plugins/m/test/code/page.rst b/plugins/m/test/code/page.rst index 0e92fae8..e3d92548 100644 --- a/plugins/m/test/code/page.rst +++ b/plugins/m/test/code/page.rst @@ -26,6 +26,11 @@ rendered as plain monospace text: :code:`code`. .. include:: console.ansi :code: ansi +Console colors: + +.. include:: console-colors.ansi + :code: ansi + .. code:: whatthefuck // this language is not highlighted -- 2.30.2