Skip to content

Commit 2262877

Browse files
committed
refactor(#2994): improve visual selection edge cases
- Use utils.path_separator for cross-platform path handling in descendant node filtering - Filter out ".." parent directory entries to prevent unsafe deletions/trashes of parent directories - Respect ui.confirm.default_yes configuration in bulk delete and trash operations for consistency with single-node behavior
1 parent c087166 commit 2262877

File tree

1 file changed

+51
-11
lines changed

1 file changed

+51
-11
lines changed

lua/nvim-tree/marks/init.lua

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ function Marks:filter_descendant_nodes(nodes)
238238
for i, a in ipairs(nodes) do
239239
for j, b in ipairs(nodes) do
240240
if i ~= j then
241-
local prefix = b.absolute_path .. "/"
241+
local prefix = b.absolute_path .. utils.path_separator
242242
if a.absolute_path:sub(1, #prefix) == prefix then
243243
dominated[i] = true
244244
break
@@ -259,11 +259,19 @@ end
259259
---@public
260260
---@param nodes Node[]
261261
function Marks:bulk_delete_nodes(nodes)
262-
if #nodes == 0 then
262+
-- Filter out parent directory entries ("..") to avoid deleting the parent directory.
263+
local filtered_nodes = {}
264+
for _, node in ipairs(nodes) do
265+
if node.name ~= ".." then
266+
table.insert(filtered_nodes, node)
267+
end
268+
end
269+
270+
if #filtered_nodes == 0 then
263271
return
264272
end
265273

266-
nodes = self:filter_descendant_nodes(nodes)
274+
nodes = self:filter_descendant_nodes(filtered_nodes)
267275

268276
local function execute()
269277
for i = #nodes, 1, -1 do
@@ -275,11 +283,23 @@ function Marks:bulk_delete_nodes(nodes)
275283
end
276284

277285
if self.explorer.opts.ui.confirm.remove then
286+
local default_yes = self.explorer.opts.ui.confirm.default_yes == true
278287
local prompt_select = string.format("Remove %d selected ?", #nodes)
279-
local prompt_input = prompt_select .. " y/N: "
280-
lib.prompt(prompt_input, prompt_select, { "", "y" }, { "No", "Yes" }, "nvimtree_visual_delete", function(item_short)
288+
local prompt_input, items_short, items_long
289+
290+
if default_yes then
291+
prompt_input = prompt_select .. " Y/n: "
292+
items_short = { "", "n" }
293+
items_long = { "Yes", "No" }
294+
else
295+
prompt_input = prompt_select .. " y/N: "
296+
items_short = { "", "y" }
297+
items_long = { "No", "Yes" }
298+
end
299+
300+
lib.prompt(prompt_input, prompt_select, items_short, items_long, "nvimtree_visual_delete", function(item_short)
281301
utils.clear_prompt()
282-
if item_short == "y" then
302+
if item_short == "y" or (default_yes and item_short ~= "n") then
283303
execute()
284304
end
285305
end)
@@ -292,11 +312,19 @@ end
292312
---@public
293313
---@param nodes Node[]
294314
function Marks:bulk_trash_nodes(nodes)
295-
if #nodes == 0 then
315+
-- Filter out parent directory entries ("..") to avoid trashing the parent directory.
316+
local filtered_nodes = {}
317+
for _, node in ipairs(nodes) do
318+
if node.name ~= ".." then
319+
table.insert(filtered_nodes, node)
320+
end
321+
end
322+
323+
if #filtered_nodes == 0 then
296324
return
297325
end
298326

299-
nodes = self:filter_descendant_nodes(nodes)
327+
nodes = self:filter_descendant_nodes(filtered_nodes)
300328

301329
local function execute()
302330
for i = #nodes, 1, -1 do
@@ -308,11 +336,23 @@ function Marks:bulk_trash_nodes(nodes)
308336
end
309337

310338
if self.explorer.opts.ui.confirm.trash then
339+
local default_yes = self.explorer.opts.ui.confirm.default_yes == true
311340
local prompt_select = string.format("Trash %d selected ?", #nodes)
312-
local prompt_input = prompt_select .. " y/N: "
313-
lib.prompt(prompt_input, prompt_select, { "", "y" }, { "No", "Yes" }, "nvimtree_visual_trash", function(item_short)
341+
local prompt_input, items_short, items_long
342+
343+
if default_yes then
344+
prompt_input = prompt_select .. " Y/n: "
345+
items_short = { "", "n" }
346+
items_long = { "Yes", "No" }
347+
else
348+
prompt_input = prompt_select .. " y/N: "
349+
items_short = { "", "y" }
350+
items_long = { "No", "Yes" }
351+
end
352+
353+
lib.prompt(prompt_input, prompt_select, items_short, items_long, "nvimtree_visual_trash", function(item_short)
314354
utils.clear_prompt()
315-
if item_short == "y" then
355+
if item_short == "y" or (default_yes and item_short ~= "n") then
316356
execute()
317357
end
318358
end)

0 commit comments

Comments
 (0)