chore: add type annotations and resolve LSP warnings (#2555)
* chore: add type annotations to (almost) all functions
* stylua
* Add classes for symlink nodes
* Replace deprecated `@vararg`
* Move node classes to `node` module
* Fix `Symlink*` classes
* add vim and libuv runtime for luals, qualify libuv types
* add scripts/luals-check, not quite ready for CI
* additional nil checks for git/init.lua and git/runner.lua
* additional nil checks for nvim-tree.lua
* wrap vim.cmd-as-a-function calls inside functions
* vim.tbl_filter predicate returns booleans
* Revert "add scripts/luals-check, not quite ready for CI"
This reverts commit c70229cad9.
* Add `MinimalNode` class in `marks` module
* Fix various LSP warnings
* stylua
* Fix `Explorer` class, update related annotations and add necessary checks
* Add missing annotations to `live-filter`
* Add temporary aliases for `uv.*` types
* Resolve remaining LSP warnings
* Revert changes not related to internal types
* Minor adjustments
* Update doc comments style
* Minor adjustments (pt. 2)
---------
Co-authored-by: Alexander Courtis <alex@courtis.org>
This commit is contained in:
parent
7d1760f892
commit
13f967f8e7
@ -23,8 +23,8 @@ local M = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Update the tree root to a directory or the directory containing
|
--- Update the tree root to a directory or the directory containing
|
||||||
--- @param path string relative or absolute
|
---@param path string relative or absolute
|
||||||
--- @param bufnr number|nil
|
---@param bufnr number|nil
|
||||||
function M.change_root(path, bufnr)
|
function M.change_root(path, bufnr)
|
||||||
-- skip if current file is in ignore_list
|
-- skip if current file is in ignore_list
|
||||||
if type(bufnr) == "number" then
|
if type(bufnr) == "number" then
|
||||||
@ -42,6 +42,10 @@ function M.change_root(path, bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local cwd = core.get_cwd()
|
local cwd = core.get_cwd()
|
||||||
|
if cwd == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local vim_cwd = vim.fn.getcwd()
|
local vim_cwd = vim.fn.getcwd()
|
||||||
|
|
||||||
-- test if in vim_cwd
|
-- test if in vim_cwd
|
||||||
@ -73,6 +77,7 @@ function M.change_root(path, bufnr)
|
|||||||
change_dir.fn(vim.fn.fnamemodify(path, ":p:h"))
|
change_dir.fn(vim.fn.fnamemodify(path, ":p:h"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param cwd string|nil
|
||||||
function M.open_replacing_current_buffer(cwd)
|
function M.open_replacing_current_buffer(cwd)
|
||||||
if view.is_visible() then
|
if view.is_visible() then
|
||||||
return
|
return
|
||||||
@ -153,10 +158,13 @@ function M.place_cursor_on_node()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return table
|
||||||
function M.get_config()
|
function M.get_config()
|
||||||
return M.config
|
return M.config
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param disable_netrw boolean
|
||||||
|
---@param hijack_netrw boolean
|
||||||
local function manage_netrw(disable_netrw, hijack_netrw)
|
local function manage_netrw(disable_netrw, hijack_netrw)
|
||||||
if hijack_netrw then
|
if hijack_netrw then
|
||||||
vim.cmd "silent! autocmd! FileExplorer *"
|
vim.cmd "silent! autocmd! FileExplorer *"
|
||||||
@ -168,14 +176,18 @@ local function manage_netrw(disable_netrw, hijack_netrw)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param name string|nil
|
||||||
function M.change_dir(name)
|
function M.change_dir(name)
|
||||||
|
if name then
|
||||||
change_dir.fn(name)
|
change_dir.fn(name)
|
||||||
|
end
|
||||||
|
|
||||||
if _config.update_focused_file.enable then
|
if _config.update_focused_file.enable then
|
||||||
find_file.fn()
|
find_file.fn()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param opts table
|
||||||
local function setup_autocommands(opts)
|
local function setup_autocommands(opts)
|
||||||
local augroup_id = vim.api.nvim_create_augroup("NvimTree", { clear = true })
|
local augroup_id = vim.api.nvim_create_augroup("NvimTree", { clear = true })
|
||||||
local function create_nvim_tree_autocmd(name, custom_opts)
|
local function create_nvim_tree_autocmd(name, custom_opts)
|
||||||
@ -671,9 +683,15 @@ local ACCEPTED_STRINGS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param conf table|nil
|
||||||
local function validate_options(conf)
|
local function validate_options(conf)
|
||||||
local msg
|
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)
|
local function validate(user, def, strs, types, prefix)
|
||||||
-- if user's option is not a table there is nothing to do
|
-- if user's option is not a table there is nothing to do
|
||||||
if type(user) ~= "table" then
|
if type(user) ~= "table" then
|
||||||
@ -756,6 +774,7 @@ function M.purge_all_state()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param conf table|nil
|
||||||
function M.setup(conf)
|
function M.setup(conf)
|
||||||
if vim.fn.has "nvim-0.8" == 0 then
|
if vim.fn.has "nvim-0.8" == 0 then
|
||||||
notify.warn "nvim-tree.lua requires Neovim 0.8 or higher"
|
notify.warn "nvim-tree.lua requires Neovim 0.8 or higher"
|
||||||
|
|||||||
@ -4,6 +4,9 @@ local find_file = require("nvim-tree.actions.finders.find-file").fn
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param search_dir string|nil
|
||||||
|
---@param input_path string
|
||||||
|
---@return string|nil
|
||||||
local function search(search_dir, input_path)
|
local function search(search_dir, input_path)
|
||||||
local realpaths_searched = {}
|
local realpaths_searched = {}
|
||||||
|
|
||||||
@ -11,6 +14,8 @@ local function search(search_dir, input_path)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param dir string
|
||||||
|
---@return string|nil
|
||||||
local function iter(dir)
|
local function iter(dir)
|
||||||
local realpath, path, name, stat, handle, _
|
local realpath, path, name, stat, handle, _
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,10 @@ local clipboard = {
|
|||||||
copy = {},
|
copy = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param source string
|
||||||
|
---@param destination string
|
||||||
|
---@return boolean
|
||||||
|
---@return string|nil
|
||||||
local function do_copy(source, destination)
|
local function do_copy(source, destination)
|
||||||
local source_stats, handle
|
local source_stats, handle
|
||||||
local success, errmsg
|
local success, errmsg
|
||||||
@ -81,6 +85,12 @@ local function do_copy(source, destination)
|
|||||||
return true
|
return true
|
||||||
end
|
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 function do_single_paste(source, dest, action_type, action_fn)
|
||||||
local dest_stats
|
local dest_stats
|
||||||
local success, errmsg, errcode
|
local success, errmsg, errcode
|
||||||
@ -140,6 +150,8 @@ local function do_single_paste(source, dest, action_type, action_fn)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@param clip table
|
||||||
local function toggle(node, clip)
|
local function toggle(node, clip)
|
||||||
if node.name == ".." then
|
if node.name == ".." then
|
||||||
return
|
return
|
||||||
@ -147,7 +159,8 @@ local function toggle(node, clip)
|
|||||||
local notify_node = notify.render_path(node.absolute_path)
|
local notify_node = notify.render_path(node.absolute_path)
|
||||||
|
|
||||||
if utils.array_remove(clip, node) then
|
if utils.array_remove(clip, node) then
|
||||||
return notify.info(notify_node .. " removed from clipboard.")
|
notify.info(notify_node .. " removed from clipboard.")
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(clip, node)
|
table.insert(clip, node)
|
||||||
@ -161,22 +174,28 @@ function M.clear_clipboard()
|
|||||||
renderer.draw()
|
renderer.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.copy(node)
|
function M.copy(node)
|
||||||
utils.array_remove(clipboard.cut, node)
|
utils.array_remove(clipboard.cut, node)
|
||||||
toggle(node, clipboard.copy)
|
toggle(node, clipboard.copy)
|
||||||
renderer.draw()
|
renderer.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.cut(node)
|
function M.cut(node)
|
||||||
utils.array_remove(clipboard.copy, node)
|
utils.array_remove(clipboard.copy, node)
|
||||||
toggle(node, clipboard.cut)
|
toggle(node, clipboard.cut)
|
||||||
renderer.draw()
|
renderer.draw()
|
||||||
end
|
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)
|
local function do_paste(node, action_type, action_fn)
|
||||||
node = lib.get_last_group_node(node)
|
node = lib.get_last_group_node(node)
|
||||||
if node.name == ".." then
|
local explorer = core.get_explorer()
|
||||||
node = core.get_explorer()
|
if node.name == ".." and explorer then
|
||||||
|
node = explorer
|
||||||
end
|
end
|
||||||
local clip = clipboard[action_type]
|
local clip = clipboard[action_type]
|
||||||
if #clip == 0 then
|
if #clip == 0 then
|
||||||
@ -202,10 +221,14 @@ local function do_paste(node, action_type, action_fn)
|
|||||||
|
|
||||||
clipboard[action_type] = {}
|
clipboard[action_type] = {}
|
||||||
if not M.config.filesystem_watchers.enable then
|
if not M.config.filesystem_watchers.enable then
|
||||||
return reloaders.reload_explorer()
|
reloaders.reload_explorer()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param source string
|
||||||
|
---@param destination string
|
||||||
|
---@return boolean
|
||||||
|
---@return string?
|
||||||
local function do_cut(source, destination)
|
local function do_cut(source, destination)
|
||||||
log.line("copy_paste", "do_cut '%s' -> '%s'", source, destination)
|
log.line("copy_paste", "do_cut '%s' -> '%s'", source, destination)
|
||||||
|
|
||||||
@ -225,12 +248,13 @@ local function do_cut(source, destination)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.paste(node)
|
function M.paste(node)
|
||||||
if clipboard.cut[1] ~= nil then
|
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
|
end
|
||||||
|
|
||||||
return do_paste(node, "copy", do_copy)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.print_clipboard()
|
function M.print_clipboard()
|
||||||
@ -248,9 +272,10 @@ function M.print_clipboard()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return notify.info(table.concat(content, "\n") .. "\n")
|
notify.info(table.concat(content, "\n") .. "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param content string
|
||||||
local function copy_to_clipboard(content)
|
local function copy_to_clipboard(content)
|
||||||
local clipboard_name
|
local clipboard_name
|
||||||
if M.config.actions.use_system_clipboard == true then
|
if M.config.actions.use_system_clipboard == true then
|
||||||
@ -264,28 +289,36 @@ local function copy_to_clipboard(content)
|
|||||||
end
|
end
|
||||||
|
|
||||||
vim.api.nvim_exec_autocmds("TextYankPost", {})
|
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
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.copy_filename(node)
|
function M.copy_filename(node)
|
||||||
return copy_to_clipboard(node.name)
|
copy_to_clipboard(node.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.copy_path(node)
|
function M.copy_path(node)
|
||||||
local absolute_path = node.absolute_path
|
local absolute_path = node.absolute_path
|
||||||
local relative_path = utils.path_relative(absolute_path, core.get_cwd())
|
local cwd = core.get_cwd()
|
||||||
|
if cwd == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local relative_path = utils.path_relative(absolute_path, cwd)
|
||||||
local content = node.nodes ~= nil and utils.path_add_trailing(relative_path) or relative_path
|
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
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.copy_absolute_path(node)
|
function M.copy_absolute_path(node)
|
||||||
local absolute_path = node.absolute_path
|
local absolute_path = node.absolute_path
|
||||||
local content = node.nodes ~= nil and utils.path_add_trailing(absolute_path) or 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
|
end
|
||||||
|
|
||||||
---Clipboard text highlight group and position when highlight_clipboard.
|
--- Clipboard text highlight group and position when highlight_clipboard.
|
||||||
---@param node table
|
---@param node Node
|
||||||
---@return HL_POSITION position none when clipboard empty
|
---@return HL_POSITION position none when clipboard empty
|
||||||
---@return string|nil group only when node present in clipboard
|
---@return string|nil group only when node present in clipboard
|
||||||
function M.get_highlight(node)
|
function M.get_highlight(node)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ local find_file = require("nvim-tree.actions.finders.find-file").fn
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param file string
|
||||||
local function create_and_notify(file)
|
local function create_and_notify(file)
|
||||||
events._dispatch_will_create_file(file)
|
events._dispatch_will_create_file(file)
|
||||||
local ok, fd = pcall(vim.loop.fs_open, file, "w", 420)
|
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)
|
events._dispatch_file_created(file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param iter function iterable
|
||||||
|
---@return integer
|
||||||
local function get_num_nodes(iter)
|
local function get_num_nodes(iter)
|
||||||
local i = 0
|
local i = 0
|
||||||
for _ in iter do
|
for _ in iter do
|
||||||
@ -27,6 +30,8 @@ local function get_num_nodes(iter)
|
|||||||
return i
|
return i
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return string
|
||||||
local function get_containing_folder(node)
|
local function get_containing_folder(node)
|
||||||
if node.nodes ~= nil then
|
if node.nodes ~= nil then
|
||||||
return utils.path_add_trailing(node.absolute_path)
|
return utils.path_add_trailing(node.absolute_path)
|
||||||
@ -35,11 +40,18 @@ local function get_containing_folder(node)
|
|||||||
return node.absolute_path:sub(0, -node_name_size - 1)
|
return node.absolute_path:sub(0, -node_name_size - 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node|nil
|
||||||
function M.fn(node)
|
function M.fn(node)
|
||||||
|
local cwd = core.get_cwd()
|
||||||
|
if cwd == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
node = node and lib.get_last_group_node(node)
|
node = node and lib.get_last_group_node(node)
|
||||||
if not node or node.name == ".." then
|
if not node or node.name == ".." then
|
||||||
node = {
|
node = {
|
||||||
absolute_path = core.get_cwd(),
|
absolute_path = cwd,
|
||||||
|
name = "",
|
||||||
nodes = core.get_explorer().nodes,
|
nodes = core.get_explorer().nodes,
|
||||||
open = true,
|
open = true,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ local M = {
|
|||||||
config = {},
|
config = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param windows integer[]
|
||||||
local function close_windows(windows)
|
local function close_windows(windows)
|
||||||
-- Prevent from closing when the win count equals 1 or 2,
|
-- Prevent from closing when the win count equals 1 or 2,
|
||||||
-- where the win to remove could be the last opened.
|
-- where the win to remove could be the last opened.
|
||||||
@ -23,6 +24,7 @@ local function close_windows(windows)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param absolute_path string
|
||||||
local function clear_buffer(absolute_path)
|
local function clear_buffer(absolute_path)
|
||||||
local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 }
|
local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 }
|
||||||
for _, buf in pairs(bufs) do
|
for _, buf in pairs(bufs) do
|
||||||
@ -44,10 +46,13 @@ local function clear_buffer(absolute_path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param cwd string
|
||||||
|
---@return boolean|nil
|
||||||
local function remove_dir(cwd)
|
local function remove_dir(cwd)
|
||||||
local handle = vim.loop.fs_scandir(cwd)
|
local handle = vim.loop.fs_scandir(cwd)
|
||||||
if type(handle) == "string" then
|
if type(handle) == "string" then
|
||||||
return notify.error(handle)
|
notify.error(handle)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
@ -75,20 +80,22 @@ local function remove_dir(cwd)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Remove a node, notify errors, dispatch events
|
--- Remove a node, notify errors, dispatch events
|
||||||
--- @param node table
|
---@param node Node
|
||||||
function M.remove(node)
|
function M.remove(node)
|
||||||
local notify_node = notify.render_path(node.absolute_path)
|
local notify_node = notify.render_path(node.absolute_path)
|
||||||
if node.nodes ~= nil and not node.link_to then
|
if node.nodes ~= nil and not node.link_to then
|
||||||
local success = remove_dir(node.absolute_path)
|
local success = remove_dir(node.absolute_path)
|
||||||
if not success then
|
if not success then
|
||||||
return notify.error("Could not remove " .. notify_node)
|
notify.error("Could not remove " .. notify_node)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
events._dispatch_folder_removed(node.absolute_path)
|
events._dispatch_folder_removed(node.absolute_path)
|
||||||
else
|
else
|
||||||
events._dispatch_will_remove_file(node.absolute_path)
|
events._dispatch_will_remove_file(node.absolute_path)
|
||||||
local success = vim.loop.fs_unlink(node.absolute_path)
|
local success = vim.loop.fs_unlink(node.absolute_path)
|
||||||
if not success then
|
if not success then
|
||||||
return notify.error("Could not remove " .. notify_node)
|
notify.error("Could not remove " .. notify_node)
|
||||||
|
return
|
||||||
end
|
end
|
||||||
events._dispatch_file_removed(node.absolute_path)
|
events._dispatch_file_removed(node.absolute_path)
|
||||||
clear_buffer(node.absolute_path)
|
clear_buffer(node.absolute_path)
|
||||||
@ -96,6 +103,7 @@ function M.remove(node)
|
|||||||
notify.info(notify_node .. " was properly removed.")
|
notify.info(notify_node .. " was properly removed.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.fn(node)
|
function M.fn(node)
|
||||||
if node.name == ".." then
|
if node.name == ".." then
|
||||||
return
|
return
|
||||||
|
|||||||
@ -20,6 +20,8 @@ local function err_fmt(from, to, reason)
|
|||||||
return string.format("Cannot rename %s -> %s: %s", from, to, reason)
|
return string.format("Cannot rename %s -> %s: %s", from, to, reason)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@param to string
|
||||||
function M.rename(node, to)
|
function M.rename(node, to)
|
||||||
local notify_from = notify.render_path(node.absolute_path)
|
local notify_from = notify.render_path(node.absolute_path)
|
||||||
local notify_to = notify.render_path(to)
|
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)
|
events._dispatch_will_rename_node(node.absolute_path, to)
|
||||||
local success, err = vim.loop.fs_rename(node.absolute_path, to)
|
local success, err = vim.loop.fs_rename(node.absolute_path, to)
|
||||||
if not success then
|
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
|
end
|
||||||
notify.info(string.format("%s -> %s", notify_from, notify_to))
|
notify.info(string.format("%s -> %s", notify_from, notify_to))
|
||||||
utils.rename_loaded_buffers(node.absolute_path, to)
|
utils.rename_loaded_buffers(node.absolute_path, to)
|
||||||
events._dispatch_node_renamed(node.absolute_path, to)
|
events._dispatch_node_renamed(node.absolute_path, to)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param default_modifier string|nil
|
||||||
|
---@return fun(node: Node, modifier: string)
|
||||||
function M.fn(default_modifier)
|
function M.fn(default_modifier)
|
||||||
default_modifier = default_modifier or ":t"
|
default_modifier = default_modifier or ":t"
|
||||||
|
|
||||||
@ -47,13 +52,18 @@ function M.fn(default_modifier)
|
|||||||
node = lib.get_node_at_cursor()
|
node = lib.get_node_at_cursor()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if node == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if type(modifier) ~= "string" then
|
if type(modifier) ~= "string" then
|
||||||
modifier = default_modifier
|
modifier = default_modifier
|
||||||
end
|
end
|
||||||
|
|
||||||
-- support for only specific modifiers have been implemented
|
-- support for only specific modifiers have been implemented
|
||||||
if not ALLOWED_MODIFIERS[modifier] then
|
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
|
end
|
||||||
|
|
||||||
node = lib.get_last_group_node(node)
|
node = lib.get_last_group_node(node)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ local M = {
|
|||||||
local utils = require "nvim-tree.utils"
|
local utils = require "nvim-tree.utils"
|
||||||
local events = require "nvim-tree.events"
|
local events = require "nvim-tree.events"
|
||||||
|
|
||||||
|
---@param absolute_path string
|
||||||
local function clear_buffer(absolute_path)
|
local function clear_buffer(absolute_path)
|
||||||
local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 }
|
local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 }
|
||||||
for _, buf in pairs(bufs) do
|
for _, buf in pairs(bufs) do
|
||||||
@ -24,6 +25,7 @@ local function clear_buffer(absolute_path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.remove(node)
|
function M.remove(node)
|
||||||
local binary = M.config.trash.cmd:gsub(" .*$", "")
|
local binary = M.config.trash.cmd:gsub(" .*$", "")
|
||||||
if vim.fn.executable(binary) == 0 then
|
if vim.fn.executable(binary) == 0 then
|
||||||
@ -76,6 +78,7 @@ function M.remove(node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.fn(node)
|
function M.fn(node)
|
||||||
if node.name == ".." then
|
if node.name == ".." then
|
||||||
return
|
return
|
||||||
|
|||||||
@ -6,6 +6,9 @@ local explorer_node = require "nvim-tree.explorer.node"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param where string
|
||||||
|
---@param what string
|
||||||
|
---@return fun()
|
||||||
function M.fn(where, what)
|
function M.fn(where, what)
|
||||||
return function()
|
return function()
|
||||||
local node_cur = lib.get_node_at_cursor()
|
local node_cur = lib.get_node_at_cursor()
|
||||||
|
|||||||
@ -6,6 +6,8 @@ local lib = require "nvim-tree.lib"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param should_close boolean|nil
|
||||||
|
---@return fun(node: Node): boolean|nil
|
||||||
function M.fn(should_close)
|
function M.fn(should_close)
|
||||||
should_close = should_close or false
|
should_close = should_close or false
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,8 @@ local Iterator = require "nvim-tree.iterators.node-iterator"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param direction string
|
||||||
|
---@return fun(node: Node): nil
|
||||||
function M.fn(direction)
|
function M.fn(direction)
|
||||||
return function(node)
|
return function(node)
|
||||||
if node.name == ".." or not direction then
|
if node.name == ".." or not direction then
|
||||||
|
|||||||
@ -2,6 +2,8 @@ local utils = require "nvim-tree.utils"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return table
|
||||||
local function get_formatted_lines(node)
|
local function get_formatted_lines(node)
|
||||||
local stats = node.fs_stat
|
local stats = node.fs_stat
|
||||||
local fpath = " fullpath: " .. node.absolute_path
|
local fpath = " fullpath: " .. node.absolute_path
|
||||||
@ -21,6 +23,7 @@ end
|
|||||||
|
|
||||||
local current_popup = nil
|
local current_popup = nil
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
local function setup_window(node)
|
local function setup_window(node)
|
||||||
local lines = get_formatted_lines(node)
|
local lines = get_formatted_lines(node)
|
||||||
|
|
||||||
@ -52,6 +55,7 @@ function M.close_popup()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.toggle_file_info(node)
|
function M.toggle_file_info(node)
|
||||||
if node.name == ".." then
|
if node.name == ".." then
|
||||||
return
|
return
|
||||||
|
|||||||
@ -6,6 +6,8 @@ local view = require "nvim-tree.view"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---Get single char from user input
|
||||||
|
---@return string
|
||||||
local function get_user_input_char()
|
local function get_user_input_char()
|
||||||
local c = vim.fn.getchar()
|
local c = vim.fn.getchar()
|
||||||
while type(c) ~= "number" do
|
while type(c) ~= "number" do
|
||||||
@ -302,6 +304,8 @@ local function edit_in_current_buf(filename)
|
|||||||
vim.cmd("keepalt keepjumps edit " .. vim.fn.fnameescape(filename))
|
vim.cmd("keepalt keepjumps edit " .. vim.fn.fnameescape(filename))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param mode string
|
||||||
|
---@param filename string
|
||||||
function M.fn(mode, filename)
|
function M.fn(mode, filename)
|
||||||
if type(mode) ~= "string" then
|
if type(mode) ~= "string" then
|
||||||
mode = ""
|
mode = ""
|
||||||
|
|||||||
@ -6,14 +6,18 @@ local M = {}
|
|||||||
---Retrieves the absolute path to the node.
|
---Retrieves the absolute path to the node.
|
||||||
---Safely handles the node representing the current directory
|
---Safely handles the node representing the current directory
|
||||||
---(the topmost node in the nvim-tree window)
|
---(the topmost node in the nvim-tree window)
|
||||||
|
---@param node Node
|
||||||
|
---@return string
|
||||||
local function get_node_path(node)
|
local function get_node_path(node)
|
||||||
if node.name == ".." then
|
local cwd = core.get_cwd()
|
||||||
return utils.path_remove_trailing(core.get_cwd())
|
if node.name == ".." and cwd then
|
||||||
|
return utils.path_remove_trailing(cwd)
|
||||||
else
|
else
|
||||||
return node.absolute_path
|
return node.absolute_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.run_file_command(node)
|
function M.run_file_command(node)
|
||||||
local node_path = get_node_path(node)
|
local node_path = get_node_path(node)
|
||||||
vim.api.nvim_input(": " .. node_path .. "<Home>")
|
vim.api.nvim_input(": " .. node_path .. "<Home>")
|
||||||
|
|||||||
@ -3,6 +3,7 @@ local utils = require "nvim-tree.utils"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.fn(node)
|
function M.fn(node)
|
||||||
if #M.config.system_open.cmd == 0 then
|
if #M.config.system_open.cmd == 0 then
|
||||||
require("nvim-tree.utils").notify.warn "Cannot open file with system application. Unrecognized platform."
|
require("nvim-tree.utils").notify.warn "Cannot open file with system application. Unrecognized platform."
|
||||||
|
|||||||
@ -8,6 +8,9 @@ local Iterator = require "nvim-tree.iterators.node-iterator"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param node Explorer|nil
|
||||||
|
---@param projects table
|
||||||
|
---@param unloaded_bufnr number|nil
|
||||||
local function refresh_nodes(node, projects, unloaded_bufnr)
|
local function refresh_nodes(node, projects, unloaded_bufnr)
|
||||||
Iterator.builder({ node })
|
Iterator.builder({ node })
|
||||||
:applier(function(n)
|
:applier(function(n)
|
||||||
@ -22,7 +25,13 @@ local function refresh_nodes(node, projects, unloaded_bufnr)
|
|||||||
:iterate()
|
:iterate()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param parent_node Node|nil
|
||||||
|
---@param projects table
|
||||||
function M.reload_node_status(parent_node, projects)
|
function M.reload_node_status(parent_node, projects)
|
||||||
|
if parent_node == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local toplevel = git.get_toplevel(parent_node.absolute_path)
|
local toplevel = git.get_toplevel(parent_node.absolute_path)
|
||||||
local status = projects[toplevel] or {}
|
local status = projects[toplevel] or {}
|
||||||
for _, node in ipairs(parent_node.nodes) do
|
for _, node in ipairs(parent_node.nodes) do
|
||||||
|
|||||||
@ -6,9 +6,15 @@ local M = {
|
|||||||
current_tab = vim.api.nvim_get_current_tabpage(),
|
current_tab = vim.api.nvim_get_current_tabpage(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param name string
|
||||||
|
---@return string|nil
|
||||||
local function clean_input_cwd(name)
|
local function clean_input_cwd(name)
|
||||||
name = vim.fn.fnameescape(name)
|
name = vim.fn.fnameescape(name)
|
||||||
local root_parent_cwd = vim.fn.fnamemodify(utils.path_remove_trailing(core.get_cwd()), ":h")
|
local cwd = core.get_cwd()
|
||||||
|
if cwd == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local root_parent_cwd = vim.fn.fnamemodify(utils.path_remove_trailing(cwd), ":h")
|
||||||
if name == ".." and root_parent_cwd then
|
if name == ".." and root_parent_cwd then
|
||||||
return vim.fn.expand(root_parent_cwd)
|
return vim.fn.expand(root_parent_cwd)
|
||||||
else
|
else
|
||||||
@ -16,17 +22,23 @@ local function clean_input_cwd(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param new_tabpage integer
|
||||||
|
---@return boolean
|
||||||
local function is_window_event(new_tabpage)
|
local function is_window_event(new_tabpage)
|
||||||
local is_event_scope_window = vim.v.event.scope == "window" or vim.v.event.changed_window
|
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
|
return is_event_scope_window and new_tabpage == M.current_tab
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param foldername string
|
||||||
|
---@return boolean
|
||||||
local function prevent_cwd_change(foldername)
|
local function prevent_cwd_change(foldername)
|
||||||
local is_same_cwd = foldername == core.get_cwd()
|
local is_same_cwd = foldername == core.get_cwd()
|
||||||
local is_restricted_above = M.options.restrict_above_cwd and foldername < vim.fn.getcwd(-1, -1)
|
local is_restricted_above = M.options.restrict_above_cwd and foldername < vim.fn.getcwd(-1, -1)
|
||||||
return is_same_cwd or is_restricted_above
|
return is_same_cwd or is_restricted_above
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param input_cwd string
|
||||||
|
---@param with_open boolean|nil
|
||||||
function M.fn(input_cwd, with_open)
|
function M.fn(input_cwd, with_open)
|
||||||
if not core.get_explorer() then
|
if not core.get_explorer() then
|
||||||
return
|
return
|
||||||
@ -38,7 +50,7 @@ function M.fn(input_cwd, with_open)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local foldername = clean_input_cwd(input_cwd)
|
local foldername = clean_input_cwd(input_cwd)
|
||||||
if prevent_cwd_change(foldername) then
|
if foldername == nil or prevent_cwd_change(foldername) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -46,14 +58,19 @@ function M.fn(input_cwd, with_open)
|
|||||||
M.force_dirchange(foldername, with_open)
|
M.force_dirchange(foldername, with_open)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param global boolean
|
||||||
|
---@param path string
|
||||||
local function cd(global, path)
|
local function cd(global, path)
|
||||||
vim.cmd((global and "cd " or "lcd ") .. vim.fn.fnameescape(path))
|
vim.cmd((global and "cd " or "lcd ") .. vim.fn.fnameescape(path))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
local function should_change_dir()
|
local function should_change_dir()
|
||||||
return M.options.enable and vim.tbl_isempty(vim.v.event)
|
return M.options.enable and vim.tbl_isempty(vim.v.event)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param f function
|
||||||
|
---@return fun(foldername: string, should_open_view: boolean|nil)
|
||||||
local function add_profiling_to(f)
|
local function add_profiling_to(f)
|
||||||
return function(foldername, should_open_view)
|
return function(foldername, should_open_view)
|
||||||
local profile = log.profile_start("change dir %s", foldername)
|
local profile = log.profile_start("change dir %s", foldername)
|
||||||
|
|||||||
@ -3,13 +3,19 @@ local core = require "nvim-tree.core"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.fn(node)
|
function M.fn(node)
|
||||||
if not node or node.name == ".." then
|
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
|
else
|
||||||
local newdir = vim.fn.fnamemodify(utils.path_remove_trailing(core.get_cwd()), ":h")
|
local cwd = core.get_cwd()
|
||||||
|
if cwd == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local newdir = vim.fn.fnamemodify(utils.path_remove_trailing(cwd), ":h")
|
||||||
require("nvim-tree.actions.root.change-dir").fn(newdir)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ local Iterator = require "nvim-tree.iterators.node-iterator"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@return fun(path: string): boolean
|
||||||
local function buf_match()
|
local function buf_match()
|
||||||
local buffer_paths = vim.tbl_map(function(buffer)
|
local buffer_paths = vim.tbl_map(function(buffer)
|
||||||
return vim.api.nvim_buf_get_name(buffer)
|
return vim.api.nvim_buf_get_name(buffer)
|
||||||
@ -22,6 +23,7 @@ local function buf_match()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param keep_buffers boolean
|
||||||
function M.fn(keep_buffers)
|
function M.fn(keep_buffers)
|
||||||
local node = lib.get_node_at_cursor()
|
local node = lib.get_node_at_cursor()
|
||||||
local explorer = core.get_explorer()
|
local explorer = core.get_explorer()
|
||||||
|
|||||||
@ -6,6 +6,8 @@ local lib = require "nvim-tree.lib"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param list string[]
|
||||||
|
---@return table
|
||||||
local function to_lookup_table(list)
|
local function to_lookup_table(list)
|
||||||
local table = {}
|
local table = {}
|
||||||
for _, element in ipairs(list) do
|
for _, element in ipairs(list) do
|
||||||
@ -15,6 +17,7 @@ local function to_lookup_table(list)
|
|||||||
return table
|
return table
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
local function expand(node)
|
local function expand(node)
|
||||||
node = lib.get_last_group_node(node)
|
node = lib.get_last_group_node(node)
|
||||||
node.open = true
|
node.open = true
|
||||||
@ -23,6 +26,9 @@ local function expand(node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param expansion_count integer
|
||||||
|
---@param node Node
|
||||||
|
---@return boolean
|
||||||
local function should_expand(expansion_count, node)
|
local function should_expand(expansion_count, node)
|
||||||
local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY
|
local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY
|
||||||
local should_exclude = M.EXCLUDE[node.name]
|
local should_exclude = M.EXCLUDE[node.name]
|
||||||
@ -57,6 +63,7 @@ local function gen_iterator()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param base_node table
|
||||||
function M.fn(base_node)
|
function M.fn(base_node)
|
||||||
local node = base_node.nodes and base_node or core.get_explorer()
|
local node = base_node.nodes and base_node or core.get_explorer()
|
||||||
if gen_iterator()(node) then
|
if gen_iterator()(node) then
|
||||||
|
|||||||
@ -6,7 +6,7 @@ local finders_find_file = require "nvim-tree.actions.finders.find-file"
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
--- Find file or buffer
|
--- Find file or buffer
|
||||||
--- @param opts ApiTreeFindFileOpts|nil|boolean legacy -> opts.buf
|
---@param opts ApiTreeFindFileOpts|nil|boolean legacy -> opts.buf
|
||||||
function M.fn(opts)
|
function M.fn(opts)
|
||||||
-- legacy arguments
|
-- legacy arguments
|
||||||
if type(opts) == "string" then
|
if type(opts) == "string" then
|
||||||
|
|||||||
@ -30,6 +30,7 @@ local Api = {
|
|||||||
|
|
||||||
--- Do nothing when setup not called.
|
--- Do nothing when setup not called.
|
||||||
--- f function to invoke
|
--- f function to invoke
|
||||||
|
---@param f function
|
||||||
local function wrap(f)
|
local function wrap(f)
|
||||||
return function(...)
|
return function(...)
|
||||||
if vim.g.NvimTreeSetup == 1 then
|
if vim.g.NvimTreeSetup == 1 then
|
||||||
@ -167,6 +168,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.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)
|
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 function edit(mode, node)
|
||||||
local path = node.absolute_path
|
local path = node.absolute_path
|
||||||
if node.link_to and not node.nodes then
|
if node.link_to and not node.nodes then
|
||||||
@ -175,6 +178,8 @@ local function edit(mode, node)
|
|||||||
require("nvim-tree.actions.node.open-file").fn(mode, path)
|
require("nvim-tree.actions.node.open-file").fn(mode, path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param mode string
|
||||||
|
---@return fun(node: table)
|
||||||
local function open_or_expand_or_dir_up(mode)
|
local function open_or_expand_or_dir_up(mode)
|
||||||
return function(node)
|
return function(node)
|
||||||
if node.name == ".." then
|
if node.name == ".." then
|
||||||
|
|||||||
@ -6,9 +6,11 @@ local log = require "nvim-tree.log"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@type Explorer|nil
|
||||||
local TreeExplorer = nil
|
local TreeExplorer = nil
|
||||||
local first_init_done = false
|
local first_init_done = false
|
||||||
|
|
||||||
|
---@param foldername string
|
||||||
function M.init(foldername)
|
function M.init(foldername)
|
||||||
local profile = log.profile_start("core init %s", foldername)
|
local profile = log.profile_start("core init %s", foldername)
|
||||||
|
|
||||||
@ -23,6 +25,7 @@ function M.init(foldername)
|
|||||||
log.profile_end(profile)
|
log.profile_end(profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return Explorer|nil
|
||||||
function M.get_explorer()
|
function M.get_explorer()
|
||||||
return TreeExplorer
|
return TreeExplorer
|
||||||
end
|
end
|
||||||
@ -31,10 +34,12 @@ function M.reset_explorer()
|
|||||||
TreeExplorer = nil
|
TreeExplorer = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return string|nil
|
||||||
function M.get_cwd()
|
function M.get_cwd()
|
||||||
return TreeExplorer and TreeExplorer.absolute_path
|
return TreeExplorer and TreeExplorer.absolute_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return integer
|
||||||
function M.get_nodes_starting_line()
|
function M.get_nodes_starting_line()
|
||||||
local offset = 1
|
local offset = 1
|
||||||
if view.is_root_folder_visible(M.get_cwd()) then
|
if view.is_root_folder_visible(M.get_cwd()) then
|
||||||
|
|||||||
@ -12,6 +12,7 @@ local severity_levels = {
|
|||||||
Hint = 4,
|
Hint = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@return table
|
||||||
local function from_nvim_lsp()
|
local function from_nvim_lsp()
|
||||||
local buffer_severity = {}
|
local buffer_severity = {}
|
||||||
|
|
||||||
@ -36,10 +37,14 @@ local function from_nvim_lsp()
|
|||||||
return buffer_severity
|
return buffer_severity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param severity integer
|
||||||
|
---@param config table
|
||||||
|
---@return boolean
|
||||||
local function is_severity_in_range(severity, config)
|
local function is_severity_in_range(severity, config)
|
||||||
return config.max <= severity and severity <= config.min
|
return config.max <= severity and severity <= config.min
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return table
|
||||||
local function from_coc()
|
local function from_coc()
|
||||||
if vim.g.coc_service_initialized ~= 1 then
|
if vim.g.coc_service_initialized ~= 1 then
|
||||||
return {}
|
return {}
|
||||||
|
|||||||
@ -21,16 +21,22 @@ M.Event = {
|
|||||||
TreeRendered = "TreeRendered",
|
TreeRendered = "TreeRendered",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param event_name string
|
||||||
|
---@return table
|
||||||
local function get_handlers(event_name)
|
local function get_handlers(event_name)
|
||||||
return global_handlers[event_name] or {}
|
return global_handlers[event_name] or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param event_name string
|
||||||
|
---@param handler function
|
||||||
function M.subscribe(event_name, handler)
|
function M.subscribe(event_name, handler)
|
||||||
local handlers = get_handlers(event_name)
|
local handlers = get_handlers(event_name)
|
||||||
table.insert(handlers, handler)
|
table.insert(handlers, handler)
|
||||||
global_handlers[event_name] = handlers
|
global_handlers[event_name] = handlers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param event_name string
|
||||||
|
---@param payload table|nil
|
||||||
local function dispatch(event_name, payload)
|
local function dispatch(event_name, payload)
|
||||||
for _, handler in pairs(get_handlers(event_name)) do
|
for _, handler in pairs(get_handlers(event_name)) do
|
||||||
local success, error = pcall(handler, payload)
|
local success, error = pcall(handler, payload)
|
||||||
|
|||||||
@ -11,10 +11,17 @@ local Watcher = require "nvim-tree.watcher"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param type_ string|nil
|
||||||
|
---@param cwd string
|
||||||
|
---@return any
|
||||||
local function get_type_from(type_, cwd)
|
local function get_type_from(type_, cwd)
|
||||||
return type_ or (vim.loop.fs_stat(cwd) or {}).type
|
return type_ or (vim.loop.fs_stat(cwd) or {}).type
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param handle uv.uv_fs_t
|
||||||
|
---@param cwd string
|
||||||
|
---@param node Node
|
||||||
|
---@param git_status table
|
||||||
local function populate_children(handle, cwd, node, git_status)
|
local function populate_children(handle, cwd, node, git_status)
|
||||||
local node_ignored = explorer_node.is_git_ignored(node)
|
local node_ignored = explorer_node.is_git_ignored(node)
|
||||||
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@param status table
|
||||||
|
---@return Node[]|nil
|
||||||
function M.explore(node, status)
|
function M.explore(node, status)
|
||||||
local cwd = node.link_to or node.absolute_path
|
local cwd = node.link_to or node.absolute_path
|
||||||
local handle = vim.loop.fs_scandir(cwd)
|
local handle = vim.loop.fs_scandir(cwd)
|
||||||
|
|||||||
@ -5,6 +5,8 @@ local M = {
|
|||||||
exclude_list = {},
|
exclude_list = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return boolean
|
||||||
local function is_excluded(path)
|
local function is_excluded(path)
|
||||||
for _, node in ipairs(M.exclude_list) do
|
for _, node in ipairs(M.exclude_list) do
|
||||||
if path:match(node) then
|
if path:match(node) then
|
||||||
@ -61,10 +63,14 @@ local function buf(path, bufinfo, unloaded_bufnr)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return boolean
|
||||||
local function dotfile(path)
|
local function dotfile(path)
|
||||||
return M.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "."
|
return M.config.filter_dotfiles and utils.path_basename(path):sub(1, 1) == "."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return boolean
|
||||||
local function custom(path)
|
local function custom(path)
|
||||||
if not M.config.filter_custom then
|
if not M.config.filter_custom then
|
||||||
return false
|
return false
|
||||||
|
|||||||
@ -7,11 +7,20 @@ local M = {}
|
|||||||
M.explore = require("nvim-tree.explorer.explore").explore
|
M.explore = require("nvim-tree.explorer.explore").explore
|
||||||
M.reload = require("nvim-tree.explorer.reload").reload
|
M.reload = require("nvim-tree.explorer.reload").reload
|
||||||
|
|
||||||
|
---@class Explorer
|
||||||
|
---@field absolute_path string
|
||||||
|
---@field nodes Node[]
|
||||||
|
---@field open boolean
|
||||||
|
|
||||||
local Explorer = {}
|
local Explorer = {}
|
||||||
Explorer.__index = Explorer
|
Explorer.__index = Explorer
|
||||||
|
|
||||||
|
---@param cwd string|nil
|
||||||
|
---@return Explorer
|
||||||
function Explorer.new(cwd)
|
function Explorer.new(cwd)
|
||||||
cwd = vim.loop.fs_realpath(cwd or vim.loop.cwd())
|
cwd = vim.loop.fs_realpath(cwd or vim.loop.cwd())
|
||||||
|
|
||||||
|
---@class Explorer
|
||||||
local explorer = setmetatable({
|
local explorer = setmetatable({
|
||||||
absolute_path = cwd,
|
absolute_path = cwd,
|
||||||
nodes = {},
|
nodes = {},
|
||||||
@ -22,12 +31,15 @@ function Explorer.new(cwd)
|
|||||||
return explorer
|
return explorer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@private
|
||||||
|
---@param node Node
|
||||||
function Explorer:_load(node)
|
function Explorer:_load(node)
|
||||||
local cwd = node.link_to or node.absolute_path
|
local cwd = node.link_to or node.absolute_path
|
||||||
local git_status = git.load_project_status(cwd)
|
local git_status = git.load_project_status(cwd)
|
||||||
M.explore(node, git_status)
|
M.explore(node, git_status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function Explorer:expand(node)
|
function Explorer:expand(node)
|
||||||
self:_load(node)
|
self:_load(node)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3,6 +3,10 @@ local watch = require "nvim-tree.explorer.watch"
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@param parent Node
|
||||||
|
---@param absolute_path string
|
||||||
|
---@param name string
|
||||||
|
---@return Node
|
||||||
function M.folder(parent, absolute_path, name)
|
function M.folder(parent, absolute_path, name)
|
||||||
local handle = vim.loop.fs_scandir(absolute_path)
|
local handle = vim.loop.fs_scandir(absolute_path)
|
||||||
local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil
|
local has_children = handle and vim.loop.fs_scandir_next(handle) ~= nil
|
||||||
@ -25,8 +29,8 @@ function M.folder(parent, absolute_path, name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- path is an executable file or directory
|
--- path is an executable file or directory
|
||||||
--- @param absolute_path string
|
---@param absolute_path string
|
||||||
--- @return boolean
|
---@return boolean|nil
|
||||||
function M.is_executable(absolute_path)
|
function M.is_executable(absolute_path)
|
||||||
if utils.is_windows or utils.is_wsl then
|
if utils.is_windows or utils.is_wsl then
|
||||||
--- executable detection on windows is buggy and not performant hence it is disabled
|
--- 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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param parent Node
|
||||||
|
---@param absolute_path string
|
||||||
|
---@param name string
|
||||||
|
---@return Node
|
||||||
function M.file(parent, absolute_path, name)
|
function M.file(parent, absolute_path, name)
|
||||||
local ext = string.match(name, ".?[^.]+%.(.*)") or ""
|
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
|
-- 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.
|
-- 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
|
-- So we need to check for link_to ~= nil when adding new links to the main tree
|
||||||
|
---@param parent Node
|
||||||
|
---@param absolute_path string
|
||||||
|
---@param name string
|
||||||
|
---@return Node
|
||||||
function M.link(parent, absolute_path, name)
|
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.
|
--- 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)
|
local link_to = vim.loop.fs_realpath(absolute_path)
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
-- node.git_status structure:
|
---@class GitStatus
|
||||||
-- {
|
---@field file string|nil
|
||||||
-- file = string | nil,
|
---@field dir table|nil
|
||||||
-- dir = {
|
|
||||||
-- direct = { string } | nil,
|
|
||||||
-- indirect = { string } | nil,
|
|
||||||
-- } | 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)
|
local function get_dir_git_status(parent_ignored, status, absolute_path)
|
||||||
if parent_ignored then
|
if parent_ignored then
|
||||||
return { file = "!!" }
|
return { file = "!!" }
|
||||||
@ -25,15 +24,24 @@ local function get_dir_git_status(parent_ignored, status, absolute_path)
|
|||||||
end
|
end
|
||||||
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 function get_git_status(parent_ignored, status, absolute_path)
|
||||||
local file_status = parent_ignored and "!!" or status.files and status.files[absolute_path]
|
local file_status = parent_ignored and "!!" or status.files and status.files[absolute_path]
|
||||||
return { file = file_status }
|
return { file = file_status }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return boolean
|
||||||
function M.has_one_child_folder(node)
|
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
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@param parent_ignored boolean
|
||||||
|
---@param status table|nil
|
||||||
function M.update_git_status(node, parent_ignored, status)
|
function M.update_git_status(node, parent_ignored, status)
|
||||||
local get_status
|
local get_status
|
||||||
if node.nodes then
|
if node.nodes then
|
||||||
@ -51,6 +59,8 @@ function M.update_git_status(node, parent_ignored, status)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return GitStatus|nil
|
||||||
function M.get_git_status(node)
|
function M.get_git_status(node)
|
||||||
local git_status = node and node.git_status
|
local git_status = node and node.git_status
|
||||||
if not git_status then
|
if not git_status then
|
||||||
@ -112,10 +122,13 @@ function M.get_git_status(node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return boolean
|
||||||
function M.is_git_ignored(node)
|
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
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.node_destroy(node)
|
function M.node_destroy(node)
|
||||||
if not node then
|
if not node then
|
||||||
return
|
return
|
||||||
|
|||||||
@ -12,6 +12,10 @@ local Watcher = require "nvim-tree.watcher"
|
|||||||
|
|
||||||
local M = {}
|
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)
|
local function update_status(nodes_by_path, node_ignored, status)
|
||||||
return function(node)
|
return function(node)
|
||||||
if nodes_by_path[node.absolute_path] then
|
if nodes_by_path[node.absolute_path] then
|
||||||
@ -21,6 +25,8 @@ local function update_status(nodes_by_path, node_ignored, status)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@param callback fun(toplevel: string|nil, project: table|nil)
|
||||||
local function reload_and_get_git_project(path, callback)
|
local function reload_and_get_git_project(path, callback)
|
||||||
local toplevel = git.get_toplevel(path)
|
local toplevel = git.get_toplevel(path)
|
||||||
|
|
||||||
@ -29,6 +35,9 @@ local function reload_and_get_git_project(path, callback)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@param project table|nil
|
||||||
|
---@param root string|nil
|
||||||
local function update_parent_statuses(node, project, root)
|
local function update_parent_statuses(node, project, root)
|
||||||
while project and node do
|
while project and node do
|
||||||
-- step up to the containing project
|
-- step up to the containing project
|
||||||
@ -58,6 +67,9 @@ local function update_parent_statuses(node, project, root)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@param git_status table
|
||||||
|
---@param unloaded_bufnr number|nil
|
||||||
function M.reload(node, git_status, unloaded_bufnr)
|
function M.reload(node, git_status, unloaded_bufnr)
|
||||||
local cwd = node.link_to or node.absolute_path
|
local cwd = node.link_to or node.absolute_path
|
||||||
local handle = vim.loop.fs_scandir(cwd)
|
local handle = vim.loop.fs_scandir(cwd)
|
||||||
@ -143,7 +155,7 @@ function M.reload(node, git_status, unloaded_bufnr)
|
|||||||
return child_names[n.absolute_path]
|
return child_names[n.absolute_path]
|
||||||
else
|
else
|
||||||
explorer_node.node_destroy(n)
|
explorer_node.node_destroy(n)
|
||||||
return nil
|
return false
|
||||||
end
|
end
|
||||||
end, node.nodes)
|
end, node.nodes)
|
||||||
)
|
)
|
||||||
@ -165,7 +177,7 @@ function M.reload(node, git_status, unloaded_bufnr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---Refresh contents and git status for a single node
|
---Refresh contents and git status for a single node
|
||||||
---@param node table
|
---@param node Node
|
||||||
---@param callback function
|
---@param callback function
|
||||||
function M.refresh_node(node, callback)
|
function M.refresh_node(node, callback)
|
||||||
if type(node) ~= "table" then
|
if type(node) ~= "table" then
|
||||||
|
|||||||
@ -3,8 +3,8 @@ local M = {}
|
|||||||
local C = {}
|
local C = {}
|
||||||
|
|
||||||
--- Predefined comparator, defaulting to name
|
--- Predefined comparator, defaulting to name
|
||||||
--- @param sorter string as per options
|
---@param sorter string as per options
|
||||||
--- @return function
|
---@return function
|
||||||
local function get_comparator(sorter)
|
local function get_comparator(sorter)
|
||||||
return C[sorter] or C.name
|
return C[sorter] or C.name
|
||||||
end
|
end
|
||||||
@ -24,8 +24,8 @@ local function tbl_slice(t, first, last)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---Evaluate `sort.folders_first` and `sort.files_first`
|
---Evaluate `sort.folders_first` and `sort.files_first`
|
||||||
---@param a table node
|
---@param a Node
|
||||||
---@param b table node
|
---@param b Node
|
||||||
---@return boolean|nil
|
---@return boolean|nil
|
||||||
local function folders_or_files_first(a, b)
|
local function folders_or_files_first(a, b)
|
||||||
if not (M.config.sort.folders_first or M.config.sort.files_first) then
|
if not (M.config.sort.folders_first or M.config.sort.files_first) then
|
||||||
@ -41,6 +41,11 @@ local function folders_or_files_first(a, b)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param t table
|
||||||
|
---@param first number
|
||||||
|
---@param mid number
|
||||||
|
---@param last number
|
||||||
|
---@param comparator fun(a: Node, b: Node): boolean
|
||||||
local function merge(t, first, mid, last, comparator)
|
local function merge(t, first, mid, last, comparator)
|
||||||
local n1 = mid - first + 1
|
local n1 = mid - first + 1
|
||||||
local n2 = last - mid
|
local n2 = last - mid
|
||||||
@ -74,6 +79,10 @@ local function merge(t, first, mid, last, comparator)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param t table
|
||||||
|
---@param first number
|
||||||
|
---@param last number
|
||||||
|
---@param comparator fun(a: Node, b: Node): boolean
|
||||||
local function split_merge(t, first, last, comparator)
|
local function split_merge(t, first, last, comparator)
|
||||||
if (last - first) < 1 then
|
if (last - first) < 1 then
|
||||||
return
|
return
|
||||||
@ -137,6 +146,10 @@ function M.sort(t)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param a Node
|
||||||
|
---@param b Node
|
||||||
|
---@param ignorecase boolean|nil
|
||||||
|
---@return boolean
|
||||||
local function node_comparator_name_ignorecase_or_not(a, b, ignorecase)
|
local function node_comparator_name_ignorecase_or_not(a, b, ignorecase)
|
||||||
if not (a and b) then
|
if not (a and b) then
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -7,6 +7,8 @@ local M = {
|
|||||||
uid = 0,
|
uid = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return boolean
|
||||||
local function is_git(path)
|
local function is_git(path)
|
||||||
-- If $GIT_DIR is set, consider its value to be equivalent to '.git'.
|
-- 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
|
-- Expand $GIT_DIR (and `path`) to a full path (see :help filename-modifiers), since
|
||||||
@ -29,6 +31,8 @@ local IGNORED_PATHS = {
|
|||||||
"/dev",
|
"/dev",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return boolean
|
||||||
local function is_folder_ignored(path)
|
local function is_folder_ignored(path)
|
||||||
for _, folder in ipairs(IGNORED_PATHS) do
|
for _, folder in ipairs(IGNORED_PATHS) do
|
||||||
if vim.startswith(path, folder) then
|
if vim.startswith(path, folder) then
|
||||||
@ -45,18 +49,14 @@ local function is_folder_ignored(path)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return Watcher|nil
|
||||||
function M.create_watcher(node)
|
function M.create_watcher(node)
|
||||||
if not M.config.filesystem_watchers.enable or type(node) ~= "table" then
|
if not M.config.filesystem_watchers.enable or type(node) ~= "table" then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
local path
|
local path = node.link_to or node.absolute_path
|
||||||
if node.type == "link" then
|
|
||||||
path = node.link_to
|
|
||||||
else
|
|
||||||
path = node.absolute_path
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_git(path) or is_folder_ignored(path) then
|
if is_git(path) or is_folder_ignored(path) then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|||||||
@ -29,6 +29,10 @@ local WATCHED_FILES = {
|
|||||||
"index", -- staging area
|
"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)
|
local function reload_git_status(toplevel, path, project, git_status)
|
||||||
if path then
|
if path then
|
||||||
for p in pairs(project.files) do
|
for p in pairs(project.files) do
|
||||||
@ -45,9 +49,9 @@ local function reload_git_status(toplevel, path, project, git_status)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Is this path in a known ignored directory?
|
--- Is this path in a known ignored directory?
|
||||||
--- @param path string
|
---@param path string
|
||||||
--- @param project table git status
|
---@param project table git status
|
||||||
--- @return boolean
|
---@return boolean
|
||||||
local function path_ignored_in_project(path, project)
|
local function path_ignored_in_project(path, project)
|
||||||
if not path or not project then
|
if not path or not project then
|
||||||
return false
|
return false
|
||||||
@ -64,7 +68,7 @@ local function path_ignored_in_project(path, project)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Reload all projects
|
--- Reload all projects
|
||||||
--- @return table projects maybe empty
|
---@return table projects maybe empty
|
||||||
function M.reload()
|
function M.reload()
|
||||||
if not M.config.git.enable then
|
if not M.config.git.enable then
|
||||||
return {}
|
return {}
|
||||||
@ -78,9 +82,9 @@ function M.reload()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Reload one project. Does nothing when no project or path is ignored
|
--- Reload one project. Does nothing when no project or path is ignored
|
||||||
--- @param toplevel string|nil
|
---@param toplevel string|nil
|
||||||
--- @param path string|nil optional path to update only
|
---@param path string|nil optional path to update only
|
||||||
--- @param callback function|nil
|
---@param callback function|nil
|
||||||
function M.reload_project(toplevel, path, callback)
|
function M.reload_project(toplevel, path, callback)
|
||||||
local project = M._projects_by_toplevel[toplevel]
|
local project = M._projects_by_toplevel[toplevel]
|
||||||
if not toplevel or not project or not M.config.git.enable then
|
if not toplevel or not project or not M.config.git.enable then
|
||||||
@ -118,7 +122,8 @@ function M.reload_project(toplevel, path, callback)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Retrieve a known project
|
--- Retrieve a known project
|
||||||
--- @return table|nil project
|
---@param toplevel string|nil
|
||||||
|
---@return table|nil project
|
||||||
function M.get_project(toplevel)
|
function M.get_project(toplevel)
|
||||||
return M._projects_by_toplevel[toplevel]
|
return M._projects_by_toplevel[toplevel]
|
||||||
end
|
end
|
||||||
@ -128,8 +133,8 @@ end
|
|||||||
--- not part of a project
|
--- not part of a project
|
||||||
--- not a directory
|
--- not a directory
|
||||||
--- path in git.disable_for_dirs
|
--- path in git.disable_for_dirs
|
||||||
--- @param path string absolute
|
---@param path string absolute
|
||||||
--- @return string|nil
|
---@return string|nil
|
||||||
function M.get_toplevel(path)
|
function M.get_toplevel(path)
|
||||||
if not M.config.git.enable then
|
if not M.config.git.enable then
|
||||||
return nil
|
return nil
|
||||||
@ -207,8 +212,8 @@ end
|
|||||||
|
|
||||||
--- Load the project status for a path. Does nothing when no toplevel for path.
|
--- Load the project status for a path. Does nothing when no toplevel for path.
|
||||||
--- Only fetches project status when unknown, otherwise returns existing.
|
--- Only fetches project status when unknown, otherwise returns existing.
|
||||||
--- @param path string absolute
|
---@param path string absolute
|
||||||
--- @return table project maybe empty
|
---@return table project maybe empty
|
||||||
function M.load_project_status(path)
|
function M.load_project_status(path)
|
||||||
if not M.config.git.enable then
|
if not M.config.git.enable then
|
||||||
return {}
|
return {}
|
||||||
@ -252,12 +257,17 @@ function M.load_project_status(path)
|
|||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if git_status then
|
||||||
M._projects_by_toplevel[toplevel] = {
|
M._projects_by_toplevel[toplevel] = {
|
||||||
files = git_status,
|
files = git_status,
|
||||||
dirs = git_utils.file_status_to_dir_status(git_status, toplevel),
|
dirs = git_utils.file_status_to_dir_status(git_status, toplevel),
|
||||||
watcher = watcher,
|
watcher = watcher,
|
||||||
}
|
}
|
||||||
return M._projects_by_toplevel[toplevel]
|
return M._projects_by_toplevel[toplevel]
|
||||||
|
else
|
||||||
|
M._toplevels_by_path[path] = false
|
||||||
|
return {}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function M.purge_state()
|
function M.purge_state()
|
||||||
|
|||||||
@ -2,13 +2,26 @@ local log = require "nvim-tree.log"
|
|||||||
local utils = require "nvim-tree.utils"
|
local utils = require "nvim-tree.utils"
|
||||||
local notify = require "nvim-tree.notify"
|
local notify = require "nvim-tree.notify"
|
||||||
|
|
||||||
|
-- TODO add "${3rd}/luv/library" to "workspace.library"
|
||||||
|
---@class uv.uv_handle_t: table
|
||||||
|
---@class uv.uv_stream_t: uv.uv_handle_t
|
||||||
|
---@class uv.uv_pipe_t: uv.uv_stream_t
|
||||||
|
|
||||||
|
---@class Runner
|
||||||
local Runner = {}
|
local Runner = {}
|
||||||
Runner.__index = Runner
|
Runner.__index = Runner
|
||||||
|
|
||||||
local timeouts = 0
|
local timeouts = 0
|
||||||
local MAX_TIMEOUTS = 5
|
local MAX_TIMEOUTS = 5
|
||||||
|
|
||||||
|
---@private
|
||||||
|
---@param status string
|
||||||
|
---@param path string|nil
|
||||||
function Runner:_parse_status_output(status, path)
|
function Runner:_parse_status_output(status, path)
|
||||||
|
if not path then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- replacing slashes if on windows
|
-- replacing slashes if on windows
|
||||||
if vim.fn.has "win32" == 1 then
|
if vim.fn.has "win32" == 1 then
|
||||||
path = path:gsub("/", "\\")
|
path = path:gsub("/", "\\")
|
||||||
@ -18,6 +31,10 @@ function Runner:_parse_status_output(status, path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@private
|
||||||
|
---@param prev_output string
|
||||||
|
---@param incoming string
|
||||||
|
---@return string
|
||||||
function Runner:_handle_incoming_data(prev_output, incoming)
|
function Runner:_handle_incoming_data(prev_output, incoming)
|
||||||
if incoming and utils.str_find(incoming, "\n") then
|
if incoming and utils.str_find(incoming, "\n") then
|
||||||
local prev = prev_output .. incoming
|
local prev = prev_output .. incoming
|
||||||
@ -46,12 +63,15 @@ function Runner:_handle_incoming_data(prev_output, incoming)
|
|||||||
end
|
end
|
||||||
|
|
||||||
for line in prev_output:gmatch "[^\n]*\n" do
|
for line in prev_output:gmatch "[^\n]*\n" do
|
||||||
self._parse_status_output(line)
|
self:_parse_status_output(line)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param stdout_handle uv.uv_pipe_t
|
||||||
|
---@param stderr_handle uv.uv_pipe_t
|
||||||
|
---@return table
|
||||||
function Runner:_getopts(stdout_handle, stderr_handle)
|
function Runner:_getopts(stdout_handle, stderr_handle)
|
||||||
local untracked = self.list_untracked and "-u" or nil
|
local untracked = self.list_untracked and "-u" or nil
|
||||||
local ignored = (self.list_untracked and self.list_ignored) and "--ignored=matching" or "--ignored=no"
|
local ignored = (self.list_untracked and self.list_ignored) and "--ignored=matching" or "--ignored=no"
|
||||||
@ -62,6 +82,7 @@ function Runner:_getopts(stdout_handle, stderr_handle)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param output string
|
||||||
function Runner:_log_raw_output(output)
|
function Runner:_log_raw_output(output)
|
||||||
if log.enabled "git" and output and type(output) == "string" then
|
if log.enabled "git" and output and type(output) == "string" then
|
||||||
log.raw("git", "%s", output)
|
log.raw("git", "%s", output)
|
||||||
@ -69,12 +90,17 @@ function Runner:_log_raw_output(output)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param callback function|nil
|
||||||
function Runner:_run_git_job(callback)
|
function Runner:_run_git_job(callback)
|
||||||
local handle, pid
|
local handle, pid
|
||||||
local stdout = vim.loop.new_pipe(false)
|
local stdout = vim.loop.new_pipe(false)
|
||||||
local stderr = vim.loop.new_pipe(false)
|
local stderr = vim.loop.new_pipe(false)
|
||||||
local timer = vim.loop.new_timer()
|
local timer = vim.loop.new_timer()
|
||||||
|
|
||||||
|
if stdout == nil or stderr == nil or timer == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local function on_finish(rc)
|
local function on_finish(rc)
|
||||||
self.rc = rc or 0
|
self.rc = rc or 0
|
||||||
if timer:is_closing() or stdout:is_closing() or stderr:is_closing() or (handle and handle:is_closing()) then
|
if timer:is_closing() or stdout:is_closing() or stderr:is_closing() or (handle and handle:is_closing()) then
|
||||||
@ -151,6 +177,7 @@ function Runner:_wait()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param opts table
|
||||||
function Runner:_finalise(opts)
|
function Runner:_finalise(opts)
|
||||||
if self.rc == -1 then
|
if self.rc == -1 then
|
||||||
log.line("git", "job timed out %s %s", opts.toplevel, opts.path)
|
log.line("git", "job timed out %s %s", opts.toplevel, opts.path)
|
||||||
@ -167,9 +194,9 @@ function Runner:_finalise(opts)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Runs a git process, which will be killed if it takes more than timeout which defaults to 400ms
|
--- Runs a git process, which will be killed if it takes more than timeout which defaults to 400ms
|
||||||
--- @param opts table
|
---@param opts table
|
||||||
--- @param callback function|nil executed passing return when complete
|
---@param callback function|nil executed passing return when complete
|
||||||
--- @return table|nil status by absolute path, nil if callback present
|
---@return table|nil status by absolute path, nil if callback present
|
||||||
function Runner.run(opts, callback)
|
function Runner.run(opts, callback)
|
||||||
local self = setmetatable({
|
local self = setmetatable({
|
||||||
toplevel = opts.toplevel,
|
toplevel = opts.toplevel,
|
||||||
|
|||||||
@ -6,9 +6,9 @@ local M = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Retrieve the git toplevel directory
|
--- Retrieve the git toplevel directory
|
||||||
--- @param cwd string path
|
---@param cwd string path
|
||||||
--- @return string|nil toplevel absolute path
|
---@return string|nil toplevel absolute path
|
||||||
--- @return string|nil git_dir absolute path
|
---@return string|nil git_dir absolute path
|
||||||
function M.get_toplevel(cwd)
|
function M.get_toplevel(cwd)
|
||||||
local profile = log.profile_start("git toplevel git_dir %s", cwd)
|
local profile = log.profile_start("git toplevel git_dir %s", cwd)
|
||||||
|
|
||||||
@ -60,6 +60,8 @@ end
|
|||||||
|
|
||||||
local untracked = {}
|
local untracked = {}
|
||||||
|
|
||||||
|
---@param cwd string
|
||||||
|
---@return string|nil
|
||||||
function M.should_show_untracked(cwd)
|
function M.should_show_untracked(cwd)
|
||||||
if untracked[cwd] ~= nil then
|
if untracked[cwd] ~= nil then
|
||||||
return untracked[cwd]
|
return untracked[cwd]
|
||||||
@ -79,12 +81,18 @@ function M.should_show_untracked(cwd)
|
|||||||
return untracked[cwd]
|
return untracked[cwd]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param t table|nil
|
||||||
|
---@param k string
|
||||||
|
---@return table
|
||||||
local function nil_insert(t, k)
|
local function nil_insert(t, k)
|
||||||
t = t or {}
|
t = t or {}
|
||||||
t[k] = true
|
t[k] = true
|
||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param status table
|
||||||
|
---@param cwd string|nil
|
||||||
|
---@return table
|
||||||
function M.file_status_to_dir_status(status, cwd)
|
function M.file_status_to_dir_status(status, cwd)
|
||||||
local direct = {}
|
local direct = {}
|
||||||
for p, s in pairs(status) do
|
for p, s in pairs(status) do
|
||||||
|
|||||||
@ -19,8 +19,8 @@ local M = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Shorten and normalise a vim command lhs
|
--- Shorten and normalise a vim command lhs
|
||||||
--- @param lhs string
|
---@param lhs string
|
||||||
--- @return string
|
---@return string
|
||||||
local function tidy_lhs(lhs)
|
local function tidy_lhs(lhs)
|
||||||
-- nvim_buf_get_keymap replaces leading "<" with "<lt>" e.g. "<lt>CTRL-v>"
|
-- nvim_buf_get_keymap replaces leading "<" with "<lt>" e.g. "<lt>CTRL-v>"
|
||||||
lhs = lhs:gsub("^<lt>", "<")
|
lhs = lhs:gsub("^<lt>", "<")
|
||||||
@ -43,15 +43,15 @@ end
|
|||||||
|
|
||||||
--- Remove prefix 'nvim-tree: '
|
--- Remove prefix 'nvim-tree: '
|
||||||
--- Hardcoded to keep default_on_attach simple
|
--- Hardcoded to keep default_on_attach simple
|
||||||
--- @param desc string
|
---@param desc string
|
||||||
--- @return string
|
---@return string
|
||||||
local function tidy_desc(desc)
|
local function tidy_desc(desc)
|
||||||
return desc and desc:gsub("^nvim%-tree: ", "") or ""
|
return desc and desc:gsub("^nvim%-tree: ", "") or ""
|
||||||
end
|
end
|
||||||
|
|
||||||
--- sort vim command lhs roughly as per :help index
|
--- sort vim command lhs roughly as per :help index
|
||||||
--- @param a string
|
---@param a string
|
||||||
--- @param b string
|
---@param b string
|
||||||
local function sort_lhs(a, b)
|
local function sort_lhs(a, b)
|
||||||
-- mouse first
|
-- mouse first
|
||||||
if a:match(PAT_MOUSE) and not b:match(PAT_MOUSE) then
|
if a:match(PAT_MOUSE) and not b:match(PAT_MOUSE) then
|
||||||
@ -79,9 +79,9 @@ local function sort_lhs(a, b)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Compute all lines for the buffer
|
--- Compute all lines for the buffer
|
||||||
--- @return table strings of text
|
---@return table strings of text
|
||||||
--- @return table arrays of arguments 3-6 for nvim_buf_add_highlight()
|
---@return table arrays of arguments 3-6 for nvim_buf_add_highlight()
|
||||||
--- @return number maximum length of text
|
---@return number maximum length of text
|
||||||
local function compute()
|
local function compute()
|
||||||
local head_lhs = "nvim-tree mappings"
|
local head_lhs = "nvim-tree mappings"
|
||||||
local head_rhs1 = "exit: q"
|
local head_rhs1 = "exit: q"
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
|
---@class NodeIterator
|
||||||
local NodeIterator = {}
|
local NodeIterator = {}
|
||||||
NodeIterator.__index = NodeIterator
|
NodeIterator.__index = NodeIterator
|
||||||
|
|
||||||
|
---@param nodes Node[]
|
||||||
|
---@return NodeIterator
|
||||||
function NodeIterator.builder(nodes)
|
function NodeIterator.builder(nodes)
|
||||||
return setmetatable({
|
return setmetatable({
|
||||||
nodes = nodes,
|
nodes = nodes,
|
||||||
@ -15,6 +18,7 @@ function NodeIterator.builder(nodes)
|
|||||||
}, NodeIterator)
|
}, NodeIterator)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return NodeIterator
|
||||||
function NodeIterator:hidden()
|
function NodeIterator:hidden()
|
||||||
self._filter_hidden = function(_)
|
self._filter_hidden = function(_)
|
||||||
return true
|
return true
|
||||||
@ -22,21 +26,29 @@ function NodeIterator:hidden()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param f fun(node: Node): boolean
|
||||||
|
---@return NodeIterator
|
||||||
function NodeIterator:matcher(f)
|
function NodeIterator:matcher(f)
|
||||||
self._match = f
|
self._match = f
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param f fun(node: Node, i: number)
|
||||||
|
---@return NodeIterator
|
||||||
function NodeIterator:applier(f)
|
function NodeIterator:applier(f)
|
||||||
self._apply_fn_on_node = f
|
self._apply_fn_on_node = f
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param f fun(node: Node): any
|
||||||
|
---@return NodeIterator
|
||||||
function NodeIterator:recursor(f)
|
function NodeIterator:recursor(f)
|
||||||
self._recurse_with = f
|
self._recurse_with = f
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return Node|nil
|
||||||
|
---@return number|nil
|
||||||
function NodeIterator:iterate()
|
function NodeIterator:iterate()
|
||||||
local iteration_count = 0
|
local iteration_count = 0
|
||||||
local function iter(nodes)
|
local function iter(nodes)
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
--- Apply mappings to a scratch buffer and return buffer local mappings
|
--- Apply mappings to a scratch buffer and return buffer local mappings
|
||||||
--- @param fn function(bufnr) on_attach or default_on_attach
|
---@param fn function(bufnr) on_attach or default_on_attach
|
||||||
--- @return table as per vim.api.nvim_buf_get_keymap
|
---@return table as per vim.api.nvim_buf_get_keymap
|
||||||
local function generate_keymap(fn)
|
local function generate_keymap(fn)
|
||||||
-- create an unlisted scratch buffer
|
-- create an unlisted scratch buffer
|
||||||
local scratch_bufnr = vim.api.nvim_create_buf(false, true)
|
local scratch_bufnr = vim.api.nvim_create_buf(false, true)
|
||||||
@ -20,6 +20,7 @@ local function generate_keymap(fn)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- stylua: ignore start
|
-- stylua: ignore start
|
||||||
|
---@param bufnr integer
|
||||||
function M.default_on_attach(bufnr)
|
function M.default_on_attach(bufnr)
|
||||||
local api = require('nvim-tree.api')
|
local api = require('nvim-tree.api')
|
||||||
|
|
||||||
@ -93,10 +94,12 @@ function M.default_on_attach(bufnr)
|
|||||||
end
|
end
|
||||||
-- stylua: ignore end
|
-- stylua: ignore end
|
||||||
|
|
||||||
|
---@return table
|
||||||
function M.get_keymap()
|
function M.get_keymap()
|
||||||
return generate_keymap(M.on_attach)
|
return generate_keymap(M.on_attach)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return table
|
||||||
function M.get_keymap_default()
|
function M.get_keymap_default()
|
||||||
return generate_keymap(M.default_on_attach)
|
return generate_keymap(M.default_on_attach)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -13,6 +13,7 @@ local M = {
|
|||||||
target_winid = nil,
|
target_winid = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@return Node|nil
|
||||||
function M.get_node_at_cursor()
|
function M.get_node_at_cursor()
|
||||||
if not core.get_explorer() then
|
if not core.get_explorer() then
|
||||||
return
|
return
|
||||||
@ -34,8 +35,8 @@ function M.get_node_at_cursor()
|
|||||||
end
|
end
|
||||||
|
|
||||||
---Create a sanitized partial copy of a node, populating children recursively.
|
---Create a sanitized partial copy of a node, populating children recursively.
|
||||||
---@param node table
|
---@param node Node|nil
|
||||||
---@return table|nil cloned node
|
---@return Node|nil cloned node
|
||||||
local function clone_node(node)
|
local function clone_node(node)
|
||||||
if not node then
|
if not node then
|
||||||
node = core.get_explorer()
|
node = core.get_explorer()
|
||||||
@ -68,19 +69,25 @@ local function clone_node(node)
|
|||||||
end
|
end
|
||||||
|
|
||||||
---Api.tree.get_nodes
|
---Api.tree.get_nodes
|
||||||
|
---@return Node[]|nil
|
||||||
function M.get_nodes()
|
function M.get_nodes()
|
||||||
return clone_node(core.get_explorer())
|
return clone_node(core.get_explorer())
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If node is grouped, return the last node in the group. Otherwise, return the given node.
|
-- 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)
|
function M.get_last_group_node(node)
|
||||||
local next_node = node
|
while node and node.group_next do
|
||||||
while next_node.group_next do
|
node = node.group_next
|
||||||
next_node = next_node.group_next
|
|
||||||
end
|
end
|
||||||
return next_node
|
|
||||||
|
---@diagnostic disable-next-line: return-type-mismatch -- it can't be nil
|
||||||
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return Node[]
|
||||||
function M.get_all_nodes_in_group(node)
|
function M.get_all_nodes_in_group(node)
|
||||||
local next_node = utils.get_parent_of_group(node)
|
local next_node = utils.get_parent_of_group(node)
|
||||||
local nodes = {}
|
local nodes = {}
|
||||||
@ -91,6 +98,7 @@ function M.get_all_nodes_in_group(node)
|
|||||||
return nodes
|
return nodes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
function M.expand_or_collapse(node)
|
function M.expand_or_collapse(node)
|
||||||
if node.has_children then
|
if node.has_children then
|
||||||
node.has_children = false
|
node.has_children = false
|
||||||
@ -119,6 +127,7 @@ function M.set_target_win()
|
|||||||
M.target_winid = id
|
M.target_winid = id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param cwd string
|
||||||
local function handle_buf_cwd(cwd)
|
local function handle_buf_cwd(cwd)
|
||||||
if M.respect_buf_cwd and cwd ~= core.get_cwd() then
|
if M.respect_buf_cwd and cwd ~= core.get_cwd() then
|
||||||
require("nvim-tree.actions.root.change-dir").fn(cwd)
|
require("nvim-tree.actions.root.change-dir").fn(cwd)
|
||||||
@ -144,6 +153,11 @@ local function should_hijack_current_buf()
|
|||||||
return should_hijack_dir or should_hijack_unnamed
|
return should_hijack_dir or should_hijack_unnamed
|
||||||
end
|
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)
|
function M.prompt(prompt_input, prompt_select, items_short, items_long, callback)
|
||||||
local function format_item(short)
|
local function format_item(short)
|
||||||
for i, s in ipairs(items_short) do
|
for i, s in ipairs(items_short) do
|
||||||
|
|||||||
@ -10,8 +10,14 @@ local function redraw()
|
|||||||
require("nvim-tree.renderer").draw()
|
require("nvim-tree.renderer").draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node_ Node|nil
|
||||||
local function reset_filter(node_)
|
local function reset_filter(node_)
|
||||||
node_ = node_ or require("nvim-tree.core").get_explorer()
|
node_ = node_ or require("nvim-tree.core").get_explorer()
|
||||||
|
|
||||||
|
if node_ == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
Iterator.builder(node_.nodes)
|
Iterator.builder(node_.nodes)
|
||||||
:hidden()
|
:hidden()
|
||||||
:applier(function(node)
|
:applier(function(node)
|
||||||
@ -47,12 +53,15 @@ local function remove_overlay()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node
|
||||||
|
---@return boolean
|
||||||
local function matches(node)
|
local function matches(node)
|
||||||
local path = node.absolute_path
|
local path = node.absolute_path
|
||||||
local name = vim.fn.fnamemodify(path, ":t")
|
local name = vim.fn.fnamemodify(path, ":t")
|
||||||
return vim.regex(M.filter):match_str(name) ~= nil
|
return vim.regex(M.filter):match_str(name) ~= nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node_ Node|nil
|
||||||
function M.apply_filter(node_)
|
function M.apply_filter(node_)
|
||||||
if not M.filter or M.filter == "" then
|
if not M.filter or M.filter == "" then
|
||||||
reset_filter(node_)
|
reset_filter(node_)
|
||||||
@ -105,6 +114,7 @@ local function configure_buffer_overlay()
|
|||||||
vim.api.nvim_buf_set_keymap(overlay_bufnr, "i", "<CR>", "<cmd>stopinsert<CR>", {})
|
vim.api.nvim_buf_set_keymap(overlay_bufnr, "i", "<CR>", "<cmd>stopinsert<CR>", {})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return integer
|
||||||
local function calculate_overlay_win_width()
|
local function calculate_overlay_win_width()
|
||||||
local wininfo = vim.fn.getwininfo(view.get_winnr())[1]
|
local wininfo = vim.fn.getwininfo(view.get_winnr())[1]
|
||||||
|
|
||||||
|
|||||||
@ -4,9 +4,9 @@ local M = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Write to log file
|
--- Write to log file
|
||||||
--- @param typ string as per log.types config
|
---@param typ string as per log.types config
|
||||||
--- @param fmt string for string.format
|
---@param fmt string for string.format
|
||||||
--- @vararg any arguments for string.format
|
---@param ... any arguments for string.format
|
||||||
function M.raw(typ, fmt, ...)
|
function M.raw(typ, fmt, ...)
|
||||||
if not M.enabled(typ) then
|
if not M.enabled(typ) then
|
||||||
return
|
return
|
||||||
@ -27,9 +27,9 @@ end
|
|||||||
|
|
||||||
--- Write profile start to log file
|
--- Write profile start to log file
|
||||||
--- START is prefixed
|
--- START is prefixed
|
||||||
--- @param fmt string for string.format
|
---@param fmt string for string.format
|
||||||
--- @vararg any arguments for string.format
|
---@param ... any arguments for string.format
|
||||||
--- @return Profile to pass to profile_end
|
---@return Profile to pass to profile_end
|
||||||
function M.profile_start(fmt, ...)
|
function M.profile_start(fmt, ...)
|
||||||
local profile = {}
|
local profile = {}
|
||||||
if M.enabled "profile" then
|
if M.enabled "profile" then
|
||||||
@ -42,7 +42,7 @@ end
|
|||||||
|
|
||||||
--- Write profile end to log file
|
--- Write profile end to log file
|
||||||
--- END is prefixed and duration in seconds is suffixed
|
--- END is prefixed and duration in seconds is suffixed
|
||||||
--- @param profile Profile returned from profile_start
|
---@param profile Profile returned from profile_start
|
||||||
function M.profile_end(profile)
|
function M.profile_end(profile)
|
||||||
if M.enabled "profile" and type(profile) == "table" then
|
if M.enabled "profile" and type(profile) == "table" then
|
||||||
local millis = profile.start and math.modf((vim.loop.hrtime() - profile.start) / 1000000) or -1
|
local millis = profile.start and math.modf((vim.loop.hrtime() - profile.start) / 1000000) or -1
|
||||||
@ -52,9 +52,9 @@ end
|
|||||||
|
|
||||||
--- Write to log file
|
--- Write to log file
|
||||||
--- time and typ are prefixed and a trailing newline is added
|
--- time and typ are prefixed and a trailing newline is added
|
||||||
--- @param typ string as per log.types config
|
---@param typ string as per log.types config
|
||||||
--- @param fmt string for string.format
|
---@param fmt string for string.format
|
||||||
--- @vararg any arguments for string.format
|
---@param ... any arguments for string.format
|
||||||
function M.line(typ, fmt, ...)
|
function M.line(typ, fmt, ...)
|
||||||
if M.enabled(typ) then
|
if M.enabled(typ) then
|
||||||
M.raw(typ, string.format("[%s] [%s] %s\n", os.date "%Y-%m-%d %H:%M:%S", typ, (fmt or "???")), ...)
|
M.raw(typ, string.format("[%s] [%s] %s\n", os.date "%Y-%m-%d %H:%M:%S", typ, (fmt or "???")), ...)
|
||||||
@ -63,17 +63,17 @@ end
|
|||||||
|
|
||||||
local inspect_opts = {}
|
local inspect_opts = {}
|
||||||
|
|
||||||
--- @param opts table
|
---@param opts table
|
||||||
function M.set_inspect_opts(opts)
|
function M.set_inspect_opts(opts)
|
||||||
inspect_opts = opts
|
inspect_opts = opts
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Write to log file the inspection of a node
|
--- Write to log file the inspection of a node
|
||||||
--- defaults to the node under cursor if none is provided
|
--- defaults to the node under cursor if none is provided
|
||||||
--- @param typ string as per log.types config
|
---@param typ string as per log.types config
|
||||||
--- @param node table|nil node to be inspected
|
---@param node table|nil node to be inspected
|
||||||
--- @param fmt string for string.format
|
---@param fmt string for string.format
|
||||||
--- @vararg any arguments for string.format
|
---@vararg any arguments for string.format
|
||||||
function M.node(typ, node, fmt, ...)
|
function M.node(typ, node, fmt, ...)
|
||||||
if M.enabled(typ) then
|
if M.enabled(typ) then
|
||||||
node = node or require("nvim-tree.lib").get_node_at_cursor()
|
node = node or require("nvim-tree.lib").get_node_at_cursor()
|
||||||
@ -82,8 +82,8 @@ function M.node(typ, node, fmt, ...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Logging is enabled for typ or all
|
--- Logging is enabled for typ or all
|
||||||
--- @param typ string as per log.types config
|
---@param typ string as per log.types config
|
||||||
--- @return boolean
|
---@return boolean
|
||||||
function M.enabled(typ)
|
function M.enabled(typ)
|
||||||
return M.path ~= nil and (M.config.types[typ] or M.config.types.all)
|
return M.path ~= nil and (M.config.types[typ] or M.config.types.all)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,7 +9,7 @@ local M = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Delete nodes; each removal will be optionally notified
|
--- Delete nodes; each removal will be optionally notified
|
||||||
--- @param nodes table
|
---@param nodes Node[]
|
||||||
local function do_delete(nodes)
|
local function do_delete(nodes)
|
||||||
for _, node in pairs(nodes) do
|
for _, node in pairs(nodes) do
|
||||||
remove_file.remove(node)
|
remove_file.remove(node)
|
||||||
|
|||||||
@ -9,7 +9,7 @@ local M = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Delete nodes; each removal will be optionally notified
|
--- Delete nodes; each removal will be optionally notified
|
||||||
--- @param nodes table
|
---@param nodes Node[]
|
||||||
local function do_trash(nodes)
|
local function do_trash(nodes)
|
||||||
for _, node in pairs(nodes) do
|
for _, node in pairs(nodes) do
|
||||||
remove_file.remove(node)
|
remove_file.remove(node)
|
||||||
|
|||||||
@ -4,18 +4,24 @@ local NvimTreeMarks = {}
|
|||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
|
---@class MinimalNode
|
||||||
|
---@field absolute_path string
|
||||||
|
|
||||||
|
---@param node Node|MinimalNode
|
||||||
local function add_mark(node)
|
local function add_mark(node)
|
||||||
NvimTreeMarks[node.absolute_path] = node
|
NvimTreeMarks[node.absolute_path] = node
|
||||||
|
|
||||||
renderer.draw()
|
renderer.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node|MinimalNode
|
||||||
local function remove_mark(node)
|
local function remove_mark(node)
|
||||||
NvimTreeMarks[node.absolute_path] = nil
|
NvimTreeMarks[node.absolute_path] = nil
|
||||||
|
|
||||||
renderer.draw()
|
renderer.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node|MinimalNode
|
||||||
function M.toggle_mark(node)
|
function M.toggle_mark(node)
|
||||||
if node.absolute_path == nil then
|
if node.absolute_path == nil then
|
||||||
return
|
return
|
||||||
@ -36,10 +42,13 @@ function M.clear_marks()
|
|||||||
renderer.draw()
|
renderer.draw()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node Node|MinimalNode
|
||||||
|
---@return table|nil
|
||||||
function M.get_mark(node)
|
function M.get_mark(node)
|
||||||
return NvimTreeMarks[node.absolute_path]
|
return NvimTreeMarks[node.absolute_path]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return table
|
||||||
function M.get_marks()
|
function M.get_marks()
|
||||||
local list = {}
|
local list = {}
|
||||||
for _, node in pairs(NvimTreeMarks) do
|
for _, node in pairs(NvimTreeMarks) do
|
||||||
|
|||||||
@ -5,6 +5,9 @@ local open_file = require "nvim-tree.actions.node.open-file"
|
|||||||
local utils = require "nvim-tree.utils"
|
local utils = require "nvim-tree.utils"
|
||||||
local lib = require "nvim-tree.lib"
|
local lib = require "nvim-tree.lib"
|
||||||
|
|
||||||
|
---@param node table
|
||||||
|
---@param where string
|
||||||
|
---@return Node|nil
|
||||||
local function get_nearest(node, where)
|
local function get_nearest(node, where)
|
||||||
local first, prev, next, last = nil, nil, nil, nil
|
local first, prev, next, last = nil, nil, nil, nil
|
||||||
local found = false
|
local found = false
|
||||||
@ -47,12 +50,16 @@ local function get_nearest(node, where)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param where string
|
||||||
|
---@param node table|nil
|
||||||
|
---@return Node|nil
|
||||||
local function get(where, node)
|
local function get(where, node)
|
||||||
if node then
|
if node then
|
||||||
return get_nearest(node, where)
|
return get_nearest(node, where)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param node table|nil
|
||||||
local function open_or_focus(node)
|
local function open_or_focus(node)
|
||||||
if node and not node.nodes and not utils.get_win_buf_from_path(node.absolute_path) then
|
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)
|
open_file.fn("edit", node.absolute_path)
|
||||||
@ -61,6 +68,8 @@ local function open_or_focus(node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param where string
|
||||||
|
---@return function
|
||||||
local function navigate_to(where)
|
local function navigate_to(where)
|
||||||
return function()
|
return function()
|
||||||
local node = lib.get_node_at_cursor()
|
local node = lib.get_node_at_cursor()
|
||||||
|
|||||||
@ -23,7 +23,7 @@ function M.reload()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param node table
|
---@param node Node
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function M.is_modified(node)
|
function M.is_modified(node)
|
||||||
return M.config.enable
|
return M.config.enable
|
||||||
|
|||||||
37
lua/nvim-tree/node.lua
Normal file
37
lua/nvim-tree/node.lua
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
---@meta
|
||||||
|
|
||||||
|
-- TODO add "${3rd}/luv/library" to "workspace.library"
|
||||||
|
---@class uv.uv_req_t: table
|
||||||
|
---@class uv.uv_fs_t: uv.uv_req_t
|
||||||
|
|
||||||
|
---@class ParentNode
|
||||||
|
---@field name string
|
||||||
|
|
||||||
|
---@class BaseNode
|
||||||
|
---@field absolute_path string
|
||||||
|
---@field executable boolean
|
||||||
|
---@field fs_stat uv.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
|
||||||
|
|
||||||
|
---@class SymlinkDirNode: DirNode
|
||||||
|
---@field link_to string
|
||||||
|
|
||||||
|
---@class SymlinkFileNode: FileNode
|
||||||
|
---@field link_to string
|
||||||
|
|
||||||
|
---@alias SymlinkNode SymlinkDirNode|SymlinkFileNode
|
||||||
|
---@alias Node ParentNode|DirNode|FileNode|SymlinkNode|Explorer
|
||||||
@ -6,6 +6,7 @@ local config = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local title_support
|
local title_support
|
||||||
|
---@return boolean
|
||||||
function M.supports_title()
|
function M.supports_title()
|
||||||
if title_support == nil then
|
if title_support == nil then
|
||||||
title_support = (package.loaded.notify and (vim.notify == require "notify" or vim.notify == require("notify").notify))
|
title_support = (package.loaded.notify and (vim.notify == require "notify" or vim.notify == require("notify").notify))
|
||||||
@ -48,6 +49,8 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return string
|
||||||
function M.render_path(path)
|
function M.render_path(path)
|
||||||
if config.absolute_path then
|
if config.absolute_path then
|
||||||
return path
|
return path
|
||||||
|
|||||||
@ -11,10 +11,15 @@ M.is_wsl = vim.fn.has "wsl" == 1
|
|||||||
-- false for WSL
|
-- false for WSL
|
||||||
M.is_windows = vim.fn.has "win32" == 1 or vim.fn.has "win32unix" == 1
|
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)
|
function M.str_find(haystack, needle)
|
||||||
return vim.fn.stridx(haystack, needle) ~= -1
|
return vim.fn.stridx(haystack, needle) ~= -1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return string|uv.uv_fs_t
|
||||||
function M.read_file(path)
|
function M.read_file(path)
|
||||||
local fd = vim.loop.fs_open(path, "r", 438)
|
local fd = vim.loop.fs_open(path, "r", 438)
|
||||||
if not fd then
|
if not fd then
|
||||||
@ -30,15 +35,19 @@ function M.read_file(path)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local path_separator = package.config:sub(1, 1)
|
local path_separator = package.config:sub(1, 1)
|
||||||
|
---@param paths string[]
|
||||||
|
---@return string
|
||||||
function M.path_join(paths)
|
function M.path_join(paths)
|
||||||
return table.concat(vim.tbl_map(M.path_remove_trailing, paths), path_separator)
|
return table.concat(vim.tbl_map(M.path_remove_trailing, paths), path_separator)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return fun(): string
|
||||||
function M.path_split(path)
|
function M.path_split(path)
|
||||||
return path:gmatch("[^" .. path_separator .. "]+" .. path_separator .. "?")
|
return path:gmatch("[^" .. path_separator .. "]+" .. path_separator .. "?")
|
||||||
end
|
end
|
||||||
|
|
||||||
---Get the basename of the given path.
|
--- Get the basename of the given path.
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return string
|
---@return string
|
||||||
function M.path_basename(path)
|
function M.path_basename(path)
|
||||||
@ -50,11 +59,15 @@ function M.path_basename(path)
|
|||||||
return path:sub(i + 1, #path)
|
return path:sub(i + 1, #path)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Get a path relative to another path.
|
--- Get a path relative to another path.
|
||||||
---@param path string
|
---@param path string
|
||||||
---@param relative_to string
|
---@param relative_to string|nil
|
||||||
---@return string
|
---@return string
|
||||||
function M.path_relative(path, relative_to)
|
function M.path_relative(path, relative_to)
|
||||||
|
if relative_to == nil then
|
||||||
|
return path
|
||||||
|
end
|
||||||
|
|
||||||
local _, r = path:find(M.path_add_trailing(relative_to), 1, true)
|
local _, r = path:find(M.path_add_trailing(relative_to), 1, true)
|
||||||
local p = path
|
local p = path
|
||||||
if r then
|
if r then
|
||||||
@ -66,6 +79,8 @@ function M.path_relative(path, relative_to)
|
|||||||
return p
|
return p
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return string
|
||||||
function M.path_add_trailing(path)
|
function M.path_add_trailing(path)
|
||||||
if path:sub(-1) == path_separator then
|
if path:sub(-1) == path_separator then
|
||||||
return path
|
return path
|
||||||
@ -74,6 +89,8 @@ function M.path_add_trailing(path)
|
|||||||
return path .. path_separator
|
return path .. path_separator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return string
|
||||||
function M.path_remove_trailing(path)
|
function M.path_remove_trailing(path)
|
||||||
local p, _ = path:gsub(path_separator .. "$", "")
|
local p, _ = path:gsub(path_separator .. "$", "")
|
||||||
return p
|
return p
|
||||||
@ -81,10 +98,12 @@ end
|
|||||||
|
|
||||||
M.path_separator = path_separator
|
M.path_separator = path_separator
|
||||||
|
|
||||||
-- get the node and index of the node from the tree that matches the predicate.
|
--- Get the node and index of the node from the tree that matches the predicate.
|
||||||
-- The explored nodes are those displayed on the view.
|
--- The explored nodes are those displayed on the view.
|
||||||
-- @param nodes list of node
|
---@param nodes Node[]
|
||||||
-- @param fn function(node): boolean
|
---@param fn fun(node: Node): boolean
|
||||||
|
---@return table|nil
|
||||||
|
---@return number
|
||||||
function M.find_node(nodes, fn)
|
function M.find_node(nodes, fn)
|
||||||
local node, i = Iterator.builder(nodes)
|
local node, i = Iterator.builder(nodes)
|
||||||
:matcher(fn)
|
:matcher(fn)
|
||||||
@ -99,6 +118,9 @@ end
|
|||||||
|
|
||||||
-- get the node in the tree state depending on the absolute path of the node
|
-- get the node in the tree state depending on the absolute path of the node
|
||||||
-- (grouped or hidden too)
|
-- (grouped or hidden too)
|
||||||
|
---@param path string
|
||||||
|
---@return Node|nil
|
||||||
|
---@return number|nil
|
||||||
function M.get_node_from_path(path)
|
function M.get_node_from_path(path)
|
||||||
local explorer = require("nvim-tree.core").get_explorer()
|
local explorer = require("nvim-tree.core").get_explorer()
|
||||||
|
|
||||||
@ -127,7 +149,9 @@ function M.get_node_from_path(path)
|
|||||||
:iterate()
|
:iterate()
|
||||||
end
|
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_)
|
function M.get_parent_of_group(node_)
|
||||||
local node = node_
|
local node = node_
|
||||||
while node.parent and node.parent.group_next do
|
while node.parent and node.parent.group_next do
|
||||||
@ -136,9 +160,9 @@ function M.get_parent_of_group(node_)
|
|||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
-- return visible nodes indexed by line
|
--- Return visible nodes indexed by line
|
||||||
-- @param nodes_all list of node
|
---@param nodes_all Node[]
|
||||||
-- @param line_start first index
|
---@param line_start number
|
||||||
---@return table
|
---@return table
|
||||||
function M.get_nodes_by_line(nodes_all, line_start)
|
function M.get_nodes_by_line(nodes_all, line_start)
|
||||||
local nodes_by_line = {}
|
local nodes_by_line = {}
|
||||||
@ -192,15 +216,15 @@ function M.rename_loaded_buffers(old_path, new_path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param path string path to file or directory
|
---@param path string path to file or directory
|
||||||
--- @return boolean
|
---@return boolean
|
||||||
function M.file_exists(path)
|
function M.file_exists(path)
|
||||||
local _, error = vim.loop.fs_stat(path)
|
local _, error = vim.loop.fs_stat(path)
|
||||||
return error == nil
|
return error == nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param path string
|
---@param path string
|
||||||
--- @return string
|
---@return string
|
||||||
function M.canonical_path(path)
|
function M.canonical_path(path)
|
||||||
if M.is_windows and path:match "^%a:" then
|
if M.is_windows and path:match "^%a:" then
|
||||||
return path:sub(1, 1):upper() .. path:sub(2)
|
return path:sub(1, 1):upper() .. path:sub(2)
|
||||||
@ -208,9 +232,9 @@ function M.canonical_path(path)
|
|||||||
return path
|
return path
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Escapes special characters in string if windows else returns unmodified string.
|
--- Escapes special characters in string if windows else returns unmodified string.
|
||||||
-- @param path string
|
---@param path string
|
||||||
-- @return path
|
---@return string|nil
|
||||||
function M.escape_special_chars(path)
|
function M.escape_special_chars(path)
|
||||||
if path == nil then
|
if path == nil then
|
||||||
return path
|
return path
|
||||||
@ -218,10 +242,10 @@ function M.escape_special_chars(path)
|
|||||||
return M.is_windows and path:gsub("%(", "\\("):gsub("%)", "\\)") or path
|
return M.is_windows and path:gsub("%(", "\\("):gsub("%)", "\\)") or path
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create empty sub-tables if not present
|
--- Create empty sub-tables if not present
|
||||||
-- @param tbl to create empty inside of
|
---@param tbl table to create empty inside of
|
||||||
-- @param path dot separated string of sub-tables
|
---@param path string dot separated string of sub-tables
|
||||||
-- @return table deepest sub-table
|
---@return table deepest sub-table
|
||||||
function M.table_create_missing(tbl, path)
|
function M.table_create_missing(tbl, path)
|
||||||
local t = tbl
|
local t = tbl
|
||||||
for s in string.gmatch(path, "([^%.]+)%.*") do
|
for s in string.gmatch(path, "([^%.]+)%.*") do
|
||||||
@ -236,13 +260,13 @@ end
|
|||||||
|
|
||||||
--- Move a value from src to dst if value is nil on dst.
|
--- Move a value from src to dst if value is nil on dst.
|
||||||
--- Remove value from src
|
--- Remove value from src
|
||||||
--- @param src table to copy from
|
---@param src table to copy from
|
||||||
--- @param src_path string dot separated string of sub-tables
|
---@param src_path string dot separated string of sub-tables
|
||||||
--- @param src_pos string value pos
|
---@param src_pos string value pos
|
||||||
--- @param dst table to copy to
|
---@param dst table to copy to
|
||||||
--- @param dst_path string dot separated string of sub-tables, created when missing
|
---@param dst_path string dot separated string of sub-tables, created when missing
|
||||||
--- @param dst_pos string value pos
|
---@param dst_pos string value pos
|
||||||
--- @param remove boolean
|
---@param remove boolean
|
||||||
function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos, remove)
|
function M.move_missing_val(src, src_path, src_pos, dst, dst_path, dst_pos, remove)
|
||||||
local ok, err = pcall(vim.validate, {
|
local ok, err = pcall(vim.validate, {
|
||||||
src = { src, "table" },
|
src = { src, "table" },
|
||||||
@ -395,7 +419,7 @@ end
|
|||||||
---Focus node passed as parameter if visible, otherwise focus first visible parent.
|
---Focus node passed as parameter if visible, otherwise focus first visible parent.
|
||||||
---If none of the parents is visible focus root.
|
---If none of the parents is visible focus root.
|
||||||
---If node is nil do nothing.
|
---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)
|
function M.focus_node_or_parent(node)
|
||||||
local explorer = require("nvim-tree.core").get_explorer()
|
local explorer = require("nvim-tree.core").get_explorer()
|
||||||
|
|
||||||
@ -417,6 +441,9 @@ function M.focus_node_or_parent(node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return integer|nil
|
||||||
|
---@return integer|nil
|
||||||
function M.get_win_buf_from_path(path)
|
function M.get_win_buf_from_path(path)
|
||||||
for _, w in pairs(vim.api.nvim_tabpage_list_wins(0)) do
|
for _, w in pairs(vim.api.nvim_tabpage_list_wins(0)) do
|
||||||
local b = vim.api.nvim_win_get_buf(w)
|
local b = vim.api.nvim_win_get_buf(w)
|
||||||
@ -433,7 +460,9 @@ function M.clear_prompt()
|
|||||||
end
|
end
|
||||||
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)
|
function M.array_shallow_clone(array)
|
||||||
local to = {}
|
local to = {}
|
||||||
for _, v in ipairs(array) do
|
for _, v in ipairs(array) do
|
||||||
@ -443,9 +472,9 @@ function M.array_shallow_clone(array)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Remove and return item from array if present.
|
--- Remove and return item from array if present.
|
||||||
--- @param array table
|
---@param array table
|
||||||
--- @param item any
|
---@param item any
|
||||||
--- @return any|nil removed
|
---@return any|nil removed
|
||||||
function M.array_remove(array, item)
|
function M.array_remove(array, item)
|
||||||
if not array then
|
if not array then
|
||||||
return nil
|
return nil
|
||||||
@ -458,20 +487,24 @@ function M.array_remove(array, item)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param array table
|
||||||
|
---@return table
|
||||||
function M.array_remove_nils(array)
|
function M.array_remove_nils(array)
|
||||||
return vim.tbl_filter(function(v)
|
return vim.tbl_filter(function(v)
|
||||||
return v ~= nil
|
return v ~= nil
|
||||||
end, array)
|
end, array)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param f fun(node: Node|nil)
|
||||||
|
---@return function
|
||||||
function M.inject_node(f)
|
function M.inject_node(f)
|
||||||
return function()
|
return function()
|
||||||
f(require("nvim-tree.lib").get_node_at_cursor())
|
f(require("nvim-tree.lib").get_node_at_cursor())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---Is the buffer named NvimTree_[0-9]+ a tree? filetype is "NvimTree" or not readable file.
|
--- 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.
|
--- 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
|
---@param bufnr number|nil may be 0 or nil for current
|
||||||
---@return boolean
|
---@return boolean
|
||||||
function M.is_nvim_tree_buf(bufnr)
|
function M.is_nvim_tree_buf(bufnr)
|
||||||
|
|||||||
@ -72,6 +72,8 @@ local BUFFER_OPTIONS = {
|
|||||||
buflisted = false,
|
buflisted = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param bufnr integer
|
||||||
|
---@return boolean
|
||||||
local function matches_bufnr(bufnr)
|
local function matches_bufnr(bufnr)
|
||||||
for _, b in pairs(BUFNR_PER_TAB) do
|
for _, b in pairs(BUFNR_PER_TAB) do
|
||||||
if b == bufnr then
|
if b == bufnr then
|
||||||
@ -89,6 +91,7 @@ local function wipe_rogue_buffer()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param bufnr integer|boolean|nil
|
||||||
local function create_buffer(bufnr)
|
local function create_buffer(bufnr)
|
||||||
wipe_rogue_buffer()
|
wipe_rogue_buffer()
|
||||||
|
|
||||||
@ -105,6 +108,8 @@ local function create_buffer(bufnr)
|
|||||||
events._dispatch_tree_attached_post(M.get_bufnr())
|
events._dispatch_tree_attached_post(M.get_bufnr())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param size number|fun():number
|
||||||
|
---@return integer
|
||||||
local function get_size(size)
|
local function get_size(size)
|
||||||
if type(size) == "number" then
|
if type(size) == "number" then
|
||||||
return size
|
return size
|
||||||
@ -116,6 +121,7 @@ local function get_size(size)
|
|||||||
return math.floor(vim.o.columns * percent_as_decimal)
|
return math.floor(vim.o.columns * percent_as_decimal)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param size number|function|nil
|
||||||
local function get_width(size)
|
local function get_width(size)
|
||||||
size = size or M.View.width
|
size = size or M.View.width
|
||||||
return get_size(size)
|
return get_size(size)
|
||||||
@ -127,6 +133,7 @@ local move_tbl = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- setup_tabpage sets up the initial state of a tab
|
-- setup_tabpage sets up the initial state of a tab
|
||||||
|
---@param tabpage integer
|
||||||
local function setup_tabpage(tabpage)
|
local function setup_tabpage(tabpage)
|
||||||
local winnr = vim.api.nvim_get_current_win()
|
local winnr = vim.api.nvim_get_current_win()
|
||||||
M.View.tabpages[tabpage] = vim.tbl_extend("force", M.View.tabpages[tabpage] or tabinitial, { winnr = winnr })
|
M.View.tabpages[tabpage] = vim.tbl_extend("force", M.View.tabpages[tabpage] or tabinitial, { winnr = winnr })
|
||||||
@ -142,6 +149,7 @@ local function set_window_options_and_buffer()
|
|||||||
vim.opt.eventignore = eventignore
|
vim.opt.eventignore = eventignore
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return table
|
||||||
local function open_win_config()
|
local function open_win_config()
|
||||||
if type(M.View.float.open_win_config) == "function" then
|
if type(M.View.float.open_win_config) == "function" then
|
||||||
return M.View.float.open_win_config()
|
return M.View.float.open_win_config()
|
||||||
@ -161,10 +169,13 @@ local function open_window()
|
|||||||
set_window_options_and_buffer()
|
set_window_options_and_buffer()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param buf integer
|
||||||
|
---@return boolean
|
||||||
local function is_buf_displayed(buf)
|
local function is_buf_displayed(buf)
|
||||||
return vim.api.nvim_buf_is_valid(buf) and vim.fn.buflisted(buf) == 1
|
return vim.api.nvim_buf_is_valid(buf) and vim.fn.buflisted(buf) == 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return number|nil
|
||||||
local function get_alt_or_next_buf()
|
local function get_alt_or_next_buf()
|
||||||
local alt_buf = vim.fn.bufnr "#"
|
local alt_buf = vim.fn.bufnr "#"
|
||||||
if is_buf_displayed(alt_buf) then
|
if is_buf_displayed(alt_buf) then
|
||||||
@ -190,11 +201,13 @@ local function switch_buf_if_last_buf()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- save_tab_state saves any state that should be preserved across redraws.
|
-- save_tab_state saves any state that should be preserved across redraws.
|
||||||
|
---@param tabnr integer
|
||||||
local function save_tab_state(tabnr)
|
local function save_tab_state(tabnr)
|
||||||
local tabpage = tabnr or vim.api.nvim_get_current_tabpage()
|
local tabpage = tabnr or vim.api.nvim_get_current_tabpage()
|
||||||
M.View.cursors[tabpage] = vim.api.nvim_win_get_cursor(M.get_winnr(tabpage))
|
M.View.cursors[tabpage] = vim.api.nvim_win_get_cursor(M.get_winnr(tabpage))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param tabpage integer
|
||||||
local function close(tabpage)
|
local function close(tabpage)
|
||||||
if not M.is_visible { tabpage = tabpage } then
|
if not M.is_visible { tabpage = tabpage } then
|
||||||
return
|
return
|
||||||
@ -236,6 +249,7 @@ function M.close()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param options table|nil
|
||||||
function M.open(options)
|
function M.open(options)
|
||||||
if M.is_visible() then
|
if M.is_visible() then
|
||||||
return
|
return
|
||||||
@ -297,6 +311,7 @@ function M.grow_from_content()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param size string|number|nil
|
||||||
function M.resize(size)
|
function M.resize(size)
|
||||||
if M.View.float.enable and not M.View.adaptive_size then
|
if M.View.float.enable and not M.View.adaptive_size then
|
||||||
-- if the floating windows's adaptive size is not desired, then the
|
-- if the floating windows's adaptive size is not desired, then the
|
||||||
@ -386,6 +401,7 @@ function M.abandon_all_windows()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param opts table|nil
|
||||||
function M.is_visible(opts)
|
function M.is_visible(opts)
|
||||||
if opts and opts.tabpage then
|
if opts and opts.tabpage then
|
||||||
if M.View.tabpages[opts.tabpage] == nil then
|
if M.View.tabpages[opts.tabpage] == nil then
|
||||||
@ -407,12 +423,15 @@ function M.is_visible(opts)
|
|||||||
return M.get_winnr() ~= nil and vim.api.nvim_win_is_valid(M.get_winnr())
|
return M.get_winnr() ~= nil and vim.api.nvim_win_is_valid(M.get_winnr())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param opts table|nil
|
||||||
function M.set_cursor(opts)
|
function M.set_cursor(opts)
|
||||||
if M.is_visible() then
|
if M.is_visible() then
|
||||||
pcall(vim.api.nvim_win_set_cursor, M.get_winnr(), opts)
|
pcall(vim.api.nvim_win_set_cursor, M.get_winnr(), opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param winnr number|nil
|
||||||
|
---@param open_if_closed boolean|nil
|
||||||
function M.focus(winnr, open_if_closed)
|
function M.focus(winnr, open_if_closed)
|
||||||
local wnr = winnr or M.get_winnr()
|
local wnr = winnr or M.get_winnr()
|
||||||
|
|
||||||
@ -428,8 +447,8 @@ function M.focus(winnr, open_if_closed)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Retrieve the winid of the open tree.
|
--- Retrieve the winid of the open tree.
|
||||||
--- @param opts ApiTreeWinIdOpts|nil
|
---@param opts ApiTreeWinIdOpts|nil
|
||||||
--- @return number|nil winid unlike get_winnr(), this returns nil if the nvim-tree window is not visible
|
---@return number|nil winid unlike get_winnr(), this returns nil if the nvim-tree window is not visible
|
||||||
function M.winid(opts)
|
function M.winid(opts)
|
||||||
local tabpage = opts and opts.tabpage
|
local tabpage = opts and opts.tabpage
|
||||||
if tabpage == 0 then
|
if tabpage == 0 then
|
||||||
@ -465,6 +484,8 @@ function M.get_bufnr()
|
|||||||
return BUFNR_PER_TAB[vim.api.nvim_get_current_tabpage()]
|
return BUFNR_PER_TAB[vim.api.nvim_get_current_tabpage()]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param bufnr number
|
||||||
|
---@return boolean
|
||||||
function M.is_buf_valid(bufnr)
|
function M.is_buf_valid(bufnr)
|
||||||
return bufnr and vim.api.nvim_buf_is_valid(bufnr) and vim.api.nvim_buf_is_loaded(bufnr)
|
return bufnr and vim.api.nvim_buf_is_valid(bufnr) and vim.api.nvim_buf_is_loaded(bufnr)
|
||||||
end
|
end
|
||||||
@ -512,6 +533,8 @@ function M._prevent_buffer_override()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param cwd string|nil
|
||||||
|
---@return boolean
|
||||||
function M.is_root_folder_visible(cwd)
|
function M.is_root_folder_visible(cwd)
|
||||||
return cwd ~= "/" and not M.View.hide_root_folder
|
return cwd ~= "/" and not M.View.hide_root_folder
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6,11 +6,13 @@ local M = {
|
|||||||
config = {},
|
config = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@class Event
|
||||||
local Event = {
|
local Event = {
|
||||||
_events = {},
|
_events = {},
|
||||||
}
|
}
|
||||||
Event.__index = Event
|
Event.__index = Event
|
||||||
|
|
||||||
|
---@class Watcher
|
||||||
local Watcher = {
|
local Watcher = {
|
||||||
_watchers = {},
|
_watchers = {},
|
||||||
}
|
}
|
||||||
@ -23,6 +25,8 @@ local FS_EVENT_FLAGS = {
|
|||||||
recursive = false,
|
recursive = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@return Event|nil
|
||||||
function Event:new(path)
|
function Event:new(path)
|
||||||
log.line("watcher", "Event:new '%s'", path)
|
log.line("watcher", "Event:new '%s'", path)
|
||||||
|
|
||||||
@ -40,6 +44,7 @@ function Event:new(path)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@return boolean
|
||||||
function Event:start()
|
function Event:start()
|
||||||
log.line("watcher", "Event:start '%s'", self._path)
|
log.line("watcher", "Event:start '%s'", self._path)
|
||||||
|
|
||||||
@ -84,10 +89,12 @@ function Event:start()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param listener function
|
||||||
function Event:add(listener)
|
function Event:add(listener)
|
||||||
table.insert(self._listeners, listener)
|
table.insert(self._listeners, listener)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param listener function
|
||||||
function Event:remove(listener)
|
function Event:remove(listener)
|
||||||
utils.array_remove(self._listeners, listener)
|
utils.array_remove(self._listeners, listener)
|
||||||
if #self._listeners == 0 then
|
if #self._listeners == 0 then
|
||||||
@ -95,6 +102,7 @@ function Event:remove(listener)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param message string|nil
|
||||||
function Event:destroy(message)
|
function Event:destroy(message)
|
||||||
log.line("watcher", "Event:destroy '%s'", self._path)
|
log.line("watcher", "Event:destroy '%s'", self._path)
|
||||||
|
|
||||||
@ -115,6 +123,11 @@ function Event:destroy(message)
|
|||||||
self.destroyed = true
|
self.destroyed = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param path string
|
||||||
|
---@param files string[]|nil
|
||||||
|
---@param callback function
|
||||||
|
---@param data table
|
||||||
|
---@return Watcher|nil
|
||||||
function Watcher:new(path, files, callback, data)
|
function Watcher:new(path, files, callback, data)
|
||||||
log.line("watcher", "Watcher:new '%s' %s", path, vim.inspect(files))
|
log.line("watcher", "Watcher:new '%s' %s", path, vim.inspect(files))
|
||||||
|
|
||||||
@ -160,7 +173,7 @@ end
|
|||||||
M.Watcher = Watcher
|
M.Watcher = Watcher
|
||||||
|
|
||||||
--- Permanently disable watchers and purge all state following a catastrophic error.
|
--- Permanently disable watchers and purge all state following a catastrophic error.
|
||||||
--- @param msg string
|
---@param msg string
|
||||||
function M.disable_watchers(msg)
|
function M.disable_watchers(msg)
|
||||||
notify.warn(string.format("Disabling watchers: %s", msg))
|
notify.warn(string.format("Disabling watchers: %s", msg))
|
||||||
M.config.filesystem_watchers.enable = false
|
M.config.filesystem_watchers.enable = false
|
||||||
@ -181,8 +194,8 @@ end
|
|||||||
|
|
||||||
--- Windows NT will present directories that cannot be enumerated.
|
--- Windows NT will present directories that cannot be enumerated.
|
||||||
--- Detect these by attempting to start an event monitor.
|
--- Detect these by attempting to start an event monitor.
|
||||||
--- @param path string
|
---@param path string
|
||||||
--- @return boolean
|
---@return boolean
|
||||||
function M.is_fs_event_capable(path)
|
function M.is_fs_event_capable(path)
|
||||||
if not utils.is_windows then
|
if not utils.is_windows then
|
||||||
return true
|
return true
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user