changeset 212:18553f595b34

Allow nested \TEXT and \EXPR commands. \TEXT within \TEXT and \EXPR within \EXPR is allowed!
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 14 May 2026 07:30:38 +0200
parents 33a722c8ae17
children d470250f8451
files docs/lexer-algpseudocode.rst pygments_lexer_pseudocode2/lexers/algpseudocode.py tests/test_algpseudo.py tests/test_filter.py
diffstat 4 files changed, 66 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/docs/lexer-algpseudocode.rst	Wed May 13 21:22:33 2026 +0200
+++ b/docs/lexer-algpseudocode.rst	Thu May 14 07:30:38 2026 +0200
@@ -59,6 +59,8 @@
     A closing curly brace can be quoted with ``\}`` to not end the
     text mode prematurely.
 
+  - ``\EXPR`` or ``\EXPRESSION`` as nested construct
+
   - ``\NAME``, ``\CALL`` and ``\GETS``
 
   - ``\REM`` and ``\REMARK`` for remarks (aka comments)
@@ -80,6 +82,8 @@
     A closing curly brace can be quoted with ``\}`` to not end the expression
     mode prematurely.
 
+  - ``\TEXT`` as nested construct
+
   - ``\REM`` and ``\REMARK`` for remarks (aka comments)
 
   - :ref:`explicit-token-types`
@@ -113,7 +117,7 @@
 
      **Type:** :py:class:`str` or :py:obj:`None`
 
-     **Default:** :py:obj:`None` (yields ``←``)
+     **Default:** :py:obj:`None` (yields ``⟵``)
 
      The operator symbol to be printed by the command ``\GETS``.
 
--- a/pygments_lexer_pseudocode2/lexers/algpseudocode.py	Wed May 13 21:22:33 2026 +0200
+++ b/pygments_lexer_pseudocode2/lexers/algpseudocode.py	Thu May 14 07:30:38 2026 +0200
@@ -365,6 +365,9 @@
             (r"(?i)\\(call|name)[ \t]*(\{)", LexBase.op_ignore, "entity-name"),
             (r"(?i)\\gets\b", op_gets),
             (r"(?i)\\text[ \t]*\{", LexBase.op_ignore, "text-statement"),
+            (r"(?i)\\expr(?:ession)?[ \t]*\{",
+             LexBase.op_ignore,
+             "block-expr"),
             include("explicit-tokentype"),
             include("remark"),
             include("keyword-constants"),
@@ -382,6 +385,9 @@
             (r"(?i)\\(call|name)[ \t]*(\{)", LexBase.op_ignore, "entity-name"),
             (r"(?i)\\gets\b", op_gets),
             (r"(?i)\\text[ \t]*\{", LexBase.op_ignore, "text-statement"),
+            (r"(?i)\\expr(?:ession)?[ \t]*\{",
+             LexBase.op_ignore,
+             "block-expr"),
             include("explicit-tokentype"),
             include("remark"),
             include("keyword-constants"),
@@ -408,6 +414,7 @@
             (r"(?i)\\expr(?:ession)?[ \t]*\{",
              LexBase.op_ignore,
              "block-expr"),
+            (r"(?i)\\text[ \t]*\{", LexBase.op_ignore, "#push"),
             include("explicit-tokentype"),
             include("remark"),
             (r"\\\\", LexBase.op_fixed(Text, "\\")),
--- a/tests/test_algpseudo.py	Wed May 13 21:22:33 2026 +0200
+++ b/tests/test_algpseudo.py	Thu May 14 07:30:38 2026 +0200
@@ -1032,6 +1032,58 @@
              ],
             pygments.lex(r"....", self.lexer))
 
+    def test_nested_expr(self):
+        self.assertTokenStreamEqualComplete(
+            [("Name.Entity", "foo"),
+             ("Text", " "),
+             ("Operator", "+"),
+             ("Text", " "),
+             ("Name.Entity", "bar"),
+             ("Text", " "),
+             ("Operator", "*"),
+             ("Text", " "),
+             ("Number.Integer", '7'),
+             ("Text.Whitespace", "\n"),
+             ],
+            pygments.lex(r"\EXPR{\EXPR{foo + bar} * 7}", self.lexer))
+
+    def test_nested_expr_in_block(self):
+        self.assertTokenStreamEqualComplete(
+            [("Text", u"◆"),
+             ("Text.Whitespace", " "),
+             ("Name.Entity", "foo"),
+             ("Text", " "),
+             ("Operator", "+"),
+             ("Text", " "),
+             ("Name.Entity", "bar"),
+             ("Text", " "),
+             ("Operator", "*"),
+             ("Text", " "),
+             ("Number.Integer", '7'),
+             ("Text.Whitespace", "\n"),
+             ],
+            pygments.lex(u"\\BLOCK{\\EXPR{\\EXPR{foo + bar} * 7}}",
+                         self.lexer))
+
+    def test_nested_text(self):
+        self.assertTokenStreamEqualComplete(
+            [("Text", "foo + bar"),
+             ("Text", " * 7"),
+             ("Text.Whitespace", "\n"),
+             ],
+            pygments.lex(r"\TEXT{\TEXT{foo + bar} * 7}", self.lexer))
+
+    def test_nested_text_in_tblock(self):
+        self.assertTokenStreamEqualComplete(
+            [("Text", u"▪"),
+             ("Text.Whitespace", " "),
+             ("Text", "bar + Foo"),
+             ("Text", " * 7"),
+             ("Text.Whitespace", "\n"),
+             ],
+            pygments.lex(u"\\TBLOCK{\\TEXT{\\TEXT{bar + Foo} * 7}}",
+                         self.lexer))
+
 
 class PygmentizeCompletely(unittest.TestCase):
 
--- a/tests/test_filter.py	Wed May 13 21:22:33 2026 +0200
+++ b/tests/test_filter.py	Thu May 14 07:30:38 2026 +0200
@@ -36,7 +36,7 @@
         self.assertTokenStreamEqual(
             [("Error", "\\"),
              ],
-            pygments.lex(r"\EXPR{", lexer))
+            pygments.lex(r"\nonexisting{", lexer))
 
     def test_error_to_genericerror_filter(self):
         #
@@ -54,7 +54,7 @@
         self.assertTokenStreamEqual(
             [("Generic.Error", "\\"),
              ],
-            pygments.lex(r"\EXPR{", lexer))
+            pygments.lex(r"\nonexisting{", lexer))
 
 
 if __name__ == "__main__":