diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 906548e65..9ecf7e702 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -215,6 +215,7 @@ | tcl | ✓ | | ✓ | | | teal | ✓ | | | `teal-language-server` | | templ | ✓ | | | `templ` | +| tera | ✓ | | | | | textproto | ✓ | ✓ | ✓ | | | tfvars | ✓ | | ✓ | `terraform-ls` | | thrift | ✓ | | | | diff --git a/languages.toml b/languages.toml index a3cb0cfa1..8ce53cfc7 100644 --- a/languages.toml +++ b/languages.toml @@ -4111,3 +4111,19 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "ghostty" source = { git = "https://github.com/bezhermoso/tree-sitter-ghostty" , rev = "8438a93b44367e962b2ea3a3b6511885bebd196a" } + +[[language]] +name = "tera" +scope = "source.tera" +file-types = ["tera"] +block-comment-tokens = [ + { start = "{#", end = "#}" }, + { start = "{#-", end = "-#}" }, + { start = "{#", end = "-#}" }, + { start = "{#-", end = "#}" }, +] +indent = { tab-width = 4, unit = " " } + +[[grammar]] +name = "tera" +source = { git = "https://github.com/uncenter/tree-sitter-tera", rev = "e8d679a29c03e64656463a892a30da626e19ed8e" } diff --git a/runtime/queries/tera/highlights.scm b/runtime/queries/tera/highlights.scm new file mode 100644 index 000000000..744bacc9a --- /dev/null +++ b/runtime/queries/tera/highlights.scm @@ -0,0 +1,225 @@ +; Variables +;---------- + +(identifier) @variable + +((identifier) @variable.builtin + (#any-of? @variable.builtin + "loop" + "__tera_context")) + +; Properties +;----------- + +(member_expression + property: (identifier)? @variable.other.member) + +; Literals +;----------- + +(string) @string + +(bool) @constant.builtin + +(number) @constant.numeric + +; Tokens +;----------- + +[ + "." + "," +] @punctuation.delimiter + +[ + "*" + "/" + "%" + "|" + "+" + "-" + "~" + "=" + "==" + "!=" + "<" + ">" + "<=" + ">=" +] @operator + +[ + "(" + ")" + "[" + "]" + "{%" + "%}" + "-%}" + "{%-" + "}}" + "{{" + "-}}" + "{{-" + "::" +] @punctuation.bracket + +; Tags +;----------- + +(comment_tag) @comment + +; Keywords +;----------- + +[ + "if" + "elif" + "else" + "endif" +] @keyword.control.conditional + +[ + "for" + "endfor" +] @keyword.control.repeat + +[ + "include" + "import" + "extends" +] @keyword.control.import + +[ + "in" + "and" + "or" + "not" + "is" +] @keyword.operator + +[ + "break" + "continue" +] @keyword.control.return + +[ + "set" + "set_global" + "filter" + "endfilter" + "block" + "endblock" + "macro" + "endmacro" + "raw" + "endraw" + "as" +] @keyword + +; Functions +;----------- + +(macro_statement + name: (identifier) @function + (parameter_list + parameter: (identifier) @variable.parameter + (optional_parameter + name: (identifier) @variable.parameter))) + +(call_expression + scope: (identifier)? @namespace + name: (identifier) @function) + +(call_expression + name: (identifier) @function.builtin + (#any-of? @function.builtin + ; Functions - https://keats.github.io/tera/docs/#built-in-functions + "range" + "now" + "throw" + "get_random" + "get_env")) + +(test_expression + test: (identifier) @function) + +(test_expression + test: (identifier) @function.builtin + (#any-of? @function.builtin + ; Tests - https://keats.github.io/tera/docs/#built-in-tests + "defined" + "undefined" + "odd" + "even" + "string" + "number" + "divisibleby" + "iterable" + "object" + "starting_with" + "ending_with" + "containing" + "matching")) + +(filter_expression + filter: (identifier) @function.method) + +(filter_expression + filter: (identifier) @function.builtin + (#any-of? @function.builtin + ; Filters - https://keats.github.io/tera/docs/#built-in-filters + "lower" + "upper" + "wordcount" + "capitalize" + "replace" + "addslashes" + "slugify" + "title" + "trim" + "trim_start" + "trim_end" + "trim_start_matches" + "trim_end_matches" + "truncate" + "linebreaksbr" + "spaceless" + "indent" + "striptags" + "first" + "last" + "nth" + "join" + "length" + "reverse" + "sort" + "unique" + "slice" + "group_by" + "filter" + "map" + "concat" + "urlencode" + "urlencode_strict" + "abs" + "pluralize" + "round" + "filesizeformat" + "date" + "escape" + "escape_xml" + "safe" + "get" + "split" + "int" + "float" + "json_encode" + "as_str" + "default")) + +; Namespaces +;----------- + +(import_statement + scope: (identifier) @namespace) diff --git a/runtime/queries/tera/injections.scm b/runtime/queries/tera/injections.scm new file mode 100644 index 000000000..2540c1f97 --- /dev/null +++ b/runtime/queries/tera/injections.scm @@ -0,0 +1,4 @@ +(frontmatter (content) @injection.content + (#set! injection.language "yaml") + (#set! injection.combined) +) diff --git a/runtime/queries/tera/locals.scm b/runtime/queries/tera/locals.scm new file mode 100644 index 000000000..04b09cb00 --- /dev/null +++ b/runtime/queries/tera/locals.scm @@ -0,0 +1,7 @@ +(identifier) @local.reference +(assignment_expression + left: (identifier) @local.definition) +(macro_statement + (parameter_list + (identifier) @local.definition)) +(macro_statement) @local.scope