Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Teal language #12081

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/src/generated/lang-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@
| tact | ✓ | ✓ | ✓ | |
| task | ✓ | | | |
| tcl | ✓ | | ✓ | |
| teal | ✓ | | | |
| templ | ✓ | | | `templ` |
| tfvars | ✓ | | ✓ | `terraform-ls` |
| thrift | ✓ | | | |
Expand Down
15 changes: 15 additions & 0 deletions languages.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1276,6 +1277,20 @@ 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" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the tree-sitter-teal repo doesn't have a LICENSE yet. Could you propose adding one and update the commit here once one is merged?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue filed: euclidianAce/tree-sitter-teal#36. Though, I'm not sure how active is the maintainer, I hope it will be resolved soon.


[[language]]
name = "teal"
scope = "source.tl"
injection-regex = "teal"
file-types = ["tl"]
comment-tokens = "--"
block-comment-tokens = { start = "--[[", end = "--]]" }
roots = [ "tlconfig.lua" ]
language-servers = [ "teal-lsp" ]

[[language]]
name = "svelte"
scope = "source.svelte"
Expand Down
15 changes: 15 additions & 0 deletions runtime/queries/teal/folds.scm
Original file line number Diff line number Diff line change
@@ -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

171 changes: 171 additions & 0 deletions runtime/queries/teal/highlights.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@

;; Primitives
(boolean) @constant.builtin.boolean
(comment) @comment
(shebang_comment) @comment
(identifier) @variable
((identifier) @variable.builtin
(#eq? @variable.builtin "self"))
(nil) @constant.builtin
(number) @constant.numeric
(string) @string
(table_constructor ["{" "}"] @constructor)
(varargs "..." @constant.builtin)
[ "," "." ":" ";" ] @punctuation.delimiter

(escape_sequence) @constant.character.escape
(format_specifier) @constant.character.escape

;; Basic statements/Keywords
[ "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.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)

;; 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) @variable.parameter)

(function_signature
(arguments
. (arg name: (identifier) @variable.builtin))
(#eq? @variable.builtin "self"))

(typeargs
"<" @punctuation.bracket
. (_) @type.parameter
. ("," . (_) @type.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.storage.type
name: (identifier) @type)
(anon_record . "record" @keyword.storage.type)
(record_body
(record_declaration
. [ "record" ] @keyword.storage.type
. name: (identifier) @type))
(record_body
(enum_declaration
. [ "enum" ] @keyword.storage.type
. name: (identifier) @type.enum))
(record_body
(interface_declaration
. [ "interface" ] @keyword.storage.type
. name: (identifier) @type))
(record_body
(typedef
. "type" @keyword.storage.type
. name: (identifier) @type . "="))
(record_body
(macroexp_declaration
. [ "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.storage.type
name: (identifier) @type)
(anon_interface . "interface" @keyword.storage.type)
(interface_body
(record_declaration
. [ "record" ] @keyword.storage.type
. name: (identifier) @type))
(interface_body
(enum_declaration
. [ "enum" ] @keyword.storage.type
. name: (identifier) @type.enum))
(interface_body
(interface_declaration
. [ "interface" ] @keyword.storage.type
. name: (identifier) @type))
(interface_body
(typedef
. "type" @keyword.storage.type
. name: (identifier) @type . "="))
(interface_body
(macroexp_declaration
. [ "macroexp" ] @keyword.storage.type))
(interface_body (metamethod "metamethod" @keyword.storage.modifier))
(interface_body (userdata) @keyword.storage.modifier)

(enum_declaration
"enum" @keyword.storage.type
name: (identifier) @type.enum)

(type_declaration "type" @keyword.storage.type)
(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
26 changes: 26 additions & 0 deletions runtime/queries/teal/locals.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

(var_declaration
declarators: (var_declarators
(var (identifier)) @local.definition.var))

(var_assignment
variables: (assignment_variables
(var (identifier) @local.definition.var) @local.definition.associated))

(arg name: (identifier) @local.definition.parameter)

(anon_function) @local.scope
((function_statement
(function_name) @local.definition.function) @local.scope
(#set! local.definition.function.local.scope "parent"))

(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) @local.reference