MVP I need for an upcoming article (and docs).
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 <mosra/m.css$master/plugins/m/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 <mosra/m.css$master/plugins/m/ansilexer.py>` file or use it
+directly from your Git clone of m.css. Example usage:
.. code:: sh
--- /dev/null
+\e[38;2;220;220;220m\e[48;2;220;220;220m██\e[0m \e[38;2;165;201;234m\e[48;2;165;201;234m██\e[0m \e[38;2;59;210;103m\e[48;2;59;210;103m██\e[0m \e[38;2;199;207;47m\e[48;2;199;207;47m██\e[0m \e[38;2;205;52;49m\e[48;2;205;52;49m██\e[0m \e[38;2;47;131;204m\e[48;2;47;131;204m▓▓\e[0m \e[38;2;116;116;116m\e[48;2;116;116;116m▒▒\e[0m
+
+\e[38;2;59;210;103m \e[0m \e[38;2;59;210;103m \e[0m \e[38;2;59;210;103m░░\e[0m \e[38;2;59;210;103m▒▒\e[0m \e[38;2;59;210;103m▓▓\e[0m \e[38;2;59;210;103m\e[48;2;59;210;103m██\e[0m
.. 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`_
--------------
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
<h1>
ANSI color escape code highlighting
</h1>
-<pre class="m-console">!<span class="g g-AnsiBlue">[</span><span class="g g-AnsiBrightWhite">mosra@don-perverzo </span><span class="g g-AnsiWhite">m.css</span><span class="g g-AnsiBlue">]</span><span class="g g-AnsiBrightCyan">$ </span></pre>
+<pre class="m-console">!<span class="g g-AnsiBlue">[</span><span class="g g-AnsiBrightWhite">mosra@don-perverzo </span><span class="g g-AnsiWhite">m.css</span><span class="g g-AnsiBlue">]</span><span class="g g-AnsiBrightCyan">$ </span></pre><pre class="m-console"><span style="color: #dcdcdc; background-color: #dcdcdc">██</span> <span style="color: #a5c9ea; background-color: #a5c9ea">██</span> <span style="color: #3bd267; background-color: #3bd267">██</span> <span style="color: #c7cf2f; background-color: #c7cf2f">██</span> <span style="color: #cd3431; background-color: #cd3431">██</span> <span style="color: #2f83cc; background-color: #2f83cc">▓▓</span> <span style="color: #747474; background-color: #747474">▒▒</span>
+
+<span style="color: #3bd267"> </span> <span style="color: #3bd267"> </span> <span style="color: #3bd267">░░</span> <span style="color: #3bd267">▒▒</span> <span style="color: #3bd267">▓▓</span> <span style="color: #3bd267; background-color: #3bd267">██</span></pre>
</div>
</div>
</div>
--- /dev/null
+../../../plugins/m/test/code/console-colors.ansi
\ No newline at end of file
!\e[0;34m[\e[1;37mmosra@don-perverzo \e[0;37mm.css\e[0;34m]\e[1;36m$ \e[0m
@endcode
+@include console-colors.ansi
+
*/
/** @page warnings Code that produces warnings
# DEALINGS IN THE SOFTWARE.
#
+import re
+
from pygments.lexer import RegexLexer
+from pygments.formatters import HtmlFormatter
from pygments.token import *
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
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()
--- /dev/null
+\e[38;2;220;220;220m\e[48;2;220;220;220m██\e[0m \e[38;2;165;201;234m\e[48;2;165;201;234m██\e[0m \e[38;2;59;210;103m\e[48;2;59;210;103m██\e[0m \e[38;2;199;207;47m\e[48;2;199;207;47m██\e[0m \e[38;2;205;52;49m\e[48;2;205;52;49m██\e[0m \e[38;2;47;131;204m\e[48;2;47;131;204m▓▓\e[0m \e[38;2;116;116;116m\e[48;2;116;116;116m▒▒\e[0m
+
+Leading zeros: \e[38;2;15;116;3m\e[48;2;15;116;3m▒▒\e[0m \e[38;2;15;116;3m▒▒\e[0m
+
+\e[38;2;59;210;103m \e[0m \e[38;2;59;210;103m \e[0m \e[38;2;59;210;103m░░\e[0m \e[38;2;59;210;103m▒▒\e[0m \e[38;2;59;210;103m▓▓\e[0m \e[38;2;59;210;103m\e[48;2;59;210;103m██\e[0m
<pre class="m-console">!<span class="g g-AnsiBlue">[</span><span class="g g-AnsiBrightWhite">mosra@don-perverzo </span><span class="g g-AnsiWhite">m.css</span><span class="g g-AnsiBlue">]</span><span class="g g-AnsiBrightCyan">$ </span>ls
CONTRIBUTING.rst CREDITS.rst <span class="g g-AnsiBrightBlue">doc</span> <span class="g g-AnsiBrightBlue">plugins</span> README.rst
COPYING <span class="g g-AnsiBrightBlue">css</span> <span class="g g-AnsiBrightBlue">documentation</span> <span class="g g-AnsiBrightBlue">pelican-theme</span> <span class="g g-AnsiBrightBlue">site</span></pre>
+<p>Console colors:</p>
+<pre class="m-console"><span style="color: #dcdcdc; background-color: #dcdcdc">██</span> <span style="color: #a5c9ea; background-color: #a5c9ea">██</span> <span style="color: #3bd267; background-color: #3bd267">██</span> <span style="color: #c7cf2f; background-color: #c7cf2f">██</span> <span style="color: #cd3431; background-color: #cd3431">██</span> <span style="color: #2f83cc; background-color: #2f83cc">▓▓</span> <span style="color: #747474; background-color: #747474">▒▒</span>
+
+Leading zeros: <span style="color: #0f7403; background-color: #0f7403">▒▒</span> <span style="color: #0f7403">▒▒</span>
+
+<span style="color: #3bd267"> </span> <span style="color: #3bd267"> </span> <span style="color: #3bd267">░░</span> <span style="color: #3bd267">▒▒</span> <span style="color: #3bd267">▓▓</span> <span style="color: #3bd267; background-color: #3bd267">██</span></pre>
<pre class="m-code">// this language is not highlighted</pre>
<p>Properly preserve backslashes: <code class="m-code"><span class="k">\frac</span><span class="nb">{</span>a<span class="nb">}{</span>b<span class="nb">}</span></code></p>
<p>Don't trim leading spaces in blocks:</p>
.. include:: console.ansi
:code: ansi
+Console colors:
+
+.. include:: console-colors.ansi
+ :code: ansi
+
.. code:: whatthefuck
// this language is not highlighted