| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 | # -*- coding: utf-8 -*-"""    pygments.lexers.gdscript    ~~~~~~~~~~~~~~~~~~~~~~    Lexer for GDScript.    :copyright: Copyright 2xxx by The Godot Engine Community    :license: MIT.    modified by Daniel J. Ramirez <[email protected]> based on the original python.py pygment    further expanded and consolidated with the godot-docs lexer by Zackery R. Smith <[email protected]> and Ste."""import refrom pygments.lexer import RegexLexer, include, bygroups, words, combinedfrom pygments.token import (    Keyword,    Literal,    Name,    Comment,    String,    Number,    Operator,    Whitespace,    Punctuation,)__all__ = ["GDScriptLexer"]class GDScriptLexer(RegexLexer):    """    For GDScript source code.    """    name = "GDScript"    url = "https://www.godotengine.org"    aliases = ["gdscript", "gd"]    filenames = ["*.gd"]    mimetypes = ["text/x-gdscript", "application/x-gdscript"]    @staticmethod    def get_classes(directory: str) -> tuple[str]:        classes = []        with open(f"{directory}/index.rst", "r", encoding="utf-8") as file:            lines = file.readlines()        inside_toctree = False        inside_toctree_body = False        skip_this_block = False        for i, line in enumerate(lines):            stripped = line.strip()            if stripped.startswith(".. toctree::"):                inside_toctree = True                skip_this_block = False                inside_toctree_body = False                continue            if not inside_toctree:                continue            if stripped.startswith(":name:"):                name = stripped.split(":", 2)[-1].strip()                if name in ["toc-class-ref-variants", "toc-class-ref-globals"]:                    skip_this_block = True                continue            if skip_this_block or stripped.startswith(":"):                continue            # Avoid skipping the empty line right before the body of the toc            if not inside_toctree_body and stripped == "":                inside_toctree_body = True                continue            if not line.startswith("    ") or stripped.startswith(".. "):                inside_toctree = False                continue            if stripped.startswith("class_"):                # Since everything is lowercase in the index, get the actual casing from the file                with open(f"{directory}/{stripped}.rst", "r", encoding="utf-8") as class_file:                    for class_line in class_file:                        match = re.match(r"_class_(\w+):", class_line)                        if match:                            classes.append(match.group(1))        return tuple(classes)    # taken from pygments/gdscript.py    @staticmethod    def inner_string_rules(ttype):        return [            # the old style '%s' % (...) string formatting            (                r"%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?"                "[hlL]?[E-GXc-giorsux%]",                String.Interpol,            ),            # backslashes, quotes, and formatting signs must be parsed one at a time            (r'[^\\\'"%\n]+', ttype),            (r'[\'"\\]', ttype),            # unhandled string formatting sign            (r"%", ttype),            # newlines are an error (use "nl" state)        ]    tokens = {        "whitespace": [(r"\s+", Whitespace)],        "comment": [            (r"##.*$", Comment.Doc),            (r"#(?:end)?region.*$", Comment.Region),            (r"#.*$", Comment.Single),        ],        "punctuation": [            (r"[]{}(),:;[]", Punctuation),            (r":\n", Punctuation),            (r"\\", Punctuation),        ],        # NOTE: from github.com/godotengine/godot-docs        "keyword": [            (                words(                    (                        # modules/gdscript/gdscript.cpp - GDScriptLanguage::get_reserved_words()                        # Declarations.                        "class",                        "class_name",                        "const",                        "enum",                        "extends",                        "func",                        "namespace",  # Reserved for potential future use.                        "signal",                        "static",                        "trait",  # Reserved for potential future use.                        "var",                        # Other keywords.                        "await",                        "breakpoint",                        "self",                        "super",                        "yield",  # Reserved for potential future use.                        # Not really keywords, but used in property syntax.                        # also colored like functions, not keywords                        #"set",                        #"get",                    ),                    suffix=r"\b",                ),                Keyword,            ),            (                words(                    (                        # modules/gdscript/gdscript.cpp - GDScriptLanguage::get_reserved_words()                        # Control flow.                        "break",                        "continue",                        "elif",                        "else",                        "for",                        "if",                        "match",                        "pass",                        "return",                        "when",                        "while",                        "yield",                    ),                    suffix=r"\b",                ),                # Custom control flow class used to give control flow keywords a different color,                # like in the Godot editor.                Keyword.ControlFlow,            ),        ],        "builtin": [            (                words(                    ("true", "false", "PI", "TAU", "NAN", "INF", "null"),                    prefix=r"(?<!\.)",                    suffix=r"\b",                ),                Literal,            ),            # NOTE: from github.com/godotengine/godot-docs            (                words(                    (                        # doc/classes/@GlobalScope.xml                        "abs",                        "absf",                        "absi",                        "acos",                        "acosh",                        "angle_difference",                        "asin",                        "asinh",                        "atan",                        "atan2",                        "atanh",                        "bezier_derivative",                        "bezier_interpolate",                        "bytes_to_var",                        "bytes_to_var_with_objects",                        "ceil",                        "ceilf",                        "ceili",                        "clamp",                        "clampf",                        "clampi",                        "cos",                        "cosh",                        "cubic_interpolate",                        "cubic_interpolate_angle",                        "cubic_interpolate_angle_in_time",                        "cubic_interpolate_in_time",                        "db_to_linear",                        "deg_to_rad",                        "ease",                        "error_string",                        "exp",                        "floor",                        "floorf",                        "floori",                        "fmod",                        "fposmod",                        "hash",                        "instance_from_id",                        "inverse_lerp",                        "is_equal_approx",                        "is_finite",                        "is_inf",                        "is_instance_id_valid",                        "is_instance_valid",                        "is_nan",                        "is_same",                        "is_zero_approx",                        "lerp",                        "lerp_angle",                        "lerpf",                        "linear_to_db",                        "log",                        "max",                        "maxf",                        "maxi",                        "min",                        "minf",                        "mini",                        "move_toward",                        "nearest_po2",                        "pingpong",                        "posmod",                        "pow",                        "print",                        "print_rich",                        "print_verbose",                        "printerr",                        "printraw",                        "prints",                        "printt",                        "push_error",                        "push_warning",                        "rad_to_deg",                        "rand_from_seed",                        "randf",                        "randf_range",                        "randfn",                        "randi",                        "randi_range",                        "randomize",                        "remap",                        "rid_allocate_id",                        "rid_from_int64",                        "rotate_toward",                        "round",                        "roundf",                        "roundi",                        "seed",                        "sign",                        "signf",                        "signi",                        "sin",                        "sinh",                        "smoothstep",                        "snapped",                        "snappedf",                        "snappedi",                        "sqrt",                        "step_decimals",                        "str",                        "str_to_var",                        "tan",                        "tanh",                        "type_convert",                        "type_string",                        "typeof",                        "var_to_bytes",                        "var_to_bytes_with_objects",                        "var_to_str",                        "weakref",                        "wrap",                        "wrapf",                        "wrapi",                        # modules/gdscript/doc_classes/@GDScript.xml                        "Color8",                        "assert",                        "char",                        "convert",                        "dict_to_inst",                        "get_stack",                        "inst_to_dict",                        "is_instance_of",                        "len",                        "load",                        "ord",                        "preload",                        "print_debug",                        "print_stack",                        "range",                        "type_exists",                    ),                    prefix=r"(?<!\.)",                    suffix=r"\b",                ),                Name.Builtin.Function,            ),            (r"((?<!\.)(self)" r")\b", Name.Builtin.Pseudo),            # NOTE: from github.com/godotengine/godot-docs            (                words(                    (                        # core/variant/variant.cpp - Variant::get_type_name()                        # `Nil` is excluded because it is not allowed in GDScript.                        "bool",                        "int",                        "float",                        "String",                        "Vector2",                        "Vector2i",                        "Rect2",                        "Rect2i",                        "Transform2D",                        "Vector3",                        "Vector3i",                        "Vector4",                        "Vector4i",                        "Plane",                        "AABB",                        "Quaternion",                        "Basis",                        "Transform3D",                        "Projection",                        "Color",                        "RID",                        "Object",                        "Callable",                        "Signal",                        "StringName",                        "NodePath",                        "Dictionary",                        "Array",                        "PackedByteArray",                        "PackedInt32Array",                        "PackedInt64Array",                        "PackedFloat32Array",                        "PackedFloat64Array",                        "PackedStringArray",                        "PackedVector2Array",                        "PackedVector3Array",                        "PackedColorArray",                        "PackedVector4Array",                        # The following are also considered types in GDScript.                        "Variant",                        "void",                    ),                    prefix=r"(?<!\.)",                    suffix=r"\b",                ),                Name.Builtin.Type,            ),            # copied from https://docs.godotengine.org/en/stable/classes/index.html            (                words(                    get_classes("./classes/"),                    prefix=r"(?<!\.)",                    suffix=r"\b",                ),                Name.Builtin,            ),            # NOTE: from github.com/godotengine/godot-docs            (                words(                    (                        # modules/gdscript/doc_classes/@GDScript.xml                        "@abstract",                        "@export",                        "@export_category",                        "@export_color_no_alpha",                        "@export_custom",                        "@export_dir",                        "@export_enum",                        "@export_exp_easing",                        "@export_file",                        "@export_file_path",                        "@export_flags",                        "@export_flags_2d_navigation",                        "@export_flags_2d_physics",                        "@export_flags_2d_render",                        "@export_flags_3d_navigation",                        "@export_flags_3d_physics",                        "@export_flags_3d_render",                        "@export_flags_avoidance",                        "@export_global_dir",                        "@export_global_file",                        "@export_group",                        "@export_multiline",                        "@export_node_path",                        "@export_placeholder",                        "@export_range",                        "@export_storage",                        "@export_subgroup",                        "@export_tool_button",                        "@icon",                        "@onready",                        "@rpc",                        "@static_unload",                        "@tool",                        "@warning_ignore",                        "@warning_ignore_restore",                        "@warning_ignore_start",                    ),                    prefix=r"(?<!\.)",                    suffix=r"\b",                ),                Name.Decorator,            ),        ],        "operator": [            (                r"!=|==|<<|>>|&&|\+=|-=|\*=|/=|%=|&=|\|=|\|\||[-~+/*%=<>&^.!|$]",                Operator,            ),            (r"(in|is|and|as|or|not)\b", Operator.Word),        ],        "number": [            (r"([\d_]+\.[\d_]*|[\d_]*\.[\d_]+)([eE][+-]?[\d_]+)?", Number.Float),            (r"[\d_]+[eE][+-]?[\d_]+", Number.Float),            (r"0[xX][a-fA-F\d_]+", Number.Hex),            (r"(-)?0[bB]([01]|(?<=[01])_)+", Number.Bin),            (r"[\d_]+", Number.Integer),        ],        "name": [(r"[a-zA-Z_]\w*", Name)],        "typehint": [            (r"[a-zA-Z_]\w*", Name.Class, "#pop"),        ],        "string_escape": [            (                r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|'                r"U[a-fA-F0-9]{6}|x[a-fA-F0-9]{2}|[0-7]{1,3})",                String.Escape,            )        ],        "string_single": inner_string_rules(String.Single),        "string_double": inner_string_rules(String.Double),        "string_other": inner_string_rules(String.Other),        "string_stringname": inner_string_rules(String.StringName),        "string_nodepath": inner_string_rules(String.NodePath),        "double_quotes": [            (r'"', String.Double, "#pop"),            (r'\\\\|\\"|\\\n', String.Escape),  # included here for raw strings            include("string_double"),        ],        "single_quotes": [            (r"'", String.Single, "#pop"),            (r"\\\\|\\'|\\\n", String.Escape),  # included here for raw strings            include("string_single"),        ],        "triple_double_quotes": [            (r'"""', String.Double, "#pop"),            include("string_double"),            include("whitespace"),        ],        "triple_single_quotes": [            (r"'''", String.Single, "#pop"),            include("string_single"),            include("whitespace"),        ],        "node_reference": [            (r'[\$%]"', String.Other, include("node_reference_double")),            (r"[\$%]'", String.Other, include("node_reference_single")),            (r"[\$%][A-Za-z_][\w/]*/?", String.Other),        ],        "node_reference_double": [            (r'"', String.Other, "#pop"),            include("string_other"),        ],        "node_reference_single": [            (r"'", String.Other, "#pop"),            include("string_other"),        ],        "stringname": [            (r'[&]"', String.StringName, include("stringname_double")),            (r"[&]'", String.StringName, include("stringname_single")),        ],        "stringname_double": [            (r'"', String.StringName, "#pop"),            include("string_stringname"),        ],        "stringname_single": [            (r"'", String.StringName, "#pop"),            include("string_stringname"),        ],        "nodepath": [            (r'[\^]"', String.NodePath, include("nodepath_double")),            (r"[\^]'", String.NodePath, include("nodepath_single")),        ],        "nodepath_double": [            (r'"', String.NodePath, "#pop"),            include("string_nodepath"),        ],        "nodepath_single": [            (r"'", String.NodePath, "#pop"),            include("string_nodepath"),        ],        "function_name": [(r"[a-zA-Z_]\w*", Name.Function.Declaration, "#pop")],        "enum_name": [(r"[a-zA-Z_]\w*", Name, "#pop")],        "function": [            (r"\b([a-zA-Z_]\w*)\s*(?=\()", Name.Function),            (                # colored like functions, even without braces                words(("set", "get",), suffix=r"\b", ),                Name.Function,            ),        ],        #######################################################################        # LEXER ENTRY POINT        #######################################################################        "root": [            include("whitespace"),            include("comment"),            include("punctuation"),            include("builtin"),            # strings            include("stringname"),            include("nodepath"),            include("node_reference"),            (                '(r)(""")',                bygroups(String.Affix, String.Double),                "triple_double_quotes",            ),            (                "(r)(''')",                bygroups(String.Affix, String.Single),                "triple_single_quotes",            ),            (                '(r)(")',                bygroups(String.Affix, String.Double),                "double_quotes",            ),            (                "(r)(')",                bygroups(String.Affix, String.Single),                "single_quotes",            ),            (                '(r?)(""")',                bygroups(String.Affix, String.Double),                combined("string_escape", "triple_double_quotes"),            ),            (                "(r?)(''')",                bygroups(String.Affix, String.Single),                combined("string_escape", "triple_single_quotes"),            ),            (                '(r?)(")',                bygroups(String.Affix, String.Double),                combined("string_escape", "double_quotes"),            ),            (                "(r?)(')",                bygroups(String.Affix, String.Single),                combined("string_escape", "single_quotes"),            ),            # consider Name after a . as instance/members variables            (r"(?<!\.)(\.)([a-zA-Z_]\w*)\b(?!\s*\()", bygroups(Operator, Name.Variable.Instance)),            include("operator"),            # Lookahead to not match the start of function_name to dodge errors on nameless lambdas            (r"(func)(\s+)(?=[a-zA-Z_])", bygroups(Keyword, Whitespace), "function_name"),            (r"(enum)(\s+)(?=[a-zA-Z_])", bygroups(Keyword, Whitespace), "enum_name"),            include("keyword"),            include("function"),            # NOTE:            #   This matches all PascalCase as a class. If this raises issues            #   please report it.            # see: https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html#naming-conventions            #(r"\s*([A-Z][a-zA-Z0-9_]*)", Name.Class),            # Only PascalCase, but exclude SCREAMING_SNAKE for constants            (r"\b([A-Z][a-z0-9]+(?:[A-Z][a-z0-9]+)*)\b", Name.Class),            include("name"),            include("number"),        ],    }def setup(sphinx):    sphinx.add_lexer("gdscript", GDScriptLexer)    return {        "parallel_read_safe": True,        "parallel_write_safe": True,    }
 |