Problem: `(ast_block)` is a supertype, of which `(symbol)` (among
others) is a subtype, which makes the final local pattern invalid.
(This was not noticed before because the parser is stuck at ABI 14
due to a missing `tree-sitter.json`.)
Solution: Fix the pattern and use supertype where appropriate.
Problem: On macOS Apple Silicon, a plain unlink can leave stale code
signature metadata in the kernel cache, causing SIGKILL on next page
fault after `TSUpdate`.
Solution: Apply the rename-then-unlink strategy unconditionally instead
of only on Windows.
Problem: non-default "release" branch tracking is broken, but the
default branch contains grammar.json.
Solution: track default `main` branch and generate parser from JSON.
Problem: plenary.nvim as test runner is overkill and no longer
maintained.
Solution: Replace with a minimal fork based on Neovim API and vendored
luassert.
Problem: `vim.system` throws an error when `uv.spawn` fails, in
particular when `cmd` or `cwd` does not exist. This kills the coroutine,
which makes the corresponding async call hang.
Solution: Wrap `vim.system` in a function that catches any error and
returns it as `stderr` in a `SystemObj`.
Co-authored-by: Christian Clason <c.clason@uni-graz.at>
Breaking change: replaced `(variable_definition)` by
`(scalar_variable)`, `(list_variable)` and `(dictionary_variable)`.
Also mark queries as unmaintained.
parser PR: https://github.com/madskjeldgaard/tree-sitter-supercollider/pull/67
removed nodes:
control_structure, if, while, for, forby, method_call,
method_name, instance_variable_setter_call, argument_calls
added nodes:
class_def_body, !==, ===
modified nodes:
function_call now has fields receiver, name and arguments
chained method calls now appear as nested function_calls (where receiver
is another function_call)
Problem: The default `install_dir` is not normalized, leading to a
false positive checkhealth failure when comparing against the normalized
`runtimepath` directories.
Solution: Use trailing slash in default `install_dir`.
uv_fs_copyfile will truncate the target first, which can result in
hard-to-debug crashes if the shared object is currently in use.
instead, unlink the target first, so that the operation doesn't modify
any in-use files. the disk space from the old parsers won't be reclaimed
until any processes using them relinquish their open file handles.
* Mark floats as number.float
* Mark function arguments as variable.parameter
* Mark _ placeholder as character.special
* Mark string interpolation delimiters as punctuation.special
When tags are embedded into markdown, they'd get spell checked, in spite
of that not really making sense. The real culprit of this issue is
markdown's spell being too "loose".
Problem: `@type` currently captures function calls but fails to
capture CTE names.
Solution: Don't capture types in invocations. Add pattern for `cte`.
- Bash does not have boolean values and the builtin `true`
and `false` commands are already covered by another capture.
- The grammar has a `number` node and it's already captured.
Problem: Gitlab has too frequent outages, which break automation.
Solution: Drop all Gitlab-hosted parsers (two of which have been
unmaintained for years).
Problem: The commit fc37d05c36 broke parsing a textobjects query.
Solution: Downgrade parser to previous commit and pin it (until we can move it to tier 1).
Highlights the dollar symbol properly in multi-symbol contexts, like `$3.some.properties`.
There was already a fix for a similar issue on #8067, but it only addressed `$.some.properties`, but not the variant with the argument number in it.
* use uniform scope node instead of literal matching
This avoids the need to refactor if other scope types are added. Maybe
helps performance as well.
* add method expression highlight
Problem: These patterns were impossible, since children need to be children of
every subtype of a supertype to be captured in this way. As subtypes
could appear as children themselves, the query code silently "skipped
over" the supertype restriction in the pattern. This was fixed in
tree-sitter v0.26.0, which now (correctly) flags these patterns as
"impossible".
Solution: Add the appropriate child nodes explicitly.
Problem: These patterns were impossible, since children need to be children of
every subtype of a supertype to be captured in this way. As subtypes
could appear as children themselves, the query code silently "skipped
over" the supertype restriction in the pattern. This was fixed in
tree-sitter v0.26.0, which now (correctly) flags these patterns as
"impossible".
Solution: Add the appropriate child nodes explicitly.
The source of truth for formatting (according to make formatquery and
CI) is now ts_query_ls, so remove the no longer required script to
prevent divergence and bitrotting.
`trace32_hll_variable` has been removed from the grammar. The
queries are now capturing `symbol` instead. `symbol` is highlighted
as variable or constant.
This change does not break existing injections that currently ship with nvim-treesitter, but instead allows additional injections to be defined by users, like those found in the Max/MSP Jitter XML Shader format.
* supported parsers _must_ commit at least `grammar.json`
* set `TREE_SITTER_JS_RUNTIME=native` when generating parser to use
built-in quickjs instead of node (requires tree-sitter 0.26)
Apex codebases commonly use Javadoc-style comments, similar to Java (Apex is Salesforce's object-oriented language).
This updates the injection query to capture javadoc nodes instead of the generic comment for better highlighting and parsing accuracy.
Some queries don't add a colon after the `inherits` keyword, which nvim
could handle but `ts_query_ls` could not, causing it to give incomplete
diagnostics.
Breaking changes:
- Node `(variable)` was renamed to `(expr_double_quotes)`.
- Node `(variable_raw)` was renamed to `(expr_single_quotes)`.
- Node `(string)` was renamed to `(str_double_quotes)`.
- Node `(raw_string)` was renamed to `(str_single_quotes)`.
- Node `(raw_string_quote)` was removed.
Commit 9d7ed4 of the Inko tree-sitter grammar introduces support for
pattern matching in `let` expressions. This requires some corresponding
changes to the "local" queries to correctly define local variables. This
is done by simply defining locals for all "identifier_pattern" nodes,
instead of only doing this for "define_variable" nodes.
Breaking changes:
1. `(comment)` node split into `(one_line_comment)` and
`(block_comment)`
2. named `(directive_foo)` nodes replaced by anonymous `"'foo"`
(with backtick!) nodes -- but not consistently
Problem: Setting `install_status` to "installed" skips any future
install or update operation (even if forced). In particular, this breaks
`:TSUpdate` when calling `install()` in config files.
Solution: Don't set "installed" when skipping install and clear status
on successful operations.
The majority of jinja variables aren't assigned any highlights at all.
Assign @variable to all identifiers.
Jinja filters without parameters are not highlighted as functions: add a
query for these.
Refine the existing @variable.member to only capture identifiers instead
of broader nodes.
This commit aligns the shebang highlighting in bash syntax to what the
Linux kernel will recognise as a valid shebang construct.
In summary, the kernel will accept both headers:
#!/usr/bin/env lua
#! /usr/bin/env lua
The second one is quite prominently used throughout documentation
online, such as on Wikipedia's page for Shebang (Unix) [1].
Some sources are adamant it wouldn't be supported at a kernel level, but
it looks to me, upon closer inspection of the current kernel code [2],
that it is indeed quite evidently valid. It'll simply skip over to the
first character that's neither a space 0x20 nor a tab 0x09.
[1] https://en.wikipedia.org/wiki/Shebang_(Unix)
[2] ec7714e494/fs/binfmt_script.c (L44-L71)
Git config's sections, variable names, and (sometimes) subsections are
case-insensitive. This commit proposes to match the full lowercase
variants in addition to the non-normalised, lowerCamelCase ones.
See `git help config`
Problem: People complain about noisy `install()`.
Solution: Gate operation summary behind `summary` install option
(default false, set to true for interactive `:TS*` commands).
Problem: Can't uninstall custom parsers without queries since
`installed_parsers` only iterates over installed queries (to include
query-only languages, and to avoid string manipulation).
Solution: Iterate over both queries and parsers to collect list of
installed languages (optionally only queries or only parsers).
Since installation now installs parsers _and_ queries, caching parsers
doesn't allow skipping the installation step (and caching queries does
not pay off).
This updates
* README
* CONTRIBUTING
* the `:h nvim-treesitter` documentation
to the current state of `main`. It also adds a pull request template for
adding a new language.
Problem: `locals.lua` was neither used nor tested, and providing it goes
against the goal of nvim-treesitter not being a required dependency for
other plugins.
Solution: Remove the module and document that the queries are provided
as-is for limited backward compatibility only.
Problem: Not easy to run all checks and tests locally. Redundant CI
workflows.
Solution: Separate CI into two workflows:
* lint: Lua files (stylua, luals), query files (valid captures,
predicates, directives using tsqueryls), docs
(SUPPORTED_LANGUAGES.md) -- does not need parser installation
* tests: parsers (ABI compatibility), query files (tsqueryls on
Linux/macOS; nvim on Windows), highlight and indent tests (separated
for better readability) -- needs parser installation (but only once)
Switch to https://github.com/nvim-treesitter/highlight-assertions fork
with ABI 15 support.
Run all tests (on Linux and macOS) through `make` (`formatlua`,
`checklua`, `lintquery`, `formatquery`, `checkquery`, `docs`, `tests`),
which downloads and caches all necessary dependencies.
Remove `update-readme` workflow (replaced by lint job on PRs).
Instead, call `require('nvim-treesitter').install( { ... } )` manually.
This gives users full control over how they want to install parsers
(sync, from grammar, limited concurrency) and obviates the need for
calling `setup` for most users.
Problem: Using git for installing parsers can lead to data loss if in a
git commit buffer.
Solution: Only support downloading via curl+tar, which are installed on
all supported platforms (since Windows 10). Curl will also be required
for WASM parsers (and for `vim.net.download()`).
Problem: Tracking parser revision in lockfile and allowing override
through the parsers module complicates the code. In addition, only
revision changes are handled robustly, not changes to other installation
info.
Solution: Track parser revision in the parsers module directly. Reload
parser table on every install or update call. Support modifying parser
table in a `User TSUpdate` autocommand.
Problem: Many parsers require node/npm to evaluate the `grammar.js`
before being able to generate a parser from it.
Solution: Generate from `grammar.json` instead, which is fully resolved.
Drops `node` and `npm` as (optional) requirements for nvim-treesitter.
Note that this requires parsers to commit the generated json iff the
grammar requires evaluation (which is currently the case for all tracked
languages).
Problem: Using `url` for both remote repo and local path complicates the
code.
Solution: Add `path` field that overrides `url` and bypasses
git-specific manipulations, i.e., the contents of the `path` are used
as-is (no git repo needed).
This means `:TSUpdate` will skip such parsers; use `:TSInstall!` instead
after making local changes.
---------
Co-authored-by: Lewis Russell <lewis6991@gmail.com>
Not doing this results in paths with a mix of '\\' and '/' for Windows.
This isn't a problem when dealing with Neovim/luv APIs, but it is a
problem when comparing strings.
Tier 1: Stable
Tier 2: Core (maintained by org members)
Tier 3: Community (maintained by external contributors, to varying
degree)
Tier 4: Unsupported (lacking active maintainer or declared
experimental); skipped in lockfile update and ignored for automatic
install by default
Norg install_info and queries are maintained by neorg.
All other parsers are compatible with C++11, so fix that as standard.
(Can be bumped if all supported platforms support C++14.)
Remove Makefile support, as it's no longer needed.
Previously java was configured to use doxygen parser for documentation
comments, but javadocs are not doxygen. Inline tags have a different
syntax, block tags are not recognized, and doxygen creates a lot of
errors during highlighting.
Add parser for javadoc comments, with queries for highlights and
injections.
This just fixes the highlighting queries so everything
isn't highlighted as a variable due to the order of the queries
meaning several queries were ignored.
I also changed the node names to be highlighted as `@tag` since KDL is an
xml-like format so `@tag` seemed more appropriate than type and it differentiates it
from the type annotations.
This does NOT update to the latest KDL version 2, that would need
grammar changes. It does "mostly" work with
KDL 2 though (notably unquoted strings seem to throw the grammar off.).
These will be introduced as part of the 0.19.0 release. This commit
updates the lockfile as well as the relevant queries to accommodate the
new expression and "in" now being a keyword.
In Prometheus, label values are treated as strings when used with the
`=` and `!=` operators, and as regular expressions when used with the
`=~` and `!~` operators.
Injecting and then highlighting all label values as regex leads to a
situation where entirely valid **string** label values containing regex
special characters are mistakenly parsed and highlighted as regex. This
results in syntax errors, causing labels to be highlighted incorrectly.
For example, in `foo{bar=~"[a-z]{1,3}"}`, `{` and `}` are regex special
characters, so regex highlighting is expected. However, in
`foo{path="/foo/{id}"}`, `{` and `}` are just part of the string and
have no special meaning, so the whole value should be highlighted as a
string.
Since Java 23, java documentation supports markdown.
It is supported by a '///' line comment followed by mandatory
white space: https://openjdk.org/jeps/467
Using (block) makes the fold behavior only work on the line that the
block starts not the start line of the statement, which is unideal when
the preceding statement spans multiple lines. instead, use all top-level
statements explicitly from https://github.com/tree-sitter/tree-sitter-css/blob/master/grammar.js
This keyword is deprecated as of 0.18.1 (released on February 12, 2025)
and is being removed as part of the upcoming 0.19.0 release.
BREAKING CHANGE: replace with `type`.
This commit makes missing nodes take formatting identical to that of
regular named nodes, with the only exception being that a newline will
not be prepended to a node name. E.g. this pattern:
```query
(MISSING identifier)
```
will *not* be changed to:
```query
(MISSING
(identifier))
```
This prevents the formatter for appending a space after the "." in a
predicate prefix, and changes it to a "#" to match all other occurrences
in the codebase.
`:TSInstallSync` relies on the `:system()` command to set
`v:shell_error` when an error code is returned during installation. On
Windows, the error code was always overwritten by `popd`'s return code.
* Parse injections before starting selection.
* Make node_incremental climb up the LanaguageTree step by step.
Previously it only considered the root parser and the bottommost
parser. Now it works well with document with deeper injections, e.g.,
```lua
vim.cmd[=[
echo 'hello' 'world!'
lua << EOF
vim.cmd[[echo 'hello' 'world!']]
EOF
]=]
```
* feat(nix): Fix function highlights when part of a set
* fix(nix): Highlight only the last identifier node in functions
* fix(nix): Higher precedence for builtins compared to functions and member vars
This patch fixes an inprecise `@string.documentation` query introduced
in https://github.com/nvim-treesitter/nvim-treesitter/pull/7391.
Specifically, the pattern `(string_literal) . (identifier)` matches also
for example `"hello"` in
```julia
foo("hello", world)
@info "hello" world
```
To fix this, this patch limits the pattern to top-level statements.
This patch adds `$` to the `@punctuation.special` capture group within
`(string_interpolation)` (e.g. `"hello $name"`) and
`(interpolation_expression)` (e.g. `:(hello $name)`) nodes.
This patch captures `::` as `@operator` within
`(unary_typed_expression)` and `(typed_expression)`. These should be the
only two cases that the parser can emit when encountering `::` in the
source, but as a fallback it is still captured as `@punctuation` in all
other cases.
The reasons for capturing `::` as an operator are i) the close relation
with the other type-operators `<:` and `>:` and ii) the fact that it is
treated as an operator by the Julia parser, just like `<:` and `>:`.
This patch fixes two issues related to `@type` capturing (split out from
https://github.com/nvim-treesitter/nvim-treesitter/pull/7392):
- Capture the RHS of `<:` and `>:` as `@type` in `(unary_expression)`s
similarly to what is already done for `(binary_expression)`s with
these operators.
- Capture children of `(curly_expression)`s inside of
`(where_expression)`s as `@type` similarly how they are handled in
`(parametrized_type_expression)`.
This patch enables `@string.documentation` capturing, and markdown
injection, for strings attached to `(call_expression)` and
`(identifier)` nodes. For example
```julia
"docs"
foo(::Int, ::Float64)
"docs"
bar
```
This patch fixes the julia `(string_literal)` injection queries after
the breaking changes in
https://github.com/tree-sitter/tree-sitter-julia/pull/153. The queries
are simplified by the fact that string content is now directly available
as a separate `(content)` child node.
Currently, for something like `(((((node))))) @cap`, the formatter will
produce `((node)) @cap`, and then after another pass it will produce
`(node) @cap`. This commit makes it so that all extraneous parentheses
are removed on the first pass.
`Cooklang` files are recognized as `cook` in vim. This prevents the parser
from attaching since it is looking for `cooklang` files, so we have to
specify the `filetype` here.
**Problem:** Rust's regex injections were not applied since the string
content is behind a `(string_content)` node, and the injections were
applied to the parent node without the `include-children` directive.
**Solution:** Apply the injections to the string content. Also highlight
them accordingly.
Problem: Overriding upstreamed predicates replaces optimized versions on
Nvim 0.11.
Solution: Now that nvim-treesitter requires Nvim 0.10, simply remove the
upstreamed predicates and directives.
If setup function was called after `FileType` autocommand triggers
the installation of parser was not done.
This commit checks if filetype is already know before adding the autocommand.
Color can be changed by directly passing color `model` and `spec`,
so make the `name` field optional.
Signed-off-by: Jonas Dujava <jonas.dujava@gmail.com>
In Nvim 0.11, `vim.treesitter.lang.get_lang(filetype)` falls back
to `filetype` by default, so filetypes no longer have to be registered
for languages with the same name.
**Problem:** Neovim's `gx` will not work when the cursor is on the first
`[` of an inline Markdown link.
**Solution:** Set the `url` metadata property on the link parent node,
rather than just the link label node
In Django templates `{{` and `{%` are interpolations, so they should be
highlighted as @punctuation.special.
Don't highlight quotes as delimiters (consistency) and add missing comma
delimiter.
Generically, macros/commands in LaTeX starting on `if` are either
directly conditionals, or have similar purpose/funcionality.
Signed-off-by: Jonas Dujava <jonas.dujava@gmail.com>
* small bugfixes of variables, records, and struct highlighting
* lockfile.json update
* fixed @constant bug, and added self.address, and network.id as builtins to highlight
* fixed associated function calls
I think these have been broken since the query parser update. Basically
the inner node for the string content was preventing injections because
include-children was not set.
Environment names are captured as `@label` in `(begin)` and `(end)`
nodes, and so should they be when we are defining environments.
Signed-off-by: Jonas Dujava <jonas.dujava@gmail.com>
Setting the url attribute on actual URLs will cause Nvim to use the OSC
8 sequence on the entire URL, which enables terminal emulators to detect
the URL even when it is wrapped.
The (uri_autolink) node must use an #offset! directive to strip the
surrounding <> characters from the URL.
Apply `@nospell` to command/label names, paths, etc.
Where appropriate, turn spelling off for the whole node.
Signed-off-by: Jonas Dujava <jonas.dujava@gmail.com>
Problem: Installing a parser using git in an active git session (e.g.,
when editing a commit message) can corrupt the corresponding repository.
Solution: Check for typical environment variables first and abort
installation if found.
`@property` should be used for key-value pairs, while `@variable.member`
is used for field-access/index-expressions. Using different captures
also provides the benefit of allowing the two to be highlighted
differently.
Problem: Cannot use short-hands for @injection.language (e.g., `py` for
Python).
Solution: Register common short-hand as filetypes for some languages.
List taken from https://github.com/helix-editor/helix/blob/master/languages.toml
Also remove deprecation custom filetype->parser mapping.
- Anchor parameter query. There's no need for multiple indent.align
captures
- Narrow down binary_operator indent.begin. From tree-sitter-r corpus
and highlight tests, this seems to be appropriate.
Problem: format-queries.lua in CI uses the bundled query parser from
Neovim, meaning breaking changes are not reflected in tests.
Solution: Install nvim-treesitter in the lint workflow and use it to
install the query parser.
This ensures that when you add a new call line in the middle of a call
chain, the line is indented like so:
foo
.bar
.new_line_here
.baz
Instead of it being indented like so:
foo
.bar
.new_line_here
.baz
Inko allows for syntax such as `some_value.42.to_string`, where `42` is
a method name. Similar to other languages that allow this (e.g. Rust),
these numeric names should be highlighted as numbers instead of
identifiers.
To fix this, the query to highlight call names is adjusted to only
highlight "name" and "constant" nodes as the function group, ensuring
the remaining possible node ("integer") continues to use the same group
as regular numbers.
feat: Add injections.scm
fix: reverse order of matching
Co-authored-by: 再生花 <hoangtun0810@gmail.com>
fix: lua match for functions
doc: Resolve conflict
fix: Amend incorrect alphabetical order
Fix indentation when the for loop expression is on multiple lines
Example:
previous:
```rust
for (
abc,
def
) in thing.iter() {
// ...
}
```
new:
```rust
for (
abc,
def
) in thing.iter() {
// ...
}
```
This maintains consistency with a lot of other languages that also have
ellipses as parameter types, which we typically highlight as
`@variable.parameter.builtin`
`preproc_arg` is used for the body of `#define` macro definition, which
is not appropriate to highlight with `@function.macro`. In addition,
this region has an injection to C, so it will get highlights anyway.
Add support for capturing function call after a broadcasted pipe.
Currently works for unbroadcasted pipe.
There might be a better more complicated way to do this, since this will capture the broadcasting dot as part of the `@_pipe` capture.
The bash manual[1] considers command and process substitutions to be
forms of expansions, so they should be highlighted the same as other
expansions. This is traditionally how they have been highlighted in the
past too.
[1] https://www.gnu.org/software/bash/manual/html_node/Shell-Expansions.html
* blueprint: Don't specially highlight template_name_qualifier. This is
similar to inheritance base class. Other languages don't highlight
them specially.
* eds: `@type` for all `*Type` keys
* chatito: `@attribute` for variation
Problem:
cb46f6e467 (diff-edf997b0c2d42d31828800641ac1f5a46487fe24a0d46ccf70bcd58a14f3868f)
introduced a regression on how `#set!` behaves with several matches in a
single pattern, breaking conceals in, e.g., taglinks.
Solution: Separate taglink etc. patterns into concealed marker and
contents. Also add URL support for concealed markdown links.
Problem: Allowing undocumented "secret" (sub)captures makes it harder
to write comprehensive colorschemes and catch inconsistent captures.
Solution: Only allow captures listed in CONTRIBUTING.md. Add useful
(cross-language) subcaptures and drop language-specific or too niche
ones.
Follow-up: Adding further `*.builtin` captures and changing queries to
use them.
Language-specific subcaptures should instead be added in user config or
a custom language plugin.
Match grammar.js from commit 0d598bb95ffe3ba63403979d0d32158210974ca5 in
latex-lsp/tree-sitter-latex
Co-authored-by: gi1242 <gi1242+nvim-treesitter@gmail.com>
Lalrpop support putting annotation like `#[precedence(level = "1")]`.
This commit aims to highlight `precedence` with the `function.macro`
highlight group, like rust does with its proc macros.
Problem: The FileType autocmd to automatically install parsers on a new
filetype (introduced in #3130) did not have augroup. As a result, when
`ts_configs.setup{ }` is called multiple times (for some reason),
duplicated installation requests will be made.
Solution: Use augroup with `clear = true`.
Context variables aren't always available, so we can't rely on them for
e.g. environment variables.
Also merge all install scripts into `script/ci-install.sh`, that way it
can be called the same way regardless of system.
This change replaces the slint parser written and maintained by @jrmoulton
with the official one hosted in the slint-ui organization on github.
A huge thank you to @jrmoulton for all his work on the tree-sitter
parser!
---------
Co-authored-by: jrmoulton <jaredmoulton3@gmail.com>
GH Actions runners use M1 hardware for `macos-14` now. Since macOS is
one of the slowest platforms for parser compilation, switching should
give us not only ARM coverage but also shorter CI times.
Add parser `php_only` for PHP files without HTML embedded.
Make queries for combined parser `php` inherit from `php_only` (no extensions needed).
---------
Co-authored-by: shirasaka <tk.shirasaka@gmail>
* fix(nim): bump parser again to include minor fix
* fix(nim): shifting around for precedence
* fix(nim): added new fields from recent parser version,
improved support for (conditional_declaration) and (variant_declaration)
* fix(nim): literals in pragmas in types would be falsly highlighted as `@variable`
* style(nim): removed trailing whitespace
* fix(nim): identifiers in (type_expression (pragma_expression)) would be
captured as `@type`
* fix(nim): changed generic parameters when declaring from @type to @parameter
* feat(nim): added @constant capture for (identifier)s x, y in
`array[x..y, type]`
* feat(nim): added @function.call capture for (identifier)s in second
argument to `varargs[type, routine]`
* feat(python): `@string.regex` capture, injection improvements
* fix(python): match regex only for first argument of re module
* chore(python): remove unneeded capture
Co-authored-by: Santos Gallegos <stsewd@proton.me>
* fix(python): only highlight string content itself as regex
---------
Co-authored-by: Santos Gallegos <stsewd@proton.me>
* feat(markdown): conceals for bullets, block quotes
* fix: remove conceals for block quotes, change list minus to em dash
* fix(markdown): allow empty bullets to be concealed
Interpolations (`{{valid js code}}`) and directive attributes
(`<element :directive="valid js code"`) can also be typescript code,
hence we can inject typescript instead of javascript here and still
be ok with highlights (bar some syntax differences between ts and js)
* feat(nim): added nim parser and queries
* correct scanner.cc to scanner.c
Co-authored-by: Christian Clason <c.clason@uni-graz.at>
* fix(nim): corrected capture for @function.macro
* feat(nim highlights): added @field capture for discriminator field in
object variant
* bumped parser version, adapted highlights.scm and condensed
injections.scm
* improved nim_format_string highlights.scm
* bump nim parser version again
* removed overlap between queries for generalized strings in
injections.scm
* improved formattin] in nim_format_string/injections.scm
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* corrected asm parser name in injections.scm
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* improved formatting in highlights.scm
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* removed @error capture from highlights.scm
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* improved wording in comment in highlights.scm
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* removed priority from (dot_expression left: @none) capture, since it's
at the end of the file anyways
* removed comments listing unused captures
* reverted @error capture in nim_format_string/highlights.scm back to
@none
* condensed string alternatives in injections.scm
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* condensed string alternatives in injections.scm (second part)
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
* added comment to explain reasoning behind priority use
* swapped order of @punctuation.delimiter and @operator to get rid of
superfluous comment
* moved macro and template keywords to @preproc capture
* removed priorities in highlights.scm and shifted @parameter capture
behind @type capture
* improved formatting in locals.scm
* added queries for missing cases of @definition.namespace capture in
locals.scm
* removed some trailing whitespace
* added @namespace queries for highlights.scm
* bumped parser version again
* removed superfluous @type capture
* removed `@type`s `has-ancestor` and removed `(_ (_ ...` structures,
but added priorities
* added missing @constant capture to some queries in highlights.scm
* fixed priority numbers so they work when injecting nim (in markdown)
* added @none captures back to injection targets
* added (assembly_statement) injection query
* added indent queries
* removed indents.scm again
* added some missing queries for dot_generic_call, concept_declaration and
pragma_statement
---------
Co-authored-by: Christian Clason <c.clason@uni-graz.at>
Co-authored-by: ObserverOfTime <chronobserver@disroot.org>
As discussed in PR#5421, capturing `@error` is inconsistent, requiring
deep nesting (or priority) in order to correctly have red backgrounds to
it.
Some queries has this capture, some don't. For consistency purposes,
removing all of them is more preferable.
For re-enabling error, either add `(ERROR) @error` or `(ERROR _ @error)`
to your custom queries.
* make sure affine_group has priority, so parens and comma will not be miscolored; added `annotation` as @attribute
* `then` is not used as conditional, so moved to keywords
* finalize function highlight added
* differentiate between constant and variable variable identifiers
I thought that this functionality was not possible but there's actually
an API for it. This seems like a useful place for others to find more
information on it.
This change does two main things:
1. Indicate that `(for_expression)`'s introduce a `@scope` (this
is the scope for the enumerators to be used within the loop).
2. Indicate that the `(identifiers)` within the `(enumerators)` are
`@definition.var`s.
---
For the following example snippet:
```scala
val fruits = List("apple", "banana", "avocado", "papaya")
val countsToFruits = fruits.groupBy(fruit => fruit.count(_ == 'a'))
for ((count, fruits) <- countsToFruits) {
println(s"with (fruits) 'a' × $count = $fruits")
}
```
The `count` and `fruits` identifiers are new definitions introduced by
the `for` expressions scope.
- Consider functions with only one value on the rhs as variables
- Applied composition: `(f . g) <param>` -> `@function.call`
- View patterns
- `@field` in record update expression
- type_tuple and type_list as variables
- quantifier for `exp_apply (<rhs>)+ (variable)`
- type_tuple and type_list as variables
- Treat signatures with only one value on the rhs as variables
(except for `IO a`) -> Fixes#5505.
- Remove redundant anchors from signature function queries.
- Move signature function queries to give them higher priority
- Scoped function types
- Add signature query to function with parameters query
* feat(julia): added missing String and AbstractString builtin types
* feat(juia): added all public built-in types in Core and Base
* feat(julia): removed private types from built-in type list
The latest release of the grammar changes the handling of consecutive
line breaks. This breaks the existing test for indents.
This commit updates the indent queries and fixes the associated test.
Problem:
Comment highlight query produces too many @spell captures.
Solution:
Remove the query. This is fine because comment parser is only used in
injection and the parent language has @spell for comment.
* Add unison
* Trivial change to force prepush hook
* Undo change
* PR Feedback - remove appended text in query after variable, update lockfile, remove main branch specification in parser
* Replacing captures with only ones in the contributing.md
* Fix typo
* Generate from grammar
* First group of suggested changes
* Update gt operator
* Remove outer parens
* Remove maybe.c
* Add comment injection
The root issue is fixed with neovim 0.9.2. But the current stable
version is neovim 0.9.1, so partially reverts the commit to make it
compatible with the current stable version.
Since 0.9, @lang syntax is still available as fallback but will soon be deprecated.
Because of that, new syntax should be adopted once 0.9 becomes the
baseline requirements for nvim-treesitter
- update health check
- update doc
- Switch to GitLab mirror repository
- Lock grammar version 2.2.0
- Revert "fix(tests): mark t32 as allowed to fail"
This reverts commit ba223ceecc.
- Revert "fix(tests): remove t32 tests"
This reverts commit 97957a547b.
- Lock grammar to version 2.1.1
- Update query for syntax hightlighting
- fix missing locals query
- reduce number of "(identifier) @variable" highlight queries
- revert to capture @function.builtin for PRACTICE call expressions
* feat(cmake): dedent for all closing brackets
* feat(cmake): indent an argument according to its previous peer
* fix(cmake); fix typo, add dedent `endwhile`
* Update parsers: ocamllex
Update its highlight to make it compatible with the new parser
* highlights(ocamllex): follow newest changes from upstream
The upstream grammar added highlights in the latest version, change our
highlight so they reflect better the intention of the grammar's author
Instead of relying on regex for matching (which matches custom symbols),
explicitly list each of the variations in `@variable.builtin, `@conditional`,
`@function.macro`.
Add `@variable.builtin` for the builtin repl variables `*1`, `*2`, `*3`, and
`*e`, which are occasionally used in tests and comments.
Move `ex-info`, `ex-cause`, `ex-data`, and `ex-message` to `@functions.builtin`.
Add missing `clojure.core` functions to `@functions.builtin` at the bottom to
minimize diff. Includes functions from 1.12-alpha2 release as well.
* fix(nickel): wrong indent on line after top level comment
Previous incorrect indentation on line after top level comment:
```
# no indent after this comment
{
another = 1
}
```
Expected result:
```
# no indent after this comment
{
another = 1
}
````
The original approach was to emulate what was in Clojure's
highlights.scm file, but it appears that there were a number of
questionable items, so some sections were removed.
As a consequence, there were some items that ended up unmentioned. An
attempt was made to rescue most of these and add some missing items to
a renamed "Special forms and builtin macros" section.
Five items were removed entirely. These are:
* Single quote
* Tilde
* Pipe
* Comma
* Semicolon
It was unclear where to put these and it's also unclear whether
highlighting them would really be beneficial. Perhaps what to do, if
anything, will become clear in the future.
`@scope` included `function_declaration` while is should have included `function_definition` instead. The former one is used to declare abstract functions while the latter one is used to define functions together with their bodies.
Problem: The current vimscript parser has not been maintained for a while, which was a blocker for packaging the coming Neovim release.
Solution: Fork parser to https://github.com/neovim/tree-sitter-vim/ and maintain it there from now on.
This will make the parsers align more closely to the ones bundled with
Neovim, because CMake uses the `-bundle` flag (instead of `-shared`) on
macOS when a library is compiled as a `MODULE`.
See, for example:
10baf89712/cmake.deps/cmake/TreesitterParserCMakeLists.txt (L6-L9)
indents now use @indent.X style captures, and indent.PROP for properties to set on those captures, as documented in the help.
Captures are:
indent.auto
indent.begin
indent.end
indent.dedent
indent.branch
indent.ignore
indent.align
indent.zero
Properties are:
indent.immediate
indent.start_at_same_line
indent.open_delimiter
indent.close_delimiter
indent.increment
indent.avoid_last_matching_next
Multiple opening delims on one line and multiple closing on a line are collapsed so as not to over indent,
The final line of @indent.align blocks which must in some cases be treated specially to avoid clashing with the next line is treated the same regardless of whether the @indent.align capture actually uses aligned indentation or just normal indentation. The indent.avoid_last_matching_next property controls this.
Adjust python to use these.
List, set, dict and tuple all use @indent.align which permits both hanging and aligned styles.
Finally, try: on it’s own will indent when typing live but make no guaranteeds about whole-file formatting.
Includes lucario387:fix-align-indent
`return ...` is usually the last line of a
function/statement, so mark some possible patterns of `return` with
`@indent_end` to dedent the line after it
The parser is currently in development, and 60-80% of MLIR files in the
test suite of MLIR, within the Arith, Math, SCF, Tensor, and Linalg
dialects parse successfully.
* fix Java indent for multiple line arguments, fixes#4448, add an additional test for methods with arguments on multiple lines
* Satisfy StyLua check
---------
Co-authored-by: Daniel Woznicki <danwoz@nettoolkit.com>
When viewing the previous rule in the `TSPlayground` the `@function`
captures were not actually matching. This led all functions to get the
`@function.call` group applied to them. This change makes it so that the
capture now works and where functions are defined will get the
`@function` group.
I've seen many people, including myself, being confused about `highlight { enable = false }` disabling the whole extension. It means it will disable highlighting, but people get it wrong thinking that they can't use textobjects or any other treesitter related stuff.
description:Missing or incorrect highlights or you want to change the way something is highlighted
labels:[highlights ]
type:'bug'
labels:[highlights]
body:
- type:markdown
@ -11,10 +12,10 @@ body:
- I have updated my neovim version to latest _master_.
- I have updated my plugin to the latest version.
- I have run `:TSUpdate`.
- I have inspected the syntax tree using https://github.com/nvim-treesitter/playground and made sure
- I have inspected the syntax tree using `:InspectTree` and made sure
that no `ERROR` nodes are in the syntax tree. nvim-treesitter can not guarantee correct highlighting in the
presence of `ERROR`s -- in this case, please report the bug directly at corresponding parser's repository. (You can find all repository URLs in [README.md](https://github.com/nvim-treesitter/nvim-treesitter#supported-languages).)
- I have used `:TSHighlightCapturesUnderCursor` from https://github.com/nvim-treesitter/playground to inspect which highlight groups Neovim is using and that legacy syntax highlighting is not interfering (i.e., what you are observing is actual tree-sitter highlighting).
- I have used `:Inspect` to inspect which highlight groups Neovim is using and that legacy syntax highlighting is not interfering (i.e., what you are observing is actual tree-sitter highlighting).
- type:textarea
attributes:
@ -34,8 +35,8 @@ body:
attributes:
label:Tree-sitter parsing result
description:|
Please provide the output of `:TSPlaygroundToggle` from https://github.com/nvim-treesitter/playground
(screenshot or plain text) with the following options enabled (pressing the key):
Please provide the output of `:InspectTree` (screenshot or plain text)
with the following options enabled (pressing the key):
- `I` (name of the parsed language)
- `t` (toggle injected languages)
- `a` (show anonymous nodes)
@ -66,7 +67,7 @@ body:
description:|
Please provide a screenshot of the current highlighting. Please also tell us the `:h colorscheme` you are using
and how to install it. If applicable, you can also upload a screenshot with the contents of
"markup.raw":"literal or verbatim text (e.g. inline code)",
"markup.raw.block":"literal or verbatim text as a stand-alone block ; (use priority 90 for blocks with injections)",
"markup.list":"list markers",
"markup.list.checked":"checked todo-style list markers",
"markup.list.unchecked":"unchecked todo-style list markers",
"diff.plus":"added text (for diff files)",
"diff.minus":"deleted text (for diff files)",
"diff.delta":"changed text (for diff files)",
"tag":"XML-style tag names (and similar)",
"tag.builtin":"builtin tag names (e.g. HTML5 tags)",
"tag.attribute":"XML-style tag attributes",
"tag.delimiter":"XML-style tag delimiters",
"conceal":"captures that are only meant to be concealed",
"spell":"for defining regions to be spellchecked",
"nospell":"for defining regions that should NOT be spellchecked",
"none":"completely disable the highlight"
},
"injections":{
"injection.content":"indicates that the captured node should have its contents re-parsed using another language",
"injection.language":"indicates that the captured node’s text may contain the name of a language that should be used to re-parse the `@injection.content`",
"injection.filename":"indicates that the captured node’s text may contain a filename; the corresponding filetype is then looked-up up via `vim.filetype.match()` and treated as the name of a language that should be used to re-parse the `@injection.content`"
},
"folds":{
"fold":"fold this node"
},
"indents":{
"indent.begin":"Specifies that the next line should be indented. Multiple indents on the same line get collapsed. Indent can also have `indent.immediate` set using a `#set!` directive, which permits the next line to indent even when the block intended to be indented has no content yet, improving interactive typing.",
"indent.end":"Used to specify that the indented region ends and any text subsequent to the capture should be dedented.",
"indent.align":"Specifies aligned indent blocks (like python aligned/hanging indent). Specify the delimiters with `indent.open_delimiter` and `indent.close_delimiter` metadata. For some languages, the last line of an `indent.align` block must not be the same indent as the natural next line, which can be controlled by setting `indent.avoid_last_matching_next`.",
"indent.dedent":"Specifies dedenting starting on the next line.",
"indent.branch":"Used to specify that a dedented region starts at the line including the captured nodes.",
"indent.ignore":"Specifies that indentation should be ignored for this node.",
"indent.auto":"Behaves like 'autoindent' buffer option.",
"indent.zero":"Sets indentation for this node to zero (no indentation)."
},
"locals":{
"local.definition":"various definitions",
"local.definition.constant":"constants",
"local.definition.function":"functions",
"local.definition.method":"methods",
"local.definition.var":"variables",
"local.definition.parameter":"parameters",
"local.definition.macro":"preprocessor macros",
"local.definition.type":"types or classes",
"local.definition.field":"fields or properties",
"local.definition.enum":"enumerations",
"local.definition.namespace":"modules or namespaces",
"local.definition.import":"imported names",
"local.definition.associated":"the associated type of a variable",
"local.scope":"scope block",
"local.reference":"identifier reference"
}
},
"valid_predicates":{
"eq":{
"any":true,
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"any",
"arity":"required"
}
],
"description":"checks for equality between two nodes, or a node and a string"
},
"any-of":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required"
},
{
"type":"string",
"arity":"required"
},
{
"type":"string",
"arity":"variadic"
}
],
"description":"match any of the given strings against the text corresponding to a node"
},
"contains":{
"any":true,
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required"
},
{
"type":"string",
"arity":"variadic"
}
],
"description":"match a string against parts of the text corresponding to a node"
},
"match":{
"any":true,
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required"
}
],
"description":"Match a regexp against the text corresponding to a node"
},
"lua-match":{
"any":true,
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required"
}
],
"description":"match a Lua pattern against the text corresponding to a node"
},
"has-ancestor":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required",
"constraint":"named_node"
},
{
"type":"string",
"arity":"variadic",
"constraint":"named_node"
}
],
"description":"match any of the given node types against all ancestors of a node"
},
"has-parent":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required",
"constraint":"named_node"
},
{
"type":"string",
"arity":"variadic",
"constraint":"named_node"
}
],
"description":"match any of the given node types against the direct ancestor of a node"
},
"kind-eq":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required",
"constraint":"named_node"
},
{
"type":"string",
"arity":"variadic",
"constraint":"named_node"
}
],
"description":"checks whether a capture corresponds to a given set of nodes"
}
},
"valid_directives":{
"set":{
"parameters":[
{
"type":"any",
"arity":"required"
},
{
"type":"any",
"arity":"optional"
},
{
"type":"any",
"arity":"optional"
}
],
"description":"sets key/value metadata for a specific match or capture"
},
"offset":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required",
"constraint":"integer"
},
{
"type":"string",
"arity":"required",
"constraint":"integer"
},
{
"type":"string",
"arity":"required",
"constraint":"integer"
},
{
"type":"string",
"arity":"required",
"constraint":"integer"
}
],
"description":"Takes the range of the captured node and applies an offset. This will set a new range in the form of a list like { {start_row}, {start_col}, {end_row}, {end_col} } for the captured node with `capture_id` as `metadata[capture_id].range`."
},
"gsub":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"required"
},
{
"type":"string",
"arity":"required"
}
],
"description":"Transforms the content of the node using a Lua pattern. This will set a new `metadata[capture_id].text`."
},
"trim":{
"parameters":[
{
"type":"capture",
"arity":"required"
},
{
"type":"string",
"arity":"optional",
"constraint":{
"enum":["0","1"]
}
},
{
"type":"string",
"arity":"optional",
"constraint":{
"enum":["0","1"]
}
},
{
"type":"string",
"arity":"optional",
"constraint":{
"enum":["0","1"]
}
},
{
"type":"string",
"arity":"optional",
"constraint":{
"enum":["0","1"]
}
}
],
"description":"Trims whitespace from the node. Sets a new `metadata[capture_id].range`. Takes a capture ID and, optionally, four integers to customize trimming behavior (`1` meaning trim, `0` meaning don't trim). When only given a capture ID, trims blank lines (lines that contain only whitespace, or are empty) from the end of the node (for backwards compatibility). Can trim all whitespace from both sides of the node if parameters are given."
* There are dedicated Matrix channels for questions and general help:
- [#nvim-treesitter](https://matrix.to/#/#nvim-treesitter:matrix.org) for questions specific to Neovim's implementation and the queries here;
- [#tree-sitter](https://matrix.to/#/#tree-sitter-chat:matrix.org) for general questions regarding treesitter queries and the `tree-sitter` CLI.
As you know, `nvim-treesitter` is roughly split in two parts:
## Parsers
- Parser configurations : for various things like `locals`, `highlights`
- What we like to call *modules* : tiny lua modules that provide a given feature, based on parser configurations
>[!IMPORTANT]
> To qualify for inclusion, a parser must meet the following criteria:
> * correspond to a filetype detected by Neovim (nightly)
> * feature complete, tested by users, and actively maintained (according to maintainer discretion)
> * hosted or mirrored on Github (other codeforges are not reliable enough for CI)
> * covered by CI using [upstream workflows](https://github.com/tree-sitter/workflows)
> * provide reference queries covered by a [`ts_query_ls` workflow](https://github.com/tree-sitter-grammars/template/blob/9c46d09d688d27c7aef31c2b32f50260de4e7906/.github/workflows/ci.yml#L69-L86)
> * if the repo contains a `src/parser.c`, it must support the latest ABI
> * if the repo does _not_ contain a `src/parser.c`, it must contain an up-to-date `src/grammar.json`
> * if the repo contains an external scanner, it must be written in C99
>
> Tier 1 parsers (preferred) in addition need to
> * make regular releases following semver (_patch_ for fixes not affecting queries; _minor_ for changes introducing new nodes or patterns; _major_ for changes removing nodes or previously valid patterns)
> * provide WASM release artifacts
Depending on which part of the plugin you want to contribute to, please read the appropriate section.
To add a new parser, edit the following files:
## Style Checks and Tests
1. In `lua/parsers.lua`, add an entry to the returned table of the following form:
We haven't implemented any functional tests yet. Feel free to contribute.
However, we check code style with `luacheck` and `stylua`!
Please install luacheck and activate our `pre-push` hook to automatically check style before
every push:
```bash
luarocks install luacheck
cargo install stylua
ln -s ../../scripts/pre-push .git/hooks/pre-push
```lua
zimbu = {
install_info = {
url = 'https://github.com/zimbulang/tree-sitter-zimbu', -- git repo; use `path` for local path
revision = 'v2.1', -- tag or commit hash
-- optional entries:
branch = 'develop', -- only needed if different from default branch
location = 'parser', -- only needed if the parser is in subdirectory of a "monorepo"
generate = true, -- only needed if repo does not contain pre-generated src/parser.c
},
maintainers = { '@me' }, -- the _query_ maintainers
requires = { 'vim' }, -- if the queries inherit from another language
readme_note = "an example language",
}
```
## Adding new modules
>[!IMPORTANT]
> The "maintainers" here refers to the person maintaining the **queries** in `nvim-treesitter`, not the parser maintainers (who likely don't use Neovim). The maintainers' duty is to review issues and PRs related to the query and to keep them updated with respect to parser changes.
If you want to see a new functionality added to `nvim-treesitter` feel free to first open an issue
to that we can track our solution!
Thus far, there is basically two types of modules:
2. If the parser name is not the same as the Vim filetype, add an entry to the `filetypes` table in `plugin/filetypes.lua`:
- Little modules (like `incremental selection`) that are built in `nvim-treesitter`, we call them
`builtin modules`.
- Bigger modules (like `completion-treesitter`, or `nvim-tree-docs`), or modules that integrate
with other plugins, that we call `remote modules`.
```lua
zimbu = { 'zu' },
```
In any case, you can build your own module! To help you started in the process, we have a template
repository designed to build new modules [here](https://github.com/nvim-treesitter/module-template).
Feel free to use it, and contact us over on our
on the "Neovim tree-sitter" [Matrix channel].
3. Update the list of [supported languages] by running `make docs` (or `./scripts/update-readme.lua` if on Windows).
## Parser configurations
4. Test if both `:TSInstall zimbu` and `:TSInstallFromGrammar zimbu` work without errors (`:checkhealth treesitter` or `./scripts/check-parsers.lua zimbu`).
Contributing to parser configurations is basically modifying one of the `queries/*/*.scm`.
Each of these `scheme` files contains a *tree-sitter query* for a given purpose.
Before going any further, we highly suggest that you [read more about tree-sitter queries](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries).
>[!IMPORTANT]
> You also need to add queries in order for the parser to actually be useful!
Each query has an appropriate name, which is then used by modules to extract data from the syntax tree.
For now these are the types of queries used by `nvim-treesitter`:
When you're done, open a Pull Request using the [provided template](.github/PULL_REQUEST_TEMPLATE/new_language.md), e.g. using `gh pr create -B main -T new_language`.
- `highlights.scm`: used for syntax highlighting, using the `highlight` module.
- `locals.scm`: used to extract keyword definitions, scopes, references, etc, using the `locals` module.
- `textobjects.scm`: used to define text objects.
- `folds.scm`: used to define folds.
- `injections.scm`: used to define injections.
## Queries
For these types there is a *norm* you will have to follow so that features work fine.
Here are some global advices:
To add (or edit existing) queries, create a corresponding `runtime/queries/zimbu/*.scm` file:
- If your language is listed [here](https://github.com/nvim-treesitter/nvim-treesitter#supported-languages),
you can install the [playground plugin](https://github.com/nvim-treesitter/playground).
- If your language is listed [here](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries),
you can debug and experiment with your queries there.
- If not, you should consider installing the [tree-sitter cli](https://github.com/tree-sitter/tree-sitter/tree/master/cli),
you should then be able to open a local playground using `tree-sitter build-wasm && tree-sitter web-ui` within the
parsers repo.
- Examples of queries can be found in [queries/](queries/)
- Matches in the bottom will override queries that are above of them.
- `highlights.scm` used for syntax highlighting,
- `injections.scm` used to specify nodes whose content should be parsed as a different language;
- `folds.scm`; used to define folds;
- `locals.scm`: used to extract keyword definitions, scopes, references, etc. (not used in this plugin).
- `indents.scm`; used to control indentation.
See [tree-sitter queries] for a basic description of the query language. The following tools can be helpful when writing or editing queries:
* [ts_query_ls] is a language server for treesitter queries, which can validate, autocomplete, and format. This tool can also be used as an offline linter and formatter (accessible through `make lintquery`, `make checkquery`, `make formatquery` targets).
* Neovim's `:InspectTree` will show the parsed tree for a buffer and highlight the text corresponding to any given node (and vice versa).
* `:EditQuery` opens a "playground" where you can write query patterns and see which parts of the buffer are captured by each capture.
>[!IMPORTANT]
> The valid captures that can be used in queries is different for each editor, so you cannot just copy them, e.g., from Helix or the parser repositories. For Neovim, all valid captures are listed below. You can verify that your changes adhere to this by running `make lintquery`.
>[!IMPORTANT]
> Since grammars can change constantly, it is important to make sure that the patterns in a query are actually valid for the parser specified in nvim-treesitter's manifest. This can be verified using `make checkquery` (which requires the parser to be installed in the default directory(!) through `nvim-treesitter`). Opening the query in Neovim with the parser installed will also show all invalid patterns, either via [ts_query_ls] or Neovim's builtin query-linter.
>[!TIP]
> Before opening a PR, run `make query` to format, lint, and check all queries.
#### Inheriting languages
If your language is an extension of a language (TypeScript is an extension of JavaScript for
example), you can include the queries from your base language by adding the following _as the first
line of your file_.
line of your file_:
```query
; inherits: lang1,(optionallang)
@ -80,184 +106,405 @@ line of your file_.
If you want to inherit a language, but don't want the languages inheriting from yours to inherit it,
you can mark the language as optional (by putting it between parenthesis).
#### Formatting
All queries are expected to follow a standard format, with every node on a single line and indented by two spaces for each level of nesting. You can automatically format the bundled queries by running `make formatquery`.
Should you need to preserve a specific format for a node, you can exempt it (and all contained nodes) by placing before it
```query
; format-ignore
```
### Highlights
As languages differ quite a lot, here is a set of captures available to you when building a `highlights.scm` query.
One important thing to note is that many of these capture groups are not supported by `neovim` for now, and will not have any
effect on highlighting. We will work on improving highlighting in the near future though.
Syntax highlighting is specified in a `highlights.scm` query, which assigns treesitter nodes to captures that can be assigned a highlight group. This feature is implemented in Neovim and documented at [`:h treesitter-highlight`](https://neovim.io/doc/user/treesitter.html#treesitter-highlight).
Note that your color scheme needs to define (or link) these captures as highlight groups. You can use Neovim's built-in `:Inspect` function to see exactly which highlight groups are applied at a given position.
#### Misc
The valid captures are listed below.
```scheme
@comment ; line and block comments
@error ; syntax/parser errors
@none ; completely disable the highlight
@preproc ; various preprocessor directives & shebangs
@markup.heading.6 ; six levels ought to be enough for anybody
@text.diff.add ; added text (for diff files)
@text.diff.delete ; deleted text (for diff files)
@markup.quote ; block quotes
@markup.math ; math environments (e.g. `$ ... $` in LaTeX)
@markup.link ; text references, footnotes, citations, etc.
@markup.link.label ; link, reference descriptions
@markup.link.url ; URL-style links
@markup.raw ; literal or verbatim text (e.g. inline code)
@markup.raw.block ; literal or verbatim text as a stand-alone block
; (use priority 90 for blocks with injections)
@markup.list ; list markers
@markup.list.checked ; checked todo-style list markers
@markup.list.unchecked ; unchecked todo-style list markers
```
#### Tags
Used for XML-like tags.
```scheme
@tag ; XML tag names
@tag.attribute ; XML tag attributes
@tag.delimiter ; XML tag delimiters
```query
@diff.plus ; added text (for diff files)
@diff.minus ; deleted text (for diff files)
@diff.delta ; changed text (for diff files)
```
#### Conceal
```scheme
@conceal ; for captures that are only used for concealing
```query
@tag ; XML-style tag names (and similar)
@tag.builtin ; builtin tag names (e.g. HTML5 tags)
@tag.attribute ; XML-style tag attributes
@tag.delimiter ; XML-style tag delimiters
```
`@conceal` must be followed by `(#set! conceal "")`.
#### Non-highlighting captures
#### Spell
```query
@conceal ; captures that are only meant to be concealed
```
```scheme
>[!TIP]
> * See [`:h tree-sitter-highlight-conceal`](https://neovim.io/doc/user/treesitter.html#treesitter-highlight-conceal).
> * The capture should be meaningful to allow proper highlighting when `set conceallevel=0`.
> * A conceal can be restricted to part of the capture via the [`#offset!` directive](https://neovim.io/doc/user/treesitter.html#treesitter-directive-offset%21).
```query
@spell ; for defining regions to be spellchecked
@nospell ; for defining regions that should NOT be spellchecked
```
### Locals
>[!TIP]
> The main types of nodes that should be spell checked are
> - comments
> - strings; where it makes sense. Strings that have interpolation or are typically used for non text purposes are not spell checked (e.g. bash).
```scheme
@definition ; various definitions
@definition.constant ; constants
@definition.function ; functions
@definition.method ; methods
@definition.var ; variables
@definition.parameter ; parameters
@definition.macro ; preprocessor macros
@definition.type ; types or classes
@definition.field ; fields or properties
@definition.enum ; enumerations
@definition.namespace ; modules or namespaces
@definition.import ; imported names
@definition.associated ; the associated type of a variable
#### Predicates
@scope ; scope block
@reference ; identifier reference
Captures can be restricted according to node contents using [predicates](https://neovim.io/doc/user/treesitter.html#treesitter-predicates).
>[!IMPORTANT]
> For performance reasons, prefer earlier predicates in this list:
>
> 1. `#eq?` (literal match)
> 2. `#any-of?` (one of several literal matches)
> 3. `#lua-match?` (match against a [Lua pattern](https://neovim.io/doc/user/luaref.html#lua-pattern))
> 4. `#match?`/`#vim-match?` (match against a [Vim regular expression](https://neovim.io/doc/user/pattern.html#regexp)
Besides those provided by Neovim, nvim-treesitter also implements
```query
#kind-eq? ; checks whether a capture corresponds to a given set of nodes
#any-kind-eq? ; checks whether any of a list of captures corresponds to a given set of nodes
```
#### Definition Scope
#### Directives
Nodes contain metadata that can be modified via [directives](https://neovim.io/doc/user/treesitter.html#treesitter-directives).
#### Priority
Captures can be assigned a priority to control precedence of highlights via the
`#set! priority <number>` directive (see [`:h treesitter-highlight-priority`](https://neovim.io/doc/user/treesitter.html#treesitter-highlight-priority)). This is useful for controlling conflicts with injected languages or when inheriting queries from other languages.
>[!NOTE]
> The default priority for treesitter highlights is `100`; queries should only
set priorities between `90` and `120`, to avoid conflict with other sources of highlighting (such as diagnostics or LSP semantic tokens).
>[!TIP]
> Precedence is also influenced by pattern order in a query file. If possible, try to achieve the correct result by reordering patterns before resorting to explicit priorities.
### Injections
Language injections are controlled by `injections.scm` queries, which specify nodes that should be parsed as a different language. This feature is implemented in Neovim and documented at
@injection.language ; dynamic detection of the injection language (i.e. the text of the captured node describes the language)
@injection.content ; region for the dynamically detected language
@injection.filename ; indicates that the captured node’s text may contain a filename; the corresponding filetype is then looked-up up via vim.filetype.match() and treated as the name of a language that should be used to re-parse the `@injection.content`
```
>[!TIP]
> When writing injection queries, try to ensure that each captured node is only matched by a single pattern.
### Folds
You can define folds for a given language by adding a `folds.scm` query. This is implemented in Neovim. The only valid capture is `@fold`:
```query
(function_definition) @fold ; fold this node
```
Folds should be given to nodes with defined start and end delimiters/patterns, or to consecutive nodes which are part of the same conceptual "grouping", such as consecutive line comments or import statements. The following items are valid fold candidates:
- Function/method definitions
- Class/interface/trait definitions
- Switch/match statements, and individual match arms
- Execution blocks (such as those found in conditional statements or loops)
- Parameter/argument lists
- Array/object/string expressions
- Consecutive import statements, consecutive line comments
The following items would *not* be valid fold candidates:
- Multiline assignment statements
- Multiline property access expressions
As a rule of thumb, these highlight captures usually reside in or around objects which should be folded:
> Treesitter-based indentation is still experimental and likely to have breaking changes in the future.
Indentation for a language is controlled by `indents.scm` queries. The following captures can be used to set the indentation for nodes, either relative or absolute
* `@indent.begin` specifies that the next line should be indented. Multiple
indents on the same line get collapsed, e.g.,
```query
(
(if_statement)
(ERROR "else") @indent.begin
)
```
You can also `#set! indent.immediate` to permit the next line to indent even when the block intended to be indented has no content yet. (This can improve interactive typing.)
For example for Python,
```query
((if_statement) @indent.begin
(#set! indent.immediate 1))
```
will allow
```python
if True:<CR>
# Auto indent to here
```
* `@indent.end` is used to specify that the indented region ends and any text subsequent to the capture should be dedented.
* `@indent.branch` is used to specify that a dedented region starts at the line _including_ the captured nodes.
* `@indent.dedent` specifies dedenting starting on the _next_ line.
* `@indent.auto` behaves like Vim's [`autoindent`](https://neovim.io/doc/user/options.html#'autoindent') buffer option (copy whatever the indentation of previous line is when opening a new line after it).
* `@indent.ignore` specifies that no indent should be added to this node.
* `@indent.zero` sets the indentation of this node to 0 (i.e., removes _all_ indentation).
* `@indent.align` can be used to specify blocks that should have the same indentation.
This allows
```
foo(a,
b,
c)
```
as well as
```
foo(
a,
b,
c)
```
and
```
foo(
a,
b,
c
)
```
To specify the delimiters to align at, `#set! indent.open_delimiter` and
`indent.close_delimiter`, e.g.,
```query
((argument_list) @indent.align
(#set! indent.open_delimiter "(")
(#set! indent.close_delimiter ")"))
```
For some languages, the last line of an `indent.align` block must not be
the same indent as the natural next line.
For example in Python,
```python
if (a > b and
c <d):
pass
```
is not correct, whereas
```python
if (a > b and
c <d):
pass
```
would be correctly indented. This behavior may be selected by setting
Logo by <ahref="https://github.com/steelsojka">@steelsojka</a>
</i>
</p>
</div>
The `nvim-treesitter` plugin provides
1. functions for installing, updating, and removing [**tree-sitter parsers**](SUPPORTED_LANGUAGES.md);
2. a collection of **queries** for enabling tree-sitter features built into Neovim for these languages;
3. a staging ground for [treesitter-based features](#Supported-features) considered for upstreaming to Neovim.
The goal of `nvim-treesitter` is both to provide a simple and easy way to use the interface for [tree-sitter](https://github.com/tree-sitter/tree-sitter) in Neovim and to provide some basic functionality such as highlighting based on it:
For details on these and how to help improving them, see [CONTRIBUTING.md](./CONTRIBUTING.md).
Traditional highlighting (left) vs Treesitter-based highlighting (right).
More examples can be found in [our gallery](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Gallery).
**Warning: Treesitter and nvim-treesitter highlighting are an experimental feature of Neovim.
Please consider the experience with this plug-in as experimental until Tree-Sitter support in Neovim is stable!
We recommend using the nightly builds of Neovim if possible.
You can find the current roadmap [here](https://github.com/nvim-treesitter/nvim-treesitter/projects/1).
The roadmap and all features of this plugin are open to change, and any suggestion will be highly appreciated!**
Nvim-treesitter is based on three interlocking features: [**language parsers**](#language-parsers), [**queries**](#adding-queries), and [**modules**](#available-modules), where *modules* provide features – e.g., highlighting – based on *queries* for syntax objects extracted from a given buffer by *language parsers*.
Users will generally only need to interact with parsers and modules as explained in the next section.
For more detailed information on setting these up, see ["Advanced setup"](#advanced-setup).
---
### Table of contents
* [Quickstart](#quickstart)
* [Supported languages](#supported-languages)
* [Available modules](#available-modules)
* [Advanced setup](#advanced-setup)
* [Extra features](#extra-features)
* [Troubleshooting](#troubleshooting)
---
>[!CAUTION]
> This is a full, incompatible, rewrite: Treat this as a different plugin you need to set up from scratch following the instructions below. If you can't or don't want to update, specify the [`master` branch](https://github.com/nvim-treesitter/nvim-treesitter/blob/master/README.md) (which is locked but will remain available for backward compatibility with Nvim 0.11).
# Quickstart
## Requirements
- **Neovim 0.8.0 or later** built with **tree-sitter 0.20.3+** (latest [nightly](https://github.com/neovim/neovim#install-from-source) recommended)
- `tar` and `curl` in your path (or alternatively `git`)
- A C compiler in your path and libstdc++ installed ([Windows users please read this!](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Windows-support)).
- Neovim 0.12.0 or later (nightly)
- `tar` and `curl` in your path
- [`tree-sitter-cli`](https://github.com/tree-sitter/tree-sitter/blob/master/crates/cli/README.md) (0.26.1 or later, installed via your package manager, **not npm**)
- a C compiler in your path (see <https://docs.rs/cc/latest/cc/#compile-time-requirements>)
>[!IMPORTANT]
> The current **support policy** for Neovim is
> * the _latest_ [stable release](https://github.com/neovim/neovim/releases/tag/stable),
> * the _latest_ [nightly prerelease](https://github.com/neovim/neovim/releases/tag/nightly).
> Other versions may work but are neither tested nor considered for fixes.
## Installation
You can install `nvim-treesitter` with your favorite package manager (or using the native `package` feature of vim, see `:h packages`).
**NOTE: This plugin is only guaranteed to work with specific versions of language parsers** (as specified in the `lockfile.json`). **When upgrading the plugin, you must make sure that all installed parsers are updated to the latest version** via `:TSUpdate`.
It is strongly recommended to automate this; e.g., if you are using [vim-plug](https://github.com/junegunn/vim-plug), put this in your `init.vim` file:
For other plugin managers such as `packer.nvim`, see this [Installation page from the wiki](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Installation) (Note that this page is community maintained).
## Language parsers
Treesitter uses a different _parser_ for every language, which needs to be generated via `tree-sitter-cli` from a `grammar.js` file, then compiled to a `.so` library that needs to be placed in neovim's `runtimepath` (typically under `parser/{language}.so`).
To simplify this, `nvim-treesitter` provides commands to automate this process.
If the language is already [supported by `nvim-treesitter`](#supported-languages), you can install it with
```vim
:TSInstall <language_to_install>
```
This command supports tab expansion.
You can also get a list of all available languages and their installation status with `:TSInstallInfo`.
Parsers not on this list can be added manually by following the steps described under ["Adding parsers"](#adding-parsers) below.
To make sure a parser is at the latest compatible version (as specified in `nvim-treesitter`'s `lockfile.json`), use `:TSUpdate {language}`. To update all parsers unconditionally, use `:TSUpdate all` or just `:TSUpdate`.
## Modules
Each module provides a distinct tree-sitter-based feature such as [highlighting](#highlight), [indentation](#indentation), or [folding](#folding); see [`:h nvim-treesitter-modules`](doc/nvim-treesitter.txt) or ["Available modules"](#available-modules) below for a list of modules and their options.
Following examples assume that you are configuring neovim with lua. If you are using vimscript, see `:help lua-heredoc`.
All modules are disabled by default and need to be activated explicitly in your `init.lua`, e.g., via
This plugin is only guaranteed to work with specific versions of language parsers** (as specified in the `parser.lua` table). **When upgrading the plugin, you must make sure that all installed parsers are updated to the latest version** via `:TSUpdate`.
It is strongly recommended to automate this; e.g., using the following spec with [lazy.nvim](https://github.com/folke/lazy.nvim):
```lua
require'nvim-treesitter.configs'.setup {
-- A list of parser names, or "all" (the four listed parsers should always be installed)
ensure_installed = { "c", "lua", "vim", "help" },
-- Install parsers synchronously (only applied to `ensure_installed`)
sync_install = false,
-- Automatically install missing parsers when entering buffer
-- Recommendation: set to false if you don't have `tree-sitter` CLI installed locally
auto_install = true,
-- List of parsers to ignore installing (for "all")
ignore_install = { "javascript" },
---- If you need to change the installation directory of the parsers (see -> Advanced Setup)
-- parser_install_dir = "/some/path/to/store/parsers", -- Remember to run vim.opt.runtimepath:append("/some/path/to/store/parsers")!
highlight = {
-- `false` will disable the whole extension
enable = true,
-- NOTE: these are the names of the parsers and not the filetype. (for example if you want to
-- disable highlighting for the `tex` filetype, you need to include `latex` in this list as this is
-- the name of the parser)
-- list of language that will be disabled
disable = { "c", "rust" },
-- Or use a function for more flexibility, e.g. to disable slow treesitter highlight for large files
disable = function(lang, buf)
local max_filesize = 100 * 1024 -- 100 KB
local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
if ok and stats and stats.size > max_filesize then
return true
end
end,
-- Setting this to true will run `:h syntax` and tree-sitter at the same time.
-- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
-- Using this option may slow down your editor, and you may see some duplicate highlights.
-- Instead of true it can also be a list of languages
additional_vim_regex_highlighting = false,
},
{
'nvim-treesitter/nvim-treesitter',
lazy = false,
build = ':TSUpdate'
}
```
Each module can also be enabled or disabled interactively through the following commands:
>[!IMPORTANT]
> This plugin does not support lazy-loading.
```vim
:TSBufEnable {module} " enable module on current buffer
:TSBufDisable {module} " disable module on current buffer
:TSEnable {module} [{ft}] " enable module on every buffer. If filetype is specified, enable only for this filetype.
:TSDisable {module} [{ft}] " disable module on every buffer. If filetype is specified, disable only for this filetype.
:TSModuleInfo [{module}] " list information about modules state for each filetype
## Setup
`nvim-treesitter` can be configured by calling `setup`. **You do not need to call `setup` for `nvim-treesitter` to work using default values.**
```lua
require('nvim-treesitter').setup {
-- Directory to install parsers and queries to (prepended to `runtimepath` to have priority)
(This is a no-op if the parsers are already installed.) Note that this function runs asynchronously; for synchronous installation in a script context ("bootstrapping"), you need to `wait()` for it to finish:
Check [`:h nvim-treesitter-commands`](doc/nvim-treesitter.txt) for a list of all available commands.
It may be necessary to reload the buffer (e.g., via `:e`) after enabling a module interactively.
# Supported languages
For `nvim-treesitter` to support a specific feature for a specific language requires both a parser for that language and an appropriate language-specific query file for that feature.
The following is a list of languages for which a parser can be installed through `:TSInstall`; a checked box means that `nvim-treesitter` also contains queries at least for the `highlight` module.
A list of the currently supported languages can be found [on this page](SUPPORTED_LANGUAGES.md). If you wish to add a new language or improve the queries for an existing one, please see our [contributing guide](CONTRIBUTING.md).
Experimental parsers are parsers that have a maintainer but are not stable enough for
daily use yet.
# Supported features
We are looking for maintainers to add more parsers and to write query files for their languages. Check our [tracking issue](https://github.com/nvim-treesitter/nvim-treesitter/issues/2282) for open language requests.
`nvim-treesitter` provides queries for the following features. **These are not automatically enabled.**
<!--This section of the README is automatically updated by a CI job-->
<!--parserinfo-->
- [x] [ada](https://github.com/briot/tree-sitter-ada) (maintained by @briot)
- [x] [agda](https://github.com/AusCyberman/tree-sitter-agda) (maintained by @Decodetalkers)
- [x] [arduino](https://github.com/ObserverOfTime/tree-sitter-arduino) (maintained by @ObserverOfTime)
- [x] [astro](https://github.com/virchau13/tree-sitter-astro) (maintained by @virchau13)
- [x] [pascal](https://github.com/Isopod/tree-sitter-pascal.git) (maintained by @Isopod)
- [x] [perl](https://github.com/ganezdragon/tree-sitter-perl) (maintained by @lcrownover)
- [x] [php](https://github.com/tree-sitter/tree-sitter-php) (maintained by @tk-shirasaka)
- [x] [phpdoc](https://github.com/claytonrcarter/tree-sitter-phpdoc) (experimental, maintained by @mikehaertl)
- [x] [pioasm](https://github.com/leo60228/tree-sitter-pioasm) (maintained by @leo60228)
- [x] [Path of Exile item filter](https://github.com/ObserverOfTime/tree-sitter-poe-filter) (experimental, maintained by @ObserverOfTime)
- [x] [prisma](https://github.com/victorhqc/tree-sitter-prisma) (maintained by @elianiva)
- [x] [proto](https://github.com/mitchellh/tree-sitter-proto) (maintained by @fsouza)
- [x] [pug](https://github.com/zealot128/tree-sitter-pug) (experimental, maintained by @zealot128)
- [x] [python](https://github.com/tree-sitter/tree-sitter-python) (maintained by @stsewd, @theHamsta)
- [x] [ql](https://github.com/tree-sitter/tree-sitter-ql) (maintained by @pwntester)
- [x] [qmljs](https://github.com/yuja/tree-sitter-qmljs) (maintained by @Decodetalkers)
- [x] [Tree-sitter query language](https://github.com/nvim-treesitter/tree-sitter-query) (maintained by @steelsojka)
- [x] [r](https://github.com/r-lib/tree-sitter-r) (maintained by @echasnovski)
- [x] [racket](https://github.com/6cdh/tree-sitter-racket) (maintained by @6cdh)
- [x] [rasi](https://github.com/Fymyte/tree-sitter-rasi) (maintained by @Fymyte)
- [x] [regex](https://github.com/tree-sitter/tree-sitter-regex) (maintained by @theHamsta)
- [x] [rego](https://github.com/FallenAngel97/tree-sitter-rego) (maintained by @FallenAngel97)
- [x] [rnoweb](https://github.com/bamonroe/tree-sitter-rnoweb) (maintained by @bamonroe)
- [x] [ron](https://github.com/amaanq/tree-sitter-ron) (maintained by @amaanq)
- [x] [rst](https://github.com/stsewd/tree-sitter-rst) (maintained by @stsewd)
- [x] [ruby](https://github.com/tree-sitter/tree-sitter-ruby) (maintained by @TravonteD)
- [x] [rust](https://github.com/tree-sitter/tree-sitter-rust) (maintained by @vigoux)
- [x] [scala](https://github.com/tree-sitter/tree-sitter-scala) (maintained by @stevanmilic)
- [x] [scheme](https://github.com/6cdh/tree-sitter-scheme) (maintained by @6cdh)
- [x] [scss](https://github.com/serenadeai/tree-sitter-scss) (maintained by @elianiva)
- [x] [slint](https://github.com/jrmoulton/tree-sitter-slint) (experimental, maintained by @jrmoulton)
- [x] [smali](https://github.com/amaanq/tree-sitter-smali) (experimental, maintained by @amaanq)
- [x] [smithy](https://github.com/indoorvivants/tree-sitter-smithy) (maintained by @amaanq, @keynmol)
- [x] [solidity](https://github.com/YongJieYongJie/tree-sitter-solidity) (maintained by @YongJieYongJie)
- [x] [sparql](https://github.com/BonaBeavis/tree-sitter-sparql) (maintained by @BonaBeavis)
- [x] [sql](https://github.com/derekstride/tree-sitter-sql) (maintained by @derekstride)
- [x] [supercollider](https://github.com/madskjeldgaard/tree-sitter-supercollider) (maintained by @madskjeldgaard)
- [x] [surface](https://github.com/connorlay/tree-sitter-surface) (maintained by @connorlay)
- [x] [svelte](https://github.com/Himujjal/tree-sitter-svelte) (maintained by @elianiva)
- [x] [swift](https://github.com/alex-pinkus/tree-sitter-swift) (maintained by @alex-pinkus)
- [x] [sxhkdrc](https://github.com/RaafatTurki/tree-sitter-sxhkdrc) (maintained by @RaafatTurki)
- [x] [t32](https://codeberg.org/xasc/tree-sitter-t32) (maintained by @xasc)
- [x] [teal](https://github.com/euclidianAce/tree-sitter-teal) (maintained by @euclidianAce)
- [x] [terraform](https://github.com/MichaHoffmann/tree-sitter-hcl) (maintained by @MichaHoffmann)
- [x] [thrift](https://github.com/duskmoon314/tree-sitter-thrift) (maintained by @amaanq, @duskmoon314)
- [x] [tiger](https://github.com/ambroisie/tree-sitter-tiger) (maintained by @ambroisie)
- [x] [tlaplus](https://github.com/tlaplus-community/tree-sitter-tlaplus) (maintained by @ahelwer, @susliko)
- [x] [todotxt](https://github.com/arnarg/tree-sitter-todotxt.git) (experimental, maintained by @arnarg)
- [x] [toml](https://github.com/ikatyang/tree-sitter-toml) (maintained by @tk-shirasaka)
- [x] [tsx](https://github.com/tree-sitter/tree-sitter-typescript) (maintained by @steelsojka)
- [x] [turtle](https://github.com/BonaBeavis/tree-sitter-turtle) (maintained by @BonaBeavis)
- [x] [twig](https://github.com/gbprod/tree-sitter-twig) (maintained by @gbprod)
- [x] [typescript](https://github.com/tree-sitter/tree-sitter-typescript) (maintained by @steelsojka)
- [x] [v](https://github.com/vlang/vls) (maintained by @kkharji)
- [x] [vala](https://github.com/vala-lang/tree-sitter-vala) (maintained by @Prince781)
- [x] [verilog](https://github.com/tree-sitter/tree-sitter-verilog) (maintained by @zegervdv)
- [x] [vhs](https://github.com/charmbracelet/tree-sitter-vhs) (maintained by @caarlos0)
- [x] [vim](https://github.com/vigoux/tree-sitter-viml) (maintained by @vigoux)
- [x] [vue](https://github.com/ikatyang/tree-sitter-vue) (maintained by @WhyNotHugo)
- [x] [wgsl](https://github.com/szebniok/tree-sitter-wgsl) (maintained by @szebniok)
- [x] [wgsl_bevy](https://github.com/theHamsta/tree-sitter-wgsl-bevy) (maintained by @theHamsta)
- [x] [yaml](https://github.com/ikatyang/tree-sitter-yaml) (maintained by @stsewd)
- [x] [yang](https://github.com/Hubro/tree-sitter-yang) (maintained by @Hubro)
- [x] [zig](https://github.com/maxxnino/tree-sitter-zig) (maintained by @maxxnino)
<!--parserinfo-->
## Highlighting
For related information on the supported languages, including related plugins, see [this wiki page](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Supported-Languages-Information).
# Available modules
Modules provide the top-level features of `nvim-treesitter`.
The following is a list of modules included in `nvim-treesitter` and their configuration via `init.lua` (where multiple modules can be combined in a single call to `setup`).
Note that not all modules work for all languages (depending on the queries available for them).
Additional modules can be provided as [external plugins](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Extra-modules-and-plugins).
#### Highlight
Consistent syntax highlighting.
Treesitter highlighting is provided by Neovim, see `:h treesitter-highlight`. To enable it for a filetype, put `vim.treesitter.start()` in a `ftplugin/<filetype>.lua` in your config directory, or place the following in your `init.lua`:
```lua
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true,
-- Setting this to true will run `:h syntax` and tree-sitter at the same time.
-- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
-- Using this option may slow down your editor, and you may see some duplicate highlights.
-- Instead of true it can also be a list of languages
additional_vim_regex_highlighting = false,
},
}
vim.api.nvim_create_autocmd('FileType', {
pattern = { '<filetype>' },
callback = function() vim.treesitter.start() end,
})
```
To customize the syntax highlighting of a capture, simply define or link a highlight group of the same name:
## Folds
Treesitter-based folding is provided by Neovim. To enable it, put the following in your `ftplugin` or `FileType` autocommand:
```lua
-- Highlight the @foo.bar capture group with the "Identifier" highlight group
vim.api.nvim_set_hl(0, "@foo.bar", { link = "Identifier" })
For a language-specific highlight, append the name of the language:
## Indentation
Treesitter-based indentation is provided by this plugin but considered **experimental**. To enable it, put the following in your `ftplugin` or `FileType` autocommand:
```lua
-- Highlight @foo.bar as "Identifier" only in Lua files
vim.api.nvim_set_hl(0, "@foo.bar.lua", { link = "Identifier" })
Incremental selection based on the named nodes from the grammar.
Injections are used for multi-language documents, see `:h treesitter-language-injections`. No setup is needed.
```lua
require'nvim-treesitter.configs'.setup {
incremental_selection = {
enable = true,
keymaps = {
init_selection = "gnn", -- set to `false` to disable one of the mappings
node_incremental = "grn",
scope_incremental = "grc",
node_decremental = "grm",
},
},
}
```
## Locals
#### Indentation
Indentation based on treesitter for the `=` operator.
**NOTE: This is an experimental feature**.
```lua
require'nvim-treesitter.configs'.setup {
indent = {
enable = true
}
}
```
#### Folding
Tree-sitter based folding. *(Technically not a module because it's per windows and not per buffer.)*
```vim
set foldmethod=expr
set foldexpr=nvim_treesitter#foldexpr()
set nofoldenable " Disable folding at startup.
```
This will respect your `foldminlines` and `foldnestmax` settings.
These queries can be used to look up definitions and references to identifiers in a given scope. They are not used in this plugin and are provided for (limited) backward compatibility.
# Advanced setup
## Changing the parser install directory
If you want to install the parsers to a custom directory you can specify this
directory with `parser_install_dir` option in that is passed to `setup`.
`nvim-treesitter` will then install the parser files into this directory.
This directory must be writeable and must be explicitly added to the
If this option is not included in the setup options, or is explicitly set to
`nil` then the default install directories will be used. If this value is set
the default directories will be ignored.
Bear in mind that any parser installed into a parser folder on the runtime path
will still be considered installed. (For example if
"~/.local/share/nvim/site/parser/c.so" exists then the "c" parser will be
considered installed, even though it is not in `parser_install_dir`)
The default paths are:
1. first the package folder. Where `nvim-treesitter` is installed.
2. second the site directory. This is the "site" subdirectory of `stdpath("data")`.
## Adding parsers
## Adding custom languages
If you have a parser that is not on the list of supported languages (either as a repository on Github or in a local directory), you can add it manually for use by `nvim-treesitter` as follows:
1. Clone the repository or [create a new project](https://tree-sitter.github.io/tree-sitter/creating-parsers#project-setup) in, say, `~/projects/tree-sitter-zimbu`. Make sure that the `tree-sitter-cli` executable is installed and in your path; see <https://tree-sitter.github.io/tree-sitter/creating-parsers#installation> for installation instructions.
2. Run `tree-sitter generate` in this directory (followed by `tree-sitter test` for good measure).
3. Add the following snippet to your `init.lua`:
1. Add the following snippet in a `User TSUpdate` autocommand:
```lua
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
parser_config.zimbu = {
install_info = {
url = "~/projects/tree-sitter-zimbu", -- local path or git repo
files = {"src/parser.c"},
-- optional entries:
branch = "main", -- default branch in case of git repo if different from master
generate_requires_npm = false, -- if stand-alone parser without npm dependencies
requires_generate_from_grammar = false, -- if folder contains pre-generated src/parser.c
},
filetype = "zu", -- if filetype does not match the parser name
If Neovim does not detect your language's filetype by default, you can use [Neovim's `vim.filetype.add()`](<https://neovim.io/doc/user/lua.html#vim.filetype.add()>) to add a custom detection rule.
You can also skip step 2 and use `:TSInstallFromGrammar zimbu` to install directly from a `grammar.js` in the top-level directory specified by `url`.
Once the parser is installed, you can update it (from the latest revision of the `main` branch if `url` is a Github repository) with `:TSUpdate zimbu`.
3. Start `nvim` and `:TSInstall zimbu`.
Note that neither `:TSInstall` nor `:TSInstallFromGrammar` copy query files from the grammar repository.
If you want your installed grammar to be useful, you must manually [add query files](#adding-queries) to your local nvim-treesitter installation.
Note also that module functionality is only triggered if your language's filetype is correctly identified.
If Neovim does not detect your language's filetype by default, you can use [Neovim's `vim.filetype.add()`](https://neovim.io/doc/user/lua.html#vim.filetype.add()) to add a custom detection rule.
>[!IMPORTANT]
> If the parser requires an external scanner, this must be written in C.
If you use a git repository for your parser and want to use a specific version, you can set the `revision` key
in the `install_info` table for you parser config.
### Modifying parsers
You can use the same approach for overriding parser information. E.g., if you always want to generate the `lua` parser from grammar, add
Queries are what `nvim-treesitter` uses to extract information from the syntax tree;
they are located in the `queries/{language}/*` runtime directories (see `:h rtp`),
like the `queries` folder of this plugin, e.g. `queries/{language}/{locals,highlights,textobjects}.scm`.
Other modules may require additional queries such as `folding.scm`. You can find a
list of all supported capture names in [CONTRIBUTING.md](https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md#parser-configurations).
All queries found in the runtime directories will be combined.
By convention, if you want to write a query, use the `queries/` directory,
but if you want to extend a query use the `after/queries/` directory.
If you want to completely override a query, you can use `:h set_query()`.
For example, to override the `injections` queries from `c` with your own:
Note: when using `set_query`, all queries in the runtime directories will be ignored.
## Adding modules
If you wish you write your own module, you need to support
- tree-sitter language detection support;
- attaching and detaching to buffers;
- all nvim-treesitter commands.
At the top level, you can use the `define_modules` function to define one or more modules or module groups:
```lua
require'nvim-treesitter'.define_modules {
my_cool_plugin = {
attach = function(bufnr, lang)
-- Do cool stuff here
end,
detach = function(bufnr)
-- Undo cool stuff here
end,
is_supported = function(lang)
-- Check if the language is supported
end
}
}
```
with the following properties:
- `module_path` specifies a require path (string) that exports a module with an `attach` and `detach` function. This is not required if the functions are on this definition.
- `enable` determines if the module is enabled by default. This is usually overridden by the user.
- `disable` takes a list of languages that this module is disabled for. This is usually overridden by the user.
- `is_supported` takes a function that takes a language and determines if this module supports that language.
- `attach` takes a function that attaches to a buffer. This is required if `module_path` is not provided.
- `detach` takes a function that detaches from a buffer. This is required if `module_path` is not provided.
# Extra features
### Statusline indicator
```vim
echo nvim_treesitter#statusline(90) " 90 can be any length
module->expression_statement->call->identifier
```
### Utilities
You can get some utility functions with
```lua
local ts_utils = require 'nvim-treesitter.ts_utils'
```
Check [`:h nvim-treesitter-utils`](doc/nvim-treesitter.txt) for more information.
# Troubleshooting
Before doing anything, make sure you have the latest version of this plugin and run `:checkhealth nvim-treesitter`.
It can also help to update the parsers via `:TSUpdate`.
#### Feature `X` does not work for `{language}`...
First, check the `health#nvim_treesitter#check` and the `health#treesitter#check` sections of `:checkhealth` for any warning.
If there is one, it's highly likely that this is the cause of the problem.
Next check the `## Parser/Features` subsection of the `health#nvim_treesitter#check` section of `:checkhealth` to ensure the desired module is enabled for your language.
If not, you might be missing query files; see [Adding queries](#adding-queries).
Finally, ensure Neovim is correctly identifying your language's filetype using the `:echo &filetype` command while one of your language's files is open in Neovim.
If not, add a short Vimscript file to nvim-treesitter's `ftdetect` runtime directory following [Neovim's documentation](https://neovim.io/doc/user/filetype.html#new-filetype) on filetype detection.
You can also quickly & temporarily set the filetype for a single buffer with the `:set filetype=langname` command to test whether it fixes the problem.
If everything is okay, then it might be an actual error.
In that case, feel free to [open an issue here](https://github.com/nvim-treesitter/nvim-treesitter/issues/new/choose).
#### I get `module 'vim.treesitter.query' not found`
Make sure you have the latest version of Neovim.
#### I get `Error detected while processing .../plugin/nvim-treesitter.vim` every time I open Neovim
This is probably due to a change in a parser's grammar or its queries.
Try updating the parser that you suspect has changed (`:TSUpdate {language}`) or all of them (`:TSUpdate`).
If the error persists after updating all parsers,
please [open an issue](https://github.com/nvim-treesitter/nvim-treesitter/issues/new/choose).
#### I get `query error: invalid node type at position`
This could be due a query file outside this plugin using outdated nodes,
or due to an outdated parser.
- Make sure you have the parsers up to date with `:TSUpdate`
- Make sure you don't have more than one `parser` runtime directory.
You can execute this command `:echo nvim_get_runtime_file('parser', v:true)` to find all runtime directories.
If you get more than one path, remove the ones that are outside this plugin (`nvim-treesitter` directory),
so the correct version of the parser is used.
#### I experience weird highlighting issues similar to [#78](https://github.com/nvim-treesitter/nvim-treesitter/issues/78)
This is a well known issue, which arises when the tree and the buffer have gotten out of sync.
As this is an upstream issue, we don't have any definite fix.
To get around this, you can force reparsing the buffer with
```vim
:write | edit | TSBufEnable highlight
```
This will save, restore and enable highlighting for the current buffer.
#### I experience bugs when using `nvim-treesitter`'s `foldexpr` similar to [#194](https://github.com/nvim-treesitter/nvim-treesitter/issues/194)
This might happen, and is known to happen, with `vim-clap`.
To avoid these kind of errors, please use `setlocal` instead of `set` for the respective filetypes.
#### I run into errors like `module 'nvim-treesitter.configs' not found` at startup
This is because of `rtp` management in `nvim`, adding `packadd
nvim-treesitter` should fix the issue.
#### I want to use Git instead of curl for downloading the parsers
Queries can be placed anywhere in your `runtimepath` under `queries/<language>`, with earlier directories taking precedence unless the queries are marked with `; extends`; see [`:h treesitter-query-modelines`](https://neovim.io/doc/user/treesitter.html#treesitter-query-modeline).
The following is a list of languages for which a parser can be installed through `:TSInstall`.
Legend:
- **Tier:**_stable_ (updates follow semver releases), _unstable_ (updates follow HEAD), _unmaintained_ (no automatic updates), or _unsupported_ (known to be broken, cannot be installed)
- **Queries** available for **H**ighlights, **F**olds, **I**ndents, In**J**ections, **L**ocals
- **Maintainer** of queries in nvim-treesitter (may be different from parser maintainer!)
<!--This section of the README is automatically updated by a CI job-->