Skip to content

Commit 57e055e

Browse files
committed
Merge branch 'master' into chore/action_cb_help_poc
2 parents 5fac9a1 + 951e10a commit 57e055e

23 files changed

+513
-144
lines changed

CONTRIBUTING.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ When adding new options, you should declare the defaults in the main `nvim-tree.
2525
Once you did, you should run the `scripts/update-help.sh`.
2626

2727
Documentation for options should also be added, see how this is done after `nvim-tree.disable_netrw` in the `nvim-tree-lua.txt` file.
28+
29+
## Pull Request
30+
31+
Please reference any issues in the description e.g. "resolves #1234".
32+
33+
Please check "allow edits by maintainers" to allow nvim-tree developers to make small changes such as documentation tweaks.

doc/nvim-tree-lua.txt

Lines changed: 198 additions & 54 deletions
Large diffs are not rendered by default.

lua/nvim-tree.lua

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,10 @@ local function setup_autocommands(opts)
414414
end,
415415
})
416416
end
417+
418+
if opts.view.float.enable then
419+
create_nvim_tree_autocmd("WinLeave", { pattern = "NvimTree_*", callback = view.close })
420+
end
417421
end
418422

419423
local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
@@ -447,13 +451,23 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
447451
number = false,
448452
relativenumber = false,
449453
signcolumn = "yes",
450-
-- @deprecated
451454
mappings = {
452455
custom_only = false,
453456
list = {
454457
-- user mappings go here
455458
},
456459
},
460+
float = {
461+
enable = false,
462+
open_win_config = {
463+
relative = "editor",
464+
border = "rounded",
465+
width = 30,
466+
height = 30,
467+
row = 1,
468+
col = 1,
469+
},
470+
},
457471
},
458472
renderer = {
459473
add_trailing = false,
@@ -462,13 +476,15 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
462476
full_name = false,
463477
highlight_opened_files = "none",
464478
root_folder_modifier = ":~",
479+
indent_width = 2,
465480
indent_markers = {
466481
enable = false,
467482
inline_arrows = true,
468483
icons = {
469484
corner = "",
470485
edge = "",
471486
item = "",
487+
bottom = "",
472488
none = " ",
473489
},
474490
},
@@ -562,6 +578,15 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
562578
max_folder_discovery = 300,
563579
exclude = {},
564580
},
581+
file_popup = {
582+
open_win_config = {
583+
col = 1,
584+
row = 1,
585+
relative = "cursor",
586+
border = "shadow",
587+
style = "minimal",
588+
},
589+
},
565590
open_file = {
566591
quit_on_open = false,
567592
resize_window = true,
@@ -606,6 +631,10 @@ local function merge_options(conf)
606631
return vim.tbl_deep_extend("force", DEFAULT_OPTS, conf or {})
607632
end
608633

634+
local FIELD_SKIP_VALIDATE = {
635+
open_win_config = true,
636+
}
637+
609638
local FIELD_OVERRIDE_TYPECHECK = {
610639
width = { string = true, ["function"] = true, number = true },
611640
height = { string = true, ["function"] = true, number = true },
@@ -623,25 +652,27 @@ local function validate_options(conf)
623652
end
624653

625654
for k, v in pairs(user) do
626-
local invalid
627-
local override_typecheck = FIELD_OVERRIDE_TYPECHECK[k] or {}
628-
if def[k] == nil then
629-
-- option does not exist
630-
invalid = string.format("unknown option: %s%s", prefix, k)
631-
elseif type(v) ~= type(def[k]) and not override_typecheck[type(v)] then
632-
-- option is of the wrong type and is not a function
633-
invalid = string.format("invalid option: %s%s expected: %s actual: %s", prefix, k, type(def[k]), type(v))
634-
end
655+
if not FIELD_SKIP_VALIDATE[k] then
656+
local invalid
657+
local override_typecheck = FIELD_OVERRIDE_TYPECHECK[k] or {}
658+
if def[k] == nil then
659+
-- option does not exist
660+
invalid = string.format("unknown option: %s%s", prefix, k)
661+
elseif type(v) ~= type(def[k]) and not override_typecheck[type(v)] then
662+
-- option is of the wrong type and is not a function
663+
invalid = string.format("invalid option: %s%s expected: %s actual: %s", prefix, k, type(def[k]), type(v))
664+
end
635665

636-
if invalid then
637-
if msg then
638-
msg = string.format("%s | %s", msg, invalid)
666+
if invalid then
667+
if msg then
668+
msg = string.format("%s | %s", msg, invalid)
669+
else
670+
msg = string.format("%s", invalid)
671+
end
672+
user[k] = nil
639673
else
640-
msg = string.format("%s", invalid)
674+
validate(v, def[k], prefix .. k .. ".")
641675
end
642-
user[k] = nil
643-
else
644-
validate(v, def[k], prefix .. k .. ".")
645676
end
646677
end
647678
end

lua/nvim-tree/actions/finders/find-file.lua

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,20 @@ function M.fn(fname)
2727

2828
local line = core.get_nodes_starting_line()
2929

30+
local absolute_paths_searched = {}
31+
3032
local found = Iterator.builder(core.get_explorer().nodes)
3133
:matcher(function(node)
3234
return node.absolute_path == fname_real or node.link_to == fname_real
3335
end)
3436
:applier(function(node)
3537
line = line + 1
38+
39+
if vim.tbl_contains(absolute_paths_searched, node.absolute_path) then
40+
return
41+
end
42+
table.insert(absolute_paths_searched, node.absolute_path)
43+
3644
local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator)
3745
local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator)
3846

lua/nvim-tree/actions/finders/search-node.lua

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,54 @@ local find_file = require("nvim-tree.actions.finders.find-file").fn
77

88
local M = {}
99

10-
local function search(dir, input_path)
11-
local path, name, stat, handle, _
10+
local function search(search_dir, input_path)
11+
local realpaths_searched = {}
1212

13-
if not dir then
13+
if not search_dir then
1414
return
1515
end
1616

17-
handle, _ = uv.fs_scandir(dir)
18-
if not handle then
19-
return
20-
end
17+
local function iter(dir)
18+
local realpath, path, name, stat, handle, _
2119

22-
name, _ = uv.fs_scandir_next(handle)
23-
while name do
24-
path = dir .. "/" .. name
20+
handle, _ = uv.fs_scandir(dir)
21+
if not handle then
22+
return
23+
end
2524

26-
stat, _ = uv.fs_stat(path)
27-
if not stat then
28-
break
25+
realpath, _ = uv.fs_realpath(dir)
26+
if not realpath or vim.tbl_contains(realpaths_searched, realpath) then
27+
return
2928
end
29+
table.insert(realpaths_searched, realpath)
30+
31+
name, _ = uv.fs_scandir_next(handle)
32+
while name do
33+
path = dir .. "/" .. name
3034

31-
if not filters.should_ignore(path) then
32-
if string.find(path, "/" .. input_path .. "$") then
33-
return path
35+
stat, _ = uv.fs_stat(path)
36+
if not stat then
37+
break
3438
end
3539

36-
if stat.type == "directory" then
37-
path = search(path, input_path)
38-
if path then
40+
if not filters.should_ignore(path) then
41+
if string.find(path, "/" .. input_path .. "$") then
3942
return path
4043
end
44+
45+
if stat.type == "directory" then
46+
path = iter(path)
47+
if path then
48+
return path
49+
end
50+
end
4151
end
42-
end
4352

44-
name, _ = uv.fs_scandir_next(handle)
53+
name, _ = uv.fs_scandir_next(handle)
54+
end
4555
end
56+
57+
return iter(search_dir)
4658
end
4759

4860
function M.fn()

lua/nvim-tree/actions/fs/create-file.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function M.fn(node)
108108
end
109109
-- INFO: defer needed when reload is automatic (watchers)
110110
vim.defer_fn(function()
111-
utils.focus_file(new_file_path)
111+
utils.focus_file(utils.path_remove_trailing(new_file_path))
112112
end, 150)
113113
end)
114114
end

lua/nvim-tree/actions/fs/remove-file.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ local luv = vim.loop
33

44
local utils = require "nvim-tree.utils"
55
local events = require "nvim-tree.events"
6+
local view = require "nvim-tree.view"
67

78
local M = {}
89

910
local function close_windows(windows)
11+
if view.View.float.enable and #a.nvim_list_wins() == 1 then
12+
return
13+
end
14+
1015
for _, window in ipairs(windows) do
1116
if a.nvim_win_is_valid(window) then
1217
a.nvim_win_close(window, true)
@@ -18,11 +23,13 @@ local function clear_buffer(absolute_path)
1823
local bufs = vim.fn.getbufinfo { bufloaded = 1, buflisted = 1 }
1924
for _, buf in pairs(bufs) do
2025
if buf.name == absolute_path then
21-
if buf.hidden == 0 and #bufs > 1 then
26+
if buf.hidden == 0 and (#bufs > 1 or view.View.float.enable) then
2227
local winnr = a.nvim_get_current_win()
2328
a.nvim_set_current_win(buf.windows[1])
2429
vim.cmd ":bn"
25-
a.nvim_set_current_win(winnr)
30+
if not view.View.float.enable then
31+
a.nvim_set_current_win(winnr)
32+
end
2633
end
2734
a.nvim_buf_delete(buf.bufnr, { force = true })
2835
if M.close_window then

lua/nvim-tree/actions/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ local DEFAULT_MAPPING_CONFIG = {
390390
function M.setup(opts)
391391
require("nvim-tree.actions.fs.trash").setup(opts)
392392
require("nvim-tree.actions.node.system-open").setup(opts)
393+
require("nvim-tree.actions.node.file-popup").setup(opts)
393394
require("nvim-tree.actions.node.open-file").setup(opts)
394395
require("nvim-tree.actions.root.change-dir").setup(opts)
395396
require("nvim-tree.actions.fs.create-file").setup(opts)

lua/nvim-tree/actions/node/file-popup.lua

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,13 @@ local function setup_window(node)
2828
local max_width = vim.fn.max(vim.tbl_map(function(n)
2929
return #n
3030
end, lines))
31-
local winnr = a.nvim_open_win(0, false, {
32-
col = 1,
33-
row = 1,
34-
relative = "cursor",
31+
local open_win_config = vim.tbl_extend("force", M.open_win_config, {
3532
width = max_width + 1,
3633
height = #lines,
37-
border = "shadow",
3834
noautocmd = true,
39-
style = "minimal",
35+
zindex = 60,
4036
})
37+
local winnr = a.nvim_open_win(0, false, open_win_config)
4138
current_popup = {
4239
winnr = winnr,
4340
file_path = node.absolute_path,
@@ -78,4 +75,8 @@ function M.toggle_file_info(node)
7875
})
7976
end
8077

78+
function M.setup(opts)
79+
M.open_win_config = opts.actions.file_popup.open_win_config
80+
end
81+
8182
return M

lua/nvim-tree/actions/node/open-file.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ function M.fn(mode, filename)
280280
end
281281

282282
function M.setup(opts)
283-
M.quit_on_open = opts.actions.open_file.quit_on_open
283+
M.quit_on_open = opts.actions.open_file.quit_on_open or opts.view.float.enable
284284
M.resize_window = opts.actions.open_file.resize_window
285285
if opts.actions.open_file.window_picker.chars then
286286
opts.actions.open_file.window_picker.chars = tostring(opts.actions.open_file.window_picker.chars):upper()

lua/nvim-tree/explorer/node-builders.lua

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ local watch = require "nvim-tree.explorer.watch"
44

55
local M = {
66
is_windows = vim.fn.has "win32" == 1,
7+
is_wsl = vim.fn.has "wsl" == 1,
78
}
89

910
function M.folder(parent, absolute_path, name)
1011
local handle = uv.fs_scandir(absolute_path)
1112
local has_children = handle and uv.fs_scandir_next(handle) ~= nil
1213

1314
return {
15+
type = "directory",
1416
absolute_path = absolute_path,
1517
fs_stat = uv.fs_stat(absolute_path),
1618
group_next = nil, -- If node is grouped, this points to the next child dir/link node
@@ -23,9 +25,19 @@ function M.folder(parent, absolute_path, name)
2325
}
2426
end
2527

26-
function M.is_executable(absolute_path, ext)
28+
function M.is_executable(parent, absolute_path, ext)
2729
if M.is_windows then
2830
return utils.is_windows_exe(ext)
31+
elseif M.is_wsl then
32+
if parent.is_wsl_windows_fs_path == nil then
33+
-- Evaluate lazily when needed and do so only once for each parent
34+
-- as 'wslpath' calls can get expensive in highly populated directories.
35+
parent.is_wsl_windows_fs_path = utils.is_wsl_windows_fs_path(absolute_path)
36+
end
37+
38+
if parent.is_wsl_windows_fs_path then
39+
return utils.is_wsl_windows_fs_exe(ext)
40+
end
2941
end
3042
return uv.fs_access(absolute_path, "X")
3143
end
@@ -34,8 +46,9 @@ function M.file(parent, absolute_path, name)
3446
local ext = string.match(name, ".?[^.]+%.(.*)") or ""
3547

3648
return {
49+
type = "file",
3750
absolute_path = absolute_path,
38-
executable = M.is_executable(absolute_path, ext),
51+
executable = M.is_executable(parent, absolute_path, ext),
3952
extension = ext,
4053
fs_stat = uv.fs_stat(absolute_path),
4154
name = name,
@@ -61,6 +74,7 @@ function M.link(parent, absolute_path, name)
6174
end
6275

6376
return {
77+
type = "link",
6478
absolute_path = absolute_path,
6579
fs_stat = uv.fs_stat(absolute_path),
6680
group_next = nil, -- If node is grouped, this points to the next child dir/link node

0 commit comments

Comments
 (0)