Skip to content

Commit 23f2688

Browse files
committed
feat(#3292): add nvim_tree.config.filesystem_watchers.whitelist_dirs
1 parent 3d385d3 commit 23f2688

4 files changed

Lines changed: 57 additions & 8 deletions

File tree

doc/nvim-tree-lua.txt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,9 @@ Windows WSL and PowerShell
844844
- Executable file detection is disabled as this is non-performant and can
845845
freeze Nvim
846846
- Some filesystem watcher error related to permissions will not be reported
847+
- Filesystem watchers can experience severe performance issues. It is strongly
848+
recommended to tightly control watcher usage via
849+
|nvim_tree.config.filesystem_watchers| {whitelist_dirs}
847850

848851
Powershell
849852
- Observed Nvim hanging after a runaway (infinite) number of events on a
@@ -1693,11 +1696,17 @@ Config: filesystem_watchers *nvim-tree-config-filesystem-watchers*
16931696
directory changes, resulting in better performance.
16941697

16951698
Watchers may be disabled for absolute directory paths via {ignore_dirs}.
1699+
This may be useful when a path is not in `.gitignore` or git integration
1700+
is disabled.
16961701
• A list of |regular-expression| to match a path, backslash escaped e.g.
16971702
`"my-proj/\\.build$"` OR
16981703
• A function that is passed an absolute path and returns `true` to disable
1699-
This may be useful when a path is not in `.gitignore` or git integration
1700-
is disabled.
1704+
1705+
Watchers may be enabled only for specific directories via
1706+
{whitelist_dirs}. When it is empty (default), watchers are enabled for all
1707+
directories. Uses same semantics as {ignore_dirs} except that the function
1708+
returns `true` to enable watchers for that path. This is strongly
1709+
recommended for windows: |nvim-tree-os-specific|.
17011710

17021711
After {max_events} consecutive filesystem events on a single directory
17031712
with an interval < {debounce_delay}:
@@ -1711,6 +1720,9 @@ Config: filesystem_watchers *nvim-tree-config-filesystem-watchers*
17111720
between filesystem change and tree update.
17121721
• {ignore_dirs}? (`string[]|(fun(path: string): boolean)`, default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", "/.zig-cache"}`)
17131722
Disable for specific directories.
1723+
• {whitelist_dirs}? (`string[]|(fun(path: string): boolean)`, default:
1724+
`{}`) Optionally enable only for specific
1725+
directories, obeying {ignore_dirs}
17141726
• {max_events}? (`integer`, default: `0` or `1000` on windows)
17151727
Disable for a single directory after {max_events}
17161728
consecutive events with an interval <
@@ -2199,6 +2211,7 @@ Following is the default configuration, see |nvim_tree.config| for details. >lua
21992211
"/target",
22002212
"/.zig-cache",
22012213
},
2214+
whitelist_dirs = {},
22022215
},
22032216
actions = {
22042217
use_system_clipboard = true,

lua/nvim-tree/_meta/config/filesystem_watchers.lua

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ error("Cannot require a meta file")
88
---With this feature, the tree will be partially updated on specific directory changes, resulting in better performance.
99
---
1010
---Watchers may be disabled for absolute directory paths via {ignore_dirs}.
11+
---This may be useful when a path is not in `.gitignore` or git integration is disabled.
1112
--- - A list of [regular-expression] to match a path, backslash escaped e.g. `"my-proj/\\.build$"` OR
1213
--- - A function that is passed an absolute path and returns `true` to disable
13-
---This may be useful when a path is not in `.gitignore` or git integration is disabled.
14+
---
15+
---Watchers may be enabled only for specific directories via {whitelist_dirs}. When it is empty (default), watchers are enabled for all directories.
16+
---Uses same semantics as {ignore_dirs} except that the function returns `true` to enable watchers for that path.
17+
---This is strongly recommended for windows: [nvim-tree-os-specific].
1418
---
1519
---After {max_events} consecutive filesystem events on a single directory with an interval < {debounce_delay}:
1620
---- The filesystem watcher will be disabled for that directory.
@@ -30,6 +34,10 @@ error("Cannot require a meta file")
3034
---(default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", "/.zig-cache"}`)
3135
---@field ignore_dirs? string[]|(fun(path: string): boolean)
3236
---
37+
---Optionally enable only for specific directories, obeying {ignore_dirs}
38+
---(default: `{}`)
39+
---@field whitelist_dirs? string[]|(fun(path: string): boolean)
40+
---
3341
---Disable for a single directory after {max_events} consecutive events with an interval < {debounce_delay}.
3442
---Set to 0 to allow unlimited consecutive events.
3543
---(default: `0` or `1000` on windows)

lua/nvim-tree/config.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ M.d = { -- config-default-start
218218
"/target",
219219
"/.zig-cache",
220220
},
221+
whitelist_dirs = {},
221222
},
222223
actions = {
223224
use_system_clipboard = true,
@@ -348,6 +349,7 @@ local ACCEPTED_TYPES = {
348349
},
349350
filesystem_watchers = {
350351
ignore_dirs = { "function" },
352+
whitelist_dirs = { "function" },
351353
},
352354
actions = {
353355
open_file = {

lua/nvim-tree/explorer/watch.lua

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ local IGNORED_PATHS = {
3333
"/dev",
3434
}
3535

36+
---Return true when a path is:
37+
---- Blacklisted via {ignore_dirs}
38+
---- Not whitelisted via {whitelist_dirs}, when it is not an empty table.
3639
---@param path string
3740
---@return boolean
3841
local function is_folder_ignored(path)
@@ -42,18 +45,41 @@ local function is_folder_ignored(path)
4245
end
4346
end
4447

45-
if type(M.config.filesystem_watchers.ignore_dirs) == "table" then
46-
for _, ignore_dir in ipairs(M.config.filesystem_watchers.ignore_dirs) do
48+
---Return true when p matches an entry in dirs, escaping for windows
49+
---@param p string absolute path
50+
---@param dirs string[] absolute or relative
51+
---@return boolean
52+
local function matches_dirs(p, dirs)
53+
for _, dir in ipairs(dirs) do
4754
if utils.is_windows then
48-
ignore_dir = ignore_dir:gsub("/", "\\\\") or ignore_dir
55+
dir = dir:gsub("/", "\\\\") or dir
4956
end
5057

51-
if vim.fn.match(path, ignore_dir) ~= -1 then
58+
if vim.fn.match(p, dir) ~= -1 then
5259
return true
5360
end
5461
end
62+
return false
63+
end
64+
65+
if type(M.config.filesystem_watchers.ignore_dirs) == "table" then
66+
if matches_dirs(path, M.config.filesystem_watchers.ignore_dirs) then
67+
return true
68+
end
5569
elseif type(M.config.filesystem_watchers.ignore_dirs) == "function" then
56-
return M.config.filesystem_watchers.ignore_dirs(path)
70+
if M.config.filesystem_watchers.ignore_dirs(path) then
71+
return true
72+
end
73+
end
74+
75+
if type(M.config.filesystem_watchers.whitelist_dirs) == "table" and #M.config.filesystem_watchers.whitelist_dirs > 0 then
76+
if not matches_dirs(path, M.config.filesystem_watchers.whitelist_dirs) then
77+
return true
78+
end
79+
elseif type(M.config.filesystem_watchers.whitelist_dirs) == "function" then
80+
if not M.config.filesystem_watchers.whitelist_dirs(path) then
81+
return true
82+
end
5783
end
5884

5985
return false

0 commit comments

Comments
 (0)