aboutsummaryrefslogtreecommitdiffstats
path: root/runtime/queries/nix
diff options
context:
space:
mode:
authorChristian Clason <c.clason@uni-graz.at>2023-06-12 09:54:30 -0600
committerChristian Clason <c.clason@uni-graz.at>2025-05-12 18:43:40 +0200
commit692b051b09935653befdb8f7ba8afdb640adf17b (patch)
tree167162b6b129ae04f68c5735078521a72917c742 /runtime/queries/nix
parentfeat(c-family): inherit injections (diff)
downloadnvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.tar
nvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.tar.gz
nvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.tar.bz2
nvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.tar.lz
nvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.tar.xz
nvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.tar.zst
nvim-treesitter-692b051b09935653befdb8f7ba8afdb640adf17b.zip
feat!: drop modules, general refactor and cleanup
Diffstat (limited to 'runtime/queries/nix')
-rw-r--r--runtime/queries/nix/folds.scm11
-rw-r--r--runtime/queries/nix/highlights.scm210
-rw-r--r--runtime/queries/nix/indents.scm75
-rw-r--r--runtime/queries/nix/injections.scm219
-rw-r--r--runtime/queries/nix/locals.scm34
5 files changed, 549 insertions, 0 deletions
diff --git a/runtime/queries/nix/folds.scm b/runtime/queries/nix/folds.scm
new file mode 100644
index 000000000..a89a5b24b
--- /dev/null
+++ b/runtime/queries/nix/folds.scm
@@ -0,0 +1,11 @@
+; Nix doesn't really have blocks, so just guess what people might want folds for
+[
+ (if_expression)
+ (with_expression)
+ (let_expression)
+ (function_expression)
+ (attrset_expression)
+ (rec_attrset_expression)
+ (list_expression)
+ (indented_string_expression)
+] @fold
diff --git a/runtime/queries/nix/highlights.scm b/runtime/queries/nix/highlights.scm
new file mode 100644
index 000000000..24e685a32
--- /dev/null
+++ b/runtime/queries/nix/highlights.scm
@@ -0,0 +1,210 @@
+; basic keywords
+[
+ "assert"
+ "in"
+ "inherit"
+ "let"
+ "rec"
+ "with"
+] @keyword
+
+; if/then/else
+[
+ "if"
+ "then"
+ "else"
+] @keyword.conditional
+
+; field access default (`a.b or c`)
+"or" @keyword.operator
+
+; comments
+(comment) @comment @spell
+
+; strings
+(string_fragment) @string
+
+(string_expression
+ "\"" @string)
+
+(indented_string_expression
+ "''" @string)
+
+; paths and URLs
+[
+ (path_expression)
+ (hpath_expression)
+ (spath_expression)
+] @string.special.path
+
+(uri_expression) @string.special.url
+
+; escape sequences
+(escape_sequence) @string.escape
+
+; delimiters
+[
+ "."
+ ";"
+ ":"
+ ","
+] @punctuation.delimiter
+
+; brackets
+[
+ "("
+ ")"
+ "["
+ "]"
+ "{"
+ "}"
+] @punctuation.bracket
+
+; `?` in `{ x ? y }:`, used to set defaults for named function arguments
+(formal
+ name: (identifier) @variable.parameter
+ "?"? @operator)
+
+; `...` in `{ ... }`, used to ignore unknown named function arguments (see above)
+(ellipses) @variable.parameter.builtin
+
+; universal is the parameter of the function expression
+; `:` in `x: y`, used to separate function argument from body (see above)
+(function_expression
+ universal: (identifier) @variable.parameter
+ ":" @punctuation.special)
+
+; function calls
+(apply_expression
+ function: (variable_expression
+ name: (identifier) @function.call))
+
+; basic identifiers
+(variable_expression) @variable
+
+(variable_expression
+ name: (identifier) @keyword.import
+ (#eq? @keyword.import "import"))
+
+(variable_expression
+ name: (identifier) @boolean
+ (#any-of? @boolean "true" "false"))
+
+; string interpolation (this was very annoying to get working properly)
+(interpolation
+ "${" @punctuation.special
+ (_)
+ "}" @punctuation.special) @none
+
+(select_expression
+ expression: (_) @_expr
+ attrpath: (attrpath
+ attr: (identifier) @variable.member)
+ (#not-eq? @_expr "builtins"))
+
+(attrset_expression
+ (binding_set
+ (binding
+ .
+ (attrpath
+ (identifier) @variable.member))))
+
+(rec_attrset_expression
+ (binding_set
+ (binding
+ .
+ (attrpath
+ (identifier) @variable.member))))
+
+function: (select_expression
+ attrpath: (attrpath
+ attr: (identifier) @function.call .))
+
+; builtin functions (with builtins prefix)
+(select_expression
+ expression: (variable_expression
+ name: (identifier) @_id)
+ attrpath: (attrpath
+ attr: (identifier) @function.builtin)
+ (#eq? @_id "builtins"))
+
+; builtin functions (without builtins prefix)
+(variable_expression
+ name: (identifier) @function.builtin
+ (#any-of? @function.builtin
+ ; nix eval --impure --expr 'with builtins; filter (x: !(elem x [ "abort" "import" "throw" ]) && isFunction builtins.${x}) (attrNames builtins)'
+ "add" "addErrorContext" "all" "any" "appendContext" "attrNames" "attrValues" "baseNameOf"
+ "bitAnd" "bitOr" "bitXor" "break" "catAttrs" "ceil" "compareVersions" "concatLists" "concatMap"
+ "concatStringsSep" "deepSeq" "derivation" "derivationStrict" "dirOf" "div" "elem" "elemAt"
+ "fetchGit" "fetchMercurial" "fetchTarball" "fetchTree" "fetchurl" "filter" "filterSource"
+ "findFile" "floor" "foldl'" "fromJSON" "fromTOML" "functionArgs" "genList" "genericClosure"
+ "getAttr" "getContext" "getEnv" "getFlake" "groupBy" "hasAttr" "hasContext" "hashFile"
+ "hashString" "head" "intersectAttrs" "isAttrs" "isBool" "isFloat" "isFunction" "isInt" "isList"
+ "isNull" "isPath" "isString" "length" "lessThan" "listToAttrs" "map" "mapAttrs" "match" "mul"
+ "parseDrvName" "partition" "path" "pathExists" "placeholder" "readDir" "readFile" "removeAttrs"
+ "replaceStrings" "scopedImport" "seq" "sort" "split" "splitVersion" "storePath" "stringLength"
+ "sub" "substring" "tail" "toFile" "toJSON" "toPath" "toString" "toXML" "trace" "traceVerbose"
+ "tryEval" "typeOf" "unsafeDiscardOutputDependency" "unsafeDiscardStringContext"
+ "unsafeGetAttrPos" "zipAttrsWith"
+ ; primops, `__<tab>` in `nix repl`
+ "__add" "__filter" "__isFunction" "__split" "__addErrorContext" "__filterSource" "__isInt"
+ "__splitVersion" "__all" "__findFile" "__isList" "__storeDir" "__any" "__floor" "__isPath"
+ "__storePath" "__appendContext" "__foldl'" "__isString" "__stringLength" "__attrNames"
+ "__fromJSON" "__langVersion" "__sub" "__attrValues" "__functionArgs" "__length" "__substring"
+ "__bitAnd" "__genList" "__lessThan" "__tail" "__bitOr" "__genericClosure" "__listToAttrs"
+ "__toFile" "__bitXor" "__getAttr" "__mapAttrs" "__toJSON" "__catAttrs" "__getContext" "__match"
+ "__toPath" "__ceil" "__getEnv" "__mul" "__toXML" "__compareVersions" "__getFlake" "__nixPath"
+ "__trace" "__concatLists" "__groupBy" "__nixVersion" "__traceVerbose" "__concatMap" "__hasAttr"
+ "__parseDrvName" "__tryEval" "__concatStringsSep" "__hasContext" "__partition" "__typeOf"
+ "__currentSystem" "__hashFile" "__path" "__unsafeDiscardOutputDependency" "__currentTime"
+ "__hashString" "__pathExists" "__unsafeDiscardStringContext" "__deepSeq" "__head" "__readDir"
+ "__unsafeGetAttrPos" "__div" "__intersectAttrs" "__readFile" "__zipAttrsWith" "__elem"
+ "__isAttrs" "__replaceStrings" "__elemAt" "__isBool" "__seq" "__fetchurl" "__isFloat" "__sort"))
+
+; constants
+(variable_expression
+ name: (identifier) @constant.builtin
+ (#any-of? @constant.builtin
+ ; nix eval --impure --expr 'with builtins; filter (x: !(isFunction builtins.${x} || isBool builtins.${x})) (attrNames builtins)'
+ "builtins" "currentSystem" "currentTime" "langVersion" "nixPath" "nixVersion" "null" "storeDir"))
+
+; function definition
+(binding
+ attrpath: (attrpath
+ attr: (identifier) @function)
+ expression: (function_expression))
+
+; unary operators
+(unary_expression
+ operator: _ @operator)
+
+; binary operators
+(binary_expression
+ operator: _ @operator)
+
+[
+ "="
+ "@"
+ "?"
+] @operator
+
+; integers, also highlight a unary -
+[
+ (unary_expression
+ "-"
+ (integer_expression))
+ (integer_expression)
+] @number
+
+; floats, also highlight a unary -
+[
+ (unary_expression
+ "-"
+ (float_expression))
+ (float_expression)
+] @number.float
+
+; exceptions
+(variable_expression
+ name: (identifier) @keyword.exception
+ (#any-of? @keyword.exception "abort" "throw"))
diff --git a/runtime/queries/nix/indents.scm b/runtime/queries/nix/indents.scm
new file mode 100644
index 000000000..757511b6b
--- /dev/null
+++ b/runtime/queries/nix/indents.scm
@@ -0,0 +1,75 @@
+[
+ (list_expression)
+ (indented_string_expression)
+ (let_expression)
+ (if_expression)
+ (binding)
+ (parenthesized_expression)
+] @indent.begin
+
+((attrset_expression) @indent.begin
+ (#not-has-parent? @indent.begin if_expression))
+
+((rec_attrset_expression) @indent.begin
+ (#not-has-parent? @indent.begin if_expression))
+
+((binding
+ "=" @indent.begin)
+ (#set! indent.immediate 1))
+
+(binding
+ ";" @indent.end)
+
+(parenthesized_expression
+ ")" @indent.branch @indent.end)
+
+(attrset_expression
+ "}" @indent.branch @indent.end)
+
+(rec_attrset_expression
+ "}" @indent.branch @indent.end)
+
+(list_expression
+ "]" @indent.branch @indent.dedent)
+
+(indented_string_expression
+ "''" @indent.branch @indent.end .)
+
+[
+ "else"
+ "in"
+] @indent.branch
+
+(let_expression
+ body: (_) @indent.end @indent.dedent)
+
+(string_fragment) @indent.ignore @indent.auto
+
+(if_expression
+ condition: (_) @indent.auto)
+
+alternative: (if_expression) @indent.dedent
+
+(interpolation) @indent.begin @indent.dedent
+
+(interpolation
+ "}" @indent.end @indent.branch)
+
+(ERROR
+ "then" @indent.begin)
+
+(ERROR
+ "then"
+ .
+ (formals) @indent.begin)
+
+(ERROR
+ "then"
+ .
+ (formals
+ "}" @indent.branch @indent.end))
+
+(ERROR
+ "let") @indent.begin
+
+(comment) @indent.ignore
diff --git a/runtime/queries/nix/injections.scm b/runtime/queries/nix/injections.scm
new file mode 100644
index 000000000..26ba6e2da
--- /dev/null
+++ b/runtime/queries/nix/injections.scm
@@ -0,0 +1,219 @@
+((comment) @injection.content
+ (#set! injection.language "comment"))
+
+((comment) @injection.language
+ . ; this is to make sure only adjacent comments are accounted for the injections
+ [
+ (string_expression
+ (string_fragment) @injection.content)
+ (indented_string_expression
+ (string_fragment) @injection.content)
+ ]
+ (#gsub! @injection.language "/%*%s*([%w%p]+)%s*%*/" "%1")
+ (#set! injection.combined))
+
+; #-style Comments
+((comment) @injection.language
+ . ; this is to make sure only adjacent comments are accounted for the injections
+ [
+ (string_expression
+ (string_fragment) @injection.content)
+ (indented_string_expression
+ (string_fragment) @injection.content)
+ ]
+ (#gsub! @injection.language "#%s*([%w%p]+)%s*" "%1")
+ (#set! injection.combined))
+
+(apply_expression
+ function: (_) @_func
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "regex")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "regex")))
+ ]
+ (#match? @_func "(^|\\.)match$")
+ (#set! injection.combined))
+
+(binding
+ attrpath: (attrpath
+ (identifier) @_path)
+ expression: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ ]
+ (#match? @_path "(^\\w+(Phase|Hook|Check)|(pre|post)[A-Z]\\w+|script)$"))
+
+(apply_expression
+ function: (_) @_func
+ argument: (_
+ (_)*
+ (_
+ (_)*
+ (binding
+ attrpath: (attrpath
+ (identifier) @_path)
+ expression: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ ])))
+ (#match? @_func "(^|\\.)writeShellApplication$")
+ (#match? @_path "^text$")
+ (#set! injection.combined))
+
+(apply_expression
+ function: (apply_expression
+ function: (apply_expression
+ function: (_) @_func))
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ ]
+ (#match? @_func "(^|\\.)runCommand((No)?CC)?(Local)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (_) @_func)
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "bash")))
+ ])
+ (#match? @_func "(^|\\.)write(Bash|Dash|ShellScript)(Bin)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (_) @_func)
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "fish")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "fish")))
+ ])
+ (#match? @_func "(^|\\.)writeFish(Bin)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (apply_expression
+ function: (_) @_func))
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "haskell")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "haskell")))
+ ])
+ (#match? @_func "(^|\\.)writeHaskell(Bin)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (apply_expression
+ function: (_) @_func))
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "javascript")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "javascript")))
+ ])
+ (#match? @_func "(^|\\.)writeJS(Bin)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (apply_expression
+ function: (_) @_func))
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "perl")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "perl")))
+ ])
+ (#match? @_func "(^|\\.)writePerl(Bin)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (apply_expression
+ function: (_) @_func))
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "python")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "python")))
+ ])
+ (#match? @_func "(^|\\.)write(PyPy|Python)[23](Bin)?$")
+ (#set! injection.combined))
+
+((apply_expression
+ function: (apply_expression
+ function: (apply_expression
+ function: (_) @_func))
+ argument: [
+ (string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "rust")))
+ (indented_string_expression
+ ((string_fragment) @injection.content
+ (#set! injection.language "rust")))
+ ])
+ (#match? @_func "(^|\\.)writeRust(Bin)?$")
+ (#set! injection.combined))
+
+; (nixosTest) testScript
+((binding
+ attrpath: (attrpath) @_attr_name
+ (#eq? @_attr_name "nodes"))
+ (binding
+ attrpath: (attrpath) @_func_name
+ (#eq? @_func_name "testScript")
+ (_
+ (string_fragment) @injection.content
+ (#set! injection.language "python")))
+ (#set! injection.combined))
+
+; home-manager Neovim plugin config
+(attrset_expression
+ (binding_set
+ (binding
+ attrpath: (attrpath) @_ty_attr
+ (_
+ (string_fragment) @_ty)
+ (#eq? @_ty_attr "type")
+ (#eq? @_ty "lua"))
+ (binding
+ attrpath: (attrpath) @_cfg_attr
+ (_
+ (string_fragment) @injection.content
+ (#set! injection.language "lua"))
+ (#eq? @_cfg_attr "config")))
+ (#set! injection.combined))
diff --git a/runtime/queries/nix/locals.scm b/runtime/queries/nix/locals.scm
new file mode 100644
index 000000000..61cab2309
--- /dev/null
+++ b/runtime/queries/nix/locals.scm
@@ -0,0 +1,34 @@
+; let bindings
+(let_expression
+ (binding_set
+ (binding
+ .
+ (attrpath) @local.definition.var))) @local.scope
+
+; rec attrsets
+(rec_attrset_expression
+ (binding_set
+ (binding
+ .
+ (attrpath) @local.definition.field))) @local.scope
+
+; functions and parameters
+(function_expression
+ .
+ [
+ (identifier) @local.definition.parameter
+ (formals
+ (formal
+ .
+ (identifier) @local.definition.parameter))
+ ]) @local.scope
+
+((formals)
+ "@"
+ (identifier) @local.definition.parameter) ; I couldn't get this to work properly inside the (function)
+
+(variable_expression
+ (identifier) @local.reference)
+
+(inherited_attrs
+ attr: (identifier) @local.reference)