You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			161 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			161 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			Python
		
	
"""
 | 
						|
    pygments.lexers.typst
 | 
						|
    ~~~~~~~~~~~~~~~~~~~~~
 | 
						|
 | 
						|
    Lexers for Typst language.
 | 
						|
 | 
						|
    :copyright: Copyright 2006-2025 by the Pygments team, see AUTHORS.
 | 
						|
    :license: BSD, see LICENSE for details.
 | 
						|
"""
 | 
						|
 | 
						|
from pygments.lexer import RegexLexer, words, bygroups, include
 | 
						|
from pygments.token import Comment, Keyword, Name, String, Punctuation, \
 | 
						|
    Whitespace, Generic, Operator, Number, Text
 | 
						|
from pygments.util import get_choice_opt
 | 
						|
 | 
						|
__all__ = ['TypstLexer']
 | 
						|
 | 
						|
 | 
						|
class TypstLexer(RegexLexer):
 | 
						|
    """
 | 
						|
    For Typst code.
 | 
						|
 | 
						|
    Additional options accepted:
 | 
						|
 | 
						|
    `start`
 | 
						|
        Specifies the starting state of the lexer (one of 'markup', 'math',
 | 
						|
        'code'). The default is 'markup'.
 | 
						|
    """
 | 
						|
 | 
						|
    name = 'Typst'
 | 
						|
    aliases = ['typst']
 | 
						|
    filenames = ['*.typ']
 | 
						|
    mimetypes = ['text/x-typst']
 | 
						|
    url = 'https://typst.app'
 | 
						|
    version_added = '2.18'
 | 
						|
 | 
						|
    MATH_SHORTHANDS = (
 | 
						|
        '[|', '|]', '||', '*', ':=', '::=', '...', '\'', '-', '=:', '!=', '>>',
 | 
						|
        '>=', '>>>', '<<', '<=', '<<<', '->', '|->', '=>', '|=>', '==>',
 | 
						|
        '-->', '~~>', '~>', '>->', '->>', '<-', '<==', '<--', '<~~', '<~',
 | 
						|
        '<-<','<<-','<->','<=>','<==>','<-->', '>', '<', '~', ':', '|'
 | 
						|
    )
 | 
						|
 | 
						|
    tokens = {
 | 
						|
        'root': [
 | 
						|
            include('markup'),
 | 
						|
        ],
 | 
						|
        # common cases going from math/markup into code mode
 | 
						|
        'into_code': [
 | 
						|
            (words(('#let', '#set', '#show'), suffix=r'\b'), Keyword.Declaration, 'inline_code'),
 | 
						|
            (words(('#import', '#include'), suffix=r'\b'), Keyword.Namespace, 'inline_code'),
 | 
						|
            (words(('#if', '#for', '#while', '#export'), suffix=r'\b'), Keyword.Reserved, 'inline_code'),
 | 
						|
            (r'#\{', Punctuation, 'code'),
 | 
						|
            (r'#\(', Punctuation, 'code'),
 | 
						|
            (r'(#[a-zA-Z_][a-zA-Z0-9_-]*)(\[)', bygroups(Name.Function, Punctuation), 'markup'),
 | 
						|
            (r'(#[a-zA-Z_][a-zA-Z0-9_-]*)(\()', bygroups(Name.Function, Punctuation), 'code'),
 | 
						|
            (words(('#true', '#false', '#none', '#auto'), suffix=r'\b'), Keyword.Constant),
 | 
						|
            (r'#[a-zA-Z_][a-zA-Z0-9_]*', Name.Variable),
 | 
						|
            (r'#0x[0-9a-fA-F]+', Number.Hex),
 | 
						|
            (r'#0b[01]+', Number.Bin),
 | 
						|
            (r'#0o[0-7]+', Number.Oct),
 | 
						|
            (r'#[0-9]+[\.e][0-9]+', Number.Float),
 | 
						|
            (r'#[0-9]+', Number.Integer),
 | 
						|
        ],
 | 
						|
        'markup': [
 | 
						|
            include('comment'),
 | 
						|
            (r'^\s*=+.*$', Generic.Heading),
 | 
						|
            (r'[*][^*]*[*]', Generic.Strong),
 | 
						|
            (r'_[^_]*_', Generic.Emph),
 | 
						|
            (r'\$', Punctuation, 'math'),
 | 
						|
            (r'`[^`]*`', String.Backtick),  # inline code
 | 
						|
            (r'^(\s*)(-)(\s+)', bygroups(Whitespace, Punctuation, Whitespace)),  # unnumbered list
 | 
						|
            (r'^(\s*)(\+)(\s+)', bygroups(Whitespace, Punctuation, Whitespace)),  # numbered list
 | 
						|
            (r'^(\s*)([0-9]+\.)', bygroups(Whitespace, Punctuation)),  # numbered list variant
 | 
						|
            (r'^(\s*)(/)(\s+)([^:]+)(:)', bygroups(Whitespace, Punctuation, Whitespace, Name.Variable, Punctuation)),  # definitions
 | 
						|
            (r'<[a-zA-Z_][a-zA-Z0-9_-]*>', Name.Label),  # label
 | 
						|
            (r'@[a-zA-Z_][a-zA-Z0-9_-]*', Name.Label),  # reference
 | 
						|
            (r'\\#', Text), # escaped
 | 
						|
            include('into_code'),
 | 
						|
            (r'```(?:.|\n)*?```', String.Backtick),  # code block
 | 
						|
            (r'https?://[0-9a-zA-Z~/%#&=\',;.+?]*', Generic.Emph),  # links
 | 
						|
            (words(('---', '\\', '~', '--', '...'), suffix=r'\B'), Punctuation),  # special chars shorthand
 | 
						|
            (r'\\\[', Punctuation),  # escaped
 | 
						|
            (r'\\\]', Punctuation),  # escaped
 | 
						|
            (r'\[', Punctuation, '#push'),
 | 
						|
            (r'\]', Punctuation, '#pop'),
 | 
						|
            (r'[ \t]+\n?|\n', Whitespace),
 | 
						|
            (r'((?![*_$`<@\\#\] ]|https?://).)+', Text),
 | 
						|
        ],
 | 
						|
        'math': [
 | 
						|
            include('comment'),
 | 
						|
            (words(('\\_', '\\^', '\\&')), Text), # escapes
 | 
						|
            (words(('_', '^', '&', ';')), Punctuation),
 | 
						|
            (words(('+', '/', '=') + MATH_SHORTHANDS), Operator),
 | 
						|
            (r'\\', Punctuation), # line break
 | 
						|
            (r'\\\$', Punctuation),  # escaped
 | 
						|
            (r'\$', Punctuation, '#pop'),  # end of math mode
 | 
						|
            include('into_code'),
 | 
						|
            (r'([a-zA-Z][a-zA-Z0-9-]*)(\s*)(\()', bygroups(Name.Function, Whitespace, Punctuation)),
 | 
						|
            (r'([a-zA-Z][a-zA-Z0-9-]*)(:)', bygroups(Name.Variable, Punctuation)), # named arguments in math functions
 | 
						|
            (r'([a-zA-Z][a-zA-Z0-9-]*)', Name.Variable), # both variables and symbols (_ isn't supported for variables)
 | 
						|
            (r'[0-9]+(\.[0-9]+)?', Number),
 | 
						|
            (r'\.{1,3}|\(|\)|,|\{|\}', Punctuation),
 | 
						|
            (r'"[^"]*"', String.Double),
 | 
						|
            (r'[ \t\n]+', Whitespace),
 | 
						|
        ],
 | 
						|
        'comment': [
 | 
						|
            (r'//.*$', Comment.Single),
 | 
						|
            (r'/[*](.|\n)*?[*]/', Comment.Multiline),
 | 
						|
        ],
 | 
						|
        'code': [
 | 
						|
            include('comment'),
 | 
						|
            (r'\[', Punctuation, 'markup'),
 | 
						|
            (r'\(|\{', Punctuation, 'code'),
 | 
						|
            (r'\)|\}', Punctuation, '#pop'),
 | 
						|
            (r'"[^"]*"', String.Double),
 | 
						|
            (r',|\.{1,2}', Punctuation),
 | 
						|
            (r'=', Operator),
 | 
						|
            (words(('and', 'or', 'not'), suffix=r'\b'), Operator.Word),
 | 
						|
            (r'=>|<=|==|!=|>|<|-=|\+=|\*=|/=|\+|-|\\|\*', Operator), # comparisons
 | 
						|
            (r'([a-zA-Z_][a-zA-Z0-9_-]*)(:)', bygroups(Name.Variable, Punctuation)),
 | 
						|
            (r'([a-zA-Z_][a-zA-Z0-9_-]*)(\()', bygroups(Name.Function, Punctuation), 'code'),
 | 
						|
            (words(('as', 'break', 'export', 'continue', 'else', 'for', 'if',
 | 
						|
                    'in', 'return', 'while'), suffix=r'\b'),
 | 
						|
             Keyword.Reserved),
 | 
						|
             (words(('import', 'include'), suffix=r'\b'), Keyword.Namespace),
 | 
						|
            (words(('auto', 'none', 'true', 'false'), suffix=r'\b'), Keyword.Constant),
 | 
						|
            (r'([0-9.]+)(mm|pt|cm|in|em|fr|%)', bygroups(Number, Keyword.Reserved)),
 | 
						|
            (r'0x[0-9a-fA-F]+', Number.Hex),
 | 
						|
            (r'0b[01]+', Number.Bin),
 | 
						|
            (r'0o[0-7]+', Number.Oct),
 | 
						|
            (r'[0-9]+[\.e][0-9]+', Number.Float),
 | 
						|
            (r'[0-9]+', Number.Integer),
 | 
						|
            (words(('let', 'set', 'show'), suffix=r'\b'), Keyword.Declaration),
 | 
						|
            # FIXME: make this work
 | 
						|
            ## (r'(import|include)( *)(")([^"])(")',
 | 
						|
            ##  bygroups(Keyword.Reserved, Text, Punctuation, String.Double, Punctuation)),
 | 
						|
            (r'([a-zA-Z_][a-zA-Z0-9_-]*)', Name.Variable),
 | 
						|
            (r'[ \t\n]+', Whitespace),
 | 
						|
            (r':', Punctuation), # from imports like "import a: b" or "show: text.with(..)"
 | 
						|
        ],
 | 
						|
        'inline_code': [
 | 
						|
            (r';\b', Punctuation, '#pop'),
 | 
						|
            (r'\n', Whitespace, '#pop'),
 | 
						|
            include('code'),
 | 
						|
        ],
 | 
						|
    }
 | 
						|
 | 
						|
    def __init__(self, **options):
 | 
						|
        self.start_state = get_choice_opt(
 | 
						|
            options, 'start', ['markup', 'code', 'math'], 'markup', True)
 | 
						|
 | 
						|
        RegexLexer.__init__(self, **options)
 | 
						|
 | 
						|
    def get_tokens_unprocessed(self, text):
 | 
						|
        stack = ['root']
 | 
						|
        if self.start_state != 'markup': # markup is equivalent to root
 | 
						|
            stack.append(self.start_state)
 | 
						|
 | 
						|
        yield from RegexLexer.get_tokens_unprocessed(self, text, stack)
 |