|
| 1 | +from pygments import highlight, lexers |
| 2 | +from pygments.style import Style |
| 3 | +from pygments.formatters import HtmlFormatter |
| 4 | +from pygments.lexer import RegexLexer, include, bygroups, words, combined |
| 5 | +from pygments.token import ( |
| 6 | + Keyword, |
| 7 | + Name, |
| 8 | + Comment, |
| 9 | + String, |
| 10 | + Error, |
| 11 | + Number, |
| 12 | + Operator, |
| 13 | + Whitespace, |
| 14 | + Punctuation, |
| 15 | +) |
| 16 | + |
| 17 | +__all__ = ["GDScriptLexer", "GDScriptStyle"] |
| 18 | + |
| 19 | +class GDScriptLexer(RegexLexer): |
| 20 | + """ |
| 21 | + For GDScript source code. |
| 22 | + """ |
| 23 | + |
| 24 | + name = "GDScript" |
| 25 | + url = 'https://www.godotengine.org' |
| 26 | + aliases = ["gdscript", "gd"] |
| 27 | + filenames = ["*.gd"] |
| 28 | + mimetypes = ["text/x-gdscript", "application/x-gdscript"] |
| 29 | + |
| 30 | + # taken from pygments/gdscript.py |
| 31 | + def innerstring_rules(ttype): |
| 32 | + return [ |
| 33 | + # the old style '%s' % (...) string formatting |
| 34 | + (r"%(\(\w+\))?[-#0 +]*([0-9]+|[*])?(\.([0-9]+|[*]))?" |
| 35 | + "[hlL]?[E-GXc-giorsux%]", |
| 36 | + String.Interpol), |
| 37 | + # backslashes, quotes and formatting signs must be parsed one at a time |
| 38 | + (r'[^\\\'"%\n]+', ttype), |
| 39 | + (r'[\'"\\]', ttype), |
| 40 | + # unhandled string formatting sign |
| 41 | + (r"%", ttype), |
| 42 | + # newlines are an error (use "nl" state) |
| 43 | + ] |
| 44 | + |
| 45 | + tokens = { |
| 46 | + "whitespace": [(r'\s+', Whitespace)], |
| 47 | + "comment": [ |
| 48 | + (r"#.*$", Comment.Single), |
| 49 | + # """ """ and ''' ''' |
| 50 | + (r'^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")', |
| 51 | + bygroups(Whitespace, String.Affix, String.Doc)), |
| 52 | + (r"^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')", |
| 53 | + bygroups(Whitespace, String.Affix, String.Doc)), |
| 54 | + ], |
| 55 | + "punctuation": [ |
| 56 | + (r"[]{}(),;[]", Punctuation), |
| 57 | + (r":\n", Punctuation), |
| 58 | + (r"\\", Punctuation), |
| 59 | + ], |
| 60 | + "keywords": [ |
| 61 | + (words(("and", "in", "not", "or", "as", "breakpoint", "class", |
| 62 | + "class_name", "extends", "is", "setget", "signal", |
| 63 | + "tool", "const", "enum", "export", "onready", "static", |
| 64 | + "var", "break", "continue", "if", "elif", "else", "for", |
| 65 | + "pass", "return", "match", "while", "remote", "master", |
| 66 | + "puppet", "remotesync", "mastersync", "puppetsync"), |
| 67 | + suffix=r"\b"), Keyword), |
| 68 | + ], |
| 69 | + "builtins": [ |
| 70 | + (words(("yield", "true", "false", "PI", "TAU", "NAN", "INF"), |
| 71 | + prefix=r"(?<!\.)", suffix=r"\b"), |
| 72 | + Name.Builtin), |
| 73 | + (words(("Color8", "ColorN", "abs", "acos", "asin", "assert", "atan", |
| 74 | + "atan2", "bytes2var", "ceil", "char", "clamp", "convert", |
| 75 | + "cos", "cosh", "db2linear", "decimals", "dectime", "deg2rad", |
| 76 | + "dict2inst", "ease", "exp", "floor", "fmod", "fposmod", |
| 77 | + "funcref", "hash", "inst2dict", "instance_from_id", "is_inf", |
| 78 | + "is_nan", "lerp", "linear2db", "load", "log", "max", "min", |
| 79 | + "nearest_po2", "pow", "preload", "print", "print_stack", |
| 80 | + "printerr", "printraw", "prints", "printt", "rad2deg", |
| 81 | + "rand_range", "rand_seed", "randf", "randi", "randomize", |
| 82 | + "range", "round", "seed", "sign", "sin", "sinh", "sqrt", |
| 83 | + "stepify", "str", "str2var", "tan", "tan", "tanh", |
| 84 | + "type_exist", "typeof", "var2bytes", "var2str", "weakref" |
| 85 | + ), prefix=r"(?<!\.)", suffix=r"\b"), |
| 86 | + Name.Builtin.Function), |
| 87 | + (r"((?<!\.)(self)" r")\b", Name.Builtin.Pseudo), |
| 88 | + (words(("bool", "int", "float", "String", "NodePath", "Vector2", |
| 89 | + "Rect2", "Transform2D", "Vector3", "Rect3", "Plane", "Quat", |
| 90 | + "Basis", "Transform", "Color", "RID", "Object", "NodePath", |
| 91 | + "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", |
| 92 | + "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", |
| 93 | + "PackedStringArray", "PackedVector2Array", "PackedVector3Array", |
| 94 | + "PackedColorArray", "null", "void"), |
| 95 | + prefix=r"(?<!\.)", suffix=r"\b"), |
| 96 | + Name.Builtin.Type), |
| 97 | + ], |
| 98 | + "operator": [ |
| 99 | + (r"!=|==|<<|>>|&&|\+=|-=|\*=|/=|%=|&=|\|=|\|\||:=|[-~+/*%=<>&^.!|$]", Operator), |
| 100 | + (r"(in|and|or|not)\b", Operator.Word), |
| 101 | + ], |
| 102 | + "numbers": [ |
| 103 | + (r"(\d+\.\d*|\d*\.\d+)([eE][+-]?[0-9]+)?j?", Number.Float), |
| 104 | + (r"\d+[eE][+-]?[0-9]+j?", Number.Float), |
| 105 | + (r"0[xX][a-fA-F0-9]+", Number.Hex), |
| 106 | + (r"\d+j?", Number.Integer), |
| 107 | + ], |
| 108 | + "name": [(r"[a-zA-Z_]\w*", Name)], |
| 109 | + "funcname": [(r"[a-zA-Z_]\w*", Name.Function, "#pop")], |
| 110 | + "typehint": [ |
| 111 | + (r"[a-zA-Z_]\w*", Name.Class, "#pop"), |
| 112 | + ], |
| 113 | + "stringescape": [ |
| 114 | + ( |
| 115 | + r'\\([\\abfnrtv"\']|\n|N\{.*?\}|u[a-fA-F0-9]{4}|' |
| 116 | + r"U[a-fA-F0-9]{8}|x[a-fA-F0-9]{2}|[0-7]{1,3})", |
| 117 | + String.Escape, |
| 118 | + ) |
| 119 | + ], |
| 120 | + "strings-single": innerstring_rules(String.Single), |
| 121 | + "strings-double": innerstring_rules(String.Double), |
| 122 | + "double_quotes": [ |
| 123 | + (r'"', String.Double, "#pop"), |
| 124 | + (r'\\\\|\\"|\\\n', String.Escape), # included here for raw strings |
| 125 | + include("strings-double"), |
| 126 | + ], |
| 127 | + "single_quotes": [ |
| 128 | + (r"'", String.Single, "#pop"), |
| 129 | + (r"\\\\|\\'|\\\n", String.Escape), # included here for raw strings |
| 130 | + include("strings-single"), |
| 131 | + ], |
| 132 | + "triple_double_quotes": [ |
| 133 | + (r'"""', String.Double, "#pop"), |
| 134 | + include("strings-double"), |
| 135 | + include("whitespace"), |
| 136 | + ], |
| 137 | + "triple_single_quotes": [ |
| 138 | + (r"'''", String.Single, "#pop"), |
| 139 | + include("strings-single"), |
| 140 | + include("whitespace"), |
| 141 | + ], |
| 142 | + "root": [ |
| 143 | + include("whitespace"), |
| 144 | + include("comment"), |
| 145 | + include("punctuation"), |
| 146 | + |
| 147 | + # strings |
| 148 | + ('([rR]|[uUbB][rR]|[rR][uUbB])(""")', |
| 149 | + bygroups(String.Affix, String.Double), |
| 150 | + "triple_double_quotes"), |
| 151 | + ("([rR]|[uUbB][rR]|[rR][uUbB])(''')", |
| 152 | + bygroups(String.Affix, String.Single), |
| 153 | + "triple_single_quotes"), |
| 154 | + ('([rR]|[uUbB][rR]|[rR][uUbB])(")', |
| 155 | + bygroups(String.Affix, String.Double), |
| 156 | + "double_quotes"), |
| 157 | + ("([rR]|[uUbB][rR]|[rR][uUbB])(')", |
| 158 | + bygroups(String.Affix, String.Single), |
| 159 | + "single_quotes"), |
| 160 | + ('([uUbB]?)(""")', |
| 161 | + bygroups(String.Affix, String.Double), |
| 162 | + combined("stringescape", "triple_double_quotes")), |
| 163 | + ("([uUbB]?)(''')", |
| 164 | + bygroups(String.Affix, String.Single), |
| 165 | + combined("stringescape", "triple_single_quotes")), |
| 166 | + ('([uUbB]?)(")', |
| 167 | + bygroups(String.Affix, String.Double), |
| 168 | + combined("stringescape", "double_quotes")), |
| 169 | + ("([uUbB]?)(')", |
| 170 | + bygroups(String.Affix, String.Single), |
| 171 | + combined("stringescape", "single_quotes")), |
| 172 | + |
| 173 | + include("operator"), |
| 174 | + include("keywords"), |
| 175 | + (r"(func)(\s+)", bygroups(Keyword, Whitespace), "funcname"), |
| 176 | + # TODO: make the discernment if the type is Name.Builtin |
| 177 | + (r"\b(\w+)\s*(:)( )", bygroups(Name.Variable, Punctuation, Whitespace), "typehint"), |
| 178 | + (r":", Punctuation), # HACK: fix missed colon captures |
| 179 | + |
| 180 | + include("builtins"), |
| 181 | + include("name"), |
| 182 | + include("numbers"), |
| 183 | + ], |
| 184 | + } |
| 185 | + |
| 186 | +class GDScriptStyle(Style): |
| 187 | + background_color = "#1d2229" |
| 188 | + |
| 189 | + styles = { |
| 190 | + Whitespace: "#bbbbbb", # for whitespace |
| 191 | + Comment: "#cdcfd2", # any kind of comments |
| 192 | + Punctuation: "#abc9ff", # punctuation (e.g. [!.,]) |
| 193 | + |
| 194 | + Keyword: "#ff7085", # Any kind of keyword; especially if it doesn’t match any of the subtypes |
| 195 | + |
| 196 | + Operator: "#abc9ff", # For any punctuation operator (e.g. +, -) |
| 197 | + Operator.Word: "#ff7085", # For any operator that is a word (e.g. not, in) |
| 198 | + |
| 199 | + Name.Builtin: "#42ffc2", # names that are available in the global namespace (NOT USED) |
| 200 | + Name.Builtin.Type: "#42ffc2", # types that are available in the global namespace |
| 201 | + Name.Builtin.Function: "#a3a3f5", # functions that are available in the global namespace |
| 202 | + Name.Function: "#57b3ff", # function names |
| 203 | + Name.Class: "#42ffc2", # class names / declarations |
| 204 | + Name.Variable: "#bce0ff", # variable names |
| 205 | + Name.Constant: "#bce0ff", # constant names |
| 206 | + Name.Decorator: "#ffb373", # decorators / annotations (TODO) |
| 207 | + |
| 208 | + String: "#ffeda1", # string literals |
| 209 | + String.Doc: "#ffeda1", # doc string literal |
| 210 | + String.Interpol: "#ffeda1", # interpolated parts (e.g. %s) |
| 211 | + String.Escape: "#ffeda1", # escape sequences |
| 212 | + |
| 213 | + Number: "#a1ffe0", # number literal |
| 214 | + |
| 215 | + Error: "border:#FF0000" # represents lexer errors (very useful for debugging) |
| 216 | + } |
0 commit comments