feat(#3292): add nvim_tree.config.filesystem_watchers.whitelist_dirs - strongly recommended for windows (#3298)

* feat(#3292): add nvim_tree.config.filesystem_watchers.whitelist_dirs

* feat(#3292): add nvim_tree.config.filesystem_watchers.whitelist_dirs

* feat(#3292): add nvim_tree.config.filesystem_watchers.whitelist_dirs
This commit is contained in:
Alexander Courtis
2026-03-26 10:40:03 +11:00
committed by GitHub
parent 3d385d3346
commit 6eaf74c991
4 changed files with 69 additions and 15 deletions

View File

@@ -844,6 +844,9 @@ Windows WSL and PowerShell
- Executable file detection is disabled as this is non-performant and can
freeze Nvim
- Some filesystem watcher error related to permissions will not be reported
- Filesystem watchers can experience severe performance issues. It is strongly
recommended to tightly control watcher usage via
|nvim_tree.config.filesystem_watchers| {whitelist_dirs}
Powershell
- Observed Nvim hanging after a runaway (infinite) number of events on a
@@ -1692,12 +1695,18 @@ Config: filesystem_watchers *nvim-tree-config-filesystem-watchers*
With this feature, the tree will be partially updated on specific
directory changes, resulting in better performance.
Watchers may be disabled for absolute directory paths via {ignore_dirs}.
• A list of |regular-expression| to match a path, backslash escaped e.g.
`"my-proj/\\.build$"` OR
• A function that is passed an absolute path and returns `true` to disable
This may be useful when a path is not in `.gitignore` or git integration
is disabled.
Blacklist watching absolute directory paths via {ignore_dirs} and
optionally whitelist via {whitelist_dirs}:
• A table of |regular-expression| that will be passed to `vim.fn.match`
• Backslashes must be escaped e.g. `"my-proj/\\.build$"`
• Literal backslashes must be double escaped to avoid |/magic| e.g.
`"C:\\\\src\\\\my-proj"`
• OR a `fun(path: string): boolean` that is passed an absolute path:
• {ignore_dirs}: return `true` to disable
• {whitelist_dirs}: return `true` to enable
{whitelist_dirs} is STRONGLY recommended for windows:
|nvim-tree-os-specific|.
After {max_events} consecutive filesystem events on a single directory
with an interval < {debounce_delay}:
@@ -1705,12 +1714,17 @@ Config: filesystem_watchers *nvim-tree-config-filesystem-watchers*
• A warning notification will be shown.
• Consider adding this directory to {ignore_dirs}
By default, {max_events} is only enabled for windows.
Fields: ~
• {enable}? (`boolean`) (default: `true`)
• {debounce_delay}? (`integer`, default: `50`) Idle milliseconds
between filesystem change and tree update.
• {ignore_dirs}? (`string[]|(fun(path: string): boolean)`, default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", "/.zig-cache"}`)
Disable for specific directories.
• {whitelist_dirs}? (`string[]|(fun(path: string): boolean)`, default:
`{}`) Optionally enable only for specific
directories.
• {max_events}? (`integer`, default: `0` or `1000` on windows)
Disable for a single directory after {max_events}
consecutive events with an interval <
@@ -2199,6 +2213,7 @@ Following is the default configuration, see |nvim_tree.config| for details. >lua
"/target",
"/.zig-cache",
},
whitelist_dirs = {},
},
actions = {
use_system_clipboard = true,

View File

@@ -7,16 +7,23 @@ error("Cannot require a meta file")
---
---With this feature, the tree will be partially updated on specific directory changes, resulting in better performance.
---
---Watchers may be disabled for absolute directory paths via {ignore_dirs}.
--- - A list of [regular-expression] to match a path, backslash escaped e.g. `"my-proj/\\.build$"` OR
--- - A function that is passed an absolute path and returns `true` to disable
---This may be useful when a path is not in `.gitignore` or git integration is disabled.
---Blacklist watching absolute directory paths via {ignore_dirs} and optionally whitelist via {whitelist_dirs}:
---- A table of |regular-expression| that will be passed to `vim.fn.match`
--- - Backslashes must be escaped e.g. `"my-proj/\\.build$"`
--- - Literal backslashes must be double escaped to avoid |/magic| e.g. `"C:\\\\src\\\\my-proj"`
---- OR a `fun(path: string): boolean` that is passed an absolute path:
--- - {ignore_dirs}: return `true` to disable
--- - {whitelist_dirs}: return `true` to enable
---
---{whitelist_dirs} is STRONGLY recommended for windows: [nvim-tree-os-specific].
---
---After {max_events} consecutive filesystem events on a single directory with an interval < {debounce_delay}:
---- The filesystem watcher will be disabled for that directory.
---- A warning notification will be shown.
---- Consider adding this directory to {ignore_dirs}
---
---By default, {max_events} is only enabled for windows.
---
---@class nvim_tree.config.filesystem_watchers
---
---(default: `true`)
@@ -30,6 +37,10 @@ error("Cannot require a meta file")
---(default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", "/.zig-cache"}`)
---@field ignore_dirs? string[]|(fun(path: string): boolean)
---
---Optionally enable only for specific directories.
---(default: `{}`)
---@field whitelist_dirs? string[]|(fun(path: string): boolean)
---
---Disable for a single directory after {max_events} consecutive events with an interval < {debounce_delay}.
---Set to 0 to allow unlimited consecutive events.
---(default: `0` or `1000` on windows)

View File

@@ -218,6 +218,7 @@ M.d = { -- config-default-start
"/target",
"/.zig-cache",
},
whitelist_dirs = {},
},
actions = {
use_system_clipboard = true,
@@ -348,6 +349,7 @@ local ACCEPTED_TYPES = {
},
filesystem_watchers = {
ignore_dirs = { "function" },
whitelist_dirs = { "function" },
},
actions = {
open_file = {

View File

@@ -33,6 +33,9 @@ local IGNORED_PATHS = {
"/dev",
}
---Return true when a path is:
---- Blacklisted via {ignore_dirs}
---- Not whitelisted via {whitelist_dirs}, when it is not an empty table.
---@param path string
---@return boolean
local function is_folder_ignored(path)
@@ -42,18 +45,41 @@ local function is_folder_ignored(path)
end
end
if type(M.config.filesystem_watchers.ignore_dirs) == "table" then
for _, ignore_dir in ipairs(M.config.filesystem_watchers.ignore_dirs) do
---Return true when p matches an entry in dirs, escaping for windows
---@param p string absolute path
---@param dirs string[] absolute or relative
---@return boolean
local function matches_dirs(p, dirs)
for _, dir in ipairs(dirs) do
if utils.is_windows then
ignore_dir = ignore_dir:gsub("/", "\\\\") or ignore_dir
dir = dir:gsub("/", "\\\\") or dir
end
if vim.fn.match(path, ignore_dir) ~= -1 then
if vim.fn.match(p, dir) ~= -1 then
return true
end
end
return false
end
if type(M.config.filesystem_watchers.ignore_dirs) == "table" then
if matches_dirs(path, M.config.filesystem_watchers.ignore_dirs) then
return true
end
elseif type(M.config.filesystem_watchers.ignore_dirs) == "function" then
return M.config.filesystem_watchers.ignore_dirs(path)
if M.config.filesystem_watchers.ignore_dirs(path) then
return true
end
end
if type(M.config.filesystem_watchers.whitelist_dirs) == "table" and #M.config.filesystem_watchers.whitelist_dirs > 0 then
if not matches_dirs(path, M.config.filesystem_watchers.whitelist_dirs) then
return true
end
elseif type(M.config.filesystem_watchers.whitelist_dirs) == "function" then
if not M.config.filesystem_watchers.whitelist_dirs(path) then
return true
end
end
return false