diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index d3bdb4a3..69930a95 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -17,6 +17,31 @@ local open = require "nvim-tree.actions.tree.open" local events = require "nvim-tree.events" local notify = require "nvim-tree.notify" +---@class ParentNode +---@field name string + +---@class BaseNode +---@field absolute_path string +---@field executable boolean +---@field fs_stat uv_fs_t +---@field git_status GitStatus|nil +---@field hidden boolean +---@field name string +---@field parent DirNode +---@field type string +---@field watcher function|nil + +---@class DirNode: BaseNode +---@field has_children boolean +---@field group_next Node|nil +---@field nodes Node[] +---@field open boolean + +---@class FileNode: BaseNode +---@field extension string + +---@alias Node ParentNode|DirNode|FileNode + local _config = {} local M = { @@ -79,6 +104,7 @@ function M.change_root(path, bufnr) change_dir.fn(vim.fn.fnamemodify(path, ":p:h")) end +---@param cwd string|nil function M.open_replacing_current_buffer(cwd) if view.is_visible() then return @@ -159,10 +185,13 @@ function M.place_cursor_on_node() end end +---@return table function M.get_config() return M.config end +---@param disable_netrw boolean +---@param hijack_netrw boolean local function manage_netrw(disable_netrw, hijack_netrw) if hijack_netrw then vim.cmd "silent! autocmd! FileExplorer *" @@ -174,6 +203,7 @@ local function manage_netrw(disable_netrw, hijack_netrw) end end +---@param name string|nil function M.change_dir(name) change_dir.fn(name) @@ -182,6 +212,7 @@ function M.change_dir(name) end end +---@param opts table local function setup_autocommands(opts) local augroup_id = vim.api.nvim_create_augroup("NvimTree", { clear = true }) local function create_nvim_tree_autocmd(name, custom_opts) @@ -677,9 +708,15 @@ local ACCEPTED_STRINGS = { }, } +---@param conf table local function validate_options(conf) local msg + ---@param user any + ---@param def any + ---@param strs table + ---@param types table + ---@param prefix string local function validate(user, def, strs, types, prefix) -- if user's option is not a table there is nothing to do if type(user) ~= "table" then @@ -762,6 +799,7 @@ function M.purge_all_state() end end +---@param conf table|nil function M.setup(conf) if vim.fn.has "nvim-0.8" == 0 then notify.warn "nvim-tree.lua requires Neovim 0.8 or higher" diff --git a/lua/nvim-tree/actions/finders/search-node.lua b/lua/nvim-tree/actions/finders/search-node.lua index 23cb1c68..10a97f4a 100644 --- a/lua/nvim-tree/actions/finders/search-node.lua +++ b/lua/nvim-tree/actions/finders/search-node.lua @@ -4,6 +4,9 @@ local find_file = require("nvim-tree.actions.finders.find-file").fn local M = {} +---@param search_dir string|nil +---@param input_path string +---@return string|nil local function search(search_dir, input_path) local realpaths_searched = {} @@ -11,6 +14,8 @@ local function search(search_dir, input_path) return end + ---@param dir string + ---@return string|nil local function iter(dir) local realpath, path, name, stat, handle, _ diff --git a/lua/nvim-tree/actions/fs/copy-paste.lua b/lua/nvim-tree/actions/fs/copy-paste.lua index 8953cd32..66739eb9 100644 --- a/lua/nvim-tree/actions/fs/copy-paste.lua +++ b/lua/nvim-tree/actions/fs/copy-paste.lua @@ -20,6 +20,10 @@ local clipboard = { copy = {}, } +---@param source string +---@param destination string +---@return boolean +---@return string|nil local function do_copy(source, destination) local source_stats, handle local success, errmsg @@ -81,6 +85,12 @@ local function do_copy(source, destination) return true end +---@param source string +---@param dest string +---@param action_type string +---@param action_fn fun(source: string, dest: string) +---@return boolean|nil -- success +---@return string|nil -- error message local function do_single_paste(source, dest, action_type, action_fn) local dest_stats local success, errmsg, errcode @@ -140,6 +150,8 @@ local function do_single_paste(source, dest, action_type, action_fn) end end +---@param node Node +---@param clip table local function toggle(node, clip) if node.name == ".." then return @@ -147,7 +159,8 @@ local function toggle(node, clip) local notify_node = notify.render_path(node.absolute_path) if utils.array_remove(clip, node) then - return notify.info(notify_node .. " removed from clipboard.") + notify.info(notify_node .. " removed from clipboard.") + return end table.insert(clip, node) @@ -161,18 +174,23 @@ function M.clear_clipboard() renderer.draw() end +---@param node Node function M.copy(node) utils.array_remove(clipboard.cut, node) toggle(node, clipboard.copy) renderer.draw() end +---@param node Node function M.cut(node) utils.array_remove(clipboard.copy, node) toggle(node, clipboard.cut) renderer.draw() end +---@param node Node +---@param action_type string +---@param action_fn fun(source: string, dest: string) local function do_paste(node, action_type, action_fn) node = lib.get_last_group_node(node) if node.name == ".." then @@ -202,10 +220,14 @@ local function do_paste(node, action_type, action_fn) clipboard[action_type] = {} if not M.config.filesystem_watchers.enable then - return reloaders.reload_explorer() + reloaders.reload_explorer() end end +---@param source string +---@param destination string +---@return boolean +---@return string? local function do_cut(source, destination) log.line("copy_paste", "do_cut '%s' -> '%s'", source, destination) @@ -225,12 +247,13 @@ local function do_cut(source, destination) return true end +---@param node Node function M.paste(node) if clipboard.cut[1] ~= nil then - return do_paste(node, "cut", do_cut) + do_paste(node, "cut", do_cut) + else + do_paste(node, "copy", do_copy) end - - return do_paste(node, "copy", do_copy) end function M.print_clipboard() @@ -248,9 +271,10 @@ function M.print_clipboard() end end - return notify.info(table.concat(content, "\n") .. "\n") + notify.info(table.concat(content, "\n") .. "\n") end +---@param content string local function copy_to_clipboard(content) local clipboard_name if M.config.actions.use_system_clipboard == true then @@ -264,28 +288,30 @@ local function copy_to_clipboard(content) end vim.api.nvim_exec_autocmds("TextYankPost", {}) - return notify.info(string.format("Copied %s to %s clipboard!", content, clipboard_name)) + notify.info(string.format("Copied %s to %s clipboard!", content, clipboard_name)) end +---@param node Node function M.copy_filename(node) - return copy_to_clipboard(node.name) + copy_to_clipboard(node.name) end +---@param node Node function M.copy_path(node) local absolute_path = node.absolute_path local relative_path = utils.path_relative(absolute_path, core.get_cwd()) local content = node.nodes ~= nil and utils.path_add_trailing(relative_path) or relative_path - return copy_to_clipboard(content) + copy_to_clipboard(content) end function M.copy_absolute_path(node) local absolute_path = node.absolute_path local content = node.nodes ~= nil and utils.path_add_trailing(absolute_path) or absolute_path - return copy_to_clipboard(content) + copy_to_clipboard(content) end ----Clipboard text highlight group and position when highlight_clipboard. ----@param node table +--- Clipboard text highlight group and position when highlight_clipboard. +---@param node Node ---@return HL_POSITION position none when clipboard empty ---@return string|nil group only when node present in clipboard function M.get_highlight(node) diff --git a/lua/nvim-tree/actions/fs/create-file.lua b/lua/nvim-tree/actions/fs/create-file.lua index 37ae4147..4f5df22d 100644 --- a/lua/nvim-tree/actions/fs/create-file.lua +++ b/lua/nvim-tree/actions/fs/create-file.lua @@ -8,6 +8,7 @@ local find_file = require("nvim-tree.actions.finders.find-file").fn local M = {} +---@param file string local function create_and_notify(file) events._dispatch_will_create_file(file) local ok, fd = pcall(vim.loop.fs_open, file, "w", 420) @@ -19,6 +20,8 @@ local function create_and_notify(file) events._dispatch_file_created(file) end +---@param iter function iterable +---@return integer local function get_num_nodes(iter) local i = 0 for _ in iter do @@ -27,6 +30,8 @@ local function get_num_nodes(iter) return i end +---@param node Node +---@return string local function get_containing_folder(node) if node.nodes ~= nil then return utils.path_add_trailing(node.absolute_path) @@ -35,6 +40,7 @@ local function get_containing_folder(node) return node.absolute_path:sub(0, -node_name_size - 1) end +---@param node Node|nil function M.fn(node) node = node and lib.get_last_group_node(node) if not node or node.name == ".." then diff --git a/lua/nvim-tree/actions/fs/remove-file.lua b/lua/nvim-tree/actions/fs/remove-file.lua index 4053a842..c1e11467 100644 --- a/lua/nvim-tree/actions/fs/remove-file.lua +++ b/lua/nvim-tree/actions/fs/remove-file.lua @@ -8,6 +8,7 @@ local M = { config = {}, } +---@param windows table local function close_windows(windows) -- Prevent from closing when the win count equals 1 or 2, -- where the win to remove could be the last opened. @@ -23,6 +24,7 @@ local function close_windows(windows) end end +---@param absolute_path string local function clear_buffer(absolute_path) local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 } for _, buf in pairs(bufs) do @@ -44,10 +46,13 @@ local function clear_buffer(absolute_path) end end +---@param cwd string +---@return boolean|nil local function remove_dir(cwd) local handle = vim.loop.fs_scandir(cwd) if type(handle) == "string" then - return notify.error(handle) + notify.error(handle) + return end while true do @@ -75,20 +80,22 @@ local function remove_dir(cwd) end --- Remove a node, notify errors, dispatch events ---- @param node table +---@param node Node function M.remove(node) local notify_node = notify.render_path(node.absolute_path) if node.nodes ~= nil and not node.link_to then local success = remove_dir(node.absolute_path) if not success then - return notify.error("Could not remove " .. notify_node) + notify.error("Could not remove " .. notify_node) + return end events._dispatch_folder_removed(node.absolute_path) else events._dispatch_will_remove_file(node.absolute_path) local success = vim.loop.fs_unlink(node.absolute_path) if not success then - return notify.error("Could not remove " .. notify_node) + notify.error("Could not remove " .. notify_node) + return end events._dispatch_file_removed(node.absolute_path) clear_buffer(node.absolute_path) @@ -96,6 +103,7 @@ function M.remove(node) notify.info(notify_node .. " was properly removed.") end +---@param node Node function M.fn(node) if node.name == ".." then return diff --git a/lua/nvim-tree/actions/fs/rename-file.lua b/lua/nvim-tree/actions/fs/rename-file.lua index 4c304d04..b458cd99 100644 --- a/lua/nvim-tree/actions/fs/rename-file.lua +++ b/lua/nvim-tree/actions/fs/rename-file.lua @@ -20,6 +20,8 @@ local function err_fmt(from, to, reason) return string.format("Cannot rename %s -> %s: %s", from, to, reason) end +---@param node Node +---@param to string function M.rename(node, to) local notify_from = notify.render_path(node.absolute_path) local notify_to = notify.render_path(to) @@ -32,13 +34,16 @@ function M.rename(node, to) events._dispatch_will_rename_node(node.absolute_path, to) local success, err = vim.loop.fs_rename(node.absolute_path, to) if not success then - return notify.warn(err_fmt(notify_from, notify_to, err)) + notify.warn(err_fmt(notify_from, notify_to, err)) + return end notify.info(string.format("%s -> %s", notify_from, notify_to)) utils.rename_loaded_buffers(node.absolute_path, to) events._dispatch_node_renamed(node.absolute_path, to) end +---@param default_modifier string|nil +---@return fun(node: Node, modifier: string) function M.fn(default_modifier) default_modifier = default_modifier or ":t" @@ -53,7 +58,8 @@ function M.fn(default_modifier) -- support for only specific modifiers have been implemented if not ALLOWED_MODIFIERS[modifier] then - return notify.warn("Modifier " .. vim.inspect(modifier) .. " is not in allowed list : " .. table.concat(ALLOWED_MODIFIERS, ",")) + notify.warn("Modifier " .. vim.inspect(modifier) .. " is not in allowed list : " .. table.concat(ALLOWED_MODIFIERS, ",")) + return end node = lib.get_last_group_node(node) diff --git a/lua/nvim-tree/actions/fs/trash.lua b/lua/nvim-tree/actions/fs/trash.lua index 41bc8ba0..82449bd2 100644 --- a/lua/nvim-tree/actions/fs/trash.lua +++ b/lua/nvim-tree/actions/fs/trash.lua @@ -8,6 +8,7 @@ local M = { local utils = require "nvim-tree.utils" local events = require "nvim-tree.events" +---@param absolute_path string local function clear_buffer(absolute_path) local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 } for _, buf in pairs(bufs) do @@ -24,6 +25,7 @@ local function clear_buffer(absolute_path) end end +---@param node Node function M.remove(node) local binary = M.config.trash.cmd:gsub(" .*$", "") if vim.fn.executable(binary) == 0 then @@ -76,6 +78,7 @@ function M.remove(node) end end +---@param node Node function M.fn(node) if node.name == ".." then return diff --git a/lua/nvim-tree/actions/moves/item.lua b/lua/nvim-tree/actions/moves/item.lua index 837fdd00..15c1bc83 100644 --- a/lua/nvim-tree/actions/moves/item.lua +++ b/lua/nvim-tree/actions/moves/item.lua @@ -6,6 +6,9 @@ local explorer_node = require "nvim-tree.explorer.node" local M = {} +---@param where string +---@param what string +---@return fun() function M.fn(where, what) return function() local node_cur = lib.get_node_at_cursor() diff --git a/lua/nvim-tree/actions/moves/parent.lua b/lua/nvim-tree/actions/moves/parent.lua index 61bce43a..598483eb 100644 --- a/lua/nvim-tree/actions/moves/parent.lua +++ b/lua/nvim-tree/actions/moves/parent.lua @@ -6,6 +6,8 @@ local lib = require "nvim-tree.lib" local M = {} +---@param should_close boolean|nil +---@return fun(node: Node): boolean|nil function M.fn(should_close) should_close = should_close or false diff --git a/lua/nvim-tree/actions/moves/sibling.lua b/lua/nvim-tree/actions/moves/sibling.lua index 6a051a88..16e95ba8 100644 --- a/lua/nvim-tree/actions/moves/sibling.lua +++ b/lua/nvim-tree/actions/moves/sibling.lua @@ -4,6 +4,8 @@ local Iterator = require "nvim-tree.iterators.node-iterator" local M = {} +---@param direction string +---@return fun(node: Node): nil function M.fn(direction) return function(node) if node.name == ".." or not direction then diff --git a/lua/nvim-tree/actions/node/file-popup.lua b/lua/nvim-tree/actions/node/file-popup.lua index 3bcc8012..1ce70fe2 100644 --- a/lua/nvim-tree/actions/node/file-popup.lua +++ b/lua/nvim-tree/actions/node/file-popup.lua @@ -2,6 +2,8 @@ local utils = require "nvim-tree.utils" local M = {} +---@param node Node +---@return table local function get_formatted_lines(node) local stats = node.fs_stat local fpath = " fullpath: " .. node.absolute_path @@ -21,6 +23,7 @@ end local current_popup = nil +---@param node Node local function setup_window(node) local lines = get_formatted_lines(node) @@ -52,6 +55,7 @@ function M.close_popup() end end +---@param node Node function M.toggle_file_info(node) if node.name == ".." then return diff --git a/lua/nvim-tree/actions/node/open-file.lua b/lua/nvim-tree/actions/node/open-file.lua index 7d08a349..576f5f59 100644 --- a/lua/nvim-tree/actions/node/open-file.lua +++ b/lua/nvim-tree/actions/node/open-file.lua @@ -14,7 +14,7 @@ local function get_user_input_char() return vim.fn.nr2char(c) end ----Get all windows in the current tabpage that aren't NvimTree. +--- Get all windows in the current tabpage that aren't NvimTree. ---@return table with valid win_ids local function usable_win_ids() local tabpage = vim.api.nvim_get_current_tabpage() @@ -302,6 +302,8 @@ local function edit_in_current_buf(filename) vim.cmd("keepalt keepjumps edit " .. vim.fn.fnameescape(filename)) end +---@param mode string +---@param filename string function M.fn(mode, filename) if type(mode) ~= "string" then mode = "" diff --git a/lua/nvim-tree/actions/node/run-command.lua b/lua/nvim-tree/actions/node/run-command.lua index 453475f6..5d0c7ee3 100644 --- a/lua/nvim-tree/actions/node/run-command.lua +++ b/lua/nvim-tree/actions/node/run-command.lua @@ -6,6 +6,8 @@ local M = {} ---Retrieves the absolute path to the node. ---Safely handles the node representing the current directory ---(the topmost node in the nvim-tree window) +---@param node Node +---@return string local function get_node_path(node) if node.name == ".." then return utils.path_remove_trailing(core.get_cwd()) @@ -14,6 +16,7 @@ local function get_node_path(node) end end +---@param node Node function M.run_file_command(node) local node_path = get_node_path(node) vim.api.nvim_input(": " .. node_path .. "") diff --git a/lua/nvim-tree/actions/node/system-open.lua b/lua/nvim-tree/actions/node/system-open.lua index 6c12d186..fa3a9d84 100644 --- a/lua/nvim-tree/actions/node/system-open.lua +++ b/lua/nvim-tree/actions/node/system-open.lua @@ -3,6 +3,7 @@ local utils = require "nvim-tree.utils" local M = {} +---@param node Node function M.fn(node) if #M.config.system_open.cmd == 0 then require("nvim-tree.utils").notify.warn "Cannot open file with system application. Unrecognized platform." diff --git a/lua/nvim-tree/actions/reloaders/reloaders.lua b/lua/nvim-tree/actions/reloaders/reloaders.lua index ffa7d073..a343012c 100644 --- a/lua/nvim-tree/actions/reloaders/reloaders.lua +++ b/lua/nvim-tree/actions/reloaders/reloaders.lua @@ -8,6 +8,9 @@ local Iterator = require "nvim-tree.iterators.node-iterator" local M = {} +---@param node Node +---@param projects table +---@param unloaded_bufnr number|nil local function refresh_nodes(node, projects, unloaded_bufnr) Iterator.builder({ node }) :applier(function(n) @@ -22,6 +25,8 @@ local function refresh_nodes(node, projects, unloaded_bufnr) :iterate() end +---@param parent_node table +---@param projects table function M.reload_node_status(parent_node, projects) local toplevel = git.get_toplevel(parent_node.absolute_path) local status = projects[toplevel] or {} diff --git a/lua/nvim-tree/actions/root/change-dir.lua b/lua/nvim-tree/actions/root/change-dir.lua index 0e667330..642160f3 100644 --- a/lua/nvim-tree/actions/root/change-dir.lua +++ b/lua/nvim-tree/actions/root/change-dir.lua @@ -6,6 +6,8 @@ local M = { current_tab = vim.api.nvim_get_current_tabpage(), } +---@param name string +---@return string local function clean_input_cwd(name) name = vim.fn.fnameescape(name) local root_parent_cwd = vim.fn.fnamemodify(utils.path_remove_trailing(core.get_cwd()), ":h") @@ -16,17 +18,23 @@ local function clean_input_cwd(name) end end +---@param new_tabpage integer +---@return boolean local function is_window_event(new_tabpage) local is_event_scope_window = vim.v.event.scope == "window" or vim.v.event.changed_window return is_event_scope_window and new_tabpage == M.current_tab end +---@param foldername string +---@return boolean local function prevent_cwd_change(foldername) local is_same_cwd = foldername == core.get_cwd() local is_restricted_above = M.options.restrict_above_cwd and foldername < vim.fn.getcwd(-1, -1) return is_same_cwd or is_restricted_above end +---@param input_cwd string +---@param with_open boolean|nil function M.fn(input_cwd, with_open) if not core.get_explorer() then return @@ -46,6 +54,8 @@ function M.fn(input_cwd, with_open) M.force_dirchange(foldername, with_open) end +---@param global boolean +---@param path string local function cd(global, path) vim.cmd((global and "cd " or "lcd ") .. vim.fn.fnameescape(path)) end @@ -54,6 +64,8 @@ local function should_change_dir() return M.options.enable and vim.tbl_isempty(vim.v.event) end +---@param f function +---@return fun(foldername: string, should_open_view: boolean|nil) local function add_profiling_to(f) return function(foldername, should_open_view) local profile = log.profile_start("change dir %s", foldername) diff --git a/lua/nvim-tree/actions/root/dir-up.lua b/lua/nvim-tree/actions/root/dir-up.lua index 439baa8c..4333d7ea 100644 --- a/lua/nvim-tree/actions/root/dir-up.lua +++ b/lua/nvim-tree/actions/root/dir-up.lua @@ -3,13 +3,14 @@ local core = require "nvim-tree.core" local M = {} +---@param node Node function M.fn(node) if not node or node.name == ".." then - return require("nvim-tree.actions.root.change-dir").fn ".." + require("nvim-tree.actions.root.change-dir").fn ".." else local newdir = vim.fn.fnamemodify(utils.path_remove_trailing(core.get_cwd()), ":h") require("nvim-tree.actions.root.change-dir").fn(newdir) - return require("nvim-tree.actions.finders.find-file").fn(node.absolute_path) + require("nvim-tree.actions.finders.find-file").fn(node.absolute_path) end end diff --git a/lua/nvim-tree/actions/tree-modifiers/collapse-all.lua b/lua/nvim-tree/actions/tree-modifiers/collapse-all.lua index d11cd78d..c6add436 100644 --- a/lua/nvim-tree/actions/tree-modifiers/collapse-all.lua +++ b/lua/nvim-tree/actions/tree-modifiers/collapse-all.lua @@ -6,6 +6,7 @@ local Iterator = require "nvim-tree.iterators.node-iterator" local M = {} +---@return fun(path: string): boolean local function buf_match() local buffer_paths = vim.tbl_map(function(buffer) return vim.api.nvim_buf_get_name(buffer) @@ -22,6 +23,7 @@ local function buf_match() end end +---@param keep_buffers boolean function M.fn(keep_buffers) local node = lib.get_node_at_cursor() local explorer = core.get_explorer() diff --git a/lua/nvim-tree/actions/tree-modifiers/expand-all.lua b/lua/nvim-tree/actions/tree-modifiers/expand-all.lua index 30ecd86d..6afc030d 100644 --- a/lua/nvim-tree/actions/tree-modifiers/expand-all.lua +++ b/lua/nvim-tree/actions/tree-modifiers/expand-all.lua @@ -57,6 +57,7 @@ local function gen_iterator() end end +---@param base_node table function M.fn(base_node) local node = base_node.nodes and base_node or core.get_explorer() if gen_iterator()(node) then diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index 0b8df43f..7d7573fc 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -30,6 +30,7 @@ local Api = { --- Do nothing when setup not called. --- f function to invoke +---@param f function local function wrap(f) return function(...) if vim.g.NvimTreeSetup == 1 then @@ -162,6 +163,8 @@ Api.fs.copy.absolute_path = wrap_node(require("nvim-tree.actions.fs.copy-paste") Api.fs.copy.filename = wrap_node(require("nvim-tree.actions.fs.copy-paste").copy_filename) Api.fs.copy.relative_path = wrap_node(require("nvim-tree.actions.fs.copy-paste").copy_path) +---@param mode string +---@param node table local function edit(mode, node) local path = node.absolute_path if node.link_to and not node.nodes then @@ -170,6 +173,8 @@ local function edit(mode, node) require("nvim-tree.actions.node.open-file").fn(mode, path) end +---@param mode string +---@return fun(node: table) local function open_or_expand_or_dir_up(mode) return function(node) if node.name == ".." then diff --git a/lua/nvim-tree/core.lua b/lua/nvim-tree/core.lua index a109c995..f6b959d2 100644 --- a/lua/nvim-tree/core.lua +++ b/lua/nvim-tree/core.lua @@ -9,6 +9,7 @@ local M = {} TreeExplorer = nil local first_init_done = false +---@param foldername string function M.init(foldername) local profile = log.profile_start("core init %s", foldername) @@ -23,14 +24,17 @@ function M.init(foldername) log.profile_end(profile) end +---@return table function M.get_explorer() return TreeExplorer end +---@return string function M.get_cwd() return TreeExplorer.absolute_path end +---@return integer function M.get_nodes_starting_line() local offset = 1 if view.is_root_folder_visible(M.get_cwd()) then diff --git a/lua/nvim-tree/diagnostics.lua b/lua/nvim-tree/diagnostics.lua index c1d783a7..93c68963 100644 --- a/lua/nvim-tree/diagnostics.lua +++ b/lua/nvim-tree/diagnostics.lua @@ -12,6 +12,7 @@ local severity_levels = { Hint = 4, } +---@return table local function from_nvim_lsp() local buffer_severity = {} @@ -36,10 +37,14 @@ local function from_nvim_lsp() return buffer_severity end +---@param severity integer +---@param config table +---@return boolean local function is_severity_in_range(severity, config) return config.max <= severity and severity <= config.min end +---@return table local function from_coc() if vim.g.coc_service_initialized ~= 1 then return {} diff --git a/lua/nvim-tree/events.lua b/lua/nvim-tree/events.lua index d2efe2d4..4ab74932 100644 --- a/lua/nvim-tree/events.lua +++ b/lua/nvim-tree/events.lua @@ -21,16 +21,22 @@ M.Event = { TreeRendered = "TreeRendered", } +---@param event_name string +---@return table local function get_handlers(event_name) return global_handlers[event_name] or {} end +---@param event_name string +---@param handler function function M.subscribe(event_name, handler) local handlers = get_handlers(event_name) table.insert(handlers, handler) global_handlers[event_name] = handlers end +---@param event_name string +---@param payload table|nil local function dispatch(event_name, payload) for _, handler in pairs(get_handlers(event_name)) do local success, error = pcall(handler, payload) diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index a8326599..0385949d 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -11,10 +11,17 @@ local Watcher = require "nvim-tree.watcher" local M = {} +---@param type_ string|nil +---@param cwd string +---@return any local function get_type_from(type_, cwd) return type_ or (vim.loop.fs_stat(cwd) or {}).type end +---@param handle uv_fs_t +---@param cwd string +---@param node Node +---@param git_status table local function populate_children(handle, cwd, node, git_status) local node_ignored = explorer_node.is_git_ignored(node) local nodes_by_path = utils.bool_record(node.nodes, "absolute_path") @@ -53,6 +60,9 @@ local function populate_children(handle, cwd, node, git_status) end end +---@param node Node +---@param status table +---@return Node[]|nil function M.explore(node, status) local cwd = node.link_to or node.absolute_path local handle = vim.loop.fs_scandir(cwd) diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index 4e332c79..54913242 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -61,10 +61,14 @@ local function buf(path, bufinfo, unloaded_bufnr) return true end +---@param path string +---@return boolean local function dotfile(path) return M.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "." end +---@param path string +---@return boolean local function custom(path) if not M.config.filter_custom then return false diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index a47ac4d7..a0cfe186 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -7,11 +7,16 @@ local M = {} M.explore = require("nvim-tree.explorer.explore").explore M.reload = require("nvim-tree.explorer.reload").reload +---@class Explorer: BaseNode local Explorer = {} Explorer.__index = Explorer +---@param cwd string|nil +---@return Explorer function Explorer.new(cwd) cwd = vim.loop.fs_realpath(cwd or vim.loop.cwd()) + + ---@class Explorer local explorer = setmetatable({ absolute_path = cwd, nodes = {}, @@ -22,12 +27,15 @@ function Explorer.new(cwd) return explorer end +---@private +---@param node Node function Explorer:_load(node) local cwd = node.link_to or node.absolute_path local git_status = git.load_project_status(cwd) M.explore(node, git_status) end +---@param node Node function Explorer:expand(node) self:_load(node) end diff --git a/lua/nvim-tree/explorer/node-builders.lua b/lua/nvim-tree/explorer/node-builders.lua index c96fe580..b6687279 100644 --- a/lua/nvim-tree/explorer/node-builders.lua +++ b/lua/nvim-tree/explorer/node-builders.lua @@ -3,6 +3,10 @@ local watch = require "nvim-tree.explorer.watch" local M = {} +---@param parent table +---@param absolute_path string +---@param name string +---@return Node function M.folder(parent, absolute_path, name) local handle = vim.loop.fs_scandir(absolute_path) local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil @@ -25,8 +29,8 @@ function M.folder(parent, absolute_path, name) end --- path is an executable file or directory ---- @param absolute_path string ---- @return boolean +---@param absolute_path string +---@return boolean|nil function M.is_executable(absolute_path) if utils.is_windows or utils.is_wsl then --- executable detection on windows is buggy and not performant hence it is disabled @@ -36,6 +40,10 @@ function M.is_executable(absolute_path) end end +---@param parent table +---@param absolute_path string +---@param name string +---@return Node function M.file(parent, absolute_path, name) local ext = string.match(name, ".?[^.]+%.(.*)") or "" @@ -55,6 +63,10 @@ end -- links (for instance libr2.so in /usr/lib) and thus even with a C program realpath fails -- when it has no real reason to. Maybe there is a reason, but errno is definitely wrong. -- So we need to check for link_to ~= nil when adding new links to the main tree +---@param parent table +---@param absolute_path string +---@param name string +---@return Node function M.link(parent, absolute_path, name) --- I dont know if this is needed, because in my understanding, there isn't hard links in windows, but just to be sure i changed it. local link_to = vim.loop.fs_realpath(absolute_path) diff --git a/lua/nvim-tree/explorer/node.lua b/lua/nvim-tree/explorer/node.lua index 3a84e6e7..a10cdeeb 100644 --- a/lua/nvim-tree/explorer/node.lua +++ b/lua/nvim-tree/explorer/node.lua @@ -1,14 +1,14 @@ local M = {} --- node.git_status structure: --- { --- file = string | nil, --- dir = { --- direct = { string } | nil, --- indirect = { string } | nil, --- } | nil, --- } +---@class GitStatus +---@field file string|nil +---@field dir table|nil + +---@param parent_ignored boolean +---@param status table|nil +---@param absolute_path string +---@return GitStatus|nil local function get_dir_git_status(parent_ignored, status, absolute_path) if parent_ignored then return { file = "!!" } @@ -25,15 +25,24 @@ local function get_dir_git_status(parent_ignored, status, absolute_path) end end +---@param parent_ignored boolean +---@param status table +---@param absolute_path string +---@return GitStatus local function get_git_status(parent_ignored, status, absolute_path) local file_status = parent_ignored and "!!" or status.files and status.files[absolute_path] return { file = file_status } end +---@param node Node +---@return boolean function M.has_one_child_folder(node) - return #node.nodes == 1 and node.nodes[1].nodes and vim.loop.fs_access(node.nodes[1].absolute_path, "R") + return #node.nodes == 1 and node.nodes[1].nodes and vim.loop.fs_access(node.nodes[1].absolute_path, "R") or false end +---@param node Node +---@param parent_ignored boolean +---@param status table|nil function M.update_git_status(node, parent_ignored, status) local get_status if node.nodes then @@ -51,6 +60,8 @@ function M.update_git_status(node, parent_ignored, status) end end +---@param node Node +---@return GitStatus|nil function M.get_git_status(node) local git_status = node and node.git_status if not git_status then @@ -112,10 +123,13 @@ function M.get_git_status(node) end end +---@param node Node +---@return boolean function M.is_git_ignored(node) - return node and node.git_status and node.git_status.file == "!!" + return node and node.git_status ~= nil and node.git_status.file == "!!" end +---@param node Node function M.node_destroy(node) if not node then return diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index cd1aa458..07e3f24b 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -12,6 +12,10 @@ local Watcher = require "nvim-tree.watcher" local M = {} +---@param nodes_by_path table +---@param node_ignored boolean +---@param status table +---@return fun(node: Node): table local function update_status(nodes_by_path, node_ignored, status) return function(node) if nodes_by_path[node.absolute_path] then @@ -21,6 +25,8 @@ local function update_status(nodes_by_path, node_ignored, status) end end +---@param path string +---@param callback fun(toplevel: string|nil, project: table|nil) local function reload_and_get_git_project(path, callback) local toplevel = git.get_toplevel(path) @@ -29,6 +35,9 @@ local function reload_and_get_git_project(path, callback) end) end +---@param node Node +---@param project table|nil +---@param root string|nil local function update_parent_statuses(node, project, root) while project and node do -- step up to the containing project @@ -58,6 +67,9 @@ local function update_parent_statuses(node, project, root) end end +---@param node Node +---@param git_status table +---@param unloaded_bufnr number|nil function M.reload(node, git_status, unloaded_bufnr) local cwd = node.link_to or node.absolute_path local handle = vim.loop.fs_scandir(cwd) @@ -165,7 +177,7 @@ function M.reload(node, git_status, unloaded_bufnr) end ---Refresh contents and git status for a single node ----@param node table +---@param node Node ---@param callback function function M.refresh_node(node, callback) if type(node) ~= "table" then diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index f2a259bc..109b96e6 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -1,10 +1,11 @@ local M = {} +---@type table[string, fun(a: node, b: node): boolean] local C = {} --- Predefined comparator, defaulting to name ---- @param sorter string as per options ---- @return function +---@param sorter string as per options +---@return function local function get_comparator(sorter) return C[sorter] or C.name end @@ -41,6 +42,11 @@ local function folders_or_files_first(a, b) end end +---@param t table +---@param first number +---@param mid number +---@param last number +---@param comparator fun(a: table, b: table): boolean local function merge(t, first, mid, last, comparator) local n1 = mid - first + 1 local n2 = last - mid @@ -74,6 +80,10 @@ local function merge(t, first, mid, last, comparator) end end +---@param t table +---@param first number +---@param last number +---@param comparator fun(a: table, b: table): boolean local function split_merge(t, first, last, comparator) if (last - first) < 1 then return @@ -137,6 +147,10 @@ function M.sort(t) end end +---@param a table +---@param b table +---@param ignorecase boolean|nil +---@return boolean local function node_comparator_name_ignorecase_or_not(a, b, ignorecase) if not (a and b) then return true diff --git a/lua/nvim-tree/explorer/watch.lua b/lua/nvim-tree/explorer/watch.lua index cbebe3b1..b9922ad0 100644 --- a/lua/nvim-tree/explorer/watch.lua +++ b/lua/nvim-tree/explorer/watch.lua @@ -7,6 +7,8 @@ local M = { uid = 0, } +---@param path string +---@return boolean local function is_git(path) -- If $GIT_DIR is set, consider its value to be equivalent to '.git'. -- Expand $GIT_DIR (and `path`) to a full path (see :help filename-modifiers), since @@ -29,6 +31,8 @@ local IGNORED_PATHS = { "/dev", } +---@param path string +---@return boolean local function is_folder_ignored(path) for _, folder in ipairs(IGNORED_PATHS) do if vim.startswith(path, folder) then @@ -45,6 +49,8 @@ local function is_folder_ignored(path) return false end +---@param node Node +---@return Watcher|nil function M.create_watcher(node) if not M.config.filesystem_watchers.enable or type(node) ~= "table" then return nil diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index d2c180c9..1175d245 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -29,6 +29,10 @@ local WATCHED_FILES = { "index", -- staging area } +--- @param toplevel string|nil +--- @param path string|nil +--- @param project table +--- @param git_status table|nil local function reload_git_status(toplevel, path, project, git_status) if path then for p in pairs(project.files) do @@ -118,6 +122,7 @@ function M.reload_project(toplevel, path, callback) end --- Retrieve a known project +--- @param toplevel string|nil --- @return table|nil project function M.get_project(toplevel) return M._projects_by_toplevel[toplevel] diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index dfcc3123..a3c5d107 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -2,12 +2,16 @@ local log = require "nvim-tree.log" local utils = require "nvim-tree.utils" local notify = require "nvim-tree.notify" +---@class Runner local Runner = {} Runner.__index = Runner local timeouts = 0 local MAX_TIMEOUTS = 5 +---@private +---@param status string +---@param path string|nil function Runner:_parse_status_output(status, path) -- replacing slashes if on windows if vim.fn.has "win32" == 1 then @@ -18,6 +22,10 @@ function Runner:_parse_status_output(status, path) end end +---@private +---@param prev_output string +---@param incoming string +---@return string function Runner:_handle_incoming_data(prev_output, incoming) if incoming and utils.str_find(incoming, "\n") then local prev = prev_output .. incoming @@ -46,12 +54,15 @@ function Runner:_handle_incoming_data(prev_output, incoming) end for line in prev_output:gmatch "[^\n]*\n" do - self._parse_status_output(line) + self:_parse_status_output(line) end return "" end +---@param stdout_handle uv_pipe_t +---@param stderr_handle uv_pipe_t +---@return table function Runner:_getopts(stdout_handle, stderr_handle) local untracked = self.list_untracked and "-u" or nil local ignored = (self.list_untracked and self.list_ignored) and "--ignored=matching" or "--ignored=no" @@ -62,6 +73,7 @@ function Runner:_getopts(stdout_handle, stderr_handle) } end +---@param output string function Runner:_log_raw_output(output) if log.enabled "git" and output and type(output) == "string" then log.raw("git", "%s", output) @@ -69,12 +81,17 @@ function Runner:_log_raw_output(output) end end +---@param callback function|nil function Runner:_run_git_job(callback) local handle, pid local stdout = vim.loop.new_pipe(false) local stderr = vim.loop.new_pipe(false) local timer = vim.loop.new_timer() + if stdout == nil or stderr == nil or timer == nil then + return + end + local function on_finish(rc) self.rc = rc or 0 if timer:is_closing() or stdout:is_closing() or stderr:is_closing() or (handle and handle:is_closing()) then @@ -151,6 +168,7 @@ function Runner:_wait() end end +---@param opts table function Runner:_finalise(opts) if self.rc == -1 then log.line("git", "job timed out %s %s", opts.toplevel, opts.path) diff --git a/lua/nvim-tree/git/utils.lua b/lua/nvim-tree/git/utils.lua index e088be6b..53969712 100644 --- a/lua/nvim-tree/git/utils.lua +++ b/lua/nvim-tree/git/utils.lua @@ -6,9 +6,9 @@ local M = { } --- Retrieve the git toplevel directory ---- @param cwd string path ---- @return string|nil toplevel absolute path ---- @return string|nil git_dir absolute path +---@param cwd string path +---@return string|nil toplevel absolute path +---@return string|nil git_dir absolute path function M.get_toplevel(cwd) local profile = log.profile_start("git toplevel git_dir %s", cwd) @@ -60,6 +60,8 @@ end local untracked = {} +---@param cwd string +---@return string|nil function M.should_show_untracked(cwd) if untracked[cwd] ~= nil then return untracked[cwd] @@ -85,6 +87,9 @@ local function nil_insert(t, k) return t end +---@param status table +---@param cwd string|nil +---@return table function M.file_status_to_dir_status(status, cwd) local direct = {} for p, s in pairs(status) do diff --git a/lua/nvim-tree/help.lua b/lua/nvim-tree/help.lua index c7342be5..2f2c9d8c 100644 --- a/lua/nvim-tree/help.lua +++ b/lua/nvim-tree/help.lua @@ -19,8 +19,8 @@ local M = { } --- Shorten and normalise a vim command lhs ---- @param lhs string ---- @return string +---@param lhs string +---@return string local function tidy_lhs(lhs) -- nvim_buf_get_keymap replaces leading "<" with "" e.g. "CTRL-v>" lhs = lhs:gsub("^", "<") @@ -43,15 +43,15 @@ end --- Remove prefix 'nvim-tree: ' --- Hardcoded to keep default_on_attach simple ---- @param desc string ---- @return string +---@param desc string +---@return string local function tidy_desc(desc) return desc and desc:gsub("^nvim%-tree: ", "") or "" end --- sort vim command lhs roughly as per :help index ---- @param a string ---- @param b string +---@param a string +---@param b string local function sort_lhs(a, b) -- mouse first if a:match(PAT_MOUSE) and not b:match(PAT_MOUSE) then @@ -79,9 +79,9 @@ local function sort_lhs(a, b) end --- Compute all lines for the buffer ---- @return table strings of text ---- @return table arrays of arguments 3-6 for nvim_buf_add_highlight() ---- @return number maximum length of text +---@return table strings of text +---@return table arrays of arguments 3-6 for nvim_buf_add_highlight() +---@return number maximum length of text local function compute() local head_lhs = "nvim-tree mappings" local head_rhs1 = "exit: q" diff --git a/lua/nvim-tree/iterators/node-iterator.lua b/lua/nvim-tree/iterators/node-iterator.lua index c1cf722f..8cd4abde 100644 --- a/lua/nvim-tree/iterators/node-iterator.lua +++ b/lua/nvim-tree/iterators/node-iterator.lua @@ -1,6 +1,9 @@ +---@class NodeIterator local NodeIterator = {} NodeIterator.__index = NodeIterator +---@param nodes Node[] +---@return NodeIterator function NodeIterator.builder(nodes) return setmetatable({ nodes = nodes, @@ -15,6 +18,7 @@ function NodeIterator.builder(nodes) }, NodeIterator) end +---@return NodeIterator function NodeIterator:hidden() self._filter_hidden = function(_) return true @@ -22,21 +26,29 @@ function NodeIterator:hidden() return self end +---@param f fun(node: Node): boolean +---@return NodeIterator function NodeIterator:matcher(f) self._match = f return self end +---@param f fun(node: Node, i: number) +---@return NodeIterator function NodeIterator:applier(f) self._apply_fn_on_node = f return self end +---@param f fun(node: Node): any +---@return NodeIterator function NodeIterator:recursor(f) self._recurse_with = f return self end +---@return Node|nil +---@return number|nil function NodeIterator:iterate() local iteration_count = 0 local function iter(nodes) diff --git a/lua/nvim-tree/keymap.lua b/lua/nvim-tree/keymap.lua index 72a9c2fe..dfe6b40f 100644 --- a/lua/nvim-tree/keymap.lua +++ b/lua/nvim-tree/keymap.lua @@ -1,8 +1,8 @@ local M = {} --- Apply mappings to a scratch buffer and return buffer local mappings ---- @param fn function(bufnr) on_attach or default_on_attach ---- @return table as per vim.api.nvim_buf_get_keymap +---@param fn function(bufnr) on_attach or default_on_attach +---@return table as per vim.api.nvim_buf_get_keymap local function generate_keymap(fn) -- create an unlisted scratch buffer local scratch_bufnr = vim.api.nvim_create_buf(false, true) @@ -93,10 +93,12 @@ function M.default_on_attach(bufnr) end -- stylua: ignore end +---@return table function M.get_keymap() return generate_keymap(M.on_attach) end +---@return table function M.get_keymap_default() return generate_keymap(M.default_on_attach) end diff --git a/lua/nvim-tree/lib.lua b/lua/nvim-tree/lib.lua index 9f0a2c45..ff14afd4 100644 --- a/lua/nvim-tree/lib.lua +++ b/lua/nvim-tree/lib.lua @@ -13,6 +13,7 @@ local M = { target_winid = nil, } +---@return Node|nil function M.get_node_at_cursor() if not core.get_explorer() then return @@ -34,8 +35,8 @@ function M.get_node_at_cursor() end ---Create a sanitized partial copy of a node, populating children recursively. ----@param node table ----@return table|nil cloned node +---@param node Node +---@return Node|nil cloned node local function clone_node(node) if not node then node = core.get_explorer() @@ -68,11 +69,14 @@ local function clone_node(node) end ---Api.tree.get_nodes +---@return Node[]|nil function M.get_nodes() return clone_node(core.get_explorer()) end -- If node is grouped, return the last node in the group. Otherwise, return the given node. +---@param node Node +---@return Node function M.get_last_group_node(node) local next_node = node while next_node.group_next do @@ -81,6 +85,8 @@ function M.get_last_group_node(node) return next_node end +---@param node Node +---@return Node[] function M.get_all_nodes_in_group(node) local next_node = utils.get_parent_of_group(node) local nodes = {} @@ -91,6 +97,7 @@ function M.get_all_nodes_in_group(node) return nodes end +---@param node Node function M.expand_or_collapse(node) if node.has_children then node.has_children = false @@ -144,6 +151,11 @@ local function should_hijack_current_buf() return should_hijack_dir or should_hijack_unnamed end +---@param prompt_input string +---@param prompt_select string +---@param items_short string[] +---@param items_long string[] +---@param callback fun(item_short: string) function M.prompt(prompt_input, prompt_select, items_short, items_long, callback) local function format_item(short) for i, s in ipairs(items_short) do diff --git a/lua/nvim-tree/live-filter.lua b/lua/nvim-tree/live-filter.lua index 6e510cba..27333a55 100644 --- a/lua/nvim-tree/live-filter.lua +++ b/lua/nvim-tree/live-filter.lua @@ -53,6 +53,7 @@ local function matches(node) return vim.regex(M.filter):match_str(name) ~= nil end +---@param node_ Node|nil function M.apply_filter(node_) if not M.filter or M.filter == "" then reset_filter(node_) diff --git a/lua/nvim-tree/marks/bulk-delete.lua b/lua/nvim-tree/marks/bulk-delete.lua index 7a9cb5a0..74a28ef7 100644 --- a/lua/nvim-tree/marks/bulk-delete.lua +++ b/lua/nvim-tree/marks/bulk-delete.lua @@ -9,7 +9,7 @@ local M = { } --- Delete nodes; each removal will be optionally notified ---- @param nodes table +--- @param nodes Node[] local function do_delete(nodes) for _, node in pairs(nodes) do remove_file.remove(node) diff --git a/lua/nvim-tree/marks/bulk-trash.lua b/lua/nvim-tree/marks/bulk-trash.lua index 532fb021..6dd6cef0 100644 --- a/lua/nvim-tree/marks/bulk-trash.lua +++ b/lua/nvim-tree/marks/bulk-trash.lua @@ -9,7 +9,7 @@ local M = { } --- Delete nodes; each removal will be optionally notified ---- @param nodes table +--- @param nodes Node[] local function do_trash(nodes) for _, node in pairs(nodes) do remove_file.remove(node) diff --git a/lua/nvim-tree/marks/init.lua b/lua/nvim-tree/marks/init.lua index 7b5773a6..867801fb 100644 --- a/lua/nvim-tree/marks/init.lua +++ b/lua/nvim-tree/marks/init.lua @@ -4,18 +4,21 @@ local NvimTreeMarks = {} local M = {} +---@param node Node local function add_mark(node) NvimTreeMarks[node.absolute_path] = node renderer.draw() end +---@param node Node local function remove_mark(node) NvimTreeMarks[node.absolute_path] = nil renderer.draw() end +---@param node Node function M.toggle_mark(node) if node.absolute_path == nil then return @@ -36,10 +39,13 @@ function M.clear_marks() renderer.draw() end +---@param node Node +---@return table|nil function M.get_mark(node) return NvimTreeMarks[node.absolute_path] end +---@return table function M.get_marks() local list = {} for _, node in pairs(NvimTreeMarks) do diff --git a/lua/nvim-tree/marks/navigation.lua b/lua/nvim-tree/marks/navigation.lua index 8a20b211..8ee3edbc 100644 --- a/lua/nvim-tree/marks/navigation.lua +++ b/lua/nvim-tree/marks/navigation.lua @@ -5,6 +5,9 @@ local open_file = require "nvim-tree.actions.node.open-file" local utils = require "nvim-tree.utils" local lib = require "nvim-tree.lib" +---@param node table +---@param where string +---@return Node|nil local function get_nearest(node, where) local first, prev, next, last = nil, nil, nil, nil local found = false @@ -47,12 +50,16 @@ local function get_nearest(node, where) end end +---@param where string +---@param node table|nil +---@return Node|nil local function get(where, node) if node then return get_nearest(node, where) end end +---@param node table|nil local function open_or_focus(node) if node and not node.nodes and not utils.get_win_buf_from_path(node.absolute_path) then open_file.fn("edit", node.absolute_path) @@ -61,6 +68,8 @@ local function open_or_focus(node) end end +---@param where string +---@return function local function navigate_to(where) return function() local node = lib.get_node_at_cursor() diff --git a/lua/nvim-tree/modified.lua b/lua/nvim-tree/modified.lua index 51025e1b..8f77ef66 100644 --- a/lua/nvim-tree/modified.lua +++ b/lua/nvim-tree/modified.lua @@ -23,7 +23,7 @@ function M.reload() end end ----@param node table +---@param node Node ---@return boolean function M.is_modified(node) return M.config.enable diff --git a/lua/nvim-tree/notify.lua b/lua/nvim-tree/notify.lua index 1a81b3c1..03f7d6de 100644 --- a/lua/nvim-tree/notify.lua +++ b/lua/nvim-tree/notify.lua @@ -6,6 +6,7 @@ local config = { } local title_support +---@return boolean function M.supports_title() if title_support == nil then title_support = (package.loaded.notify and (vim.notify == require "notify" or vim.notify == require("notify").notify)) @@ -48,6 +49,8 @@ do end end +---@param path string +---@return string function M.render_path(path) if config.absolute_path then return path diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index 637117fc..ef3c50ae 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -11,10 +11,15 @@ M.is_wsl = vim.fn.has "wsl" == 1 -- false for WSL M.is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1 +---@param haystack string +---@param needle string +---@return boolean function M.str_find(haystack, needle) return vim.fn.stridx(haystack, needle) ~= -1 end +---@param path string +---@return string|uv_fs_t function M.read_file(path) local fd = vim.loop.fs_open(path, "r", 438) if not fd then @@ -30,15 +35,19 @@ function M.read_file(path) end local path_separator = package.config:sub(1, 1) +---@param paths string[] +---@return string function M.path_join(paths) return table.concat(vim.tbl_map(M.path_remove_trailing, paths), path_separator) end +---@param path string +---@return fun(): string function M.path_split(path) return path:gmatch("[^" .. path_separator .. "]+" .. path_separator .. "?") end ----Get the basename of the given path. +--- Get the basename of the given path. ---@param path string ---@return string function M.path_basename(path) @@ -50,7 +59,7 @@ function M.path_basename(path) return path:sub(i + 1, #path) end ----Get a path relative to another path. +--- Get a path relative to another path. ---@param path string ---@param relative_to string ---@return string @@ -66,6 +75,8 @@ function M.path_relative(path, relative_to) return p end +---@param path string +---@return string function M.path_add_trailing(path) if path:sub(-1) == path_separator then return path @@ -74,6 +85,8 @@ function M.path_add_trailing(path) return path .. path_separator end +---@param path string +---@return string function M.path_remove_trailing(path) local p, _ = path:gsub(path_separator .. "$", "") return p @@ -81,10 +94,12 @@ end M.path_separator = path_separator --- get the node and index of the node from the tree that matches the predicate. --- The explored nodes are those displayed on the view. --- @param nodes list of node --- @param fn function(node): boolean +--- Get the node and index of the node from the tree that matches the predicate. +--- The explored nodes are those displayed on the view. +---@param nodes Node[] +---@param fn fun(node: Node): boolean +---@return table|nil +---@return number function M.find_node(nodes, fn) local node, i = Iterator.builder(nodes) :matcher(fn) @@ -99,6 +114,9 @@ end -- get the node in the tree state depending on the absolute path of the node -- (grouped or hidden too) +---@param path string +---@return Node|nil +---@return number|nil function M.get_node_from_path(path) local explorer = require("nvim-tree.core").get_explorer() @@ -127,7 +145,9 @@ function M.get_node_from_path(path) :iterate() end --- get the highest parent of grouped nodes +--- Get the highest parent of grouped nodes +---@param node_ Node +---@return table function M.get_parent_of_group(node_) local node = node_ while node.parent and node.parent.group_next do @@ -136,9 +156,9 @@ function M.get_parent_of_group(node_) return node end --- return visible nodes indexed by line --- @param nodes_all list of node --- @param line_start first index +--- Return visible nodes indexed by line +---@param nodes_all Node[] +---@param line_start number ---@return table function M.get_nodes_by_line(nodes_all, line_start) local nodes_by_line = {} @@ -208,9 +228,9 @@ function M.canonical_path(path) return path end --- Escapes special characters in string if windows else returns unmodified string. --- @param path string --- @return path +--- Escapes special characters in string if windows else returns unmodified string. +---@param path string +---@return string|nil function M.escape_special_chars(path) if path == nil then return path @@ -218,10 +238,10 @@ function M.escape_special_chars(path) return M.is_windows and path:gsub("%(", "\\("):gsub("%)", "\\)") or path end --- Create empty sub-tables if not present --- @param tbl to create empty inside of --- @param path dot separated string of sub-tables --- @return table deepest sub-table +--- Create empty sub-tables if not present +---@param tbl table to create empty inside of +---@param path string dot separated string of sub-tables +---@return table deepest sub-table function M.table_create_missing(tbl, path) local t = tbl for s in string.gmatch(path, "([^%.]+)%.*") do @@ -395,7 +415,7 @@ end ---Focus node passed as parameter if visible, otherwise focus first visible parent. ---If none of the parents is visible focus root. ---If node is nil do nothing. ----@param node table|nil node to focus +---@param node Node|nil node to focus function M.focus_node_or_parent(node) local explorer = require("nvim-tree.core").get_explorer() @@ -417,6 +437,9 @@ function M.focus_node_or_parent(node) end end +---@param path string +---@return integer|nil +---@return integer|nil function M.get_win_buf_from_path(path) for _, w in pairs(vim.api.nvim_tabpage_list_wins(0)) do local b = vim.api.nvim_win_get_buf(w) @@ -433,7 +456,9 @@ function M.clear_prompt() end end --- return a new table with values from array +--- Return a new table with values from array +---@param array table +---@return table function M.array_shallow_clone(array) local to = {} for _, v in ipairs(array) do @@ -443,9 +468,9 @@ function M.array_shallow_clone(array) end --- Remove and return item from array if present. ---- @param array table ---- @param item any ---- @return any|nil removed +---@param array table +---@param item any +---@return any|nil removed function M.array_remove(array, item) if not array then return nil @@ -458,20 +483,24 @@ function M.array_remove(array, item) end end +---@param array table +---@return table function M.array_remove_nils(array) return vim.tbl_filter(function(v) return v ~= nil end, array) end +---@param f fun(node: Node|nil) +---@return function function M.inject_node(f) return function() f(require("nvim-tree.lib").get_node_at_cursor()) end end ----Is the buffer named NvimTree_[0-9]+ a tree? filetype is "NvimTree" or not readable file. ----This is cheap, as the readable test should only ever be needed when resuming a vim session. +--- Is the buffer named NvimTree_[0-9]+ a tree? filetype is "NvimTree" or not readable file. +--- This is cheap, as the readable test should only ever be needed when resuming a vim session. ---@param bufnr number|nil may be 0 or nil for current ---@return boolean function M.is_nvim_tree_buf(bufnr) diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 2b54df6a..98c86017 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -236,6 +236,7 @@ function M.close() end end +---@param options table|nil function M.open(options) if M.is_visible() then return @@ -297,6 +298,7 @@ function M.grow_from_content() end end +---@param size string|number|nil function M.resize(size) if M.View.float.enable and not M.View.adaptive_size then -- if the floating windows's adaptive size is not desired, then the @@ -386,6 +388,7 @@ function M.abandon_all_windows() end end +---@param opts table|nil function M.is_visible(opts) if opts and opts.tabpage then if M.View.tabpages[opts.tabpage] == nil then @@ -407,12 +410,15 @@ function M.is_visible(opts) return M.get_winnr() ~= nil and vim.api.nvim_win_is_valid(M.get_winnr()) end +---@param opts table|nil function M.set_cursor(opts) if M.is_visible() then pcall(vim.api.nvim_win_set_cursor, M.get_winnr(), opts) end end +---@param winnr number|nil +---@param open_if_closed boolean|nil function M.focus(winnr, open_if_closed) local wnr = winnr or M.get_winnr() @@ -450,6 +456,8 @@ function M.get_bufnr() return BUFNR_PER_TAB[vim.api.nvim_get_current_tabpage()] end +---@param bufnr number +---@return boolean function M.is_buf_valid(bufnr) return bufnr and vim.api.nvim_buf_is_valid(bufnr) and vim.api.nvim_buf_is_loaded(bufnr) end @@ -497,6 +505,8 @@ function M._prevent_buffer_override() end) end +---@param cwd string|nil +---@return boolean function M.is_root_folder_visible(cwd) return cwd ~= "/" and not M.View.hide_root_folder end diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index 1693aa0f..92b3fbe4 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -6,11 +6,13 @@ local M = { config = {}, } +---@class Event local Event = { _events = {}, } Event.__index = Event +---@class Watcher local Watcher = { _watchers = {}, } @@ -23,6 +25,8 @@ local FS_EVENT_FLAGS = { recursive = false, } +---@param path string +---@return Event|nil function Event:new(path) log.line("watcher", "Event:new '%s'", path) @@ -40,6 +44,7 @@ function Event:new(path) end end +---@return boolean function Event:start() log.line("watcher", "Event:start '%s'", self._path) @@ -84,10 +89,12 @@ function Event:start() return true end +---@param listener function function Event:add(listener) table.insert(self._listeners, listener) end +---@param listener function function Event:remove(listener) utils.array_remove(self._listeners, listener) if #self._listeners == 0 then @@ -95,6 +102,7 @@ function Event:remove(listener) end end +---@param message string|nil function Event:destroy(message) log.line("watcher", "Event:destroy '%s'", self._path) @@ -115,6 +123,11 @@ function Event:destroy(message) self.destroyed = true end +---@param path string +---@param files string[]|nil +---@param callback function +---@param data table +---@return Watcher|nil function Watcher:new(path, files, callback, data) log.line("watcher", "Watcher:new '%s' %s", path, vim.inspect(files)) @@ -160,7 +173,7 @@ end M.Watcher = Watcher --- Permanently disable watchers and purge all state following a catastrophic error. ---- @param msg string +---@param msg string function M.disable_watchers(msg) notify.warn(string.format("Disabling watchers: %s", msg)) M.config.filesystem_watchers.enable = false @@ -181,8 +194,8 @@ end --- Windows NT will present directories that cannot be enumerated. --- Detect these by attempting to start an event monitor. ---- @param path string ---- @return boolean +---@param path string +---@return boolean function M.is_fs_event_capable(path) if not utils.is_windows then return true