From 48fbf095f6fddc9a0bca1e6404dc80f1ae2fab25 Mon Sep 17 00:00:00 2001 From: barsoosayque Date: Tue, 12 Nov 2024 15:46:31 +0700 Subject: [PATCH 1/4] add support for teal language --- book/src/generated/lang-support.md | 1 + languages.toml | 17 +++ runtime/queries/teal/folds.scm | 15 +++ runtime/queries/teal/highlights.scm | 167 ++++++++++++++++++++++++++++ runtime/queries/teal/locals.scm | 26 +++++ 5 files changed, 226 insertions(+) create mode 100644 runtime/queries/teal/folds.scm create mode 100644 runtime/queries/teal/highlights.scm create mode 100644 runtime/queries/teal/locals.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 09f15b374fdb..d00a8d1b561f 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -203,6 +203,7 @@ | tact | ✓ | ✓ | ✓ | | | task | ✓ | | | | | tcl | ✓ | | ✓ | | +| teal | ✓ | | | | | templ | ✓ | | | `templ` | | tfvars | ✓ | | ✓ | `terraform-ls` | | thrift | ✓ | | | | diff --git a/languages.toml b/languages.toml index f24c70d81958..615ebdc8a909 100644 --- a/languages.toml +++ b/languages.toml @@ -120,6 +120,7 @@ tinymist = { command = "tinymist" } pkgbuild-language-server = { command = "pkgbuild-language-server" } helm_ls = { command = "helm_ls", args = ["serve"] } ember-language-server = { command = "ember-language-server", args = ["--stdio"] } +teal-language-server = { command = "teal-language-server" } [language-server.ansible-language-server] command = "ansible-language-server" @@ -1276,6 +1277,22 @@ language-servers = [ "lua-language-server" ] name = "lua" source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-lua", rev = "88e446476a1e97a8724dff7a23e2d709855077f2" } +[[grammar]] +name = "teal" +source = { git = "https://github.com/euclidianAce/tree-sitter-teal", rev = "485fbdc00d811b01b2090dff4d0469fd1d0350f5" } + +[[language]] +name = "teal" +auto-format = false +scope = "source.tl" +injection-regex = "teal" +file-types = ["tl"] +comment-tokens = "--" +block-comment-tokens = { start = "--[[", end = "--]]" } +roots = [ "tlconfig.lua" ] +language-servers = [ "teal-lsp" ] +grammar = "teal" + [[language]] name = "svelte" scope = "source.svelte" diff --git a/runtime/queries/teal/folds.scm b/runtime/queries/teal/folds.scm new file mode 100644 index 000000000000..e756719a4f90 --- /dev/null +++ b/runtime/queries/teal/folds.scm @@ -0,0 +1,15 @@ +[ +(do_statement) +(numeric_for_statement) +(generic_for_statement) +(while_statement) +(repeat_statement) +(if_statement) +(function_statement) +(record_declaration) +(interface_declaration) +(enum_declaration) +(anon_function) +(table_constructor) +] @fold + diff --git a/runtime/queries/teal/highlights.scm b/runtime/queries/teal/highlights.scm new file mode 100644 index 000000000000..0a28fa7cdd49 --- /dev/null +++ b/runtime/queries/teal/highlights.scm @@ -0,0 +1,167 @@ + +;; Primitives +(boolean) @boolean +(comment) @comment +(shebang_comment) @comment +(identifier) @variable +((identifier) @variable.builtin + (#eq? @variable.builtin "self")) +(nil) @constant.builtin +(number) @number +(string) @string +(table_constructor ["{" "}"] @constructor) +(varargs "..." @constant.builtin) +[ "," "." ":" ";" ] @punctuation.delimiter + +(escape_sequence) @string.escape +(format_specifier) @string.escape + +;; Basic statements/Keywords +[ "if" "then" "elseif" "else" ] @conditional +[ "for" "while" "repeat" "until" ] @repeat +[ "in" "local" "return" (break) (goto) "do" "end" ] @keyword +(label) @label + +;; Global isn't a real keyword, but it gets special treatment in these places +(var_declaration "global" @keyword) +(type_declaration "global" @keyword) +(function_statement "global" @keyword) +(record_declaration "global" @keyword) +(interface_declaration "global" @keyword) +(enum_declaration "global" @keyword) + +(macroexp_statement "macroexp" @keyword) + +;; Ops +(bin_op (op) @operator) +(unary_op (op) @operator) +[ "=" "as" ] @operator + +;; Functions +(function_statement + "function" @keyword.function + . name: (_) @function) +(anon_function + "function" @keyword.function) +(function_body "end" @keyword.function) + +(arg name: (identifier) @parameter) + +(function_signature + (arguments + . (arg name: (identifier) @variable.builtin)) + (#eq? @variable.builtin "self")) + +(typeargs + "<" @punctuation.bracket + . (_) @parameter + . ("," . (_) @parameter)* + . ">" @punctuation.bracket) + +(function_call + (identifier) @function . (arguments)) +(function_call + (index (_) key: (identifier) @function) . (arguments)) +(function_call + (method_index (_) key: (identifier) @function) . (arguments)) + +;; Types + +; Contextual keywords in record bodies +(record_declaration + . [ "record" ] @keyword + name: (identifier) @type) +(anon_record . "record" @keyword) +(record_body + (record_declaration + . [ "record" ] @keyword + . name: (identifier) @type)) +(record_body + (enum_declaration + . [ "enum" ] @keyword + . name: (identifier) @type)) +(record_body + (interface_declaration + . [ "interface" ] @keyword + . name: (identifier) @type)) +(record_body + (typedef + . "type" @keyword + . name: (identifier) @type . "=")) +(record_body + (macroexp_declaration + . [ "macroexp" ] @keyword)) +(record_body (metamethod "metamethod" @keyword)) +(record_body (userdata) @keyword) + +; Contextual keywords in interface bodies +(interface_declaration + . [ "interface" ] @keyword + name: (identifier) @type) +(anon_interface . "interface" @keyword) +(interface_body + (record_declaration + . [ "record" ] @keyword + . name: (identifier) @type)) +(interface_body + (enum_declaration + . [ "enum" ] @keyword + . name: (identifier) @type)) +(interface_body + (interface_declaration + . [ "interface" ] @keyword + . name: (identifier) @type)) +(interface_body + (typedef + . "type" @keyword + . name: (identifier) @type . "=")) +(interface_body + (macroexp_declaration + . [ "macroexp" ] @keyword)) +(interface_body (metamethod "metamethod" @keyword)) +(interface_body (userdata) @keyword) + +(enum_declaration + "enum" @keyword + name: (identifier) @type) + +(type_declaration "type" @keyword) +(type_declaration (identifier) @type) +(simple_type) @type +(type_index) @type +(type_union "|" @operator) +(function_type "function" @type) + +;; The rest of it +(var_declaration + declarators: (var_declarators + (var name: (identifier) @variable))) +(var_declaration + declarators: (var_declarators + (var + "<" @punctuation.bracket + . attribute: (attribute) @attribute + . ">" @punctuation.bracket))) +[ "(" ")" "[" "]" "{" "}" ] @punctuation.bracket + +;; Only highlight format specifiers in calls to string.format +;; string.format('...') +;(function_call +; called_object: (index +; (identifier) @base +; key: (identifier) @entry) +; arguments: (arguments . +; (string (format_specifier) @string.escape)) +; +; (#eq? @base "string") +; (#eq? @entry "format")) + +;; ('...'):format() +;(function_call +; called_object: (method_index +; (string (format_specifier) @string.escape) +; key: (identifier) @func-name) +; (#eq? @func-name "format")) + + +(ERROR) @error diff --git a/runtime/queries/teal/locals.scm b/runtime/queries/teal/locals.scm new file mode 100644 index 000000000000..da67ae52a0d1 --- /dev/null +++ b/runtime/queries/teal/locals.scm @@ -0,0 +1,26 @@ + +(var_declaration + declarators: (var_declarators + (var (identifier)) @definition.var)) + +(var_assignment + variables: (assignment_variables + (var (identifier) @definition.var) @definition.associated)) + +(arg name: (identifier) @definition.parameter) + +(anon_function) @scope +((function_statement + (function_name) @definition.function) @scope + (#set! definition.function.scope "parent")) + +(program) @scope +(if_statement) @scope +(generic_for_statement (for_body) @scope) +(numeric_for_statement (for_body) @scope) +(repeat_statement) @scope +(while_statement (while_body) @scope) +(do_statement) @scope + +(identifier) @reference + From 2b1cd48820f1d20dd4e32ed74b41ac26add5b299 Mon Sep 17 00:00:00 2001 From: barsoosayque Date: Sat, 23 Nov 2024 12:57:48 +0700 Subject: [PATCH 2/4] update runtime for teal language --- languages.toml | 2 - runtime/queries/teal/highlights.scm | 82 +++++++++++++++-------------- runtime/queries/teal/locals.scm | 28 +++++----- 3 files changed, 57 insertions(+), 55 deletions(-) diff --git a/languages.toml b/languages.toml index 615ebdc8a909..d57144ae26e4 100644 --- a/languages.toml +++ b/languages.toml @@ -1283,7 +1283,6 @@ source = { git = "https://github.com/euclidianAce/tree-sitter-teal", rev = "485f [[language]] name = "teal" -auto-format = false scope = "source.tl" injection-regex = "teal" file-types = ["tl"] @@ -1291,7 +1290,6 @@ comment-tokens = "--" block-comment-tokens = { start = "--[[", end = "--]]" } roots = [ "tlconfig.lua" ] language-servers = [ "teal-lsp" ] -grammar = "teal" [[language]] name = "svelte" diff --git a/runtime/queries/teal/highlights.scm b/runtime/queries/teal/highlights.scm index 0a28fa7cdd49..f8adda5727e1 100644 --- a/runtime/queries/teal/highlights.scm +++ b/runtime/queries/teal/highlights.scm @@ -1,34 +1,38 @@ ;; Primitives -(boolean) @boolean +(boolean) @constant.builtin.boolean (comment) @comment (shebang_comment) @comment (identifier) @variable ((identifier) @variable.builtin (#eq? @variable.builtin "self")) (nil) @constant.builtin -(number) @number +(number) @constant.numeric (string) @string (table_constructor ["{" "}"] @constructor) (varargs "..." @constant.builtin) [ "," "." ":" ";" ] @punctuation.delimiter -(escape_sequence) @string.escape -(format_specifier) @string.escape +(escape_sequence) @constant.character.escape +(format_specifier) @constant.character.escape ;; Basic statements/Keywords -[ "if" "then" "elseif" "else" ] @conditional -[ "for" "while" "repeat" "until" ] @repeat -[ "in" "local" "return" (break) (goto) "do" "end" ] @keyword +[ "if" "then" "elseif" "else" ] @keyword.control.conditional +[ "for" "while" "repeat" "until" "do" ] @keyword.control.repeat +[ "end" ] @keyword +[ "in" ] @keyword.operator +[ "local" ] @keyword.storage.type +[ (break) (goto) ] @keyword.control +[ "return" ] @keyword.control.return (label) @label ;; Global isn't a real keyword, but it gets special treatment in these places -(var_declaration "global" @keyword) -(type_declaration "global" @keyword) -(function_statement "global" @keyword) -(record_declaration "global" @keyword) -(interface_declaration "global" @keyword) -(enum_declaration "global" @keyword) +(var_declaration "global" @keyword.storage.type) +(type_declaration "global" @keyword.storage.type) +(function_statement "global" @keyword.storage.type) +(record_declaration "global" @keyword.storage.type) +(interface_declaration "global" @keyword.storage.type) +(enum_declaration "global" @keyword.storage.type) (macroexp_statement "macroexp" @keyword) @@ -45,7 +49,7 @@ "function" @keyword.function) (function_body "end" @keyword.function) -(arg name: (identifier) @parameter) +(arg name: (identifier) @variable.parameter) (function_signature (arguments @@ -54,8 +58,8 @@ (typeargs "<" @punctuation.bracket - . (_) @parameter - . ("," . (_) @parameter)* + . (_) @type.parameter + . ("," . (_) @type.parameter)* . ">" @punctuation.bracket) (function_call @@ -69,63 +73,63 @@ ; Contextual keywords in record bodies (record_declaration - . [ "record" ] @keyword + . [ "record" ] @keyword.storage.type name: (identifier) @type) -(anon_record . "record" @keyword) +(anon_record . "record" @keyword.storage.type) (record_body (record_declaration - . [ "record" ] @keyword + . [ "record" ] @keyword.storage.type . name: (identifier) @type)) (record_body (enum_declaration - . [ "enum" ] @keyword - . name: (identifier) @type)) + . [ "enum" ] @keyword.storage.type + . name: (identifier) @type.enum)) (record_body (interface_declaration - . [ "interface" ] @keyword + . [ "interface" ] @keyword.storage.type . name: (identifier) @type)) (record_body (typedef - . "type" @keyword + . "type" @keyword.storage.type . name: (identifier) @type . "=")) (record_body (macroexp_declaration - . [ "macroexp" ] @keyword)) -(record_body (metamethod "metamethod" @keyword)) -(record_body (userdata) @keyword) + . [ "macroexp" ] @keyword.storage.type)) +(record_body (metamethod "metamethod" @keyword.storage.modifier)) +(record_body (userdata) @keyword.storage.modifier) ; Contextual keywords in interface bodies (interface_declaration - . [ "interface" ] @keyword + . [ "interface" ] @keyword.storage.type name: (identifier) @type) -(anon_interface . "interface" @keyword) +(anon_interface . "interface" @keyword.storage.type) (interface_body (record_declaration - . [ "record" ] @keyword + . [ "record" ] @keyword.storage.type . name: (identifier) @type)) (interface_body (enum_declaration - . [ "enum" ] @keyword - . name: (identifier) @type)) + . [ "enum" ] @keyword.storage.type + . name: (identifier) @type.enum)) (interface_body (interface_declaration - . [ "interface" ] @keyword + . [ "interface" ] @keyword.storage.type . name: (identifier) @type)) (interface_body (typedef - . "type" @keyword + . "type" @keyword.storage.type . name: (identifier) @type . "=")) (interface_body (macroexp_declaration - . [ "macroexp" ] @keyword)) -(interface_body (metamethod "metamethod" @keyword)) -(interface_body (userdata) @keyword) + . [ "macroexp" ] @keyword.storage.type)) +(interface_body (metamethod "metamethod" @keyword.storage.modifier)) +(interface_body (userdata) @keyword.storage.modifier) (enum_declaration - "enum" @keyword - name: (identifier) @type) + "enum" @keyword.storage.type + name: (identifier) @type.enum) -(type_declaration "type" @keyword) +(type_declaration "type" @keyword.storage.type) (type_declaration (identifier) @type) (simple_type) @type (type_index) @type diff --git a/runtime/queries/teal/locals.scm b/runtime/queries/teal/locals.scm index da67ae52a0d1..bcff155586b1 100644 --- a/runtime/queries/teal/locals.scm +++ b/runtime/queries/teal/locals.scm @@ -1,26 +1,26 @@ (var_declaration declarators: (var_declarators - (var (identifier)) @definition.var)) + (var (identifier)) @local.definition.var)) (var_assignment variables: (assignment_variables - (var (identifier) @definition.var) @definition.associated)) + (var (identifier) @local.definition.var) @local.definition.associated)) -(arg name: (identifier) @definition.parameter) +(arg name: (identifier) @local.definition.parameter) -(anon_function) @scope +(anon_function) @local.scope ((function_statement - (function_name) @definition.function) @scope - (#set! definition.function.scope "parent")) + (function_name) @local.definition.function) @local.scope + (#set! local.definition.function.local.scope "parent")) -(program) @scope -(if_statement) @scope -(generic_for_statement (for_body) @scope) -(numeric_for_statement (for_body) @scope) -(repeat_statement) @scope -(while_statement (while_body) @scope) -(do_statement) @scope +(program) @local.scope +(if_statement) @local.scope +(generic_for_statement (for_body) @local.scope) +(numeric_for_statement (for_body) @local.scope) +(repeat_statement) @local.scope +(while_statement (while_body) @local.scope) +(do_statement) @local.scope -(identifier) @reference +(identifier) @local.reference From ea5fedcfa4ad2ce0b117511b4d879916a6ae9326 Mon Sep 17 00:00:00 2001 From: barsoosayque <33784900+barsoosayque@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:11:08 +0700 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Michael Davis --- languages.toml | 2 +- runtime/queries/teal/highlights.scm | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/languages.toml b/languages.toml index d57144ae26e4..59ef58bc7ad7 100644 --- a/languages.toml +++ b/languages.toml @@ -1279,7 +1279,7 @@ source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-lua", rev [[grammar]] name = "teal" -source = { git = "https://github.com/euclidianAce/tree-sitter-teal", rev = "485fbdc00d811b01b2090dff4d0469fd1d0350f5" } +source = { git = "https://github.com/euclidianAce/tree-sitter-teal", rev = "3db655924b2ff1c54fdf6371b5425ea6b5dccefe" } [[language]] name = "teal" diff --git a/runtime/queries/teal/highlights.scm b/runtime/queries/teal/highlights.scm index f8adda5727e1..0aa41b19a247 100644 --- a/runtime/queries/teal/highlights.scm +++ b/runtime/queries/teal/highlights.scm @@ -168,4 +168,3 @@ ; (#eq? @func-name "format")) -(ERROR) @error From 2f4b8fc711879304040033803a35e487a069c3fe Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Wed, 4 Dec 2024 15:57:38 -0500 Subject: [PATCH 4/4] Adapt locals.scm queries We only use the stock locals.scm captures: `local.definiton`, `local.reference` and `local.scope`. --- runtime/queries/teal/locals.scm | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/runtime/queries/teal/locals.scm b/runtime/queries/teal/locals.scm index bcff155586b1..879aa71c1a3a 100644 --- a/runtime/queries/teal/locals.scm +++ b/runtime/queries/teal/locals.scm @@ -1,18 +1,17 @@ (var_declaration declarators: (var_declarators - (var (identifier)) @local.definition.var)) + (var (identifier)) @local.definition)) (var_assignment variables: (assignment_variables - (var (identifier) @local.definition.var) @local.definition.associated)) + (var (identifier) @local.definition))) -(arg name: (identifier) @local.definition.parameter) +(arg name: (identifier) @local.definition) (anon_function) @local.scope ((function_statement - (function_name) @local.definition.function) @local.scope - (#set! local.definition.function.local.scope "parent")) + (function_name) @local.definition) @local.scope) (program) @local.scope (if_statement) @local.scope