ltreesitter

load
require

Cursor

Cursor.copy
Cursor.current_depth
Cursor.current_descendant_index
Cursor.current_field_id
Cursor.current_field_name
Cursor.current_node
Cursor.goto_descendant
Cursor.goto_first_child
Cursor.goto_first_child_for_byte
Cursor.goto_first_child_for_point
Cursor.goto_next_sibling
Cursor.goto_parent
Cursor.reset
Cursor.reset_to

Node

Node.child
Node.child_by_field_id
Node.child_by_field_name
Node.child_count
Node.children
Node.create_cursor
Node.end_byte
Node.end_point
Node.grammar_symbol
Node.grammar_type
Node.is_extra
Node.is_missing
Node.is_named
Node.name
Node.named_child
Node.named_child_count
Node.named_children
Node.next_named_sibling
Node.next_parse_state
Node.next_sibling
Node.parse_state
Node.prev_named_sibling
Node.prev_sibling
Node.source
Node.start_byte
Node.start_point
Node.symbol
Node.type

Parser

Parser.get_ranges
Parser.get_version
Parser.language_abi_version
Parser.language_field_count
Parser.language_field_id_for_name
Parser.language_metadata
Parser.language_name
Parser.language_name_for_field_id
Parser.language_next_state
Parser.language_state_count
Parser.language_subtypes
Parser.language_supertypes
Parser.language_symbol_count
Parser.language_symbol_for_name
Parser.language_symbol_name
Parser.language_symbol_type
Parser.parse_string
Parser.parse_with
Parser.query
Parser.reset
Parser.set_ranges

Query

Query.capture
Query.exec
Query.match
Query.source
Query.with

Tree

Tree.copy
Tree.edit
Tree.edit_s
Tree.get_changed_ranges
Tree.root











load: function(file_name: string, language_name: string): Parser, string

Load a parser from a given file

Keep in mind that this includes the .so or .dll extension

On Unix this uses dlopen, on Windows this uses LoadLibrary so if a path without a path separator is given, these functions have their own path's that they will search for your file in.
So if in doubt use a file path like


local my_parser = ltreesitter.load("./my_parser.so", "my_language")


require: function(library_file_name: string, language_name?: string): Parser, string

Search package.cpath for a parser with the filename library_file_name.so or parsers/library_file_name.so (or .dll on Windows) and try to load the symbol tree_sitter_'language_name'
language_name is optional and will be set to library_file_name if not provided.

So if you want to load a Lua parser from a file named lua.so then use ltreesitter.require("lua")
But if you want to load a Lua parser from a file named parser.so then use ltreesitter.require("parser", "lua")

Like the regular require, this will error if the parser is not found or the symbol couldn't be loaded. Use either pcall or ltreesitter.load to not error out on failure.

Returns the parser and the path it was loaded from.


local my_parser, loaded_from = ltreesitter.require("my_language")
print(loaded_from) -- /home/user/.luarocks/lib/lua/5.4/parsers/my_language.so
my_parser:parse_string(...)
-- etc.



Cursor.copy: function(Cursor): Cursor

Create a copy of the given cursor


Cursor.current_depth: function(Cursor): integer

Get the depth of the cursor's current node relative to the node the cursor
was constructed with


Cursor.current_descendant_index: function(Cursor): integer

Get the cursor's current node index


Cursor.current_field_id: function(Cursor): FieldId

Get the field id of the given cursor's current node

May return nil


Cursor.current_field_name: function(Cursor): string

Get the field name of the current node under the cursor


Cursor.current_node: function(Cursor): Node

Get the current node under the cursor


Cursor.goto_descendant: function(Cursor, integer)

Move the cursor to the nth descendant of the original node this cursor was
constructed with. Zero represents the original node itself.


Cursor.goto_first_child: function(Cursor): boolean

Position the cursor at the first child of the current node


Cursor.goto_first_child_for_byte: function(Cursor, integer): integer

Move the given cursor to the first child of its current node that contains
or starts after the given offset

Returns the index of the child node or nil if no such child was found


Cursor.goto_first_child_for_point: function(Cursor, Point): integer

Move the given cursor to the first child of its current node that contains
or starts after the given point

Returns the index of the child node or nil if no such child was found


Cursor.goto_next_sibling: function(Cursor): boolean

Position the cursor at the sibling of the current node


Cursor.goto_parent: function(Cursor): boolean

Position the cursor at the parent of the current node


Cursor.reset: function(Cursor, Node)

Position the cursor at the given node


Cursor.reset_to: function(Cursor, Cursor)

Re-initialize a tree cursor to the same position as another cursor.



Node.child: function(Node, idx: integer): Node

Get the node's idx'th child (0-indexed)


Node.child_by_field_id: function(Node, FieldId): Node

Get a node's child given a field id


Node.child_by_field_name: function(Node, string): Node

Get a node's child given a field name


Node.child_count: function(Node): integer

Get the number of children a node has


Node.children: function(Node): function(): Node

Iterate over a node's children


Node.create_cursor: function(Node): Cursor

Create a new cursor at the given node


Node.end_byte: function(Node): integer

