diff --git a/syntaxes/GDResource.tmLanguage.json b/syntaxes/GDResource.tmLanguage.json index cb62604d4..c0062c4bc 100644 --- a/syntaxes/GDResource.tmLanguage.json +++ b/syntaxes/GDResource.tmLanguage.json @@ -1,10 +1,6 @@ { - "version": "v0.6.0", "scopeName": "source.gdresource", "uuid": "e076faa2-3c52-42fa-a8e6-9a7c453c1a5b", - "information_for_contributors": [ - "aster: galaster@foxmail.com" - ], "patterns": [ { "include": "#embedded_shader" diff --git a/syntaxes/GDScript.tmLanguage.json b/syntaxes/GDScript.tmLanguage.json index 827ecd361..0c50d8293 100644 --- a/syntaxes/GDScript.tmLanguage.json +++ b/syntaxes/GDScript.tmLanguage.json @@ -1,7 +1,5 @@ { - "fileTypes": [ - "gd" - ], + "fileTypes": ["gd"], "scopeName": "source.gdscript", "name": "GDScript", "patterns": [ @@ -286,8 +284,11 @@ "in_keyword": { "patterns": [ { - "match": "\\b(?<=for\\s[\\w]*\\s)(in)\\b", - "name": "keyword.control.gdscript" + "match": "\\b(for)\\s+[a-zA-Z_]\\w*\\s+(in)\\b", + "captures": { + "1": { "name": "keyword.control.gdscript" }, + "2": { "name": "keyword.control.gdscript" } + } }, { "match": "\\bin\\b", @@ -356,7 +357,7 @@ }, "patterns": [ { - "match": "(:)\\s*([\\w]*)?", + "match": "(:)\\s*([a-zA-Z_]\\w*)?", "captures": { "1": { "name": "punctuation.separator.annotation.gdscript" @@ -371,7 +372,7 @@ "name": "keyword.operator.assignment.gdscript" }, { - "match": "(setget)\\s+([\\w]*)(?:[,]\\s*([\\w]*))?", + "match": "(setget)\\s+([a-zA-Z_]\\w*)(?:[,]\\s*([a-zA-Z_]\\w*))?", "captures": { "1": { "name": "storage.type.const.gdscript" @@ -416,7 +417,7 @@ "include": "#line_continuation" }, { - "match": "\\s*(\\-\\>)\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\:", + "match": "\\s*(\\-\\>)\\s*([a-zA-Z_]\\w*)\\s*\\:", "captures": { "1": {}, "2": { @@ -448,7 +449,7 @@ "name": "storage.type.new.gdscript" } }, - "match": "\\b([a-zA-Z_][a-zA-Z_0-9]*).(new)\\(" + "match": "\\b([a-zA-Z_]\\w*).(new)\\(" }, "class_is": { "captures": { @@ -459,7 +460,7 @@ "name": "entity.name.type.class.gdscript" } }, - "match": "\\s+(is)\\s+([a-zA-Z_][a-zA-Z_0-9]*)" + "match": "\\s+(is)\\s+([a-zA-Z_]\\w*)" }, "class_enum": { "captures": { @@ -481,10 +482,10 @@ "name": "class.other.gdscript" } }, - "match": "(?<=class_name)\\s+([a-zA-Z_][a-zA-Z_0-9]*(\\.([a-zA-Z_][a-zA-Z_0-9]*))?)" + "match": "(?<=class_name)\\s+([a-zA-Z_]\\w*(\\.([a-zA-Z_]\\w*))?)" }, "extends": { - "match": "(?<=extends)\\s+[a-zA-Z_][a-zA-Z_0-9]*(\\.([a-zA-Z_][a-zA-Z_0-9]*))?", + "match": "(?<=extends)\\s+[a-zA-Z_]\\w*(\\.([a-zA-Z_]\\w*))?", "name": "entity.other.inherited-class.gdscript" }, "builtin_func": { @@ -540,11 +541,11 @@ }, "patterns": [ { - "match": "[a-zA-Z_][a-zA-Z_0-9]*/?", + "match": "[a-zA-Z_]\\w*/?", "name": "constant.character.escape" }, { - "match": "%[a-zA-Z_][a-zA-Z_0-9]*/?", + "match": "%[a-zA-Z_]\\w*/?", "name": "invalid.illegal.escape.gdscript" } ] @@ -573,7 +574,7 @@ "name": "support.class.library.gdscript" }, "signal_declaration_bare": { - "match": "(?x) \\s*\n (signal) \\s+\n ([a-zA-Z_][a-zA-Z_0-9]*)(?=[\\n\\s])", + "match": "(?x) \\s*\n (signal) \\s+\n ([a-zA-Z_]\\w*)(?=[\\n\\s])", "captures": { "1": { "name": "storage.type.function.gdscript" @@ -585,7 +586,7 @@ }, "signal_declaration": { "name": "meta.signal.gdscript", - "begin": "(?x) \\s*\n (signal) \\s+\n ([a-zA-Z_][a-zA-Z_0-9]*) \\s*\n (?=\\()", + "begin": "(?x) \\s*\n (signal) \\s+\n ([a-zA-Z_]\\w*) \\s*\n (?=\\()", "end": "((?=[#'\"\\n]))", "beginCaptures": { "1": { @@ -603,7 +604,7 @@ "include": "#line_continuation" }, { - "match": "\\s*(\\-\\>)\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\:", + "match": "\\s*(\\-\\>)\\s*([a-zA-Z_]\\w*)\\s*\\:", "captures": { "1": {}, "2": { @@ -636,7 +637,7 @@ }, "function_declaration": { "name": "meta.function.gdscript", - "begin": "(?x) \\s*\n (func) \\s+\n ([a-zA-Z_][a-zA-Z_0-9]*) \\s*\n (?=\\()", + "begin": "(?x) \\s*\n (func) \\s+\n ([a-zA-Z_]\\w*) \\s*\n (?=\\()", "end": "((:)|(?=[#'\"\\n]))", "beginCaptures": { "1": { @@ -659,7 +660,7 @@ "include": "#line_continuation" }, { - "match": "\\s*(\\-\\>)\\s*([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\:", + "match": "\\s*(\\-\\>)\\s*([a-zA-Z_]\\w*)\\s*\\:", "captures": { "1": {}, "2": { @@ -692,7 +693,7 @@ "include": "#annotated_parameter" }, { - "match": "(?x)\n ([[:alpha:]_]\\w*)\n \\s* (?: (,) | (?=[)#\\n=]))\n", + "match": "(?x)\n ([a-zA-Z_]\\w*)\n \\s* (?: (,) | (?=[)#\\n=]))\n", "captures": { "1": { "name": "variable.parameter.function.language.gdscript" @@ -730,7 +731,7 @@ ] }, "annotated_parameter": { - "begin": "(?x)\n \\b\n ([[:alpha:]_]\\w*) \\s* (:)\n", + "begin": "(?x)\n \\b\n ([a-zA-Z_]\\w*) \\s* (:)\n", "end": "(,)|(?=\\))", "beginCaptures": { "1": { @@ -795,7 +796,7 @@ "function_call": { "name": "meta.function-call.gdscript", "comment": "Regular function call of the type \"name(args)\"", - "begin": "(?x)\n \\b(?=\n ([[:alpha:]_]\\w*) \\s* (\\()\n )\n", + "begin": "(?x)\n \\b(?=\n ([a-zA-Z_]\\w*) \\s* (\\()\n )\n", "end": "(\\))", "endCaptures": { "1": { @@ -822,7 +823,7 @@ { "comment": "Some color schemas support meta.function-call.generic scope", "name": "support.function.any-method.gdscript", - "match": "(?x)\n \\b ([[:alpha:]_]\\w*) \\b\n" + "match": "(?x)\n \\b ([a-zA-Z_]\\w*) \\b\n" } ] }, @@ -841,7 +842,7 @@ "match": "(,)" }, { - "match": "\\b([[:alpha:]_]\\w*)\\s*(=)(?!=)", + "match": "\\b([a-zA-Z_]\\w*)\\s*(=)(?!=)", "captures": { "1": { "name": "variable.parameter.function-call.gdscript" diff --git a/syntaxes/GDShader.tmLanguage.json b/syntaxes/GDShader.tmLanguage.json index 97c7d5693..6b87eed87 100644 --- a/syntaxes/GDShader.tmLanguage.json +++ b/syntaxes/GDShader.tmLanguage.json @@ -76,7 +76,7 @@ }, "classifier": { "name": "meta.classifier.gdshader", - "begin": "(?=\b(?:shader_type|render_mode)\b)", + "begin": "(?=\\b(?:shader_type|render_mode)\\b)", "patterns": [ { "include": "#comment" @@ -95,11 +95,11 @@ }, "classifierKeyword": { "name": "keyword.language.classifier.gdshader", - "match": "\b(?:shader_type|render_mode)\b" + "match": "\\b(?:shader_type|render_mode)\\b" }, "identifierClassification": { "name": "entity.other.inherited-class.gdshader", - "match": "\b[a-z_]+\b" + "match": "\\b[a-z_]+\\b" }, "definition": { "patterns": [ @@ -133,7 +133,7 @@ ] }, "structDefinition": { - "begin": "(?=\b(?:struct)\b)", + "begin": "(?=\\b(?:struct)\\b)", "patterns": [ { "include": "#comment" @@ -155,11 +155,11 @@ }, "structKeyword": { "name": "keyword.other.struct.gdshader", - "match": "\b(?:struct)\b" + "match": "\\b(?:struct)\\b" }, "structName": { "name": "entity.name.type.struct.gdshader", - "match": "\b[a-zA-Z_]\\w*\b" + "match": "\\b[a-zA-Z_]\\w*\\b" }, "structDefinitionBlock": { "name": "meta.definition.block.struct.gdshader", @@ -190,7 +190,7 @@ }, "fieldDefinition": { "name": "meta.definition.field.gdshader", - "begin": "\b[a-zA-Z_]\\w*\b", + "begin": "\\b[a-zA-Z_]\\w*\\b", "beginCaptures": { "0": { "patterns": [ @@ -225,7 +225,7 @@ }, "fieldName": { "name": "entity.name.variable.field.gdshader", - "match": "\b[a-zA-Z_]\\w*\b" + "match": "\\b[a-zA-Z_]\\w*\\b" }, "keyword": { "patterns": [ @@ -254,23 +254,23 @@ }, "controlKeyword": { "name": "keyword.control.gdshader", - "match": "\b(?:if|else|do|while|for|continue|break|switch|case|default|return|discard)\b" + "match": "\\b(?:if|else|do|while|for|continue|break|switch|case|default|return|discard)\\b" }, "modifierKeyword": { "name": "storage.modifier.gdshader", - "match": "\b(?:const|global|instance|uniform|varying|in|out|inout|flat|smooth)\b" + "match": "\\b(?:const|global|instance|uniform|varying|in|out|inout|flat|smooth)\\b" }, "precisionKeyword": { "name": "storage.type.built-in.primitive.precision.gdshader", - "match": "\b(?:low|medium|high)p\b" + "match": "\\b(?:low|medium|high)p\\b" }, "typeKeyword": { "name": "support.type.gdshader", - "match": "\b(?:void|bool|[biu]?vec[234]|u?int|float|mat[234]|[iu]?sampler(?:3D|2D(?:Array)?)|samplerCube)\b" + "match": "\\b(?:void|bool|[biu]?vec[234]|u?int|float|mat[234]|[iu]?sampler(?:3D|2D(?:Array)?)|samplerCube)\\b" }, "hintKeyword": { "name": "support.type.annotation.gdshader", - "match": "\b(?:source_color|hint_(?:color|range|(?:black_)?albedo|normal|(?:default_)?(?:white|black)|aniso|anisotropy|roughness_(?:[rgba]|normal|gray))|filter_(?:nearest|linear)(?:_mipmap(?:_anisotropic)?)?|repeat_(?:en|dis)able)\b" + "match": "\\b(?:source_color|hint_(?:color|range|(?:black_)?albedo|normal|(?:default_)?(?:white|black)|aniso|anisotropy|roughness_(?:[rgba]|normal|gray))|filter_(?:nearest|linear)(?:_mipmap(?:_anisotropic)?)?|repeat_(?:en|dis)able)\\b" }, "element": { "patterns": [ @@ -314,51 +314,65 @@ }, "literalFloat": { "name": "constant.numeric.float.gdshader", - "match": "\b(?:\\d+[eE][-+]?\\d+|(?:\\d*[.]\\d+|\\d+[.])(?:[eE][-+]?\\d+)?)[fF]?" + "match": "\\b(?:\\d+[eE][-+]?\\d+|(?:\\d*[.]\\d+|\\d+[.])(?:[eE][-+]?\\d+)?)[fF]?" }, "literalInt": { "name": "constant.numeric.integer.gdshader", - "match": "\b(?:0[xX][0-9A-Fa-f]+|\\d+[uU]?)\b" + "match": "\\b(?:0[xX][0-9A-Fa-f]+|\\d+[uU]?)\\b" }, "literalBool": { "name": "constant.language.boolean.gdshader", - "match": "\b(?:false|true)\b" + "match": "\\b(?:false|true)\\b" }, "identifierType": { "name": "entity.name.type.gdshader", - "match": "\b[a-zA-Z_]\\w*(?=(?:\\s*\\[\\s*\\w*\\s*\\])?\\s+[a-zA-Z_]\\w*\b)" + "match": "\\b[a-zA-Z_]\\w*(?=(?:\\s*\\[\\s*\\w*\\s*\\])?\\s+[a-zA-Z_]\\w*\\b)" }, "constructor": { "name": "entity.name.type.constructor.gdshader", - "match": "\b[a-zA-Z_]\\w*(?=\\s*\\[\\s*\\w*\\s*\\]\\s*[(])|\b[A-Z]\\w*(?=\\s*[(])" + "match": "\\b[a-zA-Z_]\\w*(?=\\s*\\[\\s*\\w*\\s*\\]\\s*[(])|\\b[A-Z]\\w*(?=\\s*[(])" }, "processorFunction": { "name": "support.function.gdshader", - "match": "\b(?:vertex|fragment|light|start|process|sky|fog)(?=(?:\\s|/\\*(?:\\*(?!/)|[^*])*\\*/)*[(])" + "match": "\\b(?:vertex|fragment|light|start|process|sky|fog)(?=(?:\\s|/\\*(?:\\*(?!/)|[^*])*\\*/)*[(])" }, "identifierFunction": { "name": "entity.name.function.gdshader", - "match": "\b[a-zA-Z_]\\w*(?=(?:\\s|/\\*(?:\\*(?!/)|[^*])*\\*/)*[(])" + "match": "\\b[a-zA-Z_]\\w*(?=(?:\\s|/\\*(?:\\*(?!/)|[^*])*\\*/)*[(])" }, "swizzling": { - "name": "variable.other.property.gdshader", - "match": "(?<=[.]\\s*)(?:[xyzw]{2,4}|[rgba]{2,4}|[stpq]{2,4})\b" + "match": "([.])\\s*([xyzw]{2,4}|[rgba]{2,4}|[stpq]{2,4})\\b", + "captures": { + "1": { + "name": "punctuation.accessor.gdshader" + }, + "2": { + "name": "variable.other.property.gdshader" + } + } }, "identifierField": { - "name": "entity.name.variable.field.gdshader", - "match": "(?<=[.]\\s*)[a-zA-Z_]\\w*\b" + "match": "([.])\\s*([a-zA-Z_]\\w*)\\b(?!\\s*\\()", + "captures": { + "1": { + "name": "punctuation.accessor.gdshader" + }, + "2": { + "name": "entity.name.variable.field.gdshader" + } + } }, "constantFloat": { "name": "constant.language.float.gdshader", - "match": "\b(?:E|PI|TAU)\b" + "match": "\\b(?:E|PI|TAU)\\b" }, "languageVariable": { "name": "variable.language.gdshader", - "match": "\b(?:[A-Z][A-Z_0-9]*)\b" + "match": "\\b(?:[A-Z][A-Z_0-9]*)\\b" }, "identifierVariable": { "name": "variable.name.gdshader", - "match": "\b[a-zA-Z_]\\w*\b" + "match": "\\b[a-zA-Z_]\\w*\\b" }, "separator": { "patterns": [ diff --git a/syntaxes/examples/example2.gdshader b/syntaxes/examples/example2.gdshader new file mode 100644 index 000000000..9abf639d4 --- /dev/null +++ b/syntaxes/examples/example2.gdshader @@ -0,0 +1,193 @@ +shader_type spatial; +render_mode wireframe; + +const lowp vec3 v[1] = lowp vec3[1] ( vec3(0, 0, 1) ); + +void fn() { + // The required amount of scalars + vec4 a0 = vec4(0.0, 1.0, 2.0, 3.0); + // Complementary vectors and/or scalars + vec4 a1 = vec4(vec2(0.0, 1.0), vec2(2.0, 3.0)); + vec4 a2 = vec4(vec3(0.0, 1.0, 2.0), 3.0); + // A single scalar for the whole vector + vec4 a3 = vec4(0.0); + + mat2 m2 = mat2(vec2(1.0, 0.0), vec2(0.0, 1.0)); + mat3 m3 = mat3(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0)); + mat4 identity = mat4(1.0); + + mat3 basis = mat3(identity); + mat4 m4 = mat4(basis); + mat2 m2a = mat2(m4); + + vec4 a = vec4(0.0, 1.0, 2.0, 3.0); + vec3 b = a.rgb; // Creates a vec3 with vec4 components. + vec3 b1 = a.ggg; // Also valid; creates a vec3 and fills it with a single vec4 component. + vec3 b2 = a.bgr; // "b" will be vec3(2.0, 1.0, 0.0). + vec3 b3 = a.xyz; // Also rgba, xyzw are equivalent. + vec3 b4 = a.stp; // And stpq (for texture coordinates). + b.bgr = a.rgb; // Valid assignment. "b"'s "blue" component will be "a"'s "red" and vice versa. + + lowp vec4 v0 = vec4(0.0, 1.0, 2.0, 3.0); // low precision, usually 8 bits per component mapped to 0-1 + mediump vec4 v1 = vec4(0.0, 1.0, 2.0, 3.0); // medium precision, usually 16 bits or half float + highp vec4 v2 = vec4(0.0, 1.0, 2.0, 3.0); // high precision, uses full float or integer range (default) + + const vec2 aa = vec2(0.0, 1.0); + vec2 bb; + bb = aa; // valid + + const vec2 V1 = vec2(1, 1), V2 = vec2(2, 2); + + float fa = 1.0; + float fb = 1.0f; + float fc = 1e-1; + + uint ua = 1u; + uint ub = uint(1); + + bool cond = false; + // `if` and `else`. + if (cond) { + } else { + } + // Ternary operator. + // This is an expression that behaves like `if`/`else` and returns the value. + // If `cond` evaluates to `true`, `result` will be `9`. + // Otherwise, `result` will be `5`. + int i, result = cond ? 9 : 5; + // `switch`. + switch (i) { // `i` should be a signed integer expression. + case -1: + break; + case 0: + return; // `break` or `return` to avoid running the next `case`. + case 1: // Fallthrough (no `break` or `return`): will run the next `case`. + case 2: + break; + //... + default: // Only run if no `case` above matches. Optional. + break; + } + // `for` loop. Best used when the number of elements to iterate on + // is known in advance. + for (int i = 0; i < 10; i++) { + } + // `while` loop. Best used when the number of elements to iterate on + // is not known in advance. + while (cond) { + } + // `do while`. Like `while`, but always runs at least once even if `cond` + // never evaluates to `true`. + do { + } while (cond); +} + +const float PI_ = 3.14159265358979323846; + +struct PointLight { + vec3 position; + vec3 color; + float intensity; +}; + +struct Scene { + PointLight lights[2]; +}; + +const Scene scene = Scene(PointLight[2]( + PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0), + PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0) +)); + +Scene construct_scene(PointLight light1, PointLight light2) { + return Scene({light1, light2}); +} + +varying flat vec3 some_color; + +varying float var_arr[3]; + +varying smooth vec3 some_light; + +uniform float some_value; + +uniform vec4 color : hint_color; +uniform float amount : hint_range(0, 1); +uniform vec4 other_color : hint_color = vec4(1.0); + +uniform vec4 some_vector = vec4(0.0); +uniform vec4 some_color2 : hint_color = vec4(1.0); + +void vertex() { + const float arr[] = { 1.0, 0.5, 0.0 }; + COLOR.r = arr[0]; // valid + + float arr2[3]; + arr2[0] = 1.0; // setter + COLOR.r = arr2[0]; // getter + + PointLight light; + light.position = vec3(0.0); + light.color = vec3(1.0, 0.0, 0.0); + light.intensity = 0.5; + + COLOR.rgb = construct_scene( + PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), 1.0), + PointLight(vec3(0.0, 0.0, 0.0), vec3(1.0, 0.0, 1.0), 1.0) + ).lights[0].color; + + some_color = NORMAL; // Make the normal the color. + + var_arr[0] = 1.0; + var_arr[1] = 0.0; +} + +void fragment() { + float arr[3]; + + float float_arr[3] = float[3] (1.0, 0.5, 0.0); // first constructor + int int_arr[3] = int[] (2, 1, 0); // second constructor + vec2 vec2_arr[3] = { vec2(1.0, 1.0), vec2(0.5, 0.5), vec2(0.0, 0.0) }; // third constructor + bool bool_arr[] = { true, true, false }; // fourth constructor - size is defined automatically from the element count + + float a[3] = float[3] (1.0, 0.5, 0.0), + b[2] = { 1.0, 0.5 }, + c[] = { 0.7 }, + d = 0.0, + e[5]; + + float arr2[] = { 0.0, 1.0, 0.5, -1.0 }; + for (int i = 0; i < arr2.length(); i++) { + } + + ALBEDO = v[0]; + + PointLight light = PointLight(vec3(0.0), vec3(1.0, 0.0, 0.0), 0.5); + + ALBEDO = scene.lights[0].color; + + const float EPSILON = 0.0001, value = 0.f; + if (value >= 0.3 - EPSILON && value <= 0.3 + EPSILON) { + discard; + } + + ALBEDO = vec3(var_arr[0], var_arr[1], var_arr[2]); // red color + + some_light = ALBEDO * 100.0; // Make a shining light. +} + +void sum2(int a, in int b, inout int result) { + result = a + b; +} +void sub2(const int a, const in int b, out int result) { + result = a - b; +} + +global uniform sampler2D global1; +instance uniform int un = 0; + +void light() { + DIFFUSE_LIGHT = some_color * 100.; // optionally + + DIFFUSE_LIGHT = some_light; +} diff --git a/syntaxes/examples/gdscript1.gd b/syntaxes/examples/gdscript1.gd index 213a019ac..45b6aacf6 100644 --- a/syntaxes/examples/gdscript1.gd +++ b/syntaxes/examples/gdscript1.gd @@ -241,6 +241,12 @@ class InnerClass: for i in range(10): # "in" should be purple (control flow) list.append(i) + for child in get_children(): + print(child) + + for child in get_children(): + print(child) + if true and true: pass elif 'foo' in list: # "in" should be blue (boolean operator)