""" pygments.lexers.ul4 ~~~~~~~~~~~~~~~~~~~ Lexer for the UL4 templating language. More information: https://python.livinglogic.de/UL4.html :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re from pygments.lexer import RegexLexer, DelegatingLexer, bygroups, words, include from pygments.token import Comment, Text, Keyword, String, Number, Literal, \ Name, Other, Operator from pygments.lexers.web import HtmlLexer, XmlLexer, CssLexer, JavascriptLexer from pygments.lexers.python import PythonLexer __all__ = [ 'UL4Lexer', 'HTMLUL4Lexer', 'XMLUL4Lexer', 'CSSUL4Lexer', 'JavascriptUL4Lexer', 'PythonUL4Lexer', ] class UL4Lexer(RegexLexer): """ Generic lexer for UL4. .. versionadded:: 2.12 """ flags = re.MULTILINE | re.DOTALL name = 'UL4' aliases = ['ul4'] filenames = ['*.ul4'] tokens = { "root": [ ( # Template header without name: # ```` r"(<\?)(\s*)(ul4)(\s*)(\?>)", bygroups(Comment.Preproc, Text.Whitespace, Keyword, Text.Whitespace, Comment.Preproc), ), ( # Template header with name (potentially followed by the signature): # ```` r"(<\?)(\s*)(ul4)(\s*)([a-zA-Z_][a-zA-Z_0-9]*)?", bygroups(Comment.Preproc, Text.Whitespace, Keyword, Text.Whitespace, Name.Function), "ul4", # Switch to "expression" mode ), ( # Comment: # ```` r"<\?\s*note\s.*?\?>", Comment, ), ( # Template documentation: # ```` r"<\?\s*doc\s.*?\?>", String.Doc, ), ( # ```` tag for commenting out code: # ``...`` r"<\?\s*ignore\s*\?>", Comment, "ignore", # Switch to "ignore" mode ), ( # ```` tag for defining local templates # ``...`` r"(<\?)(\s*)(def)(\s*)([a-zA-Z_][a-zA-Z_0-9]*)?", bygroups(Comment.Preproc, Text.Whitespace, Keyword, Text.Whitespace, Name.Function), "ul4", # Switch to "expression" mode ), ( # The rest of the supported tags r"(<\?)(\s*)(printx|print|for|if|elif|else|while|code|renderblocks?|render)\b", bygroups(Comment.Preproc, Text.Whitespace, Keyword), "ul4", # Switch to "expression" mode ), ( # ```` tag for ending ````, ````, # ````, ````, ```` and # ```` blocks. r"(<\?)(\s*)(end)\b", bygroups(Comment.Preproc, Text.Whitespace, Keyword), "end", # Switch to "end tag" mode ), ( # ```` tag for configuring whitespace handlng r"(<\?)(\s*)(whitespace)\b", bygroups(Comment.Preproc, Text.Whitespace, Keyword), "whitespace", # Switch to "whitespace" mode ), # Plain text (r"[^<]+", Other), (r"<", Other), ], # Ignore mode ignores everything upto the matching ```` tag "ignore": [ # Nested ```` tag (r"<\?\s*ignore\s*\?>", Comment, "#push"), # ```` tag (r"<\?\s*end\s+ignore\s*\?>", Comment, "#pop"), # Everything else (r"[^<]+", Comment), (r".", Comment), ], # UL4 expressions "ul4": [ # End the tag (r"\?>", Comment.Preproc, "#pop"), # Start triple quoted string constant ("'''", String, "string13"), ('"""', String, "string23"), # Start single quoted string constant ("'", String, "string1"), ('"', String, "string2"), # Floating point number (r"\d+\.\d*([eE][+-]?\d+)?", Number.Float), (r"\.\d+([eE][+-]?\d+)?", Number.Float), (r"\d+[eE][+-]?\d+", Number.Float), # Binary integer: ``0b101010`` (r"0[bB][01]+", Number.Bin), # Octal integer: ``0o52`` (r"0[oO][0-7]+", Number.Oct), # Hexadecimal integer: ``0x2a`` (r"0[xX][0-9a-fA-F]+", Number.Hex), # Date or datetime: ``@(2000-02-29)``/``@(2000-02-29T12:34:56.987654)`` (r"@\(\d\d\d\d-\d\d-\d\d(T(\d\d:\d\d(:\d\d(\.\d{6})?)?)?)?\)", Literal.Date), # Color: ``#fff``, ``#fff8f0`` etc. (r"#[0-9a-fA-F]{8}", Literal.Color), (r"#[0-9a-fA-F]{6}", Literal.Color), (r"#[0-9a-fA-F]{3,4}", Literal.Color), # Decimal integer: ``42`` (r"\d+", Number.Integer), # Operators (r"//|==|!=|>=|<=|<<|>>|\+=|-=|\*=|/=|//=|<<=|>>=|&=|\|=|^=|=|[\[\]{},:*/().~%&|<>^+-]", Operator), # Keywords (words(("for", "in", "if", "else", "not", "is", "and", "or"), suffix=r"\b"), Keyword), # Builtin constants (words(("None", "False", "True"), suffix=r"\b"), Keyword.Constant), # Variable names (r"[a-zA-Z_][a-zA-Z0-9_]*", Name), # Whitespace (r"\s+", Text.Whitespace), ], # ```` tag for closing the last open block "end": [ (r"\?>", Comment.Preproc, "#pop"), (words(("for", "if", "def", "while", "renderblock", "renderblocks"), suffix=r"\b"), Keyword), (r"\s+", Text), ], # Content of the ```` tag: # ``keep``, ``strip`` or ``smart`` "whitespace": [ (r"\?>", Comment.Preproc, "#pop"), (words(("keep", "strip", "smart"), suffix=r"\b"), Comment.Preproc), (r"\s+", Text.Whitespace), ], # Inside a string constant "stringescapes": [ (r"""\\[\\'"abtnfr]""", String.Escape), (r"\\x[0-9a-fA-F]{2}", String.Escape), (r"\\u[0-9a-fA-F]{4}", String.Escape), (r"\\U[0-9a-fA-F]{8}", String.Escape), ], # Inside a triple quoted string started with ``'''`` "string13": [ (r"'''", String, "#pop"), include("stringescapes"), (r"[^\\']+", String), (r'.', String), ], # Inside a triple quoted string started with ``"""`` "string23": [ (r'"""', String, "#pop"), include("stringescapes"), (r'[^\\"]+', String), (r'.', String), ], # Inside a single quoted string started with ``'`` "string1": [ (r"'", String, "#pop"), include("stringescapes"), (r"[^\\']+", String), (r'.', String), ], # Inside a single quoted string started with ``"`` "string2": [ (r'"', String, "#pop"), include("stringescapes"), (r'[^\\"]+', String), (r'.', String), ], } class HTMLUL4Lexer(DelegatingLexer): """ Lexer for UL4 embedded in HTML. """ name = 'HTML+UL4' aliases = ['html+ul4'] filenames = ['*.htmlul4'] def __init__(self, **options): super().__init__(HtmlLexer, UL4Lexer, **options) class XMLUL4Lexer(DelegatingLexer): """ Lexer for UL4 embedded in XML. """ name = 'XML+UL4' aliases = ['xml+ul4'] filenames = ['*.xmlul4'] def __init__(self, **options): super().__init__(XmlLexer, UL4Lexer, **options) class CSSUL4Lexer(DelegatingLexer): """ Lexer for UL4 embedded in CSS. """ name = 'CSS+UL4' aliases = ['css+ul4'] filenames = ['*.cssul4'] def __init__(self, **options): super().__init__(CssLexer, UL4Lexer, **options) class JavascriptUL4Lexer(DelegatingLexer): """ Lexer for UL4 embedded in Javascript. """ name = 'Javascript+UL4' aliases = ['js+ul4'] filenames = ['*.jsul4'] def __init__(self, **options): super().__init__(JavascriptLexer, UL4Lexer, **options) class PythonUL4Lexer(DelegatingLexer): """ Lexer for UL4 embedded in Python. """ name = 'Python+UL4' aliases = ['py+ul4'] filenames = ['*.pyul4'] def __init__(self, **options): super().__init__(PythonLexer, UL4Lexer, **options)