*treesitter.txt* Nvim NVIM REFERENCE MANUAL Tree-sitter integration *treesitter* Type |gO| to see the table of contents. ------------------------------------------------------------------------------ VIM.TREESITTER *lua-treesitter* Nvim integrates the tree-sitter library for incremental parsing of buffers. *vim.treesitter.language_version* The latest parser ABI version that is supported by the bundled tree-sitter library. *vim.treesitter.minimum_language_version* The earliest parser ABI version that is supported by the bundled tree-sitter library. Parser files *treesitter-parsers* Parsers are the heart of tree-sitter. They are libraries that tree-sitter will search for in the `parser` runtime directory. Currently Nvim does not provide the tree-sitter parsers, instead these must be built separately, for instance using the tree-sitter utility. The only exception is a C parser being included in official builds for testing purposes. Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory. A parser can also be loaded manually using a full path: > vim.treesitter.require_language("python", "/path/to/python.so") parser = vim.treesitter.get_parser(bufnr, lang) <`bufnr=0` can be used for current buffer. `lang` will default to 'filetype'. Currently, the parser will be retained for the lifetime of a buffer but this is subject to change. A plugin should keep a reference to the parser object as long as it wants incremental updates. Parser methods *lua-treesitter-parser* tsparser:parse() *tsparser:parse()* Whenever you need to access the current syntax tree, parse the buffer: > tstree = parser:parse() { {node1, node2}, ... } < `node1` and `node2` are both considered part of the same region and will be parsed together with the parser in the same context. Tree methods *lua-treesitter-tree* tstree:root() *tstree:root()* Return the root node of this tree. tstree:copy() *tstree:copy()* Returns a copy of the `tstree`. Node methods *lua-treesitter-node* tsnode:parent() *tsnode:parent()* Get the node's immediate parent. tsnode:next_sibling() *tsnode:next_sibling()* Get the node's next sibling. tsnode:prev_sibling() *tsnode:prev_sibling()* Get the node's previous sibling. tsnode:next_named_sibling() *tsnode:next_named_sibling()* Get the node's next named sibling. tsnode:prev_named_sibling() *tsnode:prev_named_sibling()* Get the node's previous named sibling. tsnode:iter_children() *tsnode:iter_children()* Iterates over all the direct children of {tsnode}, regardless of whether they are named or not. Returns the child node plus the eventual field name corresponding to this child node. tsnode:field({name}) *tsnode:field()* Returns a table of the nodes corresponding to the {name} field. tsnode:child_count() *tsnode:child_count()* Get the node's number of children. tsnode:child({index}) *tsnode:child()* Get the node's child at the given {index}, where zero represents the first child. tsnode:named_child_count() *tsnode:named_child_count()* Get the node's number of named children. tsnode:named_child({index}) *tsnode:named_child()* Get the node's named child at the given {index}, where zero represents the first named child. tsnode:start() *tsnode:start()* Get the node's start position. Return three values: the row, column and total byte count (all zero-based). tsnode:end_() *tsnode:end_()* Get the node's end position. Return three values: the row, column and total byte count (all zero-based). tsnode:range() *tsnode:range()* Get the range of the node. Return four values: the row, column of the start position, then the row, column of the end position. tsnode:type() *tsnode:type()* Get the node's type as a string. tsnode:symbol() *tsnode:symbol()* Get the node's type as a numerical id. tsnode:named() *tsnode:named()* Check if the node is named. Named nodes correspond to named rules in the grammar, whereas anonymous nodes correspond to string literals in the grammar. tsnode:missing() *tsnode:missing()* Check if the node is missing. Missing nodes are inserted by the parser in order to recover from certain kinds of syntax errors. tsnode:has_error() *tsnode:has_error()* Check if the node is a syntax error or contains any syntax errors. tsnode:sexpr() *tsnode:sexpr()* Get an S-expression representing the node as a string. tsnode:id() *tsnode:id()* Get an unique identifier for the node inside its own tree. No guarantees are made about this identifier's internal representation, except for being a primitive lua type with value equality (so not a table). Presently it is a (non-printable) string. Note: the id is not guaranteed to be unique for nodes from different trees. *tsnode:descendant_for_range()* tsnode:descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest node within this node that spans the given range of (row, column) positions *tsnode:named_descendant_for_range()* tsnode:named_descendant_for_range({start_row}, {start_col}, {end_row}, {end_col}) Get the smallest named node within this node that spans the given range of (row, column) positions Query *lua-treesitter-query* Tree-sitter queries are supported, they are a way to do pattern-matching over a tree, using a simple to write lisp-like format. See https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax for more information on how to write queries. Note: The predicates listed in the web page above differ from those Neovim supports. See |lua-treesitter-predicates| for a complete list of predicates supported by Neovim. A `query` consists of one or more patterns. A `pattern` is defined over node types in the syntax tree. A `match` corresponds to specific elements of the syntax tree which match a pattern. Patterns may optionally define captures and predicates. A `capture` allows you to associate names with a specific node in a pattern. A `predicate` adds arbitrary metadata and conditional data to a match. Treesitter Query Predicates *lua-treesitter-predicates* When writing queries for treesitter, one might use `predicates`, that is, special scheme nodes that are evaluated to verify things on a captured node for example, the |eq?| predicate : > ((identifier) @foo (#eq? @foo "foo")) This will only match identifier corresponding to the `"foo"` text. Here is a list of built-in predicates : `eq?` *ts-predicate-eq?* This predicate will check text correspondence between nodes or strings: > ((identifier) @foo (#eq? @foo "foo")) ((node1) @left (node2) @right (#eq? @left @right)) < `match?` *ts-predicate-match?* `vim-match?` *ts-predicate-vim-match?* This will match if the provided vim regex matches the text corresponding to a node: > ((identifier) @constant (#match? @constant "^[A-Z_]+$")) < Note: the `^` and `$` anchors will respectively match the start and end of the node's text. `lua-match?` *ts-predicate-lua-match?* This will match the same way than |match?| but using lua regexes. `contains?` *ts-predicate-contains?* Will check if any of the following arguments appears in the text corresponding to the node: > ((identifier) @foo (#contains? @foo "foo")) ((identifier) @foo-bar (#contains @foo-bar "foo" "bar")) < `any-of?` *ts-predicate-any-of?* Will check if the text is the same as any of the following arguments: > ((identifier) @foo (#any-of? @foo "foo" "bar")) < This is the recommended way to check if the node matches one of many keywords for example, as it has been optimized for this. < *lua-treesitter-not-predicate* Each predicate has a `not-` prefixed predicate that is just the negation of the predicate. *vim.treesitter.query.add_predicate()* vim.treesitter.query.add_predicate({name}, {handler}) This adds a predicate with the name {name} to be used in queries. {handler} should be a function whose signature will be : > handler(match, pattern, bufnr, predicate) < *vim.treesitter.query.list_predicates()* vim.treesitter.query.list_predicates() This lists the currently available predicates to use in queries. Treesitter Query Directive *lua-treesitter-directives* Treesitter queries can also contain `directives`. Directives store metadata for a node or match and perform side effects. For example, the |set!| predicate sets metadata on the match or node : > ((identifier) @foo (#set! "type" "parameter")) Built-in directives: `set!` *ts-directive-set!* Sets key/value metadata for a specific match or capture. Value is accessible as either `metadata[key]` (match specific) or `metadata[capture_id][key]` (capture specific). Parameters: ~ {capture_id} (optional) {key} {value} Examples: > ((identifier) @foo (#set! @foo "kind" "parameter")) ((node1) @left (node2) @right (#set! "type" "pair")) < `offset!` *ts-directive-offset!* Takes the range of the captured node and applies an offset. This will generate a new range object for the captured node as `metadata[capture_id].range`. Parameters: ~ {capture_id} {start_row} {start_col} {end_row} {end_col} Example: > ((identifier) @constant (#offset! @constant 0 1 0 -1)) < Treesitter syntax highlighting (WIP) *lua-treesitter-highlight* NOTE: This is a partially implemented feature, and not usable as a default solution yet. What is documented here is a temporary interface intended for those who want to experiment with this feature and contribute to its development. Highlights are defined in the same query format as in the tree-sitter highlight crate, with some limitations and additions. Set a highlight query for a buffer with this code: > local query = [[ "for" @keyword "if" @keyword "return" @keyword (string_literal) @string (number_literal) @number (comment) @comment (preproc_function_def name: (identifier) @function) ; ... more definitions ]] highlighter = vim.treesitter.TSHighlighter.new(query, bufnr, lang) -- alternatively, to use the current buffer and its filetype: -- highlighter = vim.treesitter.TSHighlighter.new(query) -- Don't recreate the highlighter for the same buffer, instead -- modify the query like this: local query2 = [[ ... ]] highlighter:set_query(query2) *lua-treesitter-highlight-groups* The capture names, with `@` included, are directly usable as highlight groups. A fallback system is implemented, so that more specific groups fallback to more generic ones. For instance, in a language that has separate doc comments, `@comment.doc` could be used. If this group is not defined, the highlighting for an ordinary `@comment` is used. This way, existing color schemes already work out of the box, but it is possible to add more specific variants for queries that make them available. As an additional rule, captures highlights can always be specialized by language, by appending the language name after an additional dot. For instance, to highlight comments differently per language: > hi @comment.c guifg=Blue hi @comment.lua @guifg=DarkBlue hi link @comment.doc.java String < It is possible to use custom highlight groups. As an example, if we define the `@warning` group: > hi link @warning WarningMsg < the following query warns of a binary expression with two identical identifiers, highlighting both as |hl-WarningMsg|: > ((binary_expression left: (identifier) @warning.left right: (identifier) @warning.right) (eq? @warning.left @warning.right)) < Treesitter Highlighting Priority *lua-treesitter-highlight-priority* Tree-sitter uses |nvim_buf_set_extmark()| to set highlights with a default priority of 100. This enables plugins to set a highlighting priority lower or higher than tree-sitter. It is also possible to change the priority of an individual query pattern manually by setting its `"priority"` metadata attribute: > ( (super_important_node) @ImportantHighlight ; Give the whole query highlight priority higher than the default (100) (set! "priority" 105) ) < ============================================================================== Lua module: vim.treesitter *lua-treesitter-core* *get_captures_at_position()* get_captures_at_position({bufnr}, {row}, {col}) Gets a list of captures for a given cursor position Parameters: ~ {bufnr} (number) Buffer number (0 for current buffer) {row} (number) Position row {col} (number) Position column Return: ~ (table) A table of captures get_node_range({node_or_range}) *get_node_range()* Get the node's range or unpack a range table Parameters: ~ {node_or_range} (table) Return: ~ start_row, start_col, end_row, end_col get_parser({bufnr}, {lang}, {opts}) *get_parser()* Gets the parser for this bufnr / ft combination. If needed this will create the parser. Unconditionally attach the provided callback Parameters: ~ {bufnr} (number|nil) Buffer the parser should be tied to: (default current buffer) {lang} (string) |nil Filetype of this parser (default: buffer filetype) {opts} (table|nil) Options to pass to the created language tree Return: ~ (table) Parser object get_string_parser({str}, {lang}, {opts}) *get_string_parser()* Gets a string parser Parameters: ~ {str} The string to parse {lang} The language of this string {opts} Options to pass to the created language tree is_ancestor({dest}, {source}) *is_ancestor()* Determines whether a node is the ancestor of another Parameters: ~ {dest} (table) Possible ancestor {source} (table) Possible descendant node Return: ~ (boolean) True if dest is an ancestor of source is_in_node_range({node}, {line}, {col}) *is_in_node_range()* Determines whether (line, col) position is in node range Parameters: ~ {node} (table) Node defining the range {line} (number) Line (0-based) {col} (number) Column (0-based) Return: ~ (boolean) True if the position is in node range node_contains({node}, {range}) *node_contains()* Determines if a node contains a range Parameters: ~ {node} (table) {range} (table) Return: ~ (boolean) True if the node contains the range start({bufnr}, {lang}, {opts}) *start()* Start treesitter highlighting for a buffer Can be used in an ftplugin or FileType autocommand Note: By default, disables regex syntax highlighting, which may be required for some plugins. In this case, add `{ syntax = true }`. Example: > vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', callback = function(args) vim.treesitter.start(args.buf, 'latex', { syntax = true }) end }) < Parameters: ~ {bufnr} (number|nil) Buffer to be highlighted (default: current buffer) {lang} (string|nil) Language of the parser (default: buffer filetype) {opts} (table|nil) Optional keyword arguments: • `syntax` boolean Run regex syntax highlighting (default false) stop({bufnr}) *stop()* Stop treesitter highlighting for a buffer Parameters: ~ {bufnr} (number|nil) Buffer to stop highlighting (default: current buffer) ============================================================================== Lua module: vim.treesitter.language *treesitter-language* inspect_language({lang}) *inspect_language()* Inspects the provided language. Inspecting provides some useful information on the language like node names, ... Parameters: ~ {lang} The language. *require_language()* require_language({lang}, {path}, {silent}, {symbol_name}) Asserts that the provided language is installed, and optionally provide a path for the parser Parsers are searched in the `parser` runtime directory. Parameters: ~ {lang} (string) The language the parser should parse {path} (string|nil) Optional path the parser is located at {silent} (boolean|nil) Don't throw an error if language not found {symbol_name} (string|nil) Internal symbol name for the language to load ============================================================================== Lua module: vim.treesitter.query *treesitter-query* add_directive({name}, {handler}, {force}) *add_directive()* Adds a new directive to be used in queries Handlers can set match level data by setting directly on the metadata object `metadata.key = value`, additionally, handlers can set node level data by using the capture id on the metadata table `metadata[capture_id].key = value` Parameters: ~ {name} the name of the directive, without leading # {handler} the handler function to be used signature will be (match, pattern, bufnr, predicate, metadata) add_predicate({name}, {handler}, {force}) *add_predicate()* Adds a new predicate to be used in queries Parameters: ~ {name} the name of the predicate, without leading # {handler} the handler function to be used signature will be (match, pattern, bufnr, predicate) get_node_text({node}, {source}, {opts}) *get_node_text()* Gets the text corresponding to a given node Parameters: ~ {node} (table) The node {source} (table) The buffer or string from which the node is extracted {opts} (table) Optional parameters. • concat: (boolean default true) Concatenate result in a string get_query({lang}, {query_name}) *get_query()* Returns the runtime query {query_name} for {lang}. Parameters: ~ {lang} The language to use for the query {query_name} The name of the query (i.e. "highlights") Return: ~ The corresponding query, parsed. *get_query_files()* get_query_files({lang}, {query_name}, {is_included}) Gets the list of files used to make up a query Parameters: ~ {lang} The language {query_name} The name of the query to load {is_included} Internal parameter, most of the time left as `nil` list_directives() *list_directives()* Lists the currently available directives to use in queries. Return: ~ The list of supported directives. list_predicates() *list_predicates()* Return: ~ The list of supported predicates. parse_query({lang}, {query}) *parse_query()* Parse {query} as a string. (If the query is in a file, the caller should read the contents into a string before calling). Returns a `Query` (see |lua-treesitter-query|) object which can be used to search nodes in the syntax tree for the patterns defined in {query} using `iter_*` methods below. Exposes `info` and `captures` with additional context about {query}. • `captures` contains the list of unique capture names defined in {query}. -`info.captures` also points to `captures`. • `info.patterns` contains information about predicates. Parameters: ~ {lang} (string) The language {query} (string) A string containing the query (s-expr syntax) Return: ~ The query *Query:iter_captures()* Query:iter_captures({self}, {node}, {source}, {start}, {stop}) Iterate over all captures from all matches inside {node} {source} is needed if the query contains predicates, then the caller must ensure to use a freshly parsed tree consistent with the current text of the buffer (if relevant). {start_row} and {end_row} can be used to limit matches inside a row range (this is typically used with root node as the node, i e to get syntax highlight matches in the current viewport). When omitted the start and end row values are used from the given node. The iterator returns three values, a numeric id identifying the capture, the captured node, and metadata from any directives processing the match. The following example shows how to get captures by name: > for id, node, metadata in query:iter_captures(tree:root(), bufnr, first, last) do local name = query.captures[id] -- name of the capture in the query -- typically useful info about the node: local type = node:type() -- type of the captured node local row1, col1, row2, col2 = node:range() -- range of the capture ... use the info here ... end < Parameters: ~ {node} The node under which the search will occur {source} The source buffer or string to extract text from {start} The starting line of the search {stop} The stopping line of the search (end-exclusive) {self} Return: ~ The matching capture id The captured node *Query:iter_matches()* Query:iter_matches({self}, {node}, {source}, {start}, {stop}) Iterates the matches of self on a given range. Iterate over all matches within a node. The arguments are the same as for |query:iter_captures()| but the iterated values are different: an (1-based) index of the pattern in the query, a table mapping capture indices to nodes, and metadata from any directives processing the match. If the query has more than one pattern the capture table might be sparse, and e.g. `pairs()` method should be used over `ipairs`. Here an example iterating over all captures in every match: > for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do for id, node in pairs(match) do local name = query.captures[id] -- `node` was captured by the `name` capture in the match local node_data = metadata[id] -- Node level metadata ... use the info here ... end end < Parameters: ~ {node} The node under which the search will occur {source} The source buffer or string to search {start} The starting line of the search {stop} The stopping line of the search (end-exclusive) {self} Return: ~ The matching pattern id The matching match set_query({lang}, {query_name}, {text}) *set_query()* Sets the runtime query {query_name} for {lang} This allows users to override any runtime files and/or configuration set by plugins. Parameters: ~ {lang} string: The language to use for the query {query_name} string: The name of the query (i.e. "highlights") {text} string: The query text (unparsed). ============================================================================== Lua module: vim.treesitter.highlighter *treesitter-highlighter* new({tree}, {opts}) *highlighter.new()* Creates a new highlighter using Parameters: ~ {tree} The language tree to use for highlighting {opts} Table used to configure the highlighter • queries: Table to overwrite queries used by the highlighter TSHighlighter:destroy({self}) *TSHighlighter:destroy()* Removes all internal references to the highlighter Parameters: ~ {self} TSHighlighter:get_query({self}, {lang}) *TSHighlighter:get_query()* Gets the query used for Parameters: ~ {lang} A language used by the highlighter. {self} ============================================================================== Lua module: vim.treesitter.languagetree *treesitter-languagetree* LanguageTree:add_child({self}, {lang}) *LanguageTree:add_child()* Adds a child language to this tree. If the language already exists as a child, it will first be removed. Parameters: ~ {lang} The language to add. {self} LanguageTree:children({self}) *LanguageTree:children()* Returns a map of language to child tree. Parameters: ~ {self} LanguageTree:contains({self}, {range}) *LanguageTree:contains()* Determines whether {range} is contained in this language tree Parameters: ~ {range} A range, that is a `{ start_line, start_col, end_line, end_col }` table. {self} LanguageTree:destroy({self}) *LanguageTree:destroy()* Destroys this language tree and all its children. Any cleanup logic should be performed here. Note: This DOES NOT remove this tree from a parent. Instead, `remove_child` must be called on the parent to remove it. Parameters: ~ {self} *LanguageTree:for_each_child()* LanguageTree:for_each_child({self}, {fn}, {include_self}) Invokes the callback for each LanguageTree and it's children recursively Parameters: ~ {fn} The function to invoke. This is invoked with arguments (tree: LanguageTree, lang: string) {include_self} Whether to include the invoking tree in the results. {self} LanguageTree:for_each_tree({self}, {fn}) *LanguageTree:for_each_tree()* Invokes the callback for each treesitter trees recursively. Note, this includes the invoking language tree's trees as well. Parameters: ~ {fn} The callback to invoke. The callback is invoked with arguments (tree: TSTree, languageTree: LanguageTree) {self} LanguageTree:included_regions({self}) *LanguageTree:included_regions()* Gets the set of included regions Parameters: ~ {self} LanguageTree:invalidate({self}, {reload}) *LanguageTree:invalidate()* Invalidates this parser and all its children Parameters: ~ {self} LanguageTree:is_valid({self}) *LanguageTree:is_valid()* Determines whether this tree is valid. If the tree is invalid, call `parse()` . This will return the updated tree. Parameters: ~ {self} LanguageTree:lang({self}) *LanguageTree:lang()* Gets the language of this tree node. Parameters: ~ {self} *LanguageTree:language_for_range()* LanguageTree:language_for_range({self}, {range}) Gets the appropriate language that contains {range} Parameters: ~ {range} A text range, see |LanguageTree:contains| {self} *LanguageTree:named_node_for_range()* LanguageTree:named_node_for_range({self}, {range}, {opts}) Gets the smallest named node that contains {range} Parameters: ~ {range} (table) A text range {opts} (table) Options table {opts.ignore_injections} (boolean) (default true) Ignore injected languages. {self} LanguageTree:parse({self}) *LanguageTree:parse()* Parses all defined regions using a treesitter parser for the language this tree represents. This will run the injection query for this language to determine if any child languages should be created. Parameters: ~ {self} LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* Registers callbacks for the parser. Parameters: ~ {cbs} (table) An |nvim_buf_attach()|-like table argument with the following keys : • `on_bytes` : see |nvim_buf_attach()|, but this will be called after the parsers callback. • `on_changedtree` : a callback that will be called every time the tree has syntactical changes. It will only be passed one argument, which is a table of the ranges (as node ranges) that changed. • `on_child_added` : emitted when a child is added to the tree. • `on_child_removed` : emitted when a child is removed from the tree. {self} LanguageTree:remove_child({self}, {lang}) *LanguageTree:remove_child()* Removes a child language from this tree. Parameters: ~ {lang} The language to remove. {self} *LanguageTree:set_included_regions()* LanguageTree:set_included_regions({self}, {regions}) Sets the included regions that should be parsed by this parser. A region is a set of nodes and/or ranges that will be parsed in the same context. For example, `{ { node1 }, { node2} }` is two separate regions. This will be parsed by the parser in two different contexts... thus resulting in two separate trees. `{ { node1, node2 } }` is a single region consisting of two nodes. This will be parsed by the parser in a single context... thus resulting in a single tree. This allows for embedded languages to be parsed together across different nodes, which is useful for templating languages like ERB and EJS. Note, this call invalidates the tree and requires it to be parsed again. Parameters: ~ {regions} (table) list of regions this tree should manage and parse. {self} LanguageTree:source({self}) *LanguageTree:source()* Returns the source content of the language tree (bufnr or string). Parameters: ~ {self} *LanguageTree:tree_for_range()* LanguageTree:tree_for_range({self}, {range}, {opts}) Gets the tree that contains {range} Parameters: ~ {range} (table) A text range {opts} (table) Options table {opts.ignore_injections} (boolean) (default true) Ignore injected languages. {self} LanguageTree:trees({self}) *LanguageTree:trees()* Returns all trees this language tree contains. Does not include child languages. Parameters: ~ {self} new({source}, {lang}, {opts}) *languagetree.new()* Represents a single treesitter parser for a language. The language can contain child languages with in its range, hence the tree. Parameters: ~ {source} Can be a bufnr or a string of text to parse {lang} The language this tree represents {opts} Options table {opts.injections} A table of language to injection query strings. This is useful for overriding the built-in runtime file searching for the injection language query per language. vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: