diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index b8377911..8ef5d069 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -231,6 +231,7 @@ | prql | ✓ | | | | | | | ptx | ✓ | | ✓ | | | | | pug | ✓ | | | | | | +| puppet | ✓ | | ✓ | | | `puppet-languageserver` | | purescript | ✓ | ✓ | | | | `purescript-language-server` | | python | ✓ | ✓ | ✓ | ✓ | ✓ | `ty`, `ruff`, `jedi-language-server`, `pylsp`, `zuban` | | qml | ✓ | ✓ | ✓ | | | `qmlls` | diff --git a/languages.toml b/languages.toml index 12373f63..1a461050 100644 --- a/languages.toml +++ b/languages.toml @@ -110,6 +110,7 @@ pest-language-server = { command = "pest-language-server" } pkl-lsp = { command = "pkl-lsp" } pony-lsp = { command = "pony-lsp", args = ["--stdio"], config = {defines = [], ponypath = []}} prisma-language-server = { command = "prisma-language-server", args = ["--stdio"], config.prisma.enableDiagnostics = true } +puppet-languageserver = { command = "puppet-languageserver", args = ["--stdio"] } purescript-language-server = { command = "purescript-language-server", args = ["--stdio"] } pylsp = { command = "pylsp" } pyrefly = { command = "pyrefly", args = ["lsp"] } @@ -3099,7 +3100,7 @@ source = { git = "https://github.com/hongquan/tree-sitter-esdl", rev = "c824fe2b name = "pascal" scope = "source.pascal" injection-regex = "pascal" -file-types = ["pas", "pp", "inc", "lpr", "lfm"] +file-types = ["pas", "inc", "lpr", "lfm"] comment-token = "//" block-comment-tokens = { start = "{", end = "}" } indent = { tab-width = 2, unit = " " } @@ -5519,3 +5520,17 @@ indent = { tab-width = 2, unit = " " } [[grammar]] name = "concerto" source = { git = "https://github.com/accordproject/concerto-tree-sitter", rev = "920ba23ea93af56b19dfc38fcddf80b3ddc62685" } + +[[language]] +name = "puppet" +scope = "source.puppet" +injection-regex = "puppet" +file-types = ["pp"] +comment-token = "#" +block-comment-tokens = { start = "/*", end = "*/" } +indent = { tab-width = 2, unit = " " } +language-servers = ["puppet-languageserver"] + +[[grammar]] +name = "puppet" +source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-puppet", rev = "15f192929b7d317f5914de2b4accd37b349182a6" } diff --git a/runtime/queries/puppet/highlights.scm b/runtime/queries/puppet/highlights.scm new file mode 100644 index 00000000..48a89518 --- /dev/null +++ b/runtime/queries/puppet/highlights.scm @@ -0,0 +1,188 @@ +; Variables + +(identifier) @variable + +; Includes + +"include" @keyword.control.import + +(include_statement (identifier) @type) +(include_statement (class_identifier (identifier) @type .)) + +; Keywords + +[ + "class" + "inherits" + "node" + "type" + "tag" +] @keyword + +[ + "define" + "function" +] @keyword.function + +[ + "if" + "elsif" + "else" + "unless" + "case" +] @keyword.control.conditional + +(default_case "default" @keyword.control.conditional) + +; Attributes + +(attribute name: (identifier) @attribute) +(attribute name: (variable (identifier) @attribute)) + +; Parameters + +(lambda (variable (identifier) @variable.parameter)) + +(parameter (variable (identifier) @variable.parameter)) + +(function_call (identifier) @variable.parameter) + +; Functions + +(function_declaration + "function" . (identifier) @function) + +(function_call + (identifier) @function "(") + +(function_call + (field_expression "." (identifier) @function.method) "(") + +(defined_resource_type + "define" . (identifier) @function) + +; Methods + +(function_declaration + "function" . (class_identifier (identifier) @function.method .)) + +(function_call + (class_identifier (identifier) @function.method .)) + +(defined_resource_type + "define" . (class_identifier (identifier) @function.method .)) + +; Types + +(type) @type + +(builtin_type) @type.builtin + +(class_definition + (identifier) @type) +(class_definition + (class_identifier (identifier) @type .)) + +(class_inherits (identifier) @type) +(class_inherits (class_identifier (identifier) @type .)) + +(resource_declaration + (identifier) @type) +(resource_declaration + (class_identifier (identifier) @type .)) + +(node_definition (node_name (identifier) @type)) + +((identifier) @type + (#match? @type "^[A-Z]")) + +((identifier) @type.builtin + (#any-of? @type.builtin "Boolean" "Integer" "Float" "String" "Array" "Hash" "Regexp" "Variant" "Data" "Undef" "Default" "File")) + +; "Namespaces" + +(class_identifier . (identifier) @namespace) + +; Operators + +[ + "or" + "and" + "in" +] @keyword.operator + +[ + "=" + "+=" + "->" + "~>" + "<<|" + "<|" + "|>" + "|>>" + "?" + ">" + ">=" + "<=" + "<" + "==" + "!=" + "<<" + ">>" + "+" + "-" + "*" + "/" + "%" + "=~" + "!~" +] @operator + +; Punctuation + +[ + "|" + "." + "," + ";" + ":" + "::" + "=>" +] @punctuation.delimiter + +[ "{" "}" ] @punctuation.bracket + +[ "[" "]" ] @punctuation.bracket + +[ "(" ")" ] @punctuation.bracket + +(interpolation [ "${" "}" ] @punctuation.special) @none + +[ + "$" + "@" + "@@" +] @punctuation.special + +; Literals + +(number) @constant.numeric.integer + +(float) @constant.numeric.float + +(string) @string + +(escape_sequence) @constant.character.escape + +(regex) @string.regexp + +(boolean) @constant.builtin.boolean + +[ + (undef) + (default) +] @constant.builtin + +; Comments + +(comment) @comment diff --git a/runtime/queries/puppet/indents.scm b/runtime/queries/puppet/indents.scm new file mode 100644 index 00000000..d86e4160 --- /dev/null +++ b/runtime/queries/puppet/indents.scm @@ -0,0 +1,23 @@ +[ + (block) + (defined_resource_type) + (parameter_list) + (attribute_type_entry) + (resource_declaration) + (selector) + (case_statement) + (hash) + (array) +] @indent + +[ + "}" + "]" + ")" +] @outdent + +[ + (string) + (comment) + (ERROR) +] @opaque diff --git a/runtime/queries/puppet/injections.scm b/runtime/queries/puppet/injections.scm new file mode 100644 index 00000000..321c90ad --- /dev/null +++ b/runtime/queries/puppet/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/puppet/locals.scm b/runtime/queries/puppet/locals.scm new file mode 100644 index 00000000..392dbfb5 --- /dev/null +++ b/runtime/queries/puppet/locals.scm @@ -0,0 +1,34 @@ +; Scopes + +[ + (block) + (defined_resource_type) + (function_declaration) + (attribute_type_entry) + (class_definition) + (node_definition) + (resource_declaration) + (selector) + (iterator_statement) + (case_statement) + (hash) + (array) +] @local.scope + +; Definitions +; +; Only variables and parameters are tracked: types, functions and namespaces +; already get their correct highlight straight from highlights.scm, and their +; identifier segments are always the innermost node at their position, so +; resolving them again here would have no visible effect. + +(parameter (variable (identifier) @local.definition.variable.parameter)) + +(assignment . (variable (identifier) @local.definition.variable)) + +; References + +(identifier) @local.reference + +; Attribute names are hash-like keys, not variable references. +(attribute name: (identifier) @_)