diff options
author | Christian Clason <c.clason@uni-graz.at> | 2022-09-14 11:08:31 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-14 11:08:31 +0200 |
commit | ddb762f4013ac2532ad45704466058d867e3a6ed (patch) | |
tree | 2903c84de8106943a661dc193705ddf2a7c42244 | |
parent | 8b0b0a5c32d3e913f273b9eb11e572f58f7cbd35 (diff) | |
download | rneovim-ddb762f4013ac2532ad45704466058d867e3a6ed.tar.gz rneovim-ddb762f4013ac2532ad45704466058d867e3a6ed.tar.bz2 rneovim-ddb762f4013ac2532ad45704466058d867e3a6ed.zip |
docs(treesitter): clean up and update treesitter.txt (#20142)
* add type annotations to code
* clean up and expand static documentation
* consistent use of tags for static and generated docs
-rw-r--r-- | runtime/doc/lua.txt | 2 | ||||
-rw-r--r-- | runtime/doc/treesitter.txt | 762 | ||||
-rw-r--r-- | runtime/lua/vim/shared.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter.lua | 85 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/health.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/highlighter.lua | 14 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/language.lua | 16 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/languagetree.lua | 115 | ||||
-rw-r--r-- | runtime/lua/vim/treesitter/query.lua | 102 | ||||
-rwxr-xr-x | scripts/gen_vimdoc.py | 2 |
10 files changed, 576 insertions, 526 deletions
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index e5bfd9e4c6..45ee69d5e4 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1587,7 +1587,7 @@ defaulttable({create}) *vim.defaulttable()* They mimic defaultdict in python. - If `create` is `nil`, this will create a defaulttable whose constructor + If {create} is `nil`, this will create a defaulttable whose constructor function is this function, effectively allowing to create nested tables on the fly: > diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 491aea793c..dc81a31856 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -4,77 +4,75 @@ NVIM REFERENCE MANUAL -Tree-sitter integration *treesitter* +Treesitter 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: +https://tree-sitter.github.io/tree-sitter/ -Nvim integrates the tree-sitter library for incremental parsing of buffers. +WARNING: Treesitter support is still experimental and subject to frequent +changes. This documentation may also not fully reflect the latest changes. - *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. + Type |gO| to see the table of contents. -Parser files *treesitter-parsers* +============================================================================== +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. +search for in the `parser` runtime directory. By default, Nvim bundles only +parsers for C, Lua, and Vimscript, but parsers can be installed manually or +via a plugin like https://github.com/nvim-treesitter/nvim-treesitter. +Parsers are searched for as `parser/{lang}.*` in any 'runtimepath' directory. +If multiple parsers for the same language are found, the first one is used. +(This typically implies the priority "user config > plugins > bundled". A parser can also be loaded manually using a full path: > vim.treesitter.require_language("python", "/path/to/python.so") +< +============================================================================== +LANGUAGE TREES *treesitter-languagetree* + *LanguageTree* -<Create a parser for a buffer and a given language (if another plugin uses the -same buffer/language combination, it will be safely reused). Use > +As buffers can contain multiple languages (e.g., Vimscript commands in a Lua +file), multiple parsers may be needed to parse the full buffer. These are +combined in a |LanguageTree| object. - parser = vim.treesitter.get_parser(bufnr, lang) +To create a LanguageTree (parser object) for a buffer and a given language, +use > -<`bufnr=0` can be used for current buffer. `lang` will default to 'filetype'. + tsparser = 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() - -<This will return a table of immutable trees that represent the current state -of the buffer. When the plugin wants to access the state after a (possible) -edit it should call `parse()` again. If the buffer wasn't edited, the same tree -will be returned again without extra work. If the buffer was parsed before, -incremental parsing will be done of the changed parts. - -Note: to use the parser directly inside a |nvim_buf_attach| Lua callback, you -must call `get_parser()` before you register your callback. But preferably + tstree = tsparser:parse() +< +This will return a table of immutable |lua-treesitter-tree|s that represent the +current state of the buffer. When the plugin wants to access the state after a +(possible) edit it should call `parse()` again. If the buffer wasn't edited, +the same tree will be returned again without extra work. If the buffer was +parsed before, incremental parsing will be done of the changed parts. + +Note: To use the parser directly inside a |nvim_buf_attach/)| Lua callback, you +must call |get_parser()| before you register your callback. But preferably parsing shouldn't be done directly in the change callback anyway as they will be very frequent. Rather a plugin that does any kind of analysis on a tree should use a timer to throttle too frequent updates. -tsparser:set_included_regions({region_list}) *tsparser:set_included_regions()* - Changes the regions the parser should consider. This is used for language - injection. {region_list} should be of the form (all zero-based): > - { - {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. +See |lua-treesitter-languagetree| for the list of available methods. + +============================================================================== +TREESITTER TREES *treesitter-tree* + *tstree* + +A "treesitter tree" represents the parsed contents of a buffer, which can be +used to perform further analysis. It is a |luaref-userdata| reference to an +object held by the tree-sitter library. -Tree methods *lua-treesitter-tree* +An instance `tstree` of a treesitter tree supports the following methods. tstree:root() *tstree:root()* Return the root node of this tree. @@ -82,8 +80,15 @@ tstree:root() *tstree:root()* tstree:copy() *tstree:copy()* Returns a copy of the `tstree`. +============================================================================== +TREESITTER NODES *treesitter-node* + *tsnode* + +A "treesitter node" represents one specific element of the parsed contents of +a buffer, which can be captured by a |Query| for, e.g., highlighting. It is a +|luaref-userdata| reference to an object held by the tree-sitter library. -Node methods *lua-treesitter-node* +An instance `tsnode` of a treesitter node supports the following methods. tsnode:parent() *tsnode:parent()* Get the node's immediate parent. @@ -160,10 +165,10 @@ 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 + 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 + Note: The `id` is not guaranteed to be unique for nodes from different trees. *tsnode:descendant_for_range()* @@ -176,123 +181,91 @@ 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. - +============================================================================== +TREESITTER QUERIES *treesitter-query* + +Treesitter queries are a way to extract information about a parsed |tstree|, +e.g., for the purpose of highlighting. Briefly, 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. + +Queries are written in a lisp-like language documented in +https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax +Note: The predicates listed there page differ from those Nvim supports. See +|treesitter-predicates| for a complete list of predicates supported by Nvim. + +Nvim looks for queries as `*.scm` files in a `queries` directory under +`runtimepath`, where each file contains queries for a specific language and +purpose, e.g., `queries/lua/highlights.scm` for highlighting Lua files. By default, the first query on `runtimepath` is used (which usually implies that user config takes precedence over plugins, which take precedence over queries bundled with Neovim). If a query should extend other queries instead -of replacing them, use |ts-modeline-extends|. +of replacing them, use |ts-query-modeline-extends|. -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. +See |lua-treesitter-query| for the list of available methods for working with +treesitter queries from Lua. - *ts-query-modeline* -Neovim supports to customize the behavior of the queries using a set of -"modelines", that is comments in the queries starting with `;`. Here are the -currently supported modeline alternatives: - `inherits: {lang}...` *ts-modeline-inherits* - Specifies that this query should inherit the queries from {lang}. - This will recursively descend in the queries of {lang} unless wrapped - in parentheses: `({lang})`. - Note: this is meant to be used to include queries from another - language. If you want your query to extend the queries of the same - language, use `extends`. - - `extends` *ts-modeline-extends* - Specifies that this query should be used as an extension for the - query, i.e. that it should be merged with the others. - Note: the order of the extensions, and the query that will be used as - a base depends on your 'runtimepath' value. - -Note: these modeline comments must be at the top of the query, but can be -repeated, for example, the following modeline blocks are all valid: -> - ;; inherits: foo,bar - ;; extends - - ;; extends - ;; - ;; inherits: baz -< +TREESITTER QUERY PREDICATES *treesitter-predicates* -Treesitter Query Predicates *lua-treesitter-predicates* +Predicates are special scheme nodes that are evaluated to conditionally capture +nodes. For example, the |eq?| predicate can be used as follows: > -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")) +< +to only match identifier corresponding to the `"foo"` text. -This will only match identifier corresponding to the `"foo"` text. -Here is a list of built-in predicates : +The following predicates are built in: `eq?` *ts-predicate-eq?* - This predicate will check text correspondence between nodes or - strings: > + Match a string against the text corresponding to a node: > ((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: > + Match a |regexp| against 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. +< Note: The `^` and `$` anchors will 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. + Match a |lua-pattern| against the text corresponding to a node, + similar to `match?` `contains?` *ts-predicate-contains?* - Will check if any of the following arguments appears in the text - corresponding to the node: > + Match a string against parts of the text corresponding to a 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: > + Match any of the given strings against the text corresponding to + a node: > ((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. -< + keywords, 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}) +Further predicates can be added via `vim.treesitter.query.`|add_predicate()|. +Use `vim.treesitter.query.`|list_predicates()| to list all available +predicates. -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 DIRECTIVES *treesitter-directives* -Treesitter Query Directive *lua-treesitter-directives* +Treesitter directives store metadata for a node or match and perform side +effects. For example, the |set!| predicate sets metadata on the match or node: > -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: +< +The following directives are built in: `set!` *ts-directive-set!* Sets key/value metadata for a specific match or capture. Value is @@ -324,51 +297,74 @@ Built-in directives: ((identifier) @constant (#offset! @constant 0 1 0 -1)) < -Treesitter syntax highlighting (WIP) *lua-treesitter-highlight* +Further directives can be added via `vim.treesitter.query.`|add_directive()|. +Use `vim.treesitter.query.`|list_directives()| to list all available +directives. -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: > +TREESITTER QUERY MODELINES *ts-query-modeline* - local query = [[ - "for" @keyword - "if" @keyword - "return" @keyword +Neovim supports to customize the behavior of the queries using a set of +"modelines", that is comments in the queries starting with `;`. Here are the +currently supported modeline alternatives: - (string_literal) @string - (number_literal) @number - (comment) @comment + `inherits: {lang}...` *ts-query-modeline-inherits* + Specifies that this query should inherit the queries from {lang}. + This will recursively descend in the queries of {lang} unless wrapped + in parentheses: `({lang})`. + Note: This is meant to be used to include queries from another + language. If you want your query to extend the queries of the same + language, use `extends`. - (preproc_function_def name: (identifier) @function) + `extends` *ts-query-modeline-extends* + Specifies that this query should be used as an extension for the + query, i.e. that it should be merged with the others. + Note: The order of the extensions, and the query that will be used as + a base depends on your 'runtimepath' value. + +Note: These modeline comments must be at the top of the query, but can be +repeated, for example, the following two modeline blocks are both valid: > - ; ... more definitions - ]] + ;; inherits: foo,bar + ;; extends + + ;; extends + ;; + ;; inherits: baz +< +============================================================================== +TREESITTER SYNTAX HIGHLIGHTING *treesitter-highlight* - highlighter = vim.treesitter.TSHighlighter.new(query, bufnr, lang) - -- alternatively, to use the current buffer and its filetype: - -- highlighter = vim.treesitter.TSHighlighter.new(query) +Syntax highlighting is specified through queries named `highlights.scm`, +which match a |tsnode| in the parsed |tstree| to a `capture` that can be +assigned a highlight group. For example, the query > - -- Don't recreate the highlighter for the same buffer, instead - -- modify the query like this: - local query2 = [[ ... ]] - highlighter:set_query(query2) + (parameters (identifier) @parameter) +< +matches any `identifier` node inside a function `parameter` node (e.g., the +`bar` in `foo(bar)`) to the capture named `@parameter`. It is also possible to +match literal expressions (provided the parser returns them): > + "return" @keyword.return +< +Assuming a suitable parser and `highlights.scm` query is found in runtimepath, +treesitter highlighting for the current buffer can be enabled simply via +|vim.treesitter.start()|. - *lua-treesitter-highlight-groups* + *treesitter-highlight-groups* The capture names, with `@` included, are directly usable as highlight groups. +For many commonly used captures, the corresponding highlight groups are linked +to Nvim's standard |highlight-groups| by default but can be overridden in +colorschemes. + 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. +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 +As an additional rule, capture highlights can always be specialized by language, by appending the language name after an additional dot. For instance, to highlight comments differently per language: > @@ -376,68 +372,91 @@ instance, to highlight comments differently per language: > 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: > + *treesitter-highlight-spell* +The special `@spell` capture can be used to indicate that a node should be +spell checked by Nvim's builtin |spell| checker. For example, the following +capture marks comments as to be checked: > + + (comment) @spell +< + *treesitter-highlight-conceal* +Treesitter highlighting supports |conceal| via the `conceal` metadata. By +convention, nodes to be concealed are captured as `@conceal`, but any capture +can be used. For example, the following query can be used to hide code block +delimiters in Markdown: > - hi link @warning WarningMsg + (fenced_code_block_delimiter) @conceal (#set! conceal "") < -the following query warns of a binary expression with two -identical identifiers, highlighting both as |hl-WarningMsg|: > +It is also possible to replace a node with a single character, which (unlike +legacy syntax) can be given a custom highlight. For example, the following +(ill-advised) query replaces the `!=` operator by a Unicode glyph, which is +still highlighted the same as other operators: > - ((binary_expression left: (identifier) @warning.left right: (identifier) @warning.right) - (eq? @warning.left @warning.right)) + "!=" @operator (#set! conceal "≠") < -Treesitter Highlighting Priority *lua-treesitter-highlight-priority* +Conceals specified in this way respect |conceallevel|. -Tree-sitter uses |nvim_buf_set_extmark()| to set highlights with a default + *treesitter-highlight-priority* +Treesitter 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) - ) + (super_important_node) @ImportantHighlight (#set! "priority" 105) < +============================================================================== +VIM.TREESITTER *lua-treesitter* + +The remainder of this document is a reference manual for the `vim.treesitter` +Lua module, which is the main interface for Nvim's tree-sitter integration. +Most of the following content is automatically generated from the function +documentation. + + + *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. ============================================================================== Lua module: vim.treesitter *lua-treesitter-core* get_captures_at_cursor({winnr}) *get_captures_at_cursor()* - Gets a list of captures under the cursor + Returns a list of highlight capture names under the cursor Parameters: ~ {winnr} (number|nil) Window handle or 0 for current window (default) Return: ~ - (table) Named node under the cursor + string[] List of capture names *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) Table of captures + table[] Captures of the form `{ capture = "capture name", priority = + capture priority }` get_node_at_cursor({winnr}) *get_node_at_cursor()* - Gets the smallest named node under the cursor + Returns the smallest named node under the cursor Parameters: ~ {winnr} (number|nil) Window handle or 0 for current window (default) Return: ~ - (string) Named node under the cursor + (string) Name of node under the cursor *get_node_at_position()* get_node_at_position({bufnr}, {row}, {col}, {opts}) - Gets the smallest named node at position + Returns the smallest named node at the given position Parameters: ~ {bufnr} (number) Buffer number (0 for current buffer) @@ -448,56 +467,59 @@ get_node_at_position({bufnr}, {row}, {col}, {opts}) (default true) Return: ~ - (table) Named node under the cursor + userdata |tsnode| under the cursor get_node_range({node_or_range}) *get_node_range()* - Get the node's range or unpack a range table + Returns the node's range or an unpacked range table Parameters: ~ - {node_or_range} (table) + {node_or_range} (userdata|table) |tsnode| or table of positions Return: ~ - (table) start_row, start_col, end_row, end_col + (table) `{ start_row, start_col, end_row, end_col }` get_parser({bufnr}, {lang}, {opts}) *get_parser()* - Gets the parser for this bufnr / ft combination. + Returns the parser for a specific buffer and filetype and attaches it to + the buffer - If needed this will create the parser. Unconditionally attach the provided - callback + If needed, this will create the parser. Parameters: ~ {bufnr} (number|nil) Buffer the parser should be tied to (default: current buffer) - {lang} (string) |nil Filetype of this parser (default: 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 + LanguageTree |LanguageTree| object to use for parsing get_string_parser({str}, {lang}, {opts}) *get_string_parser()* - Gets a string parser + Returns a string parser Parameters: ~ - {str} The string to parse - {lang} The language of this string - {opts} Options to pass to the created language tree + {str} (string) Text to parse + {lang} (string) Language of this string + {opts} (table|nil) Options to pass to the created language tree + + Return: ~ + LanguageTree |LanguageTree| object to use for parsing 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 + {dest} userdata Possible ancestor |tsnode| + {source} userdata Possible descendant |tsnode| Return: ~ - (boolean) True if dest is an ancestor of source + (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 + {node} userdata |tsnode| defining the range {line} (number) Line (0-based) {col} (number) Column (0-based) @@ -508,30 +530,29 @@ node_contains({node}, {range}) *node_contains()* Determines if a node contains a range Parameters: ~ - {node} (table) + {node} userdata |tsnode| {range} (table) Return: ~ - (boolean) True if the node contains the range + (boolean) True if the {node} contains the {range} start({bufnr}, {lang}) *start()* - Start treesitter highlighting for a buffer + Starts treesitter highlighting for a buffer - Can be used in an ftplugin or FileType autocommand + 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 `vim.bo.syntax = 'on'` after the call to `start`. - Example: -> + Example: > - vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', - callback = function(args) - vim.treesitter.start(args.buf, 'latex') - vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed - end - }) + vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', + callback = function(args) + vim.treesitter.start(args.buf, 'latex') + vim.bo[args.buf].syntax = 'on' -- only if additional legacy syntax is needed + end + }) < Parameters: ~ @@ -541,7 +562,7 @@ start({bufnr}, {lang}) *start()* filetype) stop({bufnr}) *stop()* - Stop treesitter highlighting for a buffer + Stops treesitter highlighting for a buffer Parameters: ~ {bufnr} (number|nil) Buffer to stop highlighting (default: current @@ -549,7 +570,7 @@ stop({bufnr}) *stop()* ============================================================================== -Lua module: vim.treesitter.language *treesitter-language* +Lua module: vim.treesitter.language *lua-treesitter-language* inspect_language({lang}) *inspect_language()* Inspects the provided language. @@ -558,26 +579,32 @@ inspect_language({lang}) *inspect_language()* names, ... Parameters: ~ - {lang} The language. + {lang} (string) Language + + Return: ~ + (table) *require_language()* require_language({lang}, {path}, {silent}, {symbol_name}) - Asserts that the provided language is installed, and optionally provide a - path for the parser + Asserts that a parser for the language {lang} is installed. - Parsers are searched in the `parser` runtime directory. + Parsers are searched in the `parser` runtime directory, or the provided + {path} Parameters: ~ - {lang} (string) The language the parser should parse + {lang} (string) 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 + Return: ~ + (boolean) If the specified language is installed + ============================================================================== -Lua module: vim.treesitter.query *treesitter-query* +Lua module: vim.treesitter.query *lua-treesitter-query* add_directive({name}, {handler}, {force}) *add_directive()* Adds a new directive to be used in queries @@ -588,65 +615,74 @@ add_directive({name}, {handler}, {force}) *add_directive()* `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) + {name} (string) Name of the directive, without leading # + {handler} function(match:string, pattern:string, bufnr:number, + predicate:function, metadata:table) 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) + {name} (string) Name of the predicate, without leading # + {handler} function(match:string, pattern:string, bufnr:number, + predicate:function) 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 + {node} userdata |tsnode| + {source} (number|string) Buffer or string from which the {node} is extracted - {opts} (table) Optional parameters. - • concat: (boolean default true) Concatenate result in a - string + {opts} (table|nil) Optional parameters. + • concat: (boolean) Concatenate result in a string (default + true) + + Return: ~ + (string[]|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") + {lang} (string) Language to use for the query + {query_name} (string) Name of the query (e.g. 'highlights') Return: ~ - The corresponding query, parsed. + Query Parsed query *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` + {lang} (string) Language to get query for + {query_name} (string) Name of the query to load (e.g., 'highlights') + {is_included} (boolean|nil) Internal parameter, most of the time left + as `nil` + + Return: ~ + string[] query_files List of files to load for given query and + language list_directives() *list_directives()* Lists the currently available directives to use in queries. Return: ~ - The list of supported directives. + string[] List of supported directives. list_predicates() *list_predicates()* + Lists the currently available predicates to use in queries. + Return: ~ - The list of supported predicates. + string[] 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. + 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}. @@ -654,106 +690,109 @@ parse_query({lang}, {query}) *parse_query()* • `info.patterns` contains information about predicates. Parameters: ~ - {lang} (string) The language - {query} (string) A string containing the query (s-expr syntax) + {lang} (string) Language to use for the query + {query} (string) Query in s-expr syntax Return: ~ - The query + Query Parsed 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 + {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. + {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 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 + 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) + {node} userdata |tsnode| under which the search will occur + {source} (number|string) Source buffer or string to extract text from + {start} (number) Starting line for the search + {stop} (number) Stopping line for the search (end-exclusive) {self} Return: ~ - The matching capture id - The captured node + (number) capture Matching capture id + (table) capture_node Capture for {node} + (table) metadata for the {capture} *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 + 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: -> + 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 is 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 + 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 + local node_data = metadata[id] -- Node level metadata - ... use the info here ... - end - end + ... 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) + {node} userdata |tsnode| under which the search will occur + {source} (number|string) Source buffer or string to search + {start} (number) Starting line for the search + {stop} (number) Stopping line for the search (end-exclusive) {self} Return: ~ - The matching pattern id - The matching match + (number) pattern id + (table) match + (table) metadata set_query({lang}, {query_name}, {text}) *set_query()* - Sets the runtime query {query_name} for {lang} + Sets the runtime query named {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). + {lang} (string) Language to use for the query + {query_name} (string) Name of the query (e.g., 'highlights') + {text} (string) Query text (unparsed). ============================================================================== -Lua module: vim.treesitter.highlighter *treesitter-highlighter* +Lua module: vim.treesitter.highlighter *lua-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 + {tree} LanguageTree |LanguageTree| parser object to use for highlighting + {opts} (table|nil) Configuration of the highlighter: + • queries table overwrite queries used by the highlighter + + Return: ~ + TSHighlighter Created highlighter object TSHighlighter:destroy({self}) *TSHighlighter:destroy()* Removes all internal references to the highlighter @@ -761,25 +800,9 @@ TSHighlighter:destroy({self}) *TSHighlighter:destroy()* 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} +Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree* LanguageTree:children({self}) *LanguageTree:children()* Returns a map of language to child tree. @@ -788,15 +811,17 @@ LanguageTree:children({self}) *LanguageTree:children()* {self} LanguageTree:contains({self}, {range}) *LanguageTree:contains()* - Determines whether {range} is contained in this language tree + Determines whether {range} is contained in the |LanguageTree|. Parameters: ~ - {range} A range, that is a `{ start_line, start_col, end_line, - end_col }` table. + {range} (table) `{ start_line, start_col, end_line, end_col }` {self} + Return: ~ + (boolean) + LanguageTree:destroy({self}) *LanguageTree:destroy()* - Destroys this language tree and all its children. + Destroys this |LanguageTree| and all its children. Any cleanup logic should be performed here. @@ -807,22 +832,21 @@ LanguageTree:destroy({self}) *LanguageTree:destroy()* *LanguageTree:for_each_child()* LanguageTree:for_each_child({self}, {fn}, {include_self}) - Invokes the callback for each LanguageTree and it's children recursively + Invokes the callback for each |LanguageTree| and its 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. + {fn} function(tree: LanguageTree, lang: string) + {include_self} (boolean) 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. + Invokes the callback for each |LanguageTree| recursively. - Note, this includes the invoking language tree's trees as well. + Note: This includes the invoking tree's child trees as well. Parameters: ~ - {fn} The callback to invoke. The callback is invoked with arguments - (tree: TSTree, languageTree: LanguageTree) + {fn} function(tree: TSTree, languageTree: LanguageTree) {self} LanguageTree:included_regions({self}) *LanguageTree:included_regions()* @@ -851,23 +875,29 @@ LanguageTree:lang({self}) *LanguageTree:lang()* *LanguageTree:language_for_range()* LanguageTree:language_for_range({self}, {range}) - Gets the appropriate language that contains {range} + Gets the appropriate language that contains {range}. Parameters: ~ - {range} A text range, see |LanguageTree:contains| + {range} (table) `{ start_line, start_col, end_line, end_col }` {self} + Return: ~ + LanguageTree Managing {range} + *LanguageTree:named_node_for_range()* LanguageTree:named_node_for_range({self}, {range}, {opts}) - Gets the smallest named node that contains {range} + 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. + {range} (table) `{ start_line, start_col, end_line, end_col }` + {opts} (table|nil) Optional keyword arguments: + • ignore_injections boolean Ignore injected languages + (default true) {self} + Return: ~ + userdata|nil Found |tsnode| + 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 @@ -876,12 +906,16 @@ LanguageTree:parse({self}) *LanguageTree:parse()* Parameters: ~ {self} + Return: ~ + userdata[] Table of parsed |tstree| + (table) Change list + LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* - Registers callbacks for the parser. + Registers callbacks for the |LanguageTree|. Parameters: ~ {cbs} (table) An |nvim_buf_attach()|-like table argument with the - following keys : + following handlers: • `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 @@ -893,35 +927,6 @@ LanguageTree:register_cbs({self}, {cbs}) *LanguageTree:register_cbs()* 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). @@ -930,15 +935,18 @@ LanguageTree:source({self}) *LanguageTree:source()* *LanguageTree:tree_for_range()* LanguageTree:tree_for_range({self}, {range}, {opts}) - Gets the tree that contains {range} + 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. + {range} (table) `{ start_line, start_col, end_line, end_col }` + {opts} (table|nil) Optional keyword arguments: + • ignore_injections boolean Ignore injected languages + (default true) {self} + Return: ~ + userdata|nil Contained |tstree| + LanguageTree:trees({self}) *LanguageTree:trees()* Returns all trees this language tree contains. Does not include child languages. @@ -947,16 +955,20 @@ LanguageTree:trees({self}) *LanguageTree:trees()* {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. + A |LanguageTree| holds the treesitter parser for a given language {lang} + used to parse a buffer. As the buffer may contain injected languages, the LanguageTree needs to store parsers for these child languages as well (which in turn + may contain child languages themselves, hence the name). 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. + {source} (number|string) Buffer or a string of text to parse + {lang} (string) Root language this tree represents + {opts} (table|nil) Optional keyword arguments: + • injections table Mapping language to injection query + strings. This is useful for overriding the built-in + runtime file searching for the injection language query + per language. + + Return: ~ + LanguageTree |LanguageTree| parser object vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua index 59cb669609..de5f7240aa 100644 --- a/runtime/lua/vim/shared.lua +++ b/runtime/lua/vim/shared.lua @@ -720,7 +720,7 @@ end --- --- They mimic defaultdict in python. --- ---- If @p create is @c nil, this will create a defaulttable whose constructor function is +--- If {create} is `nil`, this will create a defaulttable whose constructor function is --- this function, effectively allowing to create nested tables on the fly: --- --- <pre> diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index d93c485dfe..89aa611acd 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -25,15 +25,15 @@ setmetatable(M, { end, }) ---- Creates a new parser. +--- Creates a new parser --- ---- It is not recommended to use this, use vim.treesitter.get_parser() instead. +--- It is not recommended to use this; use |get_parser()| instead. --- ---@param bufnr string Buffer the parser will be tied to (0 for current buffer) ---@param lang string Language of the parser ----@param opts table|nil Options to pass to the created language tree +---@param opts (table|nil) Options to pass to the created language tree --- ----@returns table Created parser object +---@return LanguageTree |LanguageTree| object to use for parsing function M._create_parser(bufnr, lang, opts) language.require_language(lang) if bufnr == 0 then @@ -73,16 +73,15 @@ function M._create_parser(bufnr, lang, opts) return self end ---- Gets the parser for this bufnr / ft combination. +--- Returns the parser for a specific buffer and filetype and attaches it to the buffer --- ---- If needed this will create the parser. ---- Unconditionally attach the provided callback +--- If needed, this will create the parser. --- ----@param bufnr number|nil Buffer the parser should be tied to (default: current buffer) ----@param lang string |nil Filetype of this parser (default: buffer filetype) ----@param opts table|nil Options to pass to the created language tree +---@param bufnr (number|nil) Buffer the parser should be tied to (default: current buffer) +---@param lang (string|nil) Filetype of this parser (default: buffer filetype) +---@param opts (table|nil) Options to pass to the created language tree --- ----@returns table Parser object +---@return LanguageTree |LanguageTree| object to use for parsing function M.get_parser(bufnr, lang, opts) opts = opts or {} @@ -102,11 +101,13 @@ function M.get_parser(bufnr, lang, opts) return parsers[bufnr] end ---- Gets a string parser +--- Returns a string parser --- ----@param str The string to parse ----@param lang The language of this string ----@param opts Options to pass to the created language tree +---@param str string Text to parse +---@param lang string Language of this string +---@param opts (table|nil) Options to pass to the created language tree +--- +---@return LanguageTree |LanguageTree| object to use for parsing function M.get_string_parser(str, lang, opts) vim.validate({ str = { str, 'string' }, @@ -119,10 +120,10 @@ end --- Determines whether a node is the ancestor of another --- ----@param dest table Possible ancestor ----@param source table Possible descendant node +---@param dest userdata Possible ancestor |tsnode| +---@param source userdata Possible descendant |tsnode| --- ----@returns (boolean) True if dest is an ancestor of source +---@return boolean True if {dest} is an ancestor of {source} function M.is_ancestor(dest, source) if not (dest and source) then return false @@ -140,11 +141,11 @@ function M.is_ancestor(dest, source) return false end ---- Get the node's range or unpack a range table +--- Returns the node's range or an unpacked range table --- ----@param node_or_range table +---@param node_or_range (userdata|table) |tsnode| or table of positions --- ----@returns table start_row, start_col, end_row, end_col +---@return table `{ start_row, start_col, end_row, end_col }` function M.get_node_range(node_or_range) if type(node_or_range) == 'table' then return unpack(node_or_range) @@ -155,11 +156,11 @@ end ---Determines whether (line, col) position is in node range --- ----@param node table Node defining the range +---@param node userdata |tsnode| defining the range ---@param line number Line (0-based) ---@param col number Column (0-based) --- ----@returns (boolean) True if the position is in node range +---@return boolean True if the position is in node range function M.is_in_node_range(node, line, col) local start_line, start_col, end_line, end_col = M.get_node_range(node) if line >= start_line and line <= end_line then @@ -178,10 +179,10 @@ function M.is_in_node_range(node, line, col) end ---Determines if a node contains a range ----@param node table +---@param node userdata |tsnode| ---@param range table --- ----@returns (boolean) True if the node contains the range +---@return boolean True if the {node} contains the {range} function M.node_contains(node, range) local start_row, start_col, end_row, end_col = node:range() local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) @@ -190,7 +191,8 @@ function M.node_contains(node, range) return start_fits and end_fits end ----Gets a list of captures for a given cursor position +---Returns a list of highlight captures at the given position +-- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row ---@param col number Position column @@ -199,7 +201,7 @@ end ---@param row number Position row ---@param col number Position column --- ----@returns (table) Table of captures +---@return table[] Captures of the form `{ capture = "capture name", priority = capture priority }` function M.get_captures_at_position(bufnr, row, col) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -246,11 +248,11 @@ function M.get_captures_at_position(bufnr, row, col) return matches end ----Gets a list of captures under the cursor +---Returns a list of highlight capture names under the cursor --- ----@param winnr number|nil Window handle or 0 for current window (default) +---@param winnr (number|nil) Window handle or 0 for current window (default) --- ----@returns (table) Named node under the cursor +---@return string[] List of capture names function M.get_captures_at_cursor(winnr) winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) @@ -267,7 +269,7 @@ function M.get_captures_at_cursor(winnr) return captures end ---- Gets the smallest named node at position +--- Returns the smallest named node at the given position --- ---@param bufnr number Buffer number (0 for current buffer) ---@param row number Position row @@ -275,7 +277,7 @@ end ---@param opts table Optional keyword arguments: --- - ignore_injections boolean Ignore injected languages (default true) --- ----@returns (table) Named node under the cursor +---@return userdata |tsnode| under the cursor function M.get_node_at_position(bufnr, row, col, opts) if bufnr == 0 then bufnr = a.nvim_get_current_buf() @@ -290,11 +292,11 @@ function M.get_node_at_position(bufnr, row, col, opts) return root_lang_tree:named_node_for_range(ts_range, opts) end ---- Gets the smallest named node under the cursor +--- Returns the smallest named node under the cursor --- ----@param winnr number|nil Window handle or 0 for current window (default) +---@param winnr (number|nil) Window handle or 0 for current window (default) --- ----@returns (string) Named node under the cursor +---@return string Name of node under the cursor function M.get_node_at_cursor(winnr) winnr = winnr or 0 local bufnr = a.nvim_win_get_buf(winnr) @@ -304,15 +306,14 @@ function M.get_node_at_cursor(winnr) :type() end ---- Start treesitter highlighting for a buffer +--- Starts treesitter highlighting for a buffer --- ---- Can be used in an ftplugin or FileType autocommand +--- 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 ``vim.bo.syntax = 'on'`` after the call to `start`. --- --- Example: ---- --- <pre> --- vim.api.nvim_create_autocmd( 'FileType', { pattern = 'tex', --- callback = function(args) @@ -322,8 +323,8 @@ end --- }) --- </pre> --- ----@param bufnr number|nil Buffer to be highlighted (default: current buffer) ----@param lang string|nil Language of the parser (default: buffer filetype) +---@param bufnr (number|nil) Buffer to be highlighted (default: current buffer) +---@param lang (string|nil) Language of the parser (default: buffer filetype) function M.start(bufnr, lang) bufnr = bufnr or a.nvim_get_current_buf() @@ -334,9 +335,9 @@ function M.start(bufnr, lang) vim.b[bufnr].ts_highlight = true end ----Stop treesitter highlighting for a buffer +--- Stops treesitter highlighting for a buffer --- ----@param bufnr number|nil Buffer to stop highlighting (default: current buffer) +---@param bufnr (number|nil) Buffer to stop highlighting (default: current buffer) function M.stop(bufnr) bufnr = bufnr or a.nvim_get_current_buf() diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua index 3bd59ca282..4995c80a02 100644 --- a/runtime/lua/vim/treesitter/health.lua +++ b/runtime/lua/vim/treesitter/health.lua @@ -3,7 +3,7 @@ local ts = vim.treesitter --- Lists the parsers currently installed --- ----@return A list of parsers +---@return string[] list of parser files function M.list_parsers() return vim.api.nvim_get_runtime_file('parser/*', true) end diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua index 1e625eddb8..83a26aff13 100644 --- a/runtime/lua/vim/treesitter/highlighter.lua +++ b/runtime/lua/vim/treesitter/highlighter.lua @@ -2,6 +2,7 @@ local a = vim.api local query = require('vim.treesitter.query') -- support reload for quick experimentation +---@class TSHighlighter local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {} TSHighlighter.__index = TSHighlighter @@ -45,9 +46,10 @@ end --- Creates a new highlighter using @param tree --- ----@param tree The language tree to use for highlighting ----@param opts Table used to configure the highlighter ---- - queries: Table to overwrite queries used by the highlighter +---@param tree LanguageTree |LanguageTree| parser object to use for highlighting +---@param opts (table|nil) Configuration of the highlighter: +--- - queries table overwrite queries used by the highlighter +---@return TSHighlighter Created highlighter object function TSHighlighter.new(tree, opts) local self = setmetatable({}, TSHighlighter) @@ -149,8 +151,10 @@ function TSHighlighter:on_changedtree(changes) end --- Gets the query used for @param lang ---- ----@param lang A language used by the highlighter. +-- +---@private +---@param lang string Language used by the highlighter. +---@return Query function TSHighlighter:get_query(lang) if not self._queries[lang] then self._queries[lang] = TSHighlighterQuery.new(lang) diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua index d14b825603..c92d63b8c4 100644 --- a/runtime/lua/vim/treesitter/language.lua +++ b/runtime/lua/vim/treesitter/language.lua @@ -2,14 +2,15 @@ local a = vim.api local M = {} ---- Asserts that the provided language is installed, and optionally provide a path for the parser +--- Asserts that a parser for the language {lang} is installed. --- ---- Parsers are searched in the `parser` runtime directory. +--- Parsers are searched in the `parser` runtime directory, or the provided {path} --- ----@param lang string The language the parser should parse ----@param path string|nil Optional path the parser is located at ----@param silent boolean|nil Don't throw an error if language not found ----@param symbol_name string|nil Internal symbol name for the language to load +---@param lang string Language the parser should parse +---@param path (string|nil) Optional path the parser is located at +---@param silent (boolean|nil) Don't throw an error if language not found +---@param symbol_name (string|nil) Internal symbol name for the language to load +---@return boolean If the specified language is installed function M.require_language(lang, path, silent, symbol_name) if vim._ts_has_language(lang) then return true @@ -42,7 +43,8 @@ end --- --- Inspecting provides some useful information on the language like node names, ... --- ----@param lang The language. +---@param lang string Language +---@return table function M.inspect_language(lang) M.require_language(lang) return vim._ts_inspect_language(lang) diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 70317a9f94..e9d70c4204 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -2,19 +2,35 @@ local a = vim.api local query = require('vim.treesitter.query') local language = require('vim.treesitter.language') +---@class LanguageTree +---@field _callbacks function[] Callback handlers +---@field _children LanguageTree[] Injected languages +---@field _injection_query table Queries defining injected languages +---@field _opts table Options +---@field _parser userdata Parser for language +---@field _regions table List of regions this tree should manage and parse +---@field _lang string Language name +---@field _regions table +---@field _source (number|string) Buffer or string to parse +---@field _trees userdata[] Reference to parsed |tstree| (one for each language) +---@field _valid boolean If the parsed tree is valid + local LanguageTree = {} LanguageTree.__index = LanguageTree ---- Represents a single treesitter parser for a language. ---- The language can contain child languages with in its range, ---- hence the tree. +--- A |LanguageTree| holds the treesitter parser for a given language {lang} used +--- to parse a buffer. As the buffer may contain injected languages, the LanguageTree +--- needs to store parsers for these child languages as well (which in turn may contain +--- child languages themselves, hence the name). --- ----@param source Can be a bufnr or a string of text to parse ----@param lang The language this tree represents ----@param opts Options table ----@param 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. +---@param source (number|string) Buffer or a string of text to parse +---@param lang string Root language this tree represents +---@param opts (table|nil) Optional keyword arguments: +--- - injections table Mapping language to injection query strings. +--- This is useful for overriding the built-in +--- runtime file searching for the injection language +--- query per language. +---@return LanguageTree |LanguageTree| parser object function LanguageTree.new(source, lang, opts) language.require_language(lang) opts = opts or {} @@ -94,6 +110,9 @@ end --- for the language this tree represents. --- This will run the injection query for this language to --- determine if any child languages should be created. +--- +---@return userdata[] Table of parsed |tstree| +---@return table Change list function LanguageTree:parse() if self._valid then return self._trees @@ -167,10 +186,10 @@ function LanguageTree:parse() return self._trees, changes end ---- Invokes the callback for each LanguageTree and it's children recursively +--- Invokes the callback for each |LanguageTree| and its children recursively --- ----@param fn The function to invoke. This is invoked with arguments (tree: LanguageTree, lang: string) ----@param include_self Whether to include the invoking tree in the results. +---@param fn function(tree: LanguageTree, lang: string) +---@param include_self boolean Whether to include the invoking tree in the results function LanguageTree:for_each_child(fn, include_self) if include_self then fn(self, self._lang) @@ -181,12 +200,11 @@ function LanguageTree:for_each_child(fn, include_self) end end ---- Invokes the callback for each treesitter trees recursively. +--- Invokes the callback for each |LanguageTree| recursively. --- ---- Note, this includes the invoking language tree's trees as well. +--- Note: This includes the invoking tree's child trees as well. --- ----@param fn The callback to invoke. The callback is invoked with arguments ---- (tree: TSTree, languageTree: LanguageTree) +---@param fn function(tree: TSTree, languageTree: LanguageTree) function LanguageTree:for_each_tree(fn) for _, tree in ipairs(self._trees) do fn(tree, self) @@ -197,11 +215,13 @@ function LanguageTree:for_each_tree(fn) end end ---- Adds a child language to this tree. +--- Adds a child language to this |LanguageTree|. --- --- If the language already exists as a child, it will first be removed. --- ----@param lang The language to add. +---@private +---@param lang string Language to add. +---@return LanguageTree Injected |LanguageTree| function LanguageTree:add_child(lang) if self._children[lang] then self:remove_child(lang) @@ -215,9 +235,10 @@ function LanguageTree:add_child(lang) return self._children[lang] end ---- Removes a child language from this tree. +--- Removes a child language from this |LanguageTree|. --- ----@param lang The language to remove. +---@private +---@param lang string Language to remove. function LanguageTree:remove_child(lang) local child = self._children[lang] @@ -229,12 +250,11 @@ function LanguageTree:remove_child(lang) end end ---- Destroys this language tree and all its children. +--- Destroys this |LanguageTree| and all its children. --- --- Any cleanup logic should be performed here. --- ---- Note: ---- This DOES NOT remove this tree from a parent. Instead, +--- Note: This DOES NOT remove this tree from a parent. Instead, --- `remove_child` must be called on the parent to remove it. function LanguageTree:destroy() -- Cleanup here @@ -243,23 +263,24 @@ function LanguageTree:destroy() end end ---- Sets the included regions that should be parsed by this parser. +--- Sets the included regions that should be parsed by this |LanguageTree|. --- 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 +--- For example, `{ { node1 }, { node2} }` contains two separate regions. +--- They 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 +--- On the other hand, `{ { 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. +--- Note: This call invalidates the tree and requires it to be parsed again. --- ----@param regions (table) list of regions this tree should manage and parse. +---@private +---@param regions table List of regions this tree should manage and parse. function LanguageTree:set_included_regions(regions) -- Transform the tables from 4 element long to 6 element long (with byte offset) for _, region in ipairs(regions) do @@ -288,7 +309,7 @@ function LanguageTree:set_included_regions(regions) -- Trees are no longer valid now that we have changed regions. -- TODO(vigoux,steelsojka): Look into doing this smarter so we can use some of the -- old trees for incremental parsing. Currently, this only - -- effects injected languages. + -- affects injected languages. self._trees = {} self:invalidate() end @@ -493,8 +514,8 @@ function LanguageTree:_on_detach(...) self:_do_callback('detach', ...) end ---- Registers callbacks for the parser. ----@param cbs table An |nvim_buf_attach()|-like table argument with the following keys : +--- Registers callbacks for the |LanguageTree|. +---@param cbs table An |nvim_buf_attach()|-like table argument with the following handlers: --- - `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 @@ -536,9 +557,10 @@ local function tree_contains(tree, range) return start_fits and end_fits end ---- Determines whether {range} is contained in this language tree +--- Determines whether {range} is contained in the |LanguageTree|. --- ----@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table. +---@param range table `{ start_line, start_col, end_line, end_col }` +---@return boolean function LanguageTree:contains(range) for _, tree in pairs(self._trees) do if tree_contains(tree, range) then @@ -549,11 +571,12 @@ function LanguageTree:contains(range) return false end ---- Gets the tree that contains {range} +--- Gets the tree that contains {range}. --- ----@param range table A text range ----@param opts table Options table ----@param opts.ignore_injections boolean (default true) Ignore injected languages. +---@param range table `{ start_line, start_col, end_line, end_col }` +---@param opts table|nil Optional keyword arguments: +--- - ignore_injections boolean Ignore injected languages (default true) +---@return userdata|nil Contained |tstree| function LanguageTree:tree_for_range(range, opts) opts = opts or {} local ignore = vim.F.if_nil(opts.ignore_injections, true) @@ -577,19 +600,21 @@ function LanguageTree:tree_for_range(range, opts) return nil end ---- Gets the smallest named node that contains {range} +--- Gets the smallest named node that contains {range}. --- ----@param range table A text range ----@param opts table Options table ----@param opts.ignore_injections boolean (default true) Ignore injected languages. +---@param range table `{ start_line, start_col, end_line, end_col }` +---@param opts table|nil Optional keyword arguments: +--- - ignore_injections boolean Ignore injected languages (default true) +---@return userdata|nil Found |tsnode| function LanguageTree:named_node_for_range(range, opts) local tree = self:tree_for_range(range, opts) return tree:root():named_descendant_for_range(unpack(range)) end ---- Gets the appropriate language that contains {range} +--- Gets the appropriate language that contains {range}. --- ----@param range A text range, see |LanguageTree:contains| +---@param range table `{ start_line, start_col, end_line, end_col }` +---@return LanguageTree Managing {range} function LanguageTree:language_for_range(range) for _, child in pairs(self._children) do if child:contains(range) then diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua index 90ed2a357c..d1dc29969b 100644 --- a/runtime/lua/vim/treesitter/query.lua +++ b/runtime/lua/vim/treesitter/query.lua @@ -3,6 +3,11 @@ local language = require('vim.treesitter.language') -- query: pattern matching on trees -- predicate matching is implemented in lua +-- +---@class Query +---@field captures string[] List of captures used in query +---@field info table Contains used queries, predicates, directives +---@field query userdata Parsed query local Query = {} Query.__index = Query @@ -35,9 +40,9 @@ local function safe_read(filename, read_quantifier) end ---@private ---- Adds @p ilang to @p base_langs, only if @p ilang is different than @lang +--- Adds {ilang} to {base_langs}, only if {ilang} is different than {lang} --- ----@return boolean true it lang == ilang +---@return boolean true If lang == ilang local function add_included_lang(base_langs, lang, ilang) if lang == ilang then return true @@ -48,9 +53,10 @@ end --- Gets the list of files used to make up a query --- ----@param lang The language ----@param query_name The name of the query to load ----@param is_included Internal parameter, most of the time left as `nil` +---@param lang string Language to get query for +---@param query_name string Name of the query to load (e.g., 'highlights') +---@param is_included (boolean|nil) Internal parameter, most of the time left as `nil` +---@return string[] query_files List of files to load for given query and language function M.get_query_files(lang, query_name, is_included) local query_path = string.format('queries/%s/%s.scm', lang, query_name) local lang_files = dedupe_files(a.nvim_get_runtime_file(query_path, true)) @@ -150,24 +156,24 @@ local explicit_queries = setmetatable({}, { end, }) ---- Sets the runtime query {query_name} for {lang} +--- Sets the runtime query named {query_name} for {lang} --- --- This allows users to override any runtime files and/or configuration --- set by plugins. --- ----@param lang string: The language to use for the query ----@param query_name string: The name of the query (i.e. "highlights") ----@param text string: The query text (unparsed). +---@param lang string Language to use for the query +---@param query_name string Name of the query (e.g., 'highlights') +---@param text string Query text (unparsed). function M.set_query(lang, query_name, text) explicit_queries[lang][query_name] = M.parse_query(lang, text) end --- Returns the runtime query {query_name} for {lang}. --- ----@param lang The language to use for the query ----@param query_name The name of the query (i.e. "highlights") +---@param lang string Language to use for the query +---@param query_name string Name of the query (e.g. 'highlights') --- ----@return The corresponding query, parsed. +---@return Query Parsed query function M.get_query(lang, query_name) if explicit_queries[lang][query_name] then return explicit_queries[lang][query_name] @@ -198,10 +204,10 @@ end) --- -` info.captures` also points to `captures`. --- - `info.patterns` contains information about predicates. --- ----@param lang string The language ----@param query string A string containing the query (s-expr syntax) +---@param lang string Language to use for the query +---@param query string Query in s-expr syntax --- ----@returns The query +---@return Query Parsed query function M.parse_query(lang, query) language.require_language(lang) local cached = query_cache[lang][query] @@ -219,10 +225,11 @@ end --- Gets the text corresponding to a given node --- ----@param node table The node ----@param source table The buffer or string from which the node is extracted ----@param opts table Optional parameters. ---- - concat: (boolean default true) Concatenate result in a string +---@param node userdata |tsnode| +---@param source (number|string) Buffer or string from which the {node} is extracted +---@param opts (table|nil) Optional parameters. +--- - concat: (boolean) Concatenate result in a string (default true) +---@return (string[]|string) function M.get_node_text(node, source, opts) opts = opts or {} local concat = vim.F.if_nil(opts.concat, true) @@ -410,9 +417,8 @@ local directive_handlers = { --- Adds a new predicate to be used in queries --- ----@param name the name of the predicate, without leading # ----@param handler the handler function to be used ---- signature will be (match, pattern, bufnr, predicate) +---@param name string Name of the predicate, without leading # +---@param handler function(match:string, pattern:string, bufnr:number, predicate:function) function M.add_predicate(name, handler, force) if predicate_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -428,9 +434,8 @@ end --- can set node level data by using the capture id on the --- metadata table `metadata[capture_id].key = value` --- ----@param name the name of the directive, without leading # ----@param handler the handler function to be used ---- signature will be (match, pattern, bufnr, predicate, metadata) +---@param name string Name of the directive, without leading # +---@param handler function(match:string, pattern:string, bufnr:number, predicate:function, metadata:table) function M.add_directive(name, handler, force) if directive_handlers[name] and not force then error(string.format('Overriding %s', name)) @@ -440,12 +445,13 @@ function M.add_directive(name, handler, force) end --- Lists the currently available directives to use in queries. ----@return The list of supported directives. +---@return string[] List of supported directives. function M.list_directives() return vim.tbl_keys(directive_handlers) end ----@return The list of supported predicates. +--- Lists the currently available predicates to use in queries. +---@return string[] List of supported predicates. function M.list_predicates() return vim.tbl_keys(predicate_handlers) end @@ -532,17 +538,16 @@ end --- Iterate over all captures from all matches inside {node} --- ---- {source} is needed if the query contains predicates, then the caller +--- {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. +--- 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 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: ---- --- <pre> --- 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 @@ -553,13 +558,14 @@ end --- end --- </pre> --- ----@param node The node under which the search will occur ----@param source The source buffer or string to extract text from ----@param start The starting line of the search ----@param stop The stopping line of the search (end-exclusive) +---@param node userdata |tsnode| under which the search will occur +---@param source (number|string) Source buffer or string to extract text from +---@param start number Starting line for the search +---@param stop number Stopping line for the search (end-exclusive) --- ----@returns The matching capture id ----@returns The captured node +---@return number capture Matching capture id +---@return table capture_node Capture for {node} +---@return table metadata for the {capture} function Query:iter_captures(node, source, start, stop) if type(source) == 'number' and source == 0 then source = vim.api.nvim_get_current_buf() @@ -589,14 +595,13 @@ end --- Iterates the matches of self on a given range. --- ---- Iterate over all matches within a node. The arguments are the same as +--- 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, +--- 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: ---- +--- Here is an example iterating over all captures in every match: --- <pre> --- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do --- for id, node in pairs(match) do @@ -610,13 +615,14 @@ end --- end --- </pre> --- ----@param node The node under which the search will occur ----@param source The source buffer or string to search ----@param start The starting line of the search ----@param stop The stopping line of the search (end-exclusive) +---@param node userdata |tsnode| under which the search will occur +---@param source (number|string) Source buffer or string to search +---@param start number Starting line for the search +---@param stop number Stopping line for the search (end-exclusive) --- ----@returns The matching pattern id ----@returns The matching match +---@return number pattern id +---@return table match +---@return table metadata function Query:iter_matches(node, source, start, stop) if type(source) == 'number' and source == 0 then source = vim.api.nvim_get_current_buf() diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py index 23ed0e3f08..766c420c7d 100755 --- a/scripts/gen_vimdoc.py +++ b/scripts/gen_vimdoc.py @@ -260,7 +260,7 @@ CONFIG = { 'helptag_fmt': lambda name: ( '*lua-treesitter-core*' if name.lower() == 'treesitter' - else f'*treesitter-{name.lower()}*'), + else f'*lua-treesitter-{name.lower()}*'), 'fn_helptag_fmt': lambda fstem, name: ( f'*{name}()*' if name != 'new' |