mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-01 11:06:54 -04:00
style: fill in missing code docs wherever applicable
This commit is contained in:
parent
fceb4ed0ec
commit
853b1ab39a
17 changed files with 431 additions and 191 deletions
|
|
@ -2,20 +2,26 @@ local api = vim.api
|
|||
|
||||
local M = {}
|
||||
|
||||
--- Creates a cache table for buffers keyed by a type name.
|
||||
--- Cache entries attach to the buffer and cleanup entries
|
||||
--- as buffers are detached.
|
||||
-- Creates a cache table for buffers keyed by a type name.
|
||||
-- Cache entries attach to the buffer and cleanup entries
|
||||
-- as buffers are detached.
|
||||
function M.create_buffer_cache()
|
||||
local cache = {}
|
||||
|
||||
---@type table<string, table<string, any>>
|
||||
local items = setmetatable({}, {
|
||||
__index = function(tbl, key)
|
||||
rawset(tbl, key, {})
|
||||
return rawget(tbl, key)
|
||||
end,
|
||||
})
|
||||
|
||||
---@type table<integer|string, boolean>
|
||||
local loaded_buffers = {}
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
---@param value any
|
||||
function cache.set(type_name, bufnr, value)
|
||||
if not loaded_buffers[bufnr] then
|
||||
loaded_buffers[bufnr] = true
|
||||
|
|
@ -34,18 +40,27 @@ function M.create_buffer_cache()
|
|||
items[tostring(bufnr)][type_name] = value
|
||||
end
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
---@return any
|
||||
function cache.get(type_name, bufnr)
|
||||
return items[tostring(bufnr)][type_name]
|
||||
end
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
---@return boolean
|
||||
function cache.has(type_name, bufnr)
|
||||
return cache.get(type_name, bufnr) ~= nil
|
||||
end
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
function cache.remove(type_name, bufnr)
|
||||
items[tostring(bufnr)][type_name] = nil
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
function cache.clear_buffer(bufnr)
|
||||
items[tostring(bufnr)] = nil
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@ local config = {
|
|||
update_strategy = "lockfile",
|
||||
parser_install_dir = nil,
|
||||
}
|
||||
|
||||
-- List of modules that need to be setup on initialization.
|
||||
---@type TSModule[][]
|
||||
local queued_modules_defs = {}
|
||||
-- Whether we've initialized the plugin yet.
|
||||
local is_initialized = false
|
||||
|
|
@ -36,10 +38,12 @@ local is_initialized = false
|
|||
---@field module_path string
|
||||
---@field enable boolean|string[]|function(string): boolean
|
||||
---@field disable boolean|string[]|function(string): boolean
|
||||
---@field keymaps table<string, string>
|
||||
---@field is_supported function(string): boolean
|
||||
---@field attach function(string)
|
||||
---@field detach function(string)
|
||||
---@field enabled_buffers table<integer, boolean>
|
||||
---@field additional_vim_regex_highlighting boolean|string[]
|
||||
|
||||
---@type {[string]: TSModule}
|
||||
local builtin_modules = {
|
||||
|
|
@ -248,7 +252,7 @@ local function recurse_modules(accumulator, root, path)
|
|||
end
|
||||
end
|
||||
|
||||
---Shows current configuration of all nvim-treesitter modules
|
||||
-- Shows current configuration of all nvim-treesitter modules
|
||||
---@param process_function function used as the `process` parameter
|
||||
--- for vim.inspect (https://github.com/kikito/inspect.lua#optionsprocess)
|
||||
local function config_info(process_function)
|
||||
|
|
@ -369,7 +373,7 @@ M.commands = {
|
|||
|
||||
---@param mod string module
|
||||
---@param lang string the language of the buffer
|
||||
---@param bufnr integer the bufnr
|
||||
---@param bufnr integer the buffer
|
||||
function M.is_enabled(mod, lang, bufnr)
|
||||
if not parsers.has_parser(lang) then
|
||||
return false
|
||||
|
|
@ -438,8 +442,8 @@ function M.setup(user_data)
|
|||
end, config.modules)
|
||||
end
|
||||
|
||||
---Defines a table of modules that can be attached/detached to buffers
|
||||
---based on language support. A module consist of the following properties:
|
||||
-- Defines a table of modules that can be attached/detached to buffers
|
||||
-- based on language support. A module consist of the following properties:
|
||||
---* @enable Whether the modules is enabled. Can be true or false.
|
||||
---* @disable A list of languages to disable the module for. Only relevant if enable is true.
|
||||
---* @keymaps A list of user mappings for a given module if relevant.
|
||||
|
|
@ -451,9 +455,11 @@ end
|
|||
--- if a `module_path` is not specified.
|
||||
---* @detach A detach function that is called for each buffer that the module is enabled for. This is required
|
||||
--- if a `module_path` is not specified.
|
||||
---Modules are not setup until `init` is invoked by the plugin. This allows modules to be defined in any order
|
||||
---and can be loaded lazily.
|
||||
---@example
|
||||
--
|
||||
-- Modules are not setup until `init` is invoked by the plugin. This allows modules to be defined in any order
|
||||
-- and can be loaded lazily.
|
||||
--
|
||||
---* @example
|
||||
---require"nvim-treesitter".define_modules {
|
||||
--- my_cool_module = {
|
||||
--- attach = function()
|
||||
|
|
@ -493,7 +499,7 @@ end
|
|||
|
||||
---Attaches a module to a buffer
|
||||
---@param mod_name string the module name
|
||||
---@param bufnr integer the bufnr
|
||||
---@param bufnr integer the buffer
|
||||
---@param lang string the language of the buffer
|
||||
function M.attach_module(mod_name, bufnr, lang)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
|
|
@ -506,9 +512,9 @@ function M.attach_module(mod_name, bufnr, lang)
|
|||
end
|
||||
end
|
||||
|
||||
---Detaches a module to a buffer
|
||||
-- Detaches a module to a buffer
|
||||
---@param mod_name string the module name
|
||||
---@param bufnr integer the bufnr
|
||||
---@param bufnr integer the buffer
|
||||
function M.detach_module(mod_name, bufnr)
|
||||
local resolved_mod = resolve_module(mod_name)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
|
|
@ -519,17 +525,18 @@ function M.detach_module(mod_name, bufnr)
|
|||
end
|
||||
end
|
||||
|
||||
---Same as attach_module, but if the module is already attached, detach it first.
|
||||
-- Same as attach_module, but if the module is already attached, detach it first.
|
||||
---@param mod_name string the module name
|
||||
---@param bufnr integer the bufnr
|
||||
---@param bufnr integer the buffer
|
||||
---@param lang string the language of the buffer
|
||||
function M.reattach_module(mod_name, bufnr, lang)
|
||||
M.detach_module(mod_name, bufnr)
|
||||
M.attach_module(mod_name, bufnr, lang)
|
||||
end
|
||||
|
||||
---Gets available modules
|
||||
-- Gets available modules
|
||||
---@param root {[string]:TSModule}|nil table to find modules
|
||||
---@return string[] modules list of module paths
|
||||
function M.available_modules(root)
|
||||
local modules = {}
|
||||
|
||||
|
|
@ -542,24 +549,24 @@ end
|
|||
|
||||
---Gets a module config by path
|
||||
---@param mod_path string path to the module
|
||||
---@return TSModule|nil the module or nil
|
||||
---@return TSModule|nil: the module or nil
|
||||
function M.get_module(mod_path)
|
||||
local mod = utils.get_at_path(config.modules, mod_path)
|
||||
|
||||
return M.is_module(mod) and mod or nil
|
||||
end
|
||||
|
||||
---Determines whether the provided table is a module.
|
||||
---A module should contain an attach and detach function.
|
||||
---@param mod table the module table
|
||||
-- Determines whether the provided table is a module.
|
||||
-- A module should contain an attach and detach function.
|
||||
---@param mod table|nil the module table
|
||||
---@return boolean
|
||||
function M.is_module(mod)
|
||||
return type(mod) == "table"
|
||||
and ((type(mod.attach) == "function" and type(mod.detach) == "function") or type(mod.module_path) == "string")
|
||||
end
|
||||
|
||||
---Initializes built-in modules and any queued modules
|
||||
---registered by plugins or the user.
|
||||
-- Initializes built-in modules and any queued modules
|
||||
-- registered by plugins or the user.
|
||||
function M.init()
|
||||
is_initialized = true
|
||||
M.define_modules(builtin_modules)
|
||||
|
|
@ -569,22 +576,17 @@ function M.init()
|
|||
end
|
||||
end
|
||||
|
||||
---If parser_install_dir is not nil is used or created.
|
||||
---If parser_install_dir is nil try the package dir of the nvim-treesitter
|
||||
---plugin first, followed by the "site" dir from "runtimepath". "site" dir will
|
||||
---be created if it doesn't exist. Using only the package dir won't work when
|
||||
---the plugin is installed with Nix, since the "/nix/store" is read-only.
|
||||
-- If parser_install_dir is not nil is used or created.
|
||||
-- If parser_install_dir is nil try the package dir of the nvim-treesitter
|
||||
-- plugin first, followed by the "site" dir from "runtimepath". "site" dir will
|
||||
-- be created if it doesn't exist. Using only the package dir won't work when
|
||||
-- the plugin is installed with Nix, since the "/nix/store" is read-only.
|
||||
---@param folder_name string|nil
|
||||
---@return string|nil, string|nil
|
||||
function M.get_parser_install_dir(folder_name)
|
||||
folder_name = folder_name or "parser"
|
||||
|
||||
local install_dir
|
||||
if config.parser_install_dir then
|
||||
install_dir = config.parser_install_dir
|
||||
else
|
||||
install_dir = utils.get_package_path()
|
||||
end
|
||||
local install_dir = config.parser_install_dir or utils.get_package_path()
|
||||
local parser_dir = utils.join_path(install_dir, folder_name)
|
||||
|
||||
return utils.create_or_reuse_writable_dir(
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr)
|
|||
end)
|
||||
|
||||
-- start..stop is an inclusive range
|
||||
|
||||
---@type table<number, number>
|
||||
local start_counts = {}
|
||||
---@type table<number, number>
|
||||
local stop_counts = {}
|
||||
|
||||
local prev_start = -1
|
||||
|
|
@ -40,11 +43,11 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr)
|
|||
local min_fold_lines = api.nvim_win_get_option(0, "foldminlines")
|
||||
|
||||
for _, match in ipairs(matches) do
|
||||
local start, stop, stop_col
|
||||
local start, stop, stop_col ---@type integer, integer, integer
|
||||
if match.metadata and match.metadata.range then
|
||||
start, _, stop, stop_col = unpack(match.metadata.range)
|
||||
start, _, stop, stop_col = unpack(match.metadata.range) ---@type integer, integer, integer, integer
|
||||
else
|
||||
start, _, stop, stop_col = match.node:range()
|
||||
start, _, stop, stop_col = match.node:range() ---@type integer, integer, integer, integer
|
||||
end
|
||||
|
||||
if stop_col == 0 then
|
||||
|
|
@ -65,6 +68,7 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr)
|
|||
end
|
||||
end
|
||||
|
||||
---@type string[]
|
||||
local levels = {}
|
||||
local current_level = 0
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@ local configs = require "nvim-treesitter.configs"
|
|||
|
||||
local M = {}
|
||||
|
||||
---@param config table
|
||||
---@param config TSModule
|
||||
---@param lang string
|
||||
---@return boolean
|
||||
local function should_enable_vim_regex(config, lang)
|
||||
local additional_hl = config.additional_vim_regex_highlighting
|
||||
local is_table = type(additional_hl) == "table"
|
||||
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
return additional_hl and (not is_table or vim.tbl_contains(additional_hl, lang))
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ local queries = require "nvim-treesitter.query"
|
|||
|
||||
local M = {}
|
||||
|
||||
---@type table<integer, table<TSNode|nil>>
|
||||
local selections = {}
|
||||
|
||||
function M.init_selection()
|
||||
|
|
@ -17,14 +18,15 @@ function M.init_selection()
|
|||
ts_utils.update_selection(buf, node)
|
||||
end
|
||||
|
||||
--- Get the range of the current visual selection.
|
||||
-- Get the range of the current visual selection.
|
||||
--
|
||||
-- The range start with 1 and the ending is inclusive.
|
||||
-- The range starts with 1 and the ending is inclusive.
|
||||
---@return integer, integer, integer, integer
|
||||
local function visual_selection_range()
|
||||
local _, csrow, cscol, _ = unpack(vim.fn.getpos "'<")
|
||||
local _, cerow, cecol, _ = unpack(vim.fn.getpos "'>")
|
||||
local _, csrow, cscol, _ = unpack(vim.fn.getpos "'<") ---@type integer, integer, integer, integer
|
||||
local _, cerow, cecol, _ = unpack(vim.fn.getpos "'>") ---@type integer, integer, integer, integer
|
||||
|
||||
local start_row, start_col, end_row, end_col
|
||||
local start_row, start_col, end_row, end_col ---@type integer, integer, integer, integer
|
||||
|
||||
if csrow < cerow or (csrow == cerow and cscol <= cecol) then
|
||||
start_row = csrow
|
||||
|
|
@ -41,12 +43,16 @@ local function visual_selection_range()
|
|||
return start_row, start_col, end_row, end_col
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return boolean
|
||||
local function range_matches(node)
|
||||
local csrow, cscol, cerow, cecol = visual_selection_range()
|
||||
local srow, scol, erow, ecol = ts_utils.get_vim_range { node:range() }
|
||||
return srow == csrow and scol == cscol and erow == cerow and ecol == cecol
|
||||
end
|
||||
|
||||
---@param get_parent fun(node: TSNode): TSNode|nil
|
||||
---@return fun():nil
|
||||
local function select_incremental(get_parent)
|
||||
return function()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
|
|
@ -67,7 +73,7 @@ local function select_incremental(get_parent)
|
|||
end
|
||||
|
||||
-- Find a node that changes the current selection.
|
||||
local node = nodes[#nodes]
|
||||
local node = nodes[#nodes] ---@type TSNode
|
||||
while true do
|
||||
local parent = get_parent(node)
|
||||
if not parent or parent == node then
|
||||
|
|
@ -116,7 +122,7 @@ function M.node_decremental()
|
|||
end
|
||||
|
||||
table.remove(selections[buf])
|
||||
local node = nodes[#nodes]
|
||||
local node = nodes[#nodes] ---@type TSNode
|
||||
ts_utils.update_selection(buf, node)
|
||||
end
|
||||
|
||||
|
|
@ -127,14 +133,16 @@ local FUNCTION_DESCRIPTIONS = {
|
|||
node_decremental = "Shrink selection to previous named node",
|
||||
}
|
||||
|
||||
---@param bufnr integer
|
||||
function M.attach(bufnr)
|
||||
local config = configs.get_module "incremental_selection"
|
||||
for funcname, mapping in pairs(config.keymaps) do
|
||||
if mapping then
|
||||
local mode
|
||||
local rhs
|
||||
---@type string, string|function
|
||||
local mode, rhs
|
||||
if funcname == "init_selection" then
|
||||
mode = "n"
|
||||
---@type function
|
||||
rhs = M[funcname]
|
||||
else
|
||||
mode = "x"
|
||||
|
|
|
|||
|
|
@ -15,16 +15,27 @@ M.comment_parsers = {
|
|||
phpdoc = true,
|
||||
}
|
||||
|
||||
---@param root TSNode
|
||||
---@param lnum integer
|
||||
---@return TSNode
|
||||
local function get_first_node_at_line(root, lnum)
|
||||
local col = vim.fn.indent(lnum)
|
||||
return root:descendant_for_range(lnum - 1, col, lnum - 1, col)
|
||||
end
|
||||
|
||||
---@param root TSNode
|
||||
---@param lnum integer
|
||||
---@return TSNode
|
||||
local function get_last_node_at_line(root, lnum)
|
||||
local col = #vim.fn.getline(lnum) - 1
|
||||
return root:descendant_for_range(lnum - 1, col, lnum - 1, col)
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param node TSNode
|
||||
---@param delimiter string
|
||||
---@return TSNode|nil child
|
||||
---@return boolean|nil is_end
|
||||
local function find_delimiter(bufnr, node, delimiter)
|
||||
for child, _ in node:iter_children() do
|
||||
if child:type() == delimiter then
|
||||
|
|
@ -77,7 +88,7 @@ function M.get_indent(lnum)
|
|||
end
|
||||
|
||||
-- Get language tree with smallest range around node that's not a comment parser
|
||||
local root, lang_tree
|
||||
local root, lang_tree ---@type TSNode, LanguageTree
|
||||
parser:for_each_tree(function(tstree, tree)
|
||||
if not tstree or M.comment_parsers[tree:lang()] then
|
||||
return
|
||||
|
|
@ -98,7 +109,7 @@ function M.get_indent(lnum)
|
|||
|
||||
local q = get_indents(vim.api.nvim_get_current_buf(), root, lang_tree:lang())
|
||||
local is_empty_line = string.match(vim.fn.getline(lnum), "^%s*$") ~= nil
|
||||
local node
|
||||
local node ---@type TSNode
|
||||
if is_empty_line then
|
||||
local prevlnum = vim.fn.prevnonblank(lnum)
|
||||
node = get_last_node_at_line(root, prevlnum)
|
||||
|
|
@ -171,8 +182,9 @@ function M.get_indent(lnum)
|
|||
-- do not indent for nodes that starts-and-ends on same line and starts on target line (lnum)
|
||||
if q.aligned_indent[node:id()] and srow ~= erow and (srow ~= lnum - 1) then
|
||||
local metadata = q.aligned_indent[node:id()]
|
||||
local o_delim_node, is_last_in_line
|
||||
local o_delim_node, is_last_in_line ---@type TSNode|nil, boolean|nil
|
||||
if metadata.delimiter then
|
||||
---@type string
|
||||
local opening_delimiter = metadata.delimiter and metadata.delimiter:sub(1, 1)
|
||||
o_delim_node, is_last_in_line = find_delimiter(bufnr, node, opening_delimiter)
|
||||
else
|
||||
|
|
@ -198,8 +210,10 @@ function M.get_indent(lnum)
|
|||
return indent
|
||||
end
|
||||
|
||||
---@type table<integer, string>
|
||||
local indent_funcs = {}
|
||||
|
||||
---@param bufnr integer
|
||||
function M.attach(bufnr)
|
||||
indent_funcs[bufnr] = vim.bo.indentexpr
|
||||
vim.bo.indentexpr = "nvim_treesitter#indent()"
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ end
|
|||
-- {'mod1', 'mod2.sub1', 'mod2.sub2', 'mod3'}
|
||||
-- ->
|
||||
-- { default = {'mod1', 'mod3'}, mod2 = {'sub1', 'sub2'}}
|
||||
---@param modulelist string[]
|
||||
---@return table
|
||||
local function namespace_modules(modulelist)
|
||||
local modules = {}
|
||||
for _, module in ipairs(modulelist) do
|
||||
|
|
@ -50,6 +52,8 @@ local function namespace_modules(modulelist)
|
|||
return modules
|
||||
end
|
||||
|
||||
---@param list string[]
|
||||
---@return integer length
|
||||
local function longest_string_length(list)
|
||||
local length = 0
|
||||
for _, value in ipairs(list) do
|
||||
|
|
@ -60,6 +64,11 @@ local function longest_string_length(list)
|
|||
return length
|
||||
end
|
||||
|
||||
---@param curbuf integer
|
||||
---@param origbuf integer
|
||||
---@param parserlist string[]
|
||||
---@param namespace string
|
||||
---@param modulelist string[]
|
||||
local function append_module_table(curbuf, origbuf, parserlist, namespace, modulelist)
|
||||
local maxlen_parser = longest_string_length(parserlist)
|
||||
table.sort(modulelist)
|
||||
|
|
@ -104,6 +113,7 @@ local function print_info_modules(parserlist, module)
|
|||
modules = namespace_modules(configs.available_modules())
|
||||
end
|
||||
|
||||
---@type string[]
|
||||
local namespaces = {}
|
||||
for k, _ in pairs(modules) do
|
||||
table.insert(namespaces, k)
|
||||
|
|
@ -150,6 +160,7 @@ local function module_info(module)
|
|||
end
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
function M.installed_parsers()
|
||||
local installed = {}
|
||||
for _, p in pairs(parsers.available_parsers()) do
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ local configs = require "nvim-treesitter.configs"
|
|||
local shell = require "nvim-treesitter.shell_command_selectors"
|
||||
|
||||
local M = {}
|
||||
|
||||
---@class LockfileInfo
|
||||
---@field revision string
|
||||
|
||||
---@type table<string, LockfileInfo>
|
||||
local lockfile = {}
|
||||
|
||||
M.compilers = { vim.fn.getenv "CC", "cc", "gcc", "clang", "cl", "zig" }
|
||||
|
|
@ -96,8 +101,8 @@ local function is_ignored_parser(lang)
|
|||
return vim.tbl_contains(configs.get_ignored_parser_installs(), lang)
|
||||
end
|
||||
|
||||
--- @param lang string
|
||||
--- @return string|nil
|
||||
---@param lang string
|
||||
---@return string|nil
|
||||
local function get_revision(lang)
|
||||
if #lockfile == 0 then
|
||||
load_lockfile()
|
||||
|
|
@ -123,8 +128,8 @@ local function get_installed_revision(lang)
|
|||
end
|
||||
|
||||
-- Clean path for use in a prefix comparison
|
||||
-- @param input string
|
||||
-- @return string
|
||||
---@param input string
|
||||
---@return string
|
||||
local function clean_path(input)
|
||||
local pth = vim.fn.fnamemodify(input, ":p")
|
||||
if fn.has "win32" == 1 then
|
||||
|
|
@ -133,7 +138,7 @@ local function clean_path(input)
|
|||
return pth
|
||||
end
|
||||
|
||||
---Checks if parser is installed with nvim-treesitter
|
||||
-- Checks if parser is installed with nvim-treesitter
|
||||
---@param lang string
|
||||
---@return boolean
|
||||
local function is_installed(lang)
|
||||
|
|
@ -159,9 +164,9 @@ local function needs_update(lang)
|
|||
return not revision or revision ~= get_installed_revision(lang)
|
||||
end
|
||||
|
||||
---@return table
|
||||
---@return string[]
|
||||
local function outdated_parsers()
|
||||
return vim.tbl_filter(function(lang)
|
||||
return vim.tbl_filter(function(lang) ---@param lang string
|
||||
return is_installed(lang) and needs_update(lang)
|
||||
end, info.installed_parsers())
|
||||
end
|
||||
|
|
@ -252,6 +257,8 @@ function M.iter_cmd(cmd_list, i, lang, success_message)
|
|||
end
|
||||
end
|
||||
|
||||
---@param cmd Command
|
||||
---@return string command
|
||||
local function get_command(cmd)
|
||||
local options = ""
|
||||
if cmd.opts and cmd.opts.args then
|
||||
|
|
@ -263,13 +270,15 @@ local function get_command(cmd)
|
|||
end
|
||||
end
|
||||
|
||||
local final = string.format("%s %s", cmd.cmd, options)
|
||||
local command = string.format("%s %s", cmd.cmd, options)
|
||||
if cmd.opts and cmd.opts.cwd then
|
||||
final = shell.make_directory_change_for_command(cmd.opts.cwd, final)
|
||||
command = shell.make_directory_change_for_command(cmd.opts.cwd, command)
|
||||
end
|
||||
return final
|
||||
return command
|
||||
end
|
||||
|
||||
---@param cmd_list Command[]
|
||||
---@return boolean
|
||||
local function iter_cmd_sync(cmd_list)
|
||||
for _, cmd in ipairs(cmd_list) do
|
||||
if cmd.info then
|
||||
|
|
@ -311,7 +320,7 @@ local function run_install(cache_folder, install_folder, lang, repo, with_sync,
|
|||
repo.url = maybe_local_path
|
||||
end
|
||||
|
||||
-- compile_location only needed for typescript installs.
|
||||
---@type string compile_location only needed for typescript installs.
|
||||
local compile_location
|
||||
if from_local_path then
|
||||
compile_location = repo.url
|
||||
|
|
@ -355,7 +364,7 @@ local function run_install(cache_folder, install_folder, lang, repo, with_sync,
|
|||
local cc = shell.select_executable(M.compilers)
|
||||
if not cc then
|
||||
api.nvim_err_writeln('No C compiler found! "' .. table.concat(
|
||||
vim.tbl_filter(function(c)
|
||||
vim.tbl_filter(function(c) ---@param c string
|
||||
return type(c) == "string"
|
||||
end, M.compilers),
|
||||
'", "'
|
||||
|
|
@ -368,6 +377,17 @@ local function run_install(cache_folder, install_folder, lang, repo, with_sync,
|
|||
revision = get_revision(lang)
|
||||
end
|
||||
|
||||
---@class Command
|
||||
---@field cmd string
|
||||
---@field info string
|
||||
---@field err string
|
||||
---@field opts CmdOpts
|
||||
|
||||
---@class CmdOpts
|
||||
---@field args string[]
|
||||
---@field cwd string
|
||||
|
||||
---@type Command[]
|
||||
local command_list = {}
|
||||
if not from_local_path then
|
||||
vim.list_extend(command_list, { shell.select_install_rm_cmd(cache_folder, project_name) })
|
||||
|
|
@ -411,7 +431,7 @@ local function run_install(cache_folder, install_folder, lang, repo, with_sync,
|
|||
shell.select_mv_cmd("parser.so", parser_lib_name, compile_location),
|
||||
{
|
||||
cmd = function()
|
||||
vim.fn.writefile({ revision or "" }, utils.join_path(configs.get_parser_info_dir(), lang .. ".revision"))
|
||||
vim.fn.writefile({ revision or "" }, utils.join_path(configs.get_parser_info_dir() or "", lang .. ".revision"))
|
||||
end,
|
||||
},
|
||||
{ -- auto-attach modules after installation
|
||||
|
|
@ -432,7 +452,7 @@ local function run_install(cache_folder, install_folder, lang, repo, with_sync,
|
|||
end
|
||||
|
||||
---@param lang string
|
||||
---@param ask_reinstall boolean
|
||||
---@param ask_reinstall boolean|string
|
||||
---@param cache_folder string
|
||||
---@param install_folder string
|
||||
---@param with_sync boolean
|
||||
|
|
@ -465,6 +485,14 @@ local function install_lang(lang, ask_reinstall, cache_folder, install_folder, w
|
|||
run_install(cache_folder, install_folder, lang, install_info, with_sync, generate_from_grammar)
|
||||
end
|
||||
|
||||
---@class InstallOptions
|
||||
---@field with_sync boolean
|
||||
---@field ask_reinstall boolean|string
|
||||
---@field generate_from_grammar boolean
|
||||
---@field exclude_configured_parsers boolean
|
||||
|
||||
-- Install a parser
|
||||
---@param options? InstallOptions
|
||||
---@return function
|
||||
local function install(options)
|
||||
options = options or {}
|
||||
|
|
@ -491,8 +519,8 @@ local function install(options)
|
|||
end
|
||||
assert(install_folder)
|
||||
|
||||
local languages
|
||||
local ask
|
||||
local languages ---@type string[]
|
||||
local ask ---@type boolean|string
|
||||
if ... == "all" then
|
||||
languages = parsers.available_parsers()
|
||||
ask = false
|
||||
|
|
@ -533,6 +561,7 @@ function M.update(options)
|
|||
M.lockfile = {}
|
||||
reset_progress_counter()
|
||||
if ... and ... ~= "all" then
|
||||
---@type string[]
|
||||
local languages = vim.tbl_flatten { ... }
|
||||
local installed = 0
|
||||
for _, lang in ipairs(languages) do
|
||||
|
|
@ -578,6 +607,7 @@ function M.uninstall(...)
|
|||
end
|
||||
ensure_installed_parsers = utils.difference(ensure_installed_parsers, configs.get_ignored_parser_installs())
|
||||
|
||||
---@type string[]
|
||||
local languages = vim.tbl_flatten { ... }
|
||||
for _, lang in ipairs(languages) do
|
||||
local install_dir, err = configs.get_parser_install_dir()
|
||||
|
|
@ -634,7 +664,7 @@ function M.uninstall(...)
|
|||
end
|
||||
|
||||
function M.write_lockfile(verbose, skip_langs)
|
||||
local sorted_parsers = {}
|
||||
local sorted_parsers = {} ---@type Parser[]
|
||||
-- Load previous lockfile
|
||||
load_lockfile()
|
||||
skip_langs = skip_langs or {}
|
||||
|
|
@ -643,6 +673,8 @@ function M.write_lockfile(verbose, skip_langs)
|
|||
table.insert(sorted_parsers, { name = k, parser = v })
|
||||
end
|
||||
|
||||
---@param a Parser
|
||||
---@param b Parser
|
||||
table.sort(sorted_parsers, function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
|
@ -650,7 +682,7 @@ function M.write_lockfile(verbose, skip_langs)
|
|||
for _, v in ipairs(sorted_parsers) do
|
||||
if not vim.tbl_contains(skip_langs, v.name) then
|
||||
-- I'm sure this can be done in aync way with iter_cmd
|
||||
local sha
|
||||
local sha ---@type string
|
||||
if v.parser.install_info.branch then
|
||||
sha = vim.split(
|
||||
vim.fn.systemlist(
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@ function M.iter_locals(bufnr, root)
|
|||
return queries.iter_group_results(bufnr, "locals", root)
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@return any
|
||||
function M.get_locals(bufnr)
|
||||
return queries.get_matches(bufnr, "locals")
|
||||
end
|
||||
|
||||
--- Creates unique id for a node based on text and range
|
||||
-- @param scope: the scope node of the definition
|
||||
-- @param bufnr: the buffer
|
||||
-- @param node_text: the node text to use
|
||||
-- @returns a string id
|
||||
-- Creates unique id for a node based on text and range
|
||||
---@param scope TSNode: the scope node of the definition
|
||||
---@param node_text string: the node text to use
|
||||
---@return string: a string id
|
||||
function M.get_definition_id(scope, node_text)
|
||||
-- Add a valid starting character in case node text doesn't start with a valid one.
|
||||
return table.concat({ "k", node_text or "", scope:range() }, "_")
|
||||
|
|
@ -76,10 +77,13 @@ function M.get_references(bufnr)
|
|||
return refs
|
||||
end
|
||||
|
||||
--- Gets a table with all the scopes containing a node
|
||||
-- Gets a table with all the scopes containing a node
|
||||
-- The order is from most specific to least (bottom up)
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return TSNode[]
|
||||
function M.get_scope_tree(node, bufnr)
|
||||
local scopes = {}
|
||||
local scopes = {} ---@type TSNode[]
|
||||
|
||||
for scope in M.iter_scope_tree(node, bufnr) do
|
||||
table.insert(scopes, scope)
|
||||
|
|
@ -88,7 +92,10 @@ function M.get_scope_tree(node, bufnr)
|
|||
return scopes
|
||||
end
|
||||
|
||||
--- Iterates over a nodes scopes moving from the bottom up
|
||||
-- Iterates over a nodes scopes moving from the bottom up
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return fun(): TSNode|nil
|
||||
function M.iter_scope_tree(node, bufnr)
|
||||
local last_node = node
|
||||
return function()
|
||||
|
|
@ -105,12 +112,12 @@ function M.iter_scope_tree(node, bufnr)
|
|||
end
|
||||
|
||||
-- Gets a table of all nodes and their 'kinds' from a locals list
|
||||
-- @param local_def the local list result
|
||||
-- @returns a list of node entries
|
||||
---@param local_def any: the local list result
|
||||
---@return table: a list of node entries
|
||||
function M.get_local_nodes(local_def)
|
||||
local result = {}
|
||||
|
||||
M.recurse_local_nodes(local_def, function(def, node, kind)
|
||||
M.recurse_local_nodes(local_def, function(def, _node, kind)
|
||||
table.insert(result, vim.tbl_extend("keep", { kind = kind }, def))
|
||||
end)
|
||||
|
||||
|
|
@ -123,10 +130,10 @@ end
|
|||
-- * The node
|
||||
-- * The full definition match `@definition.var.something` -> 'var.something'
|
||||
-- * The last definition match `@definition.var.something` -> 'something'
|
||||
-- @param The locals result
|
||||
-- @param The accumulator function
|
||||
-- @param The full match path to append to
|
||||
-- @param The last match
|
||||
---@param local_def any The locals result
|
||||
---@param accumulator function The accumulator function
|
||||
---@param full_match? string The full match path to append to
|
||||
---@param last_match? string The last match
|
||||
function M.recurse_local_nodes(local_def, accumulator, full_match, last_match)
|
||||
if type(local_def) ~= "table" then
|
||||
return
|
||||
|
|
@ -141,7 +148,7 @@ function M.recurse_local_nodes(local_def, accumulator, full_match, last_match)
|
|||
end
|
||||
end
|
||||
|
||||
--- Get a single dimension table to look definition nodes.
|
||||
-- Get a single dimension table to look definition nodes.
|
||||
-- Keys are generated by using the range of the containing scope and the text of the definition node.
|
||||
-- This makes looking up a definition for a given scope a simple key lookup.
|
||||
--
|
||||
|
|
@ -152,8 +159,8 @@ end
|
|||
-- Usage lookups require finding the definition of the node, so `find_definition`
|
||||
-- is called very frequently, which is why this lookup must be fast as possible.
|
||||
--
|
||||
-- @param bufnr: the buffer
|
||||
-- @returns a table for looking up definitions
|
||||
---@param bufnr integer: the buffer
|
||||
---@return table result: a table for looking up definitions
|
||||
M.get_definitions_lookup_table = ts_utils.memoize_by_buf_tick(function(bufnr)
|
||||
local definitions = M.get_definitions(bufnr)
|
||||
local result = {}
|
||||
|
|
@ -173,19 +180,19 @@ M.get_definitions_lookup_table = ts_utils.memoize_by_buf_tick(function(bufnr)
|
|||
return result
|
||||
end)
|
||||
|
||||
--- Gets all the scopes of a definition based on the scope type
|
||||
-- Gets all the scopes of a definition based on the scope type
|
||||
-- Scope types can be
|
||||
--
|
||||
-- "parent": Uses the parent of the containing scope, basically, skipping a scope
|
||||
-- "global": Uses the top most scope
|
||||
-- "local": Uses the containing scope of the definition. This is the default
|
||||
--
|
||||
-- @param node: the definition node
|
||||
-- @param bufnr: the buffer
|
||||
-- @param scope_type: the scope type
|
||||
---@param node TSNode: the definition node
|
||||
---@param bufnr integer: the buffer
|
||||
---@param scope_type string: the scope type
|
||||
function M.get_definition_scopes(node, bufnr, scope_type)
|
||||
local scopes = {}
|
||||
local scope_count = 1
|
||||
local scope_count = 1 ---@type integer|nil
|
||||
|
||||
-- Definition is valid for the containing scope
|
||||
-- and the containing scope of that scope
|
||||
|
|
@ -209,6 +216,11 @@ function M.get_definition_scopes(node, bufnr, scope_type)
|
|||
return scopes
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return TSNode node
|
||||
---@return TSNode scope
|
||||
---@return string|nil kind
|
||||
function M.find_definition(node, bufnr)
|
||||
local def_lookup = M.get_definitions_lookup_table(bufnr)
|
||||
local node_text = ts_query.get_node_text(node, bufnr)
|
||||
|
|
@ -227,11 +239,11 @@ function M.find_definition(node, bufnr)
|
|||
end
|
||||
|
||||
-- Finds usages of a node in a given scope.
|
||||
-- @param node the node to find usages for
|
||||
-- @param scope_node the node to look within
|
||||
-- @returns a list of nodes
|
||||
---@param node TSNode the node to find usages for
|
||||
---@param scope_node TSNode the node to look within
|
||||
---@return TSNode[]: a list of nodes
|
||||
function M.find_usages(node, scope_node, bufnr)
|
||||
local bufnr = bufnr or api.nvim_get_current_buf()
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local node_text = ts_query.get_node_text(node, bufnr)
|
||||
|
||||
if not node_text or #node_text < 1 then
|
||||
|
|
@ -258,6 +270,10 @@ function M.find_usages(node, scope_node, bufnr)
|
|||
return usages
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@param bufnr? integer
|
||||
---@param allow_scope? boolean
|
||||
---@return TSNode|nil
|
||||
function M.containing_scope(node, bufnr, allow_scope)
|
||||
local bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local allow_scope = allow_scope == nil or allow_scope == true
|
||||
|
|
@ -284,8 +300,8 @@ function M.nested_scope(node, cursor_pos)
|
|||
return
|
||||
end
|
||||
|
||||
local row = cursor_pos.row
|
||||
local col = cursor_pos.col
|
||||
local row = cursor_pos.row ---@type integer
|
||||
local col = cursor_pos.col ---@type integer
|
||||
local scope = M.containing_scope(node)
|
||||
|
||||
for _, child in ipairs(ts_utils.get_named_children(scope)) do
|
||||
|
|
@ -321,6 +337,8 @@ function M.next_scope(node)
|
|||
end
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return TSNode|nil
|
||||
function M.previous_scope(node)
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ local filetype_to_parsername = {
|
|||
---@field filetype string
|
||||
---@field maintainers string[]
|
||||
---@field experimental boolean|nil
|
||||
---@field readme_name string|nil
|
||||
|
||||
---@type ParserInfo[]
|
||||
local list = setmetatable({}, {
|
||||
|
|
@ -1542,11 +1543,13 @@ function M.ft_to_lang(ft)
|
|||
end
|
||||
end
|
||||
|
||||
-- Get a list of all available parsers
|
||||
---@return string[]
|
||||
function M.available_parsers()
|
||||
if vim.fn.executable "tree-sitter" == 1 and vim.fn.executable "node" == 1 then
|
||||
return vim.tbl_keys(M.list)
|
||||
else
|
||||
return vim.tbl_filter(function(p)
|
||||
return vim.tbl_filter(function(p) ---@param p string
|
||||
return not M.list[p].install_info.requires_generate_from_grammar
|
||||
end, vim.tbl_keys(M.list))
|
||||
end
|
||||
|
|
@ -1598,9 +1601,9 @@ function M.get_tree_root(bufnr)
|
|||
return M.get_parser(bufnr):parse()[1]:root()
|
||||
end
|
||||
|
||||
-- get language of given buffer
|
||||
-- @param optional buffer number or current buffer
|
||||
-- @returns language string of buffer
|
||||
-- Gets the language of a given buffer
|
||||
---@param bufnr number? or current buffer
|
||||
---@return string
|
||||
function M.get_buf_lang(bufnr)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
return M.ft_to_lang(api.nvim_buf_get_option(bufnr, "ft"))
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ local EMPTY_ITER = function() end
|
|||
|
||||
M.built_in_query_groups = { "highlights", "locals", "folds", "indents", "injections" }
|
||||
|
||||
--- Creates a function that checks whether a given query exists
|
||||
--- for a specific language.
|
||||
-- Creates a function that checks whether a given query exists
|
||||
-- for a specific language.
|
||||
---@param query string
|
||||
---@return function(string): boolean
|
||||
---@return fun(string): boolean
|
||||
local function get_query_guard(query)
|
||||
return function(lang)
|
||||
return M.has_query_files(lang, query)
|
||||
|
|
@ -49,6 +49,9 @@ do
|
|||
})
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param query_group string
|
||||
---@return any
|
||||
function M.get_matches(bufnr, query_group)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local cached_local = query_cache.get(query_group, bufnr)
|
||||
|
|
@ -94,9 +97,10 @@ do
|
|||
end
|
||||
|
||||
-- cache will auto set the table for each lang if it is nil
|
||||
---@type table<string, table<string, Query>>
|
||||
local cache = setmetatable({}, mt)
|
||||
|
||||
--- Same as `vim.treesitter.query` except will return cached values
|
||||
-- Same as `vim.treesitter.query` except will return cached values
|
||||
---@param lang string
|
||||
---@param query_name string
|
||||
function M.get_query(lang, query_name)
|
||||
|
|
@ -107,12 +111,13 @@ do
|
|||
return cache[lang][query_name]
|
||||
end
|
||||
|
||||
--- Invalidates the query file cache.
|
||||
--- If lang and query_name is both present, will reload for only the lang and query_name.
|
||||
--- If only lang is present, will reload all query_names for that lang
|
||||
--- If none are present, will reload everything
|
||||
---@param lang string
|
||||
---@param query_name string
|
||||
-- Invalidates the query file cache.
|
||||
--
|
||||
-- If lang and query_name is both present, will reload for only the lang and query_name.
|
||||
-- If only lang is present, will reload all query_names for that lang
|
||||
-- If none are present, will reload everything
|
||||
---@param lang? string
|
||||
---@param query_name? string
|
||||
function M.invalidate_query_cache(lang, query_name)
|
||||
if lang and query_name then
|
||||
cache[lang][query_name] = nil
|
||||
|
|
@ -137,7 +142,7 @@ do
|
|||
end
|
||||
end
|
||||
|
||||
--- This function is meant for an autocommand and not to be used. Only use if file is a query file.
|
||||
-- This function is meant for an autocommand and not to be used. Only use if file is a query file.
|
||||
---@param fname string
|
||||
function M.invalidate_query_file(fname)
|
||||
local fnamemodify = vim.fn.fnamemodify
|
||||
|
|
@ -145,14 +150,14 @@ function M.invalidate_query_file(fname)
|
|||
end
|
||||
|
||||
---@class QueryInfo
|
||||
---@field root LanguageTree
|
||||
---@field root TSNode
|
||||
---@field source integer
|
||||
---@field start integer
|
||||
---@field stop integer
|
||||
|
||||
---@param bufnr integer
|
||||
---@param query_name string
|
||||
---@param root LanguageTree
|
||||
---@param root TSNode
|
||||
---@param root_lang string|nil
|
||||
---@return Query|nil, QueryInfo|nil
|
||||
local function prepare_query(bufnr, query_name, root, root_lang)
|
||||
|
|
@ -214,15 +219,21 @@ end
|
|||
---@param end_row integer
|
||||
function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
||||
-- A function that splits a string on '.'
|
||||
local function split(string)
|
||||
---@param to_split string
|
||||
---@return string[]
|
||||
local function split(to_split)
|
||||
local t = {}
|
||||
for str in string.gmatch(string, "([^.]+)") do
|
||||
for str in string.gmatch(to_split, "([^.]+)") do
|
||||
table.insert(t, str)
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
-- Given a path (i.e. a List(String)) this functions inserts value at path
|
||||
---@param object any
|
||||
---@param path string[]
|
||||
---@param value any
|
||||
local function insert_to_path(object, path, value)
|
||||
local curr_obj = object
|
||||
|
||||
|
|
@ -256,6 +267,7 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
end
|
||||
|
||||
-- Add some predicates for testing
|
||||
---@type string[][] ( TODO: make pred type so this can be pred[])
|
||||
local preds = query.info.patterns[pattern]
|
||||
if preds then
|
||||
for _, pred in pairs(preds) do
|
||||
|
|
@ -279,22 +291,22 @@ function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
|||
return iterator
|
||||
end
|
||||
|
||||
--- Return all nodes corresponding to a specific capture path (like @definition.var, @reference.type)
|
||||
---Works like M.get_references or M.get_scopes except you can choose the capture
|
||||
---Can also be a nested capture like @definition.function to get all nodes defining a function.
|
||||
---
|
||||
-- Return all nodes corresponding to a specific capture path (like @definition.var, @reference.type)
|
||||
-- Works like M.get_references or M.get_scopes except you can choose the capture
|
||||
-- Can also be a nested capture like @definition.function to get all nodes defining a function.
|
||||
--
|
||||
---@param bufnr integer the buffer
|
||||
---@param captures string|string[]
|
||||
---@param query_group string the name of query group (highlights or injections for example)
|
||||
---@param root LanguageTree|nil node from where to start the search
|
||||
---@param root TSNode|nil node from where to start the search
|
||||
---@param lang string|nil the language from where to get the captures.
|
||||
--- Root nodes can have several languages.
|
||||
--- Root nodes can have several languages.
|
||||
---@return table|nil
|
||||
function M.get_capture_matches(bufnr, captures, query_group, root, lang)
|
||||
if type(captures) == "string" then
|
||||
captures = { captures }
|
||||
end
|
||||
local strip_captures = {}
|
||||
local strip_captures = {} ---@type string[]
|
||||
for i, capture in ipairs(captures) do
|
||||
if capture:sub(1, 1) ~= "@" then
|
||||
error 'Captures must start with "@"'
|
||||
|
|
@ -342,14 +354,21 @@ function M.iter_captures(bufnr, query_name, root, lang)
|
|||
return wrapped_iter
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param capture_string string
|
||||
---@param query_group string
|
||||
---@param filter_predicate fun(match: table): boolean
|
||||
---@param scoring_function fun(match: table): number
|
||||
---@param root TSNode
|
||||
---@return table|unknown
|
||||
function M.find_best_match(bufnr, capture_string, query_group, filter_predicate, scoring_function, root)
|
||||
if string.sub(capture_string, 1, 1) == "@" then
|
||||
--remove leading "@"
|
||||
capture_string = string.sub(capture_string, 2)
|
||||
end
|
||||
|
||||
local best
|
||||
local best_score
|
||||
local best ---@type table|nil
|
||||
local best_score ---@type number
|
||||
|
||||
for maybe_match in M.iter_group_results(bufnr, query_group, root) do
|
||||
local match = utils.get_at_path(maybe_match, capture_string)
|
||||
|
|
@ -372,8 +391,8 @@ end
|
|||
---Iterates matches from a query file.
|
||||
---@param bufnr integer the buffer
|
||||
---@param query_group string the query file to use
|
||||
---@param root LanguageTree the root node
|
||||
---@param root_lang string|nil the root node lang, if known
|
||||
---@param root TSNode the root node
|
||||
---@param root_lang? string the root node lang, if known
|
||||
function M.iter_group_results(bufnr, query_group, root, root_lang)
|
||||
local query, params = prepare_query(bufnr, query_group, root, root_lang)
|
||||
if not query then
|
||||
|
|
@ -396,13 +415,14 @@ end
|
|||
|
||||
---@alias CaptureResFn function(string, LanguageTree, LanguageTree): string, string
|
||||
|
||||
--- Same as get_capture_matches except this will recursively get matches for every language in the tree.
|
||||
---@param bufnr integer The bufnr
|
||||
-- Same as get_capture_matches except this will recursively get matches for every language in the tree.
|
||||
---@param bufnr integer The buffer
|
||||
---@param capture_or_fn string|CaptureResFn The capture to get. If a function is provided then that
|
||||
--- function will be used to resolve both the capture and query argument.
|
||||
--- The function can return `nil` to ignore that tree.
|
||||
---@param query_type string The query to get the capture from. This is ignore if a function is provided
|
||||
--- for the captuer argument.
|
||||
--- function will be used to resolve both the capture and query argument.
|
||||
--- The function can return `nil` to ignore that tree.
|
||||
---@param query_type string? The query to get the capture from. This is ignored if a function is provided
|
||||
--- for the capture argument.
|
||||
---@return table[]
|
||||
function M.get_capture_matches_recursively(bufnr, capture_or_fn, query_type)
|
||||
---@type CaptureResFn
|
||||
local type_fn
|
||||
|
|
@ -422,7 +442,7 @@ function M.get_capture_matches_recursively(bufnr, capture_or_fn, query_type)
|
|||
local capture, type_ = type_fn(lang, tree, lang_tree)
|
||||
|
||||
if capture then
|
||||
vim.list_extend(matches, M.get_capture_matches(bufnr, capture, type_, tree:root(), lang))
|
||||
vim.list_extend(matches, M.get_capture_matches(bufnr, capture, type_, tree:root(), lang) or {})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,12 +20,17 @@ local function valid_args(name, pred, count, strict_count)
|
|||
return true
|
||||
end
|
||||
|
||||
query.add_predicate("nth?", function(match, pattern, bufnr, pred)
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_predicate("nth?", function(match, _pattern, _bufnr, pred)
|
||||
if not valid_args("nth?", pred, 2, true) then
|
||||
return
|
||||
end
|
||||
|
||||
local node = match[pred[2]]
|
||||
local node = match[pred[2]] ---@type TSNode
|
||||
local n = tonumber(pred[3])
|
||||
if node and node:parent() and node:parent():named_child_count() > n then
|
||||
return node:parent():named_child(n) == node
|
||||
|
|
@ -34,7 +39,12 @@ query.add_predicate("nth?", function(match, pattern, bufnr, pred)
|
|||
return false
|
||||
end)
|
||||
|
||||
local function has_ancestor(match, pattern, bufnr, pred)
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
local function has_ancestor(match, _pattern, _bufnr, pred)
|
||||
if not valid_args(pred[1], pred, 2) then
|
||||
return
|
||||
end
|
||||
|
|
@ -65,7 +75,12 @@ query.add_predicate("has-ancestor?", has_ancestor)
|
|||
|
||||
query.add_predicate("has-parent?", has_ancestor)
|
||||
|
||||
query.add_predicate("is?", function(match, pattern, bufnr, pred)
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_predicate("is?", function(match, _pattern, bufnr, pred)
|
||||
if not valid_args("is?", pred, 2) then
|
||||
return
|
||||
end
|
||||
|
|
@ -84,7 +99,12 @@ query.add_predicate("is?", function(match, pattern, bufnr, pred)
|
|||
return vim.tbl_contains(types, kind)
|
||||
end)
|
||||
|
||||
query.add_predicate("has-type?", function(match, pattern, bufnr, pred)
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_predicate("has-type?", function(match, _pattern, _bufnr, pred)
|
||||
if not valid_args(pred[1], pred, 2) then
|
||||
return
|
||||
end
|
||||
|
|
@ -102,8 +122,14 @@ end)
|
|||
-- Just avoid some annoying warnings for this directive
|
||||
query.add_directive("make-range!", function() end)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _ string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@param metadata table
|
||||
---@return boolean|nil
|
||||
query.add_directive("downcase!", function(match, _, bufnr, pred, metadata)
|
||||
local text, key, value
|
||||
local text, key, value ---@type string|string[], string, string|integer
|
||||
|
||||
if #pred == 3 then
|
||||
-- (#downcase! @capture "key")
|
||||
|
|
@ -129,13 +155,19 @@ query.add_directive("downcase!", function(match, _, bufnr, pred, metadata)
|
|||
end
|
||||
end)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@param metadata table
|
||||
---@return boolean|nil
|
||||
query.add_directive("exclude_children!", function(match, _pattern, _bufnr, pred, metadata)
|
||||
local capture_id = pred[2]
|
||||
local node = match[capture_id]
|
||||
local start_row, start_col, end_row, end_col = node:range()
|
||||
local ranges = {}
|
||||
for i = 0, node:named_child_count() - 1 do
|
||||
local child = node:named_child(i)
|
||||
local child = node:named_child(i) ---@type TSNode
|
||||
local child_start_row, child_start_col, child_end_row, child_end_col = child:range()
|
||||
if child_start_row > start_row or child_start_col > start_col then
|
||||
table.insert(ranges, {
|
||||
|
|
@ -156,6 +188,11 @@ end)
|
|||
|
||||
-- Trim blank lines from end of the region
|
||||
-- Arguments are the captures to trim.
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _ string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@param metadata table
|
||||
query.add_directive("trim!", function(match, _, bufnr, pred, metadata)
|
||||
for _, id in ipairs { select(2, unpack(pred)) } do
|
||||
local node = match[id]
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ local utils = require "nvim-treesitter.utils"
|
|||
|
||||
-- Convert path for cmd.exe on Windows.
|
||||
-- This is needed when vim.opt.shellslash is in use.
|
||||
---@param p string
|
||||
---@return string
|
||||
local function cmdpath(p)
|
||||
if vim.opt.shellslash:get() then
|
||||
local r = p:gsub("/", "\\")
|
||||
|
|
@ -14,6 +16,10 @@ end
|
|||
|
||||
local M = {}
|
||||
|
||||
---@param directory string
|
||||
---@param cwd string
|
||||
---@param info_msg string
|
||||
---@return table
|
||||
function M.select_mkdir_cmd(directory, cwd, info_msg)
|
||||
if fn.has "win32" == 1 then
|
||||
return {
|
||||
|
|
@ -38,6 +44,9 @@ function M.select_mkdir_cmd(directory, cwd, info_msg)
|
|||
end
|
||||
end
|
||||
|
||||
---@param file string
|
||||
---@param info_msg string
|
||||
---@return table
|
||||
function M.select_rm_file_cmd(file, info_msg)
|
||||
if fn.has "win32" == 1 then
|
||||
return {
|
||||
|
|
@ -60,13 +69,17 @@ function M.select_rm_file_cmd(file, info_msg)
|
|||
end
|
||||
end
|
||||
|
||||
---@param executables string[]
|
||||
---@return string|nil
|
||||
function M.select_executable(executables)
|
||||
return vim.tbl_filter(function(c)
|
||||
return vim.tbl_filter(function(c) ---@param c string
|
||||
return c ~= vim.NIL and fn.executable(c) == 1
|
||||
end, executables)[1]
|
||||
end
|
||||
|
||||
---@param repo InstallInfo
|
||||
---@param compiler string
|
||||
---@return string[]
|
||||
function M.select_compiler_args(repo, compiler)
|
||||
if string.match(compiler, "cl$") or string.match(compiler, "cl.exe$") then
|
||||
return {
|
||||
|
|
@ -98,7 +111,7 @@ function M.select_compiler_args(repo, compiler)
|
|||
"-Os",
|
||||
}
|
||||
if
|
||||
#vim.tbl_filter(function(file)
|
||||
#vim.tbl_filter(function(file) ---@param file string
|
||||
local ext = vim.fn.fnamemodify(file, ":e")
|
||||
return ext == "cc" or ext == "cpp" or ext == "cxx"
|
||||
end, repo.files) > 0
|
||||
|
|
@ -186,6 +199,12 @@ function M.select_mv_cmd(from, to, cwd)
|
|||
end
|
||||
end
|
||||
|
||||
---@param repo InstallInfo
|
||||
---@param project_name string
|
||||
---@param cache_folder string
|
||||
---@param revision string|nil
|
||||
---@param prefer_git boolean
|
||||
---@return table
|
||||
function M.select_download_commands(repo, project_name, cache_folder, revision, prefer_git)
|
||||
local can_use_tar = vim.fn.executable "tar" == 1 and vim.fn.executable "curl" == 1
|
||||
local is_github = repo.url:find("github.com", 1, true)
|
||||
|
|
@ -277,6 +296,9 @@ function M.select_download_commands(repo, project_name, cache_folder, revision,
|
|||
end
|
||||
end
|
||||
|
||||
---@param dir string
|
||||
---@param command string
|
||||
---@return string command
|
||||
function M.make_directory_change_for_command(dir, command)
|
||||
if fn.has "win32" == 1 then
|
||||
return string.format("pushd %s & %s & popd", cmdpath(dir), command)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ local function get_node_text(node, bufnr)
|
|||
end
|
||||
|
||||
---@private
|
||||
---@param node TSNode
|
||||
---@param type_patterns string[]
|
||||
---@param transform_fn fun(line: string): string
|
||||
---@param bufnr integer
|
||||
---@return string
|
||||
function M._get_line_for_node(node, type_patterns, transform_fn, bufnr)
|
||||
local node_type = node:type()
|
||||
local is_valid = false
|
||||
|
|
@ -51,7 +56,7 @@ function M._get_line_for_node(node, type_patterns, transform_fn, bufnr)
|
|||
return line:gsub("%%", "%%%%")
|
||||
end
|
||||
|
||||
--- Gets the actual text content of a node
|
||||
-- Gets the actual text content of a node
|
||||
-- @deprecated Use vim.treesitter.query.get_node_text
|
||||
-- @param node the node to get the text from
|
||||
-- @param bufnr the buffer containing the node
|
||||
|
|
@ -64,7 +69,7 @@ function M.get_node_text(node, bufnr)
|
|||
return get_node_text(node, bufnr)
|
||||
end
|
||||
|
||||
--- Determines whether a node is the parent of another
|
||||
-- Determines whether a node is the parent of another
|
||||
-- @param dest the possible parent
|
||||
-- @param source the possible child node
|
||||
function M.is_parent(dest, source)
|
||||
|
|
@ -84,12 +89,12 @@ function M.is_parent(dest, source)
|
|||
return false
|
||||
end
|
||||
|
||||
--- Get next node with same parent
|
||||
-- @param node node
|
||||
-- @param allow_switch_parents allow switching parents if last node
|
||||
-- @param allow_next_parent allow next parent if last node and next parent without children
|
||||
-- Get next node with same parent
|
||||
---@param node TSNode
|
||||
---@param allow_switch_parents? boolean allow switching parents if last node
|
||||
---@param allow_next_parent? boolean allow next parent if last node and next parent without children
|
||||
function M.get_next_node(node, allow_switch_parents, allow_next_parent)
|
||||
local destination_node
|
||||
local destination_node ---@type TSNode
|
||||
local parent = node:parent()
|
||||
|
||||
if not parent then
|
||||
|
|
@ -116,12 +121,12 @@ function M.get_next_node(node, allow_switch_parents, allow_next_parent)
|
|||
return destination_node
|
||||
end
|
||||
|
||||
--- Get previous node with same parent
|
||||
-- @param node node
|
||||
-- @param allow_switch_parents allow switching parents if first node
|
||||
-- @param allow_previous_parent allow previous parent if first node and previous parent without children
|
||||
-- Get previous node with same parent
|
||||
---@param node TSNode
|
||||
---@param allow_switch_parents? boolean allow switching parents if first node
|
||||
---@param allow_previous_parent? boolean allow previous parent if first node and previous parent without children
|
||||
function M.get_previous_node(node, allow_switch_parents, allow_previous_parent)
|
||||
local destination_node
|
||||
local destination_node ---@type TSNode
|
||||
local parent = node:parent()
|
||||
if not parent then
|
||||
return
|
||||
|
|
@ -148,7 +153,7 @@ function M.get_previous_node(node, allow_switch_parents, allow_previous_parent)
|
|||
end
|
||||
|
||||
function M.get_named_children(node)
|
||||
local nodes = {}
|
||||
local nodes = {} ---@type TSNode[]
|
||||
for i = 0, node:named_child_count() - 1, 1 do
|
||||
nodes[i + 1] = node:named_child(i)
|
||||
end
|
||||
|
|
@ -166,7 +171,7 @@ function M.get_node_at_cursor(winnr, ignore_injected_langs)
|
|||
return
|
||||
end
|
||||
|
||||
local root
|
||||
local root ---@type TSNode|nil
|
||||
if ignore_injected_langs then
|
||||
for _, tree in ipairs(root_lang_tree:trees()) do
|
||||
local tree_root = tree:root()
|
||||
|
|
@ -209,6 +214,9 @@ function M.get_root_for_position(line, col, root_lang_tree)
|
|||
return nil, nil, lang_tree
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param node TSNode
|
||||
---@return TSNode result
|
||||
function M.get_root_for_node(node)
|
||||
local parent = node
|
||||
local result = node
|
||||
|
|
@ -228,12 +236,17 @@ function M.highlight_node(node, buf, hl_namespace, hl_group)
|
|||
M.highlight_range({ node:range() }, buf, hl_namespace, hl_group)
|
||||
end
|
||||
|
||||
--- Get a compatible vim range (1 index based) from a TS node range.
|
||||
-- Get a compatible vim range (1 index based) from a TS node range.
|
||||
--
|
||||
-- TS nodes start with 0 and the end col is ending exclusive.
|
||||
-- They also treat a EOF/EOL char as a char ending in the first
|
||||
-- col of the next row.
|
||||
---comment
|
||||
---@param range integer[]
|
||||
---@param buf integer|nil
|
||||
---@return integer, integer, integer, integer
|
||||
function M.get_vim_range(range, buf)
|
||||
---@type integer, integer, integer, integer
|
||||
local srow, scol, erow, ecol = unpack(range)
|
||||
srow = srow + 1
|
||||
scol = scol + 1
|
||||
|
|
@ -253,7 +266,9 @@ function M.get_vim_range(range, buf)
|
|||
end
|
||||
|
||||
function M.highlight_range(range, buf, hl_namespace, hl_group)
|
||||
---@type integer, integer, integer, integer
|
||||
local start_row, start_col, end_row, end_col = unpack(range)
|
||||
---@diagnostic disable-next-line: missing-parameter
|
||||
vim.highlight.range(buf, hl_namespace, hl_group, { start_row, start_col }, { end_row, end_col })
|
||||
end
|
||||
|
||||
|
|
@ -288,13 +303,15 @@ function M.update_selection(buf, node, selection_mode)
|
|||
end
|
||||
|
||||
-- Byte length of node range
|
||||
---@param node TSNode
|
||||
---@return number
|
||||
function M.node_length(node)
|
||||
local _, _, start_byte = node:start()
|
||||
local _, _, end_byte = node:end_()
|
||||
return end_byte - start_byte
|
||||
end
|
||||
|
||||
--- @deprecated Use `vim.treesitter.is_in_node_range()` instead
|
||||
---@deprecated Use `vim.treesitter.is_in_node_range()` instead
|
||||
function M.is_in_node_range(node, line, col)
|
||||
vim.notify_once(
|
||||
"nvim-treesitter.ts_utils.is_in_node_range is deprecated: use vim.treesitter.is_in_node_range",
|
||||
|
|
@ -303,7 +320,7 @@ function M.is_in_node_range(node, line, col)
|
|||
return ts.is_in_node_range(node, line, col)
|
||||
end
|
||||
|
||||
--- @deprecated Use `vim.treesitter.get_node_range()` instead
|
||||
---@deprecated Use `vim.treesitter.get_node_range()` instead
|
||||
function M.get_node_range(node_or_range)
|
||||
vim.notify_once(
|
||||
"nvim-treesitter.ts_utils.get_node_range is deprecated: use vim.treesitter.get_node_range",
|
||||
|
|
@ -312,6 +329,8 @@ function M.get_node_range(node_or_range)
|
|||
return ts.get_node_range(node_or_range)
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return table
|
||||
function M.node_to_lsp_range(node)
|
||||
local start_line, start_col, end_line, end_col = ts.get_node_range(node)
|
||||
local rtn = {}
|
||||
|
|
@ -320,16 +339,18 @@ function M.node_to_lsp_range(node)
|
|||
return rtn
|
||||
end
|
||||
|
||||
--- Memoizes a function based on the buffer tick of the provided bufnr.
|
||||
-- Memoizes a function based on the buffer tick of the provided bufnr.
|
||||
-- The cache entry is cleared when the buffer is detached to avoid memory leaks.
|
||||
-- @param fn: the fn to memoize, taking the bufnr as first argument
|
||||
-- @param options:
|
||||
-- The options argument is a table with two optional values:
|
||||
-- - bufnr: extracts a bufnr from the given arguments.
|
||||
-- - key: extracts the cache key from the given arguments.
|
||||
-- @returns a memoized function
|
||||
---@param fn function the fn to memoize, taking the buffer as first argument
|
||||
---@param options? {bufnr: integer?, key: string|fun(...): string?} the memoization options
|
||||
---@return function: a memoized function
|
||||
function M.memoize_by_buf_tick(fn, options)
|
||||
options = options or {}
|
||||
|
||||
---@type table<string, {result: any, last_tick: integer}>
|
||||
local cache = {}
|
||||
local bufnr_fn = utils.to_func(options.bufnr or utils.identity)
|
||||
local key_fn = utils.to_func(options.key or utils.identity)
|
||||
|
|
@ -424,6 +445,7 @@ function M.goto_node(node, goto_end, avoid_set_jump)
|
|||
utils.set_jump()
|
||||
end
|
||||
local range = { M.get_vim_range { node:range() } }
|
||||
---@type table<number>
|
||||
local position
|
||||
if not goto_end then
|
||||
position = { range[1], range[2] }
|
||||
|
|
|
|||
|
|
@ -5,12 +5,15 @@ local luv = vim.loop
|
|||
local M = {}
|
||||
|
||||
-- Wrapper around vim.notify with common options set.
|
||||
---@param msg string
|
||||
---@param log_level number|nil
|
||||
---@param opts table|nil
|
||||
function M.notify(msg, log_level, opts)
|
||||
local default_opts = { title = "nvim-treesitter" }
|
||||
vim.notify(msg, log_level, vim.tbl_extend("force", default_opts, opts or {}))
|
||||
end
|
||||
|
||||
-- Returns the system specific path separator.
|
||||
-- Returns the system-specific path separator.
|
||||
---@return string
|
||||
function M.get_path_sep()
|
||||
return (fn.has "win32" == 1 and not vim.opt.shellslash:get()) and "\\" or "/"
|
||||
|
|
@ -18,10 +21,13 @@ end
|
|||
|
||||
-- Returns a function that joins the given arguments with separator. Arguments
|
||||
-- can't be nil. Example:
|
||||
--
|
||||
--[[
|
||||
print(M.generate_join(" ")("foo", "bar"))
|
||||
print(M.generate_join(" ")("foo", "bar"))
|
||||
--]]
|
||||
-- prints "foo bar"
|
||||
--prints "foo bar"
|
||||
---@param separator string
|
||||
---@return fun(...: string): string
|
||||
function M.generate_join(separator)
|
||||
return function(...)
|
||||
return table.concat({ ... }, separator)
|
||||
|
|
@ -32,13 +38,18 @@ M.join_path = M.generate_join(M.get_path_sep())
|
|||
|
||||
M.join_space = M.generate_join " "
|
||||
|
||||
--- Define user defined vim command which calls nvim-treesitter module function
|
||||
--- - If module name is 'mod', it should be defined in hierarchy 'nvim-treesitter.mod'
|
||||
--- - A table with name 'commands' should be defined in 'mod' which needs to be passed as
|
||||
--- the commands param of this function
|
||||
---
|
||||
---@param mod string, Name of the module that resides in the hierarchy - nvim-treesitter.module
|
||||
---@param commands table, Command list for the module
|
||||
---@class Command
|
||||
---@field run function
|
||||
---@field f_args string
|
||||
---@field args string
|
||||
|
||||
-- Define user defined vim command which calls nvim-treesitter module function
|
||||
-- - If module name is 'mod', it should be defined in hierarchy 'nvim-treesitter.mod'
|
||||
-- - A table with name 'commands' should be defined in 'mod' which needs to be passed as
|
||||
-- the commands param of this function
|
||||
--
|
||||
---@param mod string Name of the module that resides in the hierarchy - nvim-treesitter.module
|
||||
---@param commands table<string, Command> Command list for the module
|
||||
--- - {command_name} Name of the vim user defined command, Keys:
|
||||
--- - {run}: (function) callback function that needs to be executed
|
||||
--- - {f_args}: (string, default <f-args>)
|
||||
|
|
@ -46,7 +57,7 @@ M.join_space = M.generate_join " "
|
|||
--- - {args}: (string, optional)
|
||||
--- - vim command attributes
|
||||
---
|
||||
---Example:
|
||||
---* @example
|
||||
--- If module is nvim-treesitter.custom_mod
|
||||
--- <pre>
|
||||
--- M.commands = {
|
||||
|
|
@ -136,18 +147,22 @@ function M.get_site_dir()
|
|||
end
|
||||
|
||||
-- Gets a property at path
|
||||
-- @param tbl the table to access
|
||||
-- @param path the '.' separated path
|
||||
-- @returns the value at path or nil
|
||||
---@param tbl table the table to access
|
||||
---@param path string the '.' separated path
|
||||
---@return table|nil result the value at path or nil
|
||||
function M.get_at_path(tbl, path)
|
||||
if path == "" then
|
||||
return tbl
|
||||
end
|
||||
|
||||
local segments = vim.split(path, ".", true)
|
||||
---@type table[]|table
|
||||
local result = tbl
|
||||
|
||||
for _, segment in ipairs(segments) do
|
||||
if type(result) == "table" then
|
||||
---@type table
|
||||
-- TODO: figure out the actual type of tbl
|
||||
result = result[segment]
|
||||
end
|
||||
end
|
||||
|
|
@ -159,17 +174,9 @@ function M.set_jump()
|
|||
vim.cmd "normal! m'"
|
||||
end
|
||||
|
||||
function M.index_of(tbl, obj)
|
||||
for i, o in ipairs(tbl) do
|
||||
if o == obj then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Filters a list based on the given predicate
|
||||
-- @param tbl The list to filter
|
||||
-- @param predicate The predicate to filter with
|
||||
---@param tbl any[] The list to filter
|
||||
---@param predicate fun(v:any, i:number):boolean The predicate to filter with
|
||||
function M.filter(tbl, predicate)
|
||||
local result = {}
|
||||
|
||||
|
|
@ -184,8 +191,9 @@ end
|
|||
|
||||
-- Returns a list of all values from the first list
|
||||
-- that are not present in the second list.
|
||||
-- @params tbl1 The first table
|
||||
-- @params tbl2 The second table
|
||||
---@param tbl1 any[] The first table
|
||||
---@param tbl2 any[] The second table
|
||||
---@return table
|
||||
function M.difference(tbl1, tbl2)
|
||||
return M.filter(tbl1, function(v)
|
||||
return not vim.tbl_contains(tbl2, v)
|
||||
|
|
@ -196,12 +204,19 @@ function M.identity(a)
|
|||
return a
|
||||
end
|
||||
|
||||
-- Returns a function returning the given value
|
||||
---@param a any
|
||||
---@return fun():any
|
||||
function M.constant(a)
|
||||
return function()
|
||||
return a
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns a function that returns the given value if it is a function,
|
||||
-- otherwise returns a function that returns the given value.
|
||||
---@param a any
|
||||
---@return fun(...):any
|
||||
function M.to_func(a)
|
||||
return type(a) == "function" and a or M.constant(a)
|
||||
end
|
||||
|
|
@ -209,7 +224,10 @@ end
|
|||
---@return string|nil
|
||||
function M.ts_cli_version()
|
||||
if fn.executable "tree-sitter" == 1 then
|
||||
local handle = io.popen "tree-sitter -V"
|
||||
local handle = io.popen "tree-sitter -V"
|
||||
if not handle then
|
||||
return
|
||||
end
|
||||
local result = handle:read "*a"
|
||||
handle:close()
|
||||
return vim.split(result, "\n")[1]:match "[^tree%psitter ].*"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
-- Execute as `nvim --headless -c "luafile ./scripts/update-readme.lua"`
|
||||
|
||||
---@class Parser
|
||||
---@field name string
|
||||
---@field parser ParserInfo
|
||||
|
||||
local parsers = require("nvim-treesitter.parsers").get_parser_configs()
|
||||
local sorted_parsers = {}
|
||||
|
||||
|
|
@ -6,12 +11,15 @@ for k, v in pairs(parsers) do
|
|||
table.insert(sorted_parsers, { name = k, parser = v })
|
||||
end
|
||||
|
||||
---@param a Parser
|
||||
---@param b Parser
|
||||
table.sort(sorted_parsers, function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
|
||||
local generated_text = ""
|
||||
|
||||
---@param v Parser
|
||||
for _, v in ipairs(sorted_parsers) do
|
||||
local link = "[" .. (v.parser.readme_name or v.name) .. "](" .. v.parser.install_info.url .. ")"
|
||||
|
||||
|
|
@ -41,7 +49,7 @@ local new_readme_text = string.gsub(
|
|||
)
|
||||
vim.fn.writefile(vim.fn.split(new_readme_text, "\n"), "README.md")
|
||||
|
||||
if string.find(readme_text, generated_text, 1, "plain") then
|
||||
if string.find(readme_text, generated_text, 1, true) then
|
||||
print "README.md is up-to-date!"
|
||||
vim.cmd "q"
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
-- Execute as `nvim --headless -c "luafile ./scripts/write-lockfile.lua"`
|
||||
|
||||
---@type string|any[]
|
||||
local skip_langs = vim.fn.getenv "SKIP_LOCKFILE_UPDATE_FOR_LANGS"
|
||||
|
||||
if skip_langs == vim.NIL then
|
||||
skip_langs = {}
|
||||
else
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
skip_langs = vim.fn.split(skip_langs, ",")
|
||||
end
|
||||
|
||||
print("Skipping languages: " .. vim.inspect(skip_langs))
|
||||
require("nvim-treesitter.install").write_lockfile("verbose", skip_langs)
|
||||
vim.cmd "q"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue