Source code for finesse.script.highlighter

"""KatScript lexer for syntax highlighting with Pygments.

Note that this plugin is used in the documentation as well, it provides the syntax
highlighting for the code-block:katscript directive
"""

from pygments.lexer import Lexer, RegexLexer, using, bygroups
import pygments
import pygments.token as token
import re


[docs]class KatScriptPygmentsLexer(Lexer): name = "KatScript" aliases = ["katscript", "kat"] filenames = ["*.kat"] # Default map of KatToken types to pygments.token types. token_map = { # POWER and FLOORDIVIDE aren't needed since Pygments instead assumes these to be # two TIMES and DIVIDE tokens respectively. "COMMENT": token.Comment, "BOOLEAN": token.Keyword.Reserved, "NONE": token.Text, "REFERENCE": token.Name.Variable, "NUMBER": token.Number, "DIVIDE": token.Operator, "EQUALS": token.Operator, "MINUS": token.Operator, "PLUS": token.Operator, "TIMES": token.Operator, "COMMA": token.Punctuation, "LPAREN": token.Punctuation, "RPAREN": token.Punctuation, "LBRACKET": token.Punctuation, "RBRACKET": token.Punctuation, "STRING": token.String, "NAME": token.Text, "NEWLINE": token.Text, "WHITESPACE": token.Text, }
[docs] def get_tokens_unprocessed(self, text): from finesse.script.parser import KatParser import finesse.script.containers as containers parser = KatParser() script = parser.parse(text) # Many tokens are typed as "NAME", with no other information available in # `script.sorted_tokens`. We therefore first do a pass through # `script.arguments` (where this information is available), and tag those that # have some special meaning. for arg in script.arguments: if isinstance(arg, containers.KatFunction): arg.directive._syntax_highlight_type = token.Name.Function.Magic elif isinstance(arg, containers.KatElement): arg.directive._syntax_highlight_type = token.Keyword.Type arg.name._syntax_highlight_type = token.Text for tok in script.sorted_tokens: if isinstance(tok, containers.KatMetaToken): continue elif hasattr(tok, "_syntax_highlight_type"): # If we've already tagged this token, just use the tagged type. yield tok.start_index, tok._syntax_highlight_type, tok.raw_value elif tok.type == "NAME" and "." in tok.raw_value: # Assume any "foo.bar" style tokens are variables. split = tok.raw_value.split(".") yield tok.start_index, token.Text, split[0] pos = tok.start_index + len(split[0]) for s in split[1:]: yield pos, token.Punctuation, "." pos += 1 yield pos, token.Text, s pos += len(s) elif tok.type == "REFERENCE": # Don't highlight the initial "&" in a reference, as it's really an # operator. yield tok.start_index, token.Operator, tok.raw_value[0] yield tok.start_index + 1, self.token_map[tok.type], tok.raw_value[1:] else: yield tok.start_index, self.token_map[tok.type], tok.raw_value
[docs]class KatScriptSubstringPygmentsLexer(RegexLexer): name = "KatScriptInPython" aliases = ["katscriptinpython"] flags = re.DOTALL tokens = { "root": [ ( r'(.+?""")([\s\n]*#kat)', bygroups(using(pygments.lexers.python.PythonLexer), None), "katscript", ), (".+", using(pygments.lexers.python.PythonLexer)), ], "katscript": [ ( '(.*?)(""")', bygroups( using(KatScriptPygmentsLexer), using(pygments.lexers.python.PythonLexer), ), "#pop", ), ], }