310 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			310 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
"""
 | 
						|
    pygments.lexers.ul4
 | 
						|
    ~~~~~~~~~~~~~~~~~~~
 | 
						|
 | 
						|
    Lexer for the UL4 templating language.
 | 
						|
 | 
						|
    :copyright: Copyright 2006-2025 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.
 | 
						|
    """
 | 
						|
 | 
						|
    flags = re.MULTILINE | re.DOTALL
 | 
						|
 | 
						|
    name = 'UL4'
 | 
						|
    aliases = ['ul4']
 | 
						|
    filenames = ['*.ul4']
 | 
						|
    url = 'https://python.livinglogic.de/UL4.html'
 | 
						|
    version_added = '2.12'
 | 
						|
 | 
						|
    tokens = {
 | 
						|
        "root": [
 | 
						|
            (
 | 
						|
                # Template header without name:
 | 
						|
                # ``<?ul4?>``
 | 
						|
                r"(<\?)(\s*)(ul4)(\s*)(\?>)",
 | 
						|
                bygroups(Comment.Preproc, Text.Whitespace, Keyword,
 | 
						|
                         Text.Whitespace, Comment.Preproc),
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # Template header with name (potentially followed by the signature):
 | 
						|
                # ``<?ul4 foo(bar=42)?>``
 | 
						|
                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:
 | 
						|
                # ``<?note?>...<?end note?>``
 | 
						|
                r"<\?\s*note\s*\?>",
 | 
						|
                Comment,
 | 
						|
                "note", # Switch to "note" mode
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # Comment:
 | 
						|
                # ``<?note foobar?>``
 | 
						|
                r"<\?\s*note\s.*?\?>",
 | 
						|
                Comment,
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # Template documentation:
 | 
						|
                # ``<?doc?>...<?end doc?>``
 | 
						|
                r"<\?\s*doc\s*\?>",
 | 
						|
                String.Doc,
 | 
						|
                "doc",
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # Template documentation:
 | 
						|
                # ``<?doc foobar?>``
 | 
						|
                r"<\?\s*doc\s.*?\?>",
 | 
						|
                String.Doc,
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # ``<?ignore?>`` tag for commenting out code:
 | 
						|
                # ``<?ignore?>...<?end ignore?>``
 | 
						|
                r"<\?\s*ignore\s*\?>",
 | 
						|
                Comment,
 | 
						|
                "ignore", # Switch to "ignore" mode
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # ``<?def?>`` tag for defining local templates
 | 
						|
                # ``<?def foo(bar=42)?>...<?end def?>``
 | 
						|
                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
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # ``<?end?>`` tag for ending ``<?def?>``, ``<?for?>``,
 | 
						|
                # ``<?if?>``, ``<?while?>``, ``<?renderblock?>`` and
 | 
						|
                # ``<?renderblocks?>`` blocks.
 | 
						|
                r"(<\?)(\s*)(end)\b",
 | 
						|
                bygroups(Comment.Preproc, Text.Whitespace, Keyword),
 | 
						|
                "end", # Switch to "end tag" mode
 | 
						|
            ),
 | 
						|
            (
 | 
						|
                # ``<?whitespace?>`` 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 ``<?end ignore?>`` tag
 | 
						|
        "ignore": [
 | 
						|
            # Nested ``<?ignore?>`` tag
 | 
						|
            (r"<\?\s*ignore\s*\?>", Comment, "#push"),
 | 
						|
            # ``<?end ignore?>`` tag
 | 
						|
            (r"<\?\s*end\s+ignore\s*\?>", Comment, "#pop"),
 | 
						|
            # Everything else
 | 
						|
            (r"[^<]+", Comment),
 | 
						|
            (r".", Comment),
 | 
						|
        ],
 | 
						|
        # Note mode ignores everything upto the matching ``<?end note?>`` tag
 | 
						|
        "note": [
 | 
						|
            # Nested ``<?note?>`` tag
 | 
						|
            (r"<\?\s*note\s*\?>", Comment, "#push"),
 | 
						|
            # ``<?end note?>`` tag
 | 
						|
            (r"<\?\s*end\s+note\s*\?>", Comment, "#pop"),
 | 
						|
            # Everything else
 | 
						|
            (r"[^<]+", Comment),
 | 
						|
            (r".", Comment),
 | 
						|
        ],
 | 
						|
        # Doc mode ignores everything upto the matching ``<?end doc?>`` tag
 | 
						|
        "doc": [
 | 
						|
            # Nested ``<?doc?>`` tag
 | 
						|
            (r"<\?\s*doc\s*\?>", String.Doc, "#push"),
 | 
						|
            # ``<?end doc?>`` tag
 | 
						|
            (r"<\?\s*end\s+doc\s*\?>", String.Doc, "#pop"),
 | 
						|
            # Everything else
 | 
						|
            (r"[^<]+", String.Doc),
 | 
						|
            (r".", String.Doc),
 | 
						|
        ],
 | 
						|
        # 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),
 | 
						|
        ],
 | 
						|
        # ``<?end ...?>`` 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 ``<?whitespace ...?>`` 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']
 | 
						|
    url = 'https://python.livinglogic.de/UL4.html'
 | 
						|
    version_added = ''
 | 
						|
 | 
						|
    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']
 | 
						|
    url = 'https://python.livinglogic.de/UL4.html'
 | 
						|
    version_added = ''
 | 
						|
 | 
						|
    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']
 | 
						|
    url = 'https://python.livinglogic.de/UL4.html'
 | 
						|
    version_added = ''
 | 
						|
 | 
						|
    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']
 | 
						|
    url = 'https://python.livinglogic.de/UL4.html'
 | 
						|
    version_added = ''
 | 
						|
 | 
						|
    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']
 | 
						|
    url = 'https://python.livinglogic.de/UL4.html'
 | 
						|
    version_added = ''
 | 
						|
 | 
						|
    def __init__(self, **options):
 | 
						|
        super().__init__(PythonLexer, UL4Lexer, **options)
 |