chiark / gitweb /
m.code: support inverse video in the ANSI lexer.
authorVladimír Vondruš <mosra@centrum.cz>
Tue, 21 Feb 2023 10:47:30 +0000 (11:47 +0100)
committerVladimír Vondruš <mosra@centrum.cz>
Tue, 21 Feb 2023 10:47:46 +0000 (11:47 +0100)
I'm very glad for the extremely extensive code coverage here. Without
it, I'd break half of other stuff by accident.

css/m-dark+documentation.compiled.css
css/m-dark.compiled.css
css/m-light+documentation.compiled.css
css/m-light.compiled.css
css/pygments-console.css
css/pygments-console.py
plugins/ansilexer.py
plugins/m/test/code/console-colors.ansi
plugins/m/test/code/page.html

index 9e36c569e4de7de6fc5733324084e7bbec074895..e24e570b46b4990369f04825a49c72663b90832a 100644 (file)
@@ -2619,12 +2619,14 @@ article:last-child, article section:last-child { margin-bottom: 0; }
 .m-console .g-AnsiBrightCyan { color: #16a085; font-weight: bold }
 .m-console .g-AnsiBrightDefault { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightGreen { color: #1cdc9a; font-weight: bold }
+.m-console .g-AnsiBrightInvertedDefault { color: #1a1c1d; font-weight: bold }
 .m-console .g-AnsiBrightMagenta { color: #8e44ad; font-weight: bold }
 .m-console .g-AnsiBrightRed { color: #c0392b; font-weight: bold }
 .m-console .g-AnsiBrightWhite { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightYellow { color: #fdbc4b; font-weight: bold }
 .m-console .g-AnsiCyan { color: #1abc9c }
 .m-console .g-AnsiGreen { color: #11d116 }
+.m-console .g-AnsiInvertedDefault { color: #1a1c1d }
 .m-console .g-AnsiMagenta { color: #9b59b6 }
 .m-console .g-AnsiRed { color: #ed1515 }
 .m-console .g-AnsiWhite { color: #fcfcfc }
index 587e8da80a5c5c8e016d278dcc7d267c9fb8356e..571467e65c9c1a03ee2e843b6700beedf7a6bcf1 100644 (file)
@@ -2619,12 +2619,14 @@ article:last-child, article section:last-child { margin-bottom: 0; }
 .m-console .g-AnsiBrightCyan { color: #16a085; font-weight: bold }
 .m-console .g-AnsiBrightDefault { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightGreen { color: #1cdc9a; font-weight: bold }
+.m-console .g-AnsiBrightInvertedDefault { color: #1a1c1d; font-weight: bold }
 .m-console .g-AnsiBrightMagenta { color: #8e44ad; font-weight: bold }
 .m-console .g-AnsiBrightRed { color: #c0392b; font-weight: bold }
 .m-console .g-AnsiBrightWhite { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightYellow { color: #fdbc4b; font-weight: bold }
 .m-console .g-AnsiCyan { color: #1abc9c }
 .m-console .g-AnsiGreen { color: #11d116 }
+.m-console .g-AnsiInvertedDefault { color: #1a1c1d }
 .m-console .g-AnsiMagenta { color: #9b59b6 }
 .m-console .g-AnsiRed { color: #ed1515 }
 .m-console .g-AnsiWhite { color: #fcfcfc }
index ea5206acdf009c7a6f09be426cca2ce6e980a4f3..31ebcdab24f014c4c8a09db7004b732072b62e81 100644 (file)
@@ -2552,12 +2552,14 @@ article:last-child, article section:last-child { margin-bottom: 0; }
 .m-console .g-AnsiBrightCyan { color: #16a085; font-weight: bold }
 .m-console .g-AnsiBrightDefault { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightGreen { color: #1cdc9a; font-weight: bold }
+.m-console .g-AnsiBrightInvertedDefault { color: #1a1c1d; font-weight: bold }
 .m-console .g-AnsiBrightMagenta { color: #8e44ad; font-weight: bold }
 .m-console .g-AnsiBrightRed { color: #c0392b; font-weight: bold }
 .m-console .g-AnsiBrightWhite { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightYellow { color: #fdbc4b; font-weight: bold }
 .m-console .g-AnsiCyan { color: #1abc9c }
 .m-console .g-AnsiGreen { color: #11d116 }
+.m-console .g-AnsiInvertedDefault { color: #1a1c1d }
 .m-console .g-AnsiMagenta { color: #9b59b6 }
 .m-console .g-AnsiRed { color: #ed1515 }
 .m-console .g-AnsiWhite { color: #fcfcfc }
index 421cb46d4bc12ad64f0c7d9446910556a1fd3343..a8c42325c1f975076012ea7a77ad972ed5dde4ec 100644 (file)
@@ -2552,12 +2552,14 @@ article:last-child, article section:last-child { margin-bottom: 0; }
 .m-console .g-AnsiBrightCyan { color: #16a085; font-weight: bold }
 .m-console .g-AnsiBrightDefault { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightGreen { color: #1cdc9a; font-weight: bold }
+.m-console .g-AnsiBrightInvertedDefault { color: #1a1c1d; font-weight: bold }
 .m-console .g-AnsiBrightMagenta { color: #8e44ad; font-weight: bold }
 .m-console .g-AnsiBrightRed { color: #c0392b; font-weight: bold }
 .m-console .g-AnsiBrightWhite { color: #ffffff; font-weight: bold }
 .m-console .g-AnsiBrightYellow { color: #fdbc4b; font-weight: bold }
 .m-console .g-AnsiCyan { color: #1abc9c }
 .m-console .g-AnsiGreen { color: #11d116 }
+.m-console .g-AnsiInvertedDefault { color: #1a1c1d }
 .m-console .g-AnsiMagenta { color: #9b59b6 }
 .m-console .g-AnsiRed { color: #ed1515 }
 .m-console .g-AnsiWhite { color: #fcfcfc }
index 0446bbd87d3aa32d763655c3bc70e065ae80dd80..d74ad0036cb7846aa417cf0da4eefb3c7bcccdeb 100644 (file)
 .m-console .g-AnsiBrightCyan { color: #16a085; font-weight: bold } /* Generic.AnsiBrightCyan */
 .m-console .g-AnsiBrightDefault { color: #ffffff; font-weight: bold } /* Generic.AnsiBrightDefault */
 .m-console .g-AnsiBrightGreen { color: #1cdc9a; font-weight: bold } /* Generic.AnsiBrightGreen */
+.m-console .g-AnsiBrightInvertedDefault { color: #1a1c1d; font-weight: bold } /* Generic.AnsiBrightInvertedDefault */
 .m-console .g-AnsiBrightMagenta { color: #8e44ad; font-weight: bold } /* Generic.AnsiBrightMagenta */
 .m-console .g-AnsiBrightRed { color: #c0392b; font-weight: bold } /* Generic.AnsiBrightRed */
 .m-console .g-AnsiBrightWhite { color: #ffffff; font-weight: bold } /* Generic.AnsiBrightWhite */
 .m-console .g-AnsiBrightYellow { color: #fdbc4b; font-weight: bold } /* Generic.AnsiBrightYellow */
 .m-console .g-AnsiCyan { color: #1abc9c } /* Generic.AnsiCyan */
 .m-console .g-AnsiGreen { color: #11d116 } /* Generic.AnsiGreen */
+.m-console .g-AnsiInvertedDefault { color: #1a1c1d } /* Generic.AnsiInvertedDefault */
 .m-console .g-AnsiMagenta { color: #9b59b6 } /* Generic.AnsiMagenta */
 .m-console .g-AnsiRed { color: #ed1515 } /* Generic.AnsiRed */
 .m-console .g-AnsiWhite { color: #fcfcfc } /* Generic.AnsiWhite */
index 49955a40b8c174035dbb026c248a20a7257081d3..e0bee34b75f5016e2f9d6773c0104bcf85d8ca12 100644 (file)
@@ -40,6 +40,7 @@ class ConsoleStyle(Style):
 
         # ANSI highlighting. Same order as in Konsole style dialog, following
         # the Breeze theme.
+        Generic.AnsiInvertedDefault:          '#1a1c1d',
         Generic.AnsiBlack:                    '#232627',
         Generic.AnsiRed:                      '#ed1515',
         Generic.AnsiGreen:                    '#11d116',
@@ -48,6 +49,7 @@ class ConsoleStyle(Style):
         Generic.AnsiMagenta:                  '#9b59b6',
         Generic.AnsiCyan:                     '#1abc9c',
         Generic.AnsiWhite:                    '#fcfcfc',
+        Generic.AnsiBrightInvertedDefault:    'bold #1a1c1d',
         Generic.AnsiBrightBlack:              'bold #7f8c8d',
         Generic.AnsiBrightRed:                'bold #c0392b',
         Generic.AnsiBrightGreen:              'bold #1cdc9a',
index 0524650753fc17610b3d2587ff87dc10f8c2e9bd..fd791d26973224a1b6555daece95ee97c55efe9b 100644 (file)
@@ -30,9 +30,8 @@ from pygments.lexer import RegexLexer
 from pygments.formatters import HtmlFormatter
 from pygments.token import *
 
-# Support ANSI SGR codes in input, styling the output.
-# Code definitions are taken from
-# http://man7.org/linux/man-pages/man4/console_codes.4.html, which
+# Support ANSI SGR codes in input, styling the output. Code definitions are
+# taken from http://man7.org/linux/man-pages/man4/console_codes.4.html, which
 # appears in part below, in case it disappears:
 #
 # ECMA-48 Set Graphics Rendition
@@ -100,9 +99,8 @@ from pygments.token import *
 # For historical reasons, all "brown"s above are replaced with "yellow"
 # by m.css.
 #
-# AnsiLexer supports commands 0, 1, 22, 30–39, 40–49, 90–97, and 100–107
-# (ranges inclusive).
-# All other commands will be ignored completely.
+# AnsiLexer supports commands 0, 1, 7, 22, 27, 30–39, 40–49, 90–97, and 100–107
+# (ranges inclusive). All other commands will be ignored completely.
 #
 # Foreground colors named Bright* are not affected by the "bright" SGR
 # setting—they will always appear bright, even after command 22 resets the
@@ -152,6 +150,7 @@ class AnsiLexer(RegexLexer):
         RegexLexer.__init__(self, **options)
 
         self._bright = False
+        self._invert = False
         self._foreground = ''
         self._background = ''
 
@@ -169,12 +168,17 @@ class AnsiLexer(RegexLexer):
             command = parameters.pop(0)
             if command == 0:
                 self._bright = False
+                self._invert = False
                 self._foreground = ''
                 self._background = ''
             elif command == 1:
                 self._bright = True
+            elif command == 7:
+                self._invert = True
             elif command == 22:
                 self._bright = False
+            elif command == 27:
+                self._invert = False
             elif command >= 30 and command <= 37:
                 self._foreground = self._named_colors[command - 30]
             elif command == 38:
@@ -204,15 +208,35 @@ class AnsiLexer(RegexLexer):
                 self._background = ('Bright' +
                                     self._named_colors[command - 100])
 
-        if self._bright and self._foreground in self._named_colors:
-            token = 'Bright' + self._foreground
-        elif self._bright and not self._foreground:
-            token = 'BrightDefault'
+        # For "inverse video", foreground and background colors are swapped
+        if self._invert:
+            foreground, background = self._background, self._foreground
         else:
-            token = self._foreground
+            foreground, background = self._foreground, self._background
 
-        if (self._background):
-            token += '-On' + self._background
+        # If the bright bit is set for named colors (foreground or background
+        # in case of reverse video), use their bright variant
+        if self._bright and (not foreground or (foreground in self._named_colors)):
+            token = 'Bright'
+        else:
+            token = ''
+
+        # If the foreground color (or background in case of inverse video) is
+        # set, use it. Otherwise pick a default if it's needed for the bright
+        # variant, for inverse video or both.
+        if foreground:
+            token += foreground
+        else:
+            if self._invert:
+                token += 'Inverted'
+            if token:
+                token += 'Default'
+
+        # If the background color is set (or foreground in case of inverse
+        # video), use it as well. This gets subsequently separated to either a
+        # secondary CSS class or a separate background-color style item.
+        if background:
+            token += '-On' + background
 
         if token:
             token = 'Generic.Ansi' + token
index c17093c7e0816fbda240875fd1675e5e39f52b65..7a3016f036637679f42d122c824f6c4a08dbe741 100644 (file)
@@ -85,15 +85,21 @@ nor do RGB or palette-based colors\e[0m
   \e[38;2;0;128;128;48;2;0;128;128mRGB 0,128,128 on RGB 0,128,128\e[0m
   \e[38;2;192;192;0;48;2;0;128;128mRGB 192,192,0 on RGB 0,128,128\e[0m
 
+\e[1mInverted colors:\e[0m
+  \e[34mBlue \e[7;34mInverted\e[7;34m Inverted again\e[0m Reset
+  \e[34mBlue \e[7;34mInverted\e[27;34m Inverted back\e[0m Reset
+  \e[34mBlue \e[1;7;34mInverted and bright\e[7;34m Inverted again\e[0m Reset
+  \e[34mBlue \e[1;7;34mInverted and bright\e[27;34m Inverted back\e[0m Reset
+  \e[1;34mBright blue \e[7;34mInverted\e[7;34m Inverted again\e[0m Reset
+  \e[1;34mBright blue \e[7;34mInverted\e[27;34m Inverted back\e[0m Reset
+
 \e[1mOther commands are ignored\e[0m
   \e[2mhalf-bright\e[0m
   \e[4mset underscore\e[0m
   \e[5mset blink\e[0m
-  \e[7mset reverse video\e[0m
   \e[10mreset selected mapping, display control flag, and toggle\e[0m
   \e[11mselect null mapping, set display control flag, reset\e[0m
   \e[12mselect null mapping, set display control flag, set toggle\e[0m
   \e[21mset underline\e[0m
   \e[24munderline off\e[0m
   \e[25mblink off\e[0m
-  \e[27mreverse video off\e[0m
index 2a63fc1e06fc20bd4d5b88a3329c0e92955b6385..59fdeb41c2e9c985e41efa2214c6499286d7135d 100644 (file)
@@ -138,18 +138,24 @@ ASan reports:
   <span style="color: #008080; background-color: #008080">RGB 0,128,128 on RGB 0,128,128</span>
   <span style="color: #c0c000; background-color: #008080">RGB 192,192,0 on RGB 0,128,128</span>
 
+<span class="g g-AnsiBrightDefault">Inverted colors:</span>
+  <span class="g g-AnsiBlue">Blue </span><span class="g g-AnsiInvertedDefault g-AnsiBackgroundBlue">Inverted Inverted again</span> Reset
+  <span class="g g-AnsiBlue">Blue </span><span class="g g-AnsiInvertedDefault g-AnsiBackgroundBlue">Inverted</span><span class="g g-AnsiBlue"> Inverted back</span> Reset
+  <span class="g g-AnsiBlue">Blue </span><span class="g g-AnsiBrightInvertedDefault g-AnsiBackgroundBlue">Inverted and bright Inverted again</span> Reset
+  <span class="g g-AnsiBlue">Blue </span><span class="g g-AnsiBrightInvertedDefault g-AnsiBackgroundBlue">Inverted and bright</span><span class="g g-AnsiBrightBlue"> Inverted back</span> Reset
+  <span class="g g-AnsiBrightBlue">Bright blue </span><span class="g g-AnsiBrightInvertedDefault g-AnsiBackgroundBlue">Inverted Inverted again</span> Reset
+  <span class="g g-AnsiBrightBlue">Bright blue </span><span class="g g-AnsiBrightInvertedDefault g-AnsiBackgroundBlue">Inverted</span><span class="g g-AnsiBrightBlue"> Inverted back</span> Reset
+
 <span class="g g-AnsiBrightDefault">Other commands are ignored</span>
   half-bright
   set underscore
   set blink
-  set reverse video
   reset selected mapping, display control flag, and toggle
   select null mapping, set display control flag, reset
   select null mapping, set display control flag, set toggle
   set underline
   underline off
-  blink off
-  reverse video off</pre>
+  blink off</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> ... and backticks:
 <code class="m-code"><span class="na">:ref:</span><span class="nv">`a function &lt;os.path.join()&gt;`</span></code></p>