Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions doc/nvim-tree-lua.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1692,25 +1695,36 @@ 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}:
• 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.

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 <
Expand Down Expand Up @@ -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,
Expand Down
19 changes: 15 additions & 4 deletions lua/nvim-tree/_meta/config/filesystem_watchers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand All @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions lua/nvim-tree/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ M.d = { -- config-default-start
"/target",
"/.zig-cache",
},
whitelist_dirs = {},
},
actions = {
use_system_clipboard = true,
Expand Down Expand Up @@ -348,6 +349,7 @@ local ACCEPTED_TYPES = {
},
filesystem_watchers = {
ignore_dirs = { "function" },
whitelist_dirs = { "function" },
},
actions = {
open_file = {
Expand Down
36 changes: 31 additions & 5 deletions lua/nvim-tree/explorer/watch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
Loading