Merge branch 'master' into 2941-move-lib-to-explorer

This commit is contained in:
Alexander Courtis
2024-10-25 12:34:25 +11:00
6 changed files with 67 additions and 41 deletions

View File

@@ -2,6 +2,8 @@ local log = require("nvim-tree.log")
local view = require("nvim-tree.view") local view = require("nvim-tree.view")
local utils = require("nvim-tree.utils") local utils = require("nvim-tree.utils")
local core = require("nvim-tree.core") local core = require("nvim-tree.core")
local DirectoryNode = require("nvim-tree.node.directory")
local Iterator = require("nvim-tree.iterators.node-iterator") local Iterator = require("nvim-tree.iterators.node-iterator")
local M = {} local M = {}
@@ -59,19 +61,27 @@ function M.fn(path)
local link_match = node.link_to and vim.startswith(path_real, node.link_to .. utils.path_separator) local link_match = node.link_to and vim.startswith(path_real, node.link_to .. utils.path_separator)
if abs_match or link_match then if abs_match or link_match then
if not node.group_next then local dir = node:as(DirectoryNode)
node.open = true if dir then
if not dir.group_next then
dir.open = true
end end
if #node.nodes == 0 then if #dir.nodes == 0 then
core.get_explorer():expand(node) core.get_explorer():expand(dir)
if node.group_next and incremented_line then if dir.group_next and incremented_line then
line = line - 1 line = line - 1
end end
end end
end end
end
end) end)
:recursor(function(node) :recursor(function(node)
node = node and node:as(DirectoryNode)
if node then
return node.group_next and { node.group_next } or (node.open and #node.nodes > 0 and node.nodes) return node.group_next and { node.group_next } or (node.open and #node.nodes > 0 and node.nodes)
else
return nil
end
end) end)
:iterate() :iterate()

View File

@@ -72,7 +72,7 @@ local function move(explorer, where, what, skip_gitignored)
end end
end end
---@param node Node ---@param node DirectoryNode
local function expand_node(node) local function expand_node(node)
if node:is(DirectoryNode) and not node.open then if node:is(DirectoryNode) and not node.open then
---@cast node DirectoryNode ---@cast node DirectoryNode
@@ -101,9 +101,9 @@ local function move_next_recursive(explorer, what, skip_gitignored)
if node_init.name ~= ".." then -- root node cannot have a status if node_init.name ~= ".." then -- root node cannot have a status
valid = status_is_valid(node_init, what, skip_gitignored) valid = status_is_valid(node_init, what, skip_gitignored)
end end
if node_init:is(DirectoryNode) and valid and not node_init.open then local node_dir = node_init:as(DirectoryNode)
---@cast node_init DirectoryNode if node_dir and valid and not node_dir.open then
node_init:expand_or_collapse(false) node_dir:expand_or_collapse(false)
end end
move(explorer, "next", what, skip_gitignored) move(explorer, "next", what, skip_gitignored)
@@ -120,20 +120,15 @@ local function move_next_recursive(explorer, what, skip_gitignored)
-- i is used to limit iterations. -- i is used to limit iterations.
local i = 0 local i = 0
local is_dir = node_cur.nodes ~= nil local dir_cur = node_cur:as(DirectoryNode)
while is_dir and i < MAX_DEPTH do while dir_cur and i < MAX_DEPTH do
expand_node(node_cur) expand_node(dir_cur)
move(explorer, "next", what, skip_gitignored) move(explorer, "next", what, skip_gitignored)
-- Save current node. -- Save current node.
node_cur = explorer:get_node_at_cursor() node_cur = explorer:get_node_at_cursor()
-- Update is_dir. dir_cur = node_cur and node_cur:as(DirectoryNode)
if node_cur then
is_dir = node_cur.nodes ~= nil
else
is_dir = false
end
i = i + 1 i = i + 1
end end
@@ -187,8 +182,10 @@ local function move_prev_recursive(explorer, what, skip_gitignored)
end end
-- 4.2) -- 4.2)
local node_dir = node_cur local node_dir = node_cur:as(DirectoryNode)
if node_dir then
expand_node(node_dir) expand_node(node_dir)
end
-- 4.3) -- 4.3)
if node_init.name == ".." then -- root node if node_init.name == ".." then -- root node

View File

@@ -331,9 +331,9 @@ local function open_in_new_window(filename, mode)
local fname local fname
if M.relative_path then if M.relative_path then
fname = vim.fn.fnameescape(utils.path_relative(filename, vim.fn.getcwd())) fname = utils.escape_special_chars(vim.fn.fnameescape(utils.path_relative(filename, vim.fn.getcwd())))
else else
fname = vim.fn.fnameescape(filename) fname = utils.escape_special_chars(vim.fn.fnameescape(filename))
end end
local command local command
@@ -370,28 +370,27 @@ end
---@param mode string ---@param mode string
---@param filename string ---@param filename string
function M.fn(mode, filename) function M.fn(mode, filename)
local fname = utils.escape_special_chars(filename)
if type(mode) ~= "string" then if type(mode) ~= "string" then
mode = "" mode = ""
end end
if mode == "tabnew" then if mode == "tabnew" then
return open_file_in_tab(fname) return open_file_in_tab(filename)
end end
if mode == "drop" then if mode == "drop" then
return drop(fname) return drop(filename)
end end
if mode == "tab_drop" then if mode == "tab_drop" then
return tab_drop(fname) return tab_drop(filename)
end end
if mode == "edit_in_place" then if mode == "edit_in_place" then
return edit_in_current_buf(fname) return edit_in_current_buf(filename)
end end
local buf_loaded = is_already_loaded(fname) local buf_loaded = is_already_loaded(filename)
local found_win = utils.get_win_buf_from_path(filename) local found_win = utils.get_win_buf_from_path(filename)
if found_win and (mode == "preview" or mode == "preview_no_picker") then if found_win and (mode == "preview" or mode == "preview_no_picker") then
@@ -399,7 +398,7 @@ function M.fn(mode, filename)
end end
if not found_win then if not found_win then
open_in_new_window(fname, mode) open_in_new_window(filename, mode)
else else
vim.api.nvim_set_current_win(found_win) vim.api.nvim_set_current_win(found_win)
vim.bo.bufhidden = "" vim.bo.bufhidden = ""

View File

@@ -65,7 +65,7 @@ end
---@param items_short string[] ---@param items_short string[]
---@param items_long string[] ---@param items_long string[]
---@param kind string|nil ---@param kind string|nil
---@param callback fun(item_short: string) ---@param callback fun(item_short: string|nil)
function M.prompt(prompt_input, prompt_select, items_short, items_long, kind, callback) function M.prompt(prompt_input, prompt_select, items_short, items_long, kind, 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

View File

@@ -2,10 +2,6 @@ local git = require("nvim-tree.git")
local Class = require("nvim-tree.class") local Class = require("nvim-tree.class")
---TODO #2886
---TODO remove all @cast
---TODO remove all references to directory fields:
---Abstract Node class. ---Abstract Node class.
---Uses the abstract factory pattern to instantiate child instances. ---Uses the abstract factory pattern to instantiate child instances.
---@class (exact) Node: Class ---@class (exact) Node: Class

View File

@@ -59,6 +59,17 @@ function M.path_basename(path)
return path:sub(i + 1, #path) return path:sub(i + 1, #path)
end end
--- Check if there are parentheses before brackets, it causes problems for windows.
--- Refer to issue #2862 and #2961 for more details.
local function has_parentheses_and_brackets(path)
local _, i_parentheses = path:find("(", 1, true)
local _, i_brackets = path:find("[", 1, true)
if i_parentheses and i_brackets then
return true
end
return false
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|nil ---@param relative_to string|nil
@@ -68,13 +79,18 @@ function M.path_relative(path, relative_to)
return path return path
end end
local _, r = path:find(M.path_add_trailing(relative_to), 1, true) local norm_path = path
local p = path if M.is_windows and has_parentheses_and_brackets(path) then
norm_path = path:gsub("/", "\\")
end
local _, r = norm_path:find(M.path_add_trailing(relative_to), 1, true)
local p = norm_path
if r then if r then
-- take the relative path starting after '/' -- take the relative path starting after '/'
-- if somehow given a completely matching path, -- if somehow given a completely matching path,
-- returns "" -- returns ""
p = path:sub(r + 1) p = norm_path:sub(r + 1)
end end
return p return p
end end
@@ -272,6 +288,14 @@ function M.canonical_path(path)
return path return path
end end
--- Escapes special characters in string for windows, refer to issue #2862 and #2961 for more details.
local function escape_special_char_for_windows(path)
if has_parentheses_and_brackets(path) then
return path:gsub("\\", "/"):gsub("/ ", "\\ ")
end
return path:gsub("%(", "\\("):gsub("%)", "\\)")
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 string|nil ---@return string|nil
@@ -279,7 +303,7 @@ function M.escape_special_chars(path)
if path == nil then if path == nil then
return path return path
end end
return M.is_windows and path:gsub("\\", "/") or path return M.is_windows and escape_special_char_for_windows(path) or path
end end
--- Create empty sub-tables if not present --- Create empty sub-tables if not present