Get the byte of the source string that the given node ends at


Node.end_point: function(Node): Point

Get the row and column of where the given node ends


Node.grammar_symbol: function(Node): Symbol

Returns the type of a given node as a numeric id as it appears in the grammar ignoring aliases

This is what should be used in `Parser:language_next_state` instead of `Node:symbol`


Node.grammar_type: function(Node): string

Returns the type of a given node as a string as it appears in the grammar ignoring aliases


Node.is_extra: function(Node): boolean

Get whether or not the current node is extra


Node.is_missing: function(Node): boolean

Get whether or not the current node is missing


Node.is_named: function(Node): boolean

Get whether or not the current node is named


Node.name: function(Node): string

Returns the type of a given node as a string


print(node) -- => (comment)
print(node:name()) -- => comment


Node.named_child: function(Node, idx: integer): Node

Get the node's idx'th named child (0-indexed)


Node.named_child_count: function(Node): integer

Get the number of named children a node has


Node.named_children: function(Node): function(): Node

Iterate over a node's named children


Node.next_named_sibling: function(Node): Node

Get a node's next named sibling


Node.next_parse_state: function(Node): StateId

Get the parse state after this node


Node.next_sibling: function(Node): Node

Get a node's next sibling


Node.parse_state: function(Node): StateId

Get this node's parse state


Node.prev_named_sibling: function(Node): Node

Get a node's previous named sibling


Node.prev_sibling: function(Node): Node

Get a node's previous sibling


Node.source: function(Node): string

Get the substring of the source that was parsed to create Node


Node.start_byte: function(Node): integer

Get the byte of the source string that the given node starts at


Node.start_point: function(Node): Point

Get the row and column of where the given node starts


Node.symbol: function(Node): Symbol

Returns the type of a given node as a numeric id


Node.type: function(Node): string

Get the type of the given node



Parser.get_ranges: function(Parser): {Range}

Get the ranges of text that the parser will include when parsing


Parser.get_version: function(Parser): integer

get the api version of the parser's language


Parser.language_abi_version: function(Parser): integer

Get the ABI version number for the given parser's language


Parser.language_field_count: function(Parser): integer

Get the number of distinct field names in the given parser's language


Parser.language_field_id_for_name: function(Parser, string): FieldId

Get the numeric id for the given field name


Parser.language_metadata: function(Parser): LanguageMetadata

Get the metadata for the given parser's language. This information relies on
the language author providing the correct data in the language's
`tree-sitter.json`

May return nil


Parser.language_name: function(Parser): string

Get the name of the language this parser is for. May return nil.


Parser.language_name_for_field_id: function(Parser, FieldId): string

Get the name for a numeric field id


Parser.language_next_state: function(Parser, StateId, Symbol): StateId

Get the next parse state


Parser.language_state_count: function(Parser): integer

Get the number of valid states in the given parser's language


Parser.language_subtypes: function(Parser, supertype: Symbol): {Symbol}

Get a list of all supertype symbols for the given parser's language


Parser.language_supertypes: function(Parser): {Symbol}

Get a list of all supertype symbols for the given parser's language


Parser.language_symbol_count: function(Parser): integer

Get the number of distinct node types in the given parser's language


Parser.language_symbol_for_name: function(Parser, string, is_named: boolean): Symbol

Get the numerical id for the given node type string


Parser.language_symbol_name: function(Parser, Symbol): string

Get a node type string for the given symbol id


Parser.language_symbol_type: function(Parser, Symbol): SymbolType

Check whether the given node type id belongs to named nodes, anonymous nodes,
or hidden nodes


Parser.parse_string: function(Parser, string, ?Encoding, ?Tree): Tree

Uses the given parser to parse the string

If Tree is provided then it will be used to create a new updated tree
(but it is the responsibility of the programmer to make the correct Tree:edit calls)


Parser.parse_with: function( Parser, reader: (function(integer, Point): string), progress_callback?: (function(has_error: boolean, byte_offset: integer): boolean), encoding?: Encoding, old_tree?: Tree ): Tree

reader should be a function that takes a byte index
and a Point and returns the text at that point. The
function should return either nil or an empty string
to signal that there is no more text.

progress_callback should be a function that takes a boolean
signalling if an error has occurred, and an integer byte offset. This
function will be called intermittently while parsing and may return `true`
to cancel parsing.

A Tree can be provided to reuse parts of it for parsing,
provided the Tree:edit has been called previously

encoding defaults to "utf-8" when not provided.

May return nil if the progress callback cancelled parsing


Parser.query: function(Parser, string): Query

Create a query out of the given string for the language of the given parser


Parser.reset: function(Parser)

Reset the parser, causing the next parse to start from the beginning


Parser.set_ranges: function(Parser, {Range}): boolean

Sets the ranges that Parser will include when parsing, so you don't have to parse an entire document, but the ranges in the tree will still match the document.
The array of Ranges must satisfy the following relationship: for a positive integer i within the length of ranges: {Range}:


ranges[i].end_byte <= ranges[i + 1].start_byte


returns whether or not setting the range succeeded



Query.capture: function(Query, Node, start?: integer | Point, end_?: integer | Point): function(): (Node, string)

Iterate over the captures of a given query in Node, name pairs.
start and end are optional.
They must be passed together with the same type, describing either two bytes or two points.
If passed, the query will be executed within the range denoted.
If not passed, the default behaviour is to execute the query through the entire range of the node.


local q = parser:query[[ (comment) @my_match ]]
for capture, name in q:capture(node) do
print(capture, name) -- => (comment), "my_match"
end


Query.exec: function(Query, Node, start?: integer | Point, end_?: integer | Point)

Runs a query. That's it. Nothing more, nothing less.
This is intended to be used with the Query.with method and predicates that have side effects,
i.e. for when you would use Query.match or Query.capture, but do nothing in the for loop.
start and end are optional.
They must be passed together with the same type, describing either two bytes or two points.
If passed, the query will be executed within the range denoted.
If not passed, the default behaviour is to execute the query through the entire range of the node.


local parser = ltreesitter.require("teal")

-- grab a node to query against
local root_node = parser:parse_string[[
local x: string = "foo"
local y: string = "bar"
]]:root()

parser
:query[[(
(var_declaration
(var) @var-name
(string) @value)
(#set! @var-name @value)
)]]
:with{["set!"] = function(a, b) _G[a] = b:sub(2, -2) end}
:exec(root_node)

print(x) -- => foo
print(y) -- => bar



If you'd like to interact with the matches/captures of a query, see the Query.match and Query.capture iterators


Query.match: function(Query, Node, start?: integer | Point, end_?: integer | Point): function(): Match

Iterate over the matches of a given query.
start and end are optional.
They must be passed together with the same type, describing either two bytes or two points.
If passed, the query will be executed within the range denoted.
If not passed, the default behaviour is to execute the query through the entire range of the node.

The match object is a record populated with all the information given by treesitter


interface Match
id: integer
pattern_index: integer
capture_count: integer
captures: {string:Node|{Node}}
end


If a capture can only contain at most one node (as is the case with regular (node) @capture-name patterns and (node)? @capture-name patterns),
it will either be nil or that Node.

If a capture can containe multiple nodes (as is the case with (node)* @capture-name and (node)+ @capture-name patterns)
it will either be nil or an array of Node

Example:

local q = parser:query[[ (comment) @my_match ]]
for match in q:match(node) do
print(match.captures.my_match)
end


Query.source: function(Query): string

Gets the source that the query was initialized with


Query.with: function(Query, {string:function(...: string | Node | {Node}): any...}): Query

Creates a new query equipped with predicates defined in the {string:function} map given

Predicates that end in a '?' character will be seen as conditions that must be met for the pattern to be matched.
Predicates that don't will be seen just as functions to be executed given the matches provided.

Additionally, you will not have access to the return values of these functions, if you'd like to keep the results of a computation, make your functions have side-effects to write somewhere you can access.

By default the following predicates are provided.
(#eq? ...) will match if all arguments provided are equal
(#match? text pattern) will match the provided text matches the given pattern. Matches are determined by Lua's standard string.match function.
(#find? text substring) will match if text contains substring. The substring is found with Lua's standard string.find, but the search always starts from the beginning, and pattern matching is disabled. This is equivalent to string.find(text, substring, 0, true)

Predicate evaluation order:

Since predicates that end with a `?` affect whether a node matches, these are run first, in the order they appear in the query's source. Once all `?` queries are run, all the non-`?` queries are run in the order they appear in the query's source.

Example:
The following snippet will match lua functions that have a single LDoc/EmmyLua style comment above them


local parser = ltreesitter.require("lua")

-- grab a node to query against
local root_node = parser:parse_string[[
---@Doc this does stuff
local function stuff_doer()
do_stuff()
end
]]:root()

for match in parser
:query[[(
(comment) @the-comment
.
(function_definition
(function_name) @the-function-name)
(#is-doc-comment? @the-comment)
)]]
:with{
["is-doc-comment?"] = function(str)
return str:source():sub(1, 4) == "---@"
end
}
:match(root_node)
do
print("Function: " .. match.captures["the-function-name"] .. " has documentation")
print(" " .. match.captures["the-comment"])
end



Tree.copy: function(Tree): Tree

Creates a copy of the tree. Tree-sitter recommends to create copies if you are going to use multithreading since tree accesses are not thread-safe, but copying them is cheap and quick


Tree.edit: function( Tree, start_byte: integer, old_end_byte: integer, new_end_byte: integer, start_point_row: integer, start_point_col: integer, old_end_point_row: integer, old_end_point_col: integer, new_end_point_row: integer, new_end_point_col: integer )

Create an edit to the given tree


Tree.edit_s: function(Tree, TreeEdit)

Create an edit to the given tree


Tree.get_changed_ranges: function(old: Tree, new: Tree): {Range}

Compare an old syntax tree to a new syntax tree.
This would usually be called right after a set of calls to Tree.edit(_s) and Parser.parse_{string,with}


Tree.root: function(Tree): Node

Returns the root node of the given parse tree