diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 052708b43d5..efda562f1c8 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -202,11 +202,14 @@ local function setup_autocommands(opts) end, }) - local has_watchers = opts.filesystem_watchers.enable - - if opts.auto_reload_on_write and not has_watchers then - create_nvim_tree_autocmd("BufWritePost", { callback = reloaders.reload_explorer }) - end + create_nvim_tree_autocmd("BufWritePost", { + callback = function() + if opts.auto_reload_on_write and not opts.filesystem_watchers.enable then + log.line("dev", "BufWritePost reloading") + reloaders.reload_explorer() + end + end, + }) create_nvim_tree_autocmd("BufReadPost", { callback = function(data) @@ -236,12 +239,14 @@ local function setup_autocommands(opts) end, }) - if not has_watchers and opts.git.enable then - create_nvim_tree_autocmd("User", { - pattern = { "FugitiveChanged", "NeogitStatusRefreshed" }, - callback = reloaders.reload_git, - }) - end + create_nvim_tree_autocmd("User", { + pattern = { "FugitiveChanged", "NeogitStatusRefreshed" }, + callback = function() + if not opts.filesystem_watchers.enable and opts.git.enable then + reloaders.reload_git() + end + end, + }) if opts.tab.sync.open then create_nvim_tree_autocmd("TabEnter", { callback = vim.schedule_wrap(M.tab_enter) }) @@ -277,16 +282,16 @@ local function setup_autocommands(opts) create_nvim_tree_autocmd({ "BufEnter", "BufNewFile" }, { callback = M.open_on_directory }) end - if opts.reload_on_bufenter and not has_watchers then - create_nvim_tree_autocmd("BufEnter", { - pattern = "NvimTree_*", - callback = function() + create_nvim_tree_autocmd("BufEnter", { + pattern = "NvimTree_*", + callback = function() + if opts.reload_on_bufenter and not opts.filesystem_watchers.enable then if utils.is_nvim_tree_buf(0) then reloaders.reload_explorer() end - end, - }) - end + end + end, + }) if opts.view.centralize_selection then create_nvim_tree_autocmd("BufEnter", { @@ -655,6 +660,16 @@ local function validate_options(conf) end end +function M.purge_all_state() + require("nvim-tree.watcher").purge_watchers() + view.close_all_tabs() + view.abandon_all_windows() + if core.get_explorer() ~= nil then + git.purge_state() + TreeExplorer = nil + end +end + function M.setup(conf) if vim.fn.has "nvim-0.8" == 0 then vim.notify_once("nvim-tree.lua requires Neovim 0.8 or higher", vim.log.levels.WARN) @@ -703,6 +718,7 @@ function M.setup(conf) require("nvim-tree.marks").setup(opts) require("nvim-tree.modified").setup(opts) require("nvim-tree.help").setup(opts) + require("nvim-tree.watcher").setup(opts) if M.config.renderer.icons.show.file and pcall(require, "nvim-web-devicons") then require("nvim-web-devicons").setup() end @@ -714,13 +730,7 @@ function M.setup(conf) commands.setup() else -- subsequent calls to setup - require("nvim-tree.watcher").purge_watchers() - view.close_all_tabs() - view.abandon_all_windows() - if core.get_explorer() ~= nil then - git.purge_state() - TreeExplorer = nil - end + M.purge_all_state() end vim.g.NvimTreeSetup = 1 diff --git a/lua/nvim-tree/actions/fs/copy-paste.lua b/lua/nvim-tree/actions/fs/copy-paste.lua index 79a8f7fa4a9..406272913d9 100644 --- a/lua/nvim-tree/actions/fs/copy-paste.lua +++ b/lua/nvim-tree/actions/fs/copy-paste.lua @@ -7,7 +7,9 @@ local notify = require "nvim-tree.notify" local find_file = require("nvim-tree.actions.finders.find-file").fn -local M = {} +local M = { + config = {}, +} local clipboard = { move = {}, @@ -175,7 +177,7 @@ local function do_paste(node, action_type, action_fn) end clipboard[action_type] = {} - if M.enable_reload then + if not M.config.filesystem_watchers.enable then return require("nvim-tree.actions.reloaders.reloaders").reload_explorer() end end @@ -226,7 +228,7 @@ function M.print_clipboard() end local function copy_to_clipboard(content) - if M.use_system_clipboard == true then + if M.config.actions.use_system_clipboard == true then vim.fn.setreg("+", content) vim.fn.setreg('"', content) return notify.info(string.format("Copied %s to system clipboard!", content)) @@ -255,8 +257,8 @@ function M.copy_absolute_path(node) end function M.setup(opts) - M.use_system_clipboard = opts.actions.use_system_clipboard - M.enable_reload = not opts.filesystem_watchers.enable + M.config.filesystem_watchers = opts.filesystem_watchers + M.config.actions = opts.actions end return M diff --git a/lua/nvim-tree/actions/fs/create-file.lua b/lua/nvim-tree/actions/fs/create-file.lua index cd0a83800f1..74f4ff37565 100644 --- a/lua/nvim-tree/actions/fs/create-file.lua +++ b/lua/nvim-tree/actions/fs/create-file.lua @@ -96,8 +96,4 @@ function M.fn(node) end) end -function M.setup(opts) - M.enable_reload = not opts.filesystem_watchers.enable -end - return M diff --git a/lua/nvim-tree/actions/fs/remove-file.lua b/lua/nvim-tree/actions/fs/remove-file.lua index 9acf6c516b0..6b91b1df0a2 100644 --- a/lua/nvim-tree/actions/fs/remove-file.lua +++ b/lua/nvim-tree/actions/fs/remove-file.lua @@ -4,7 +4,9 @@ local view = require "nvim-tree.view" local lib = require "nvim-tree.lib" local notify = require "nvim-tree.notify" -local M = {} +local M = { + config = {}, +} local function close_windows(windows) if view.View.float.enable and #vim.api.nvim_list_wins() == 1 then @@ -31,7 +33,7 @@ local function clear_buffer(absolute_path) end end vim.api.nvim_buf_delete(buf.bufnr, { force = true }) - if M.close_window then + if M.config.actions.remove_file.close_window then close_windows(buf.windows) end return @@ -90,7 +92,7 @@ function M.fn(node) clear_buffer(node.absolute_path) end notify.info(node.absolute_path .. " was properly removed.") - if M.enable_reload then + if not M.config.filesystem_watchers.enable then require("nvim-tree.actions.reloaders.reloaders").reload_explorer() end end @@ -110,10 +112,9 @@ function M.fn(node) end function M.setup(opts) - M.config = {} - M.config.ui = opts.ui or {} - M.enable_reload = not opts.filesystem_watchers.enable - M.close_window = opts.actions.remove_file.close_window + M.config.ui = opts.ui + M.config.actions = opts.actions + M.config.filesystem_watchers = opts.filesystem_watchers end return M diff --git a/lua/nvim-tree/actions/fs/rename-file.lua b/lua/nvim-tree/actions/fs/rename-file.lua index fd6ad85b13a..9e686e41dab 100644 --- a/lua/nvim-tree/actions/fs/rename-file.lua +++ b/lua/nvim-tree/actions/fs/rename-file.lua @@ -5,7 +5,9 @@ local notify = require "nvim-tree.notify" local find_file = require("nvim-tree.actions.finders.find-file").fn -local M = {} +local M = { + config = {}, +} local ALLOWED_MODIFIERS = { [":p:h"] = true, @@ -83,7 +85,7 @@ function M.fn(default_modifier) end M.rename(node, prepend .. new_file_path .. append) - if M.enable_reload then + if not M.config.filesystem_watchers.enable then require("nvim-tree.actions.reloaders.reloaders").reload_explorer() end @@ -93,7 +95,7 @@ function M.fn(default_modifier) end function M.setup(opts) - M.enable_reload = not opts.filesystem_watchers.enable + M.config.filesystem_watchers = opts.filesystem_watchers end return M diff --git a/lua/nvim-tree/actions/fs/trash.lua b/lua/nvim-tree/actions/fs/trash.lua index ea38511a843..137468ce8e7 100644 --- a/lua/nvim-tree/actions/fs/trash.lua +++ b/lua/nvim-tree/actions/fs/trash.lua @@ -1,7 +1,9 @@ local lib = require "nvim-tree.lib" local notify = require "nvim-tree.notify" -local M = {} +local M = { + config = {}, +} local utils = require "nvim-tree.utils" local events = require "nvim-tree.events" @@ -68,7 +70,7 @@ function M.fn(node) return end events._dispatch_folder_removed(node.absolute_path) - if M.enable_reload then + if not M.config.filesystem_watchers.enable then require("nvim-tree.actions.reloaders.reloaders").reload_explorer() end end) @@ -80,7 +82,7 @@ function M.fn(node) end events._dispatch_file_removed(node.absolute_path) clear_buffer(node.absolute_path) - if M.enable_reload then + if not M.config.filesystem_watchers.enable then require("nvim-tree.actions.reloaders.reloaders").reload_explorer() end end) @@ -102,10 +104,9 @@ function M.fn(node) end function M.setup(opts) - M.config = {} - M.config.ui = opts.ui or {} - M.config.trash = opts.trash or {} - M.enable_reload = not opts.filesystem_watchers.enable + M.config.ui = opts.ui + M.config.trash = opts.trash + M.config.filesystem_watchers = opts.filesystem_watchers end return M diff --git a/lua/nvim-tree/actions/init.lua b/lua/nvim-tree/actions/init.lua index a2798b5aec3..d845296a9d4 100644 --- a/lua/nvim-tree/actions/init.lua +++ b/lua/nvim-tree/actions/init.lua @@ -6,7 +6,6 @@ function M.setup(opts) require("nvim-tree.actions.node.file-popup").setup(opts) require("nvim-tree.actions.node.open-file").setup(opts) require("nvim-tree.actions.root.change-dir").setup(opts) - require("nvim-tree.actions.fs.create-file").setup(opts) require("nvim-tree.actions.fs.rename-file").setup(opts) require("nvim-tree.actions.fs.remove-file").setup(opts) require("nvim-tree.actions.fs.copy-paste").setup(opts) diff --git a/lua/nvim-tree/explorer/watch.lua b/lua/nvim-tree/explorer/watch.lua index 50afb5a3da8..dad1738c4f5 100644 --- a/lua/nvim-tree/explorer/watch.lua +++ b/lua/nvim-tree/explorer/watch.lua @@ -2,7 +2,10 @@ local log = require "nvim-tree.log" local utils = require "nvim-tree.utils" local Watcher = require("nvim-tree.watcher").Watcher -local M = {} +local M = { + config = {}, + uid = 0, +} local function is_git(path) return vim.fn.fnamemodify(path, ":t") == ".git" @@ -23,7 +26,7 @@ local function is_folder_ignored(path) end end - for _, ignore_dir in ipairs(M.ignore_dirs) do + for _, ignore_dir in ipairs(M.config.filesystem_watchers.ignore_dirs) do if vim.fn.match(path, ignore_dir) ~= -1 then return true end @@ -33,7 +36,7 @@ local function is_folder_ignored(path) end function M.create_watcher(node) - if not M.enabled or type(node) ~= "table" then + if not M.config.filesystem_watchers.enable or type(node) ~= "table" then return nil end @@ -50,7 +53,7 @@ function M.create_watcher(node) local function callback(watcher) log.line("watcher", "node event scheduled refresh %s", watcher.context) - utils.debounce(watcher.context, M.debounce_delay, function() + utils.debounce(watcher.context, M.config.filesystem_watchers.debounce_delay, function() if watcher.destroyed then return end @@ -72,9 +75,7 @@ function M.create_watcher(node) end function M.setup(opts) - M.enabled = opts.filesystem_watchers.enable - M.debounce_delay = opts.filesystem_watchers.debounce_delay - M.ignore_dirs = opts.filesystem_watchers.ignore_dirs + M.config.filesystem_watchers = opts.filesystem_watchers M.uid = 0 end diff --git a/lua/nvim-tree/marks/bulk-move.lua b/lua/nvim-tree/marks/bulk-move.lua index ee0e2e8b2ac..9384c21f7f6 100644 --- a/lua/nvim-tree/marks/bulk-move.lua +++ b/lua/nvim-tree/marks/bulk-move.lua @@ -4,7 +4,9 @@ local utils = require "nvim-tree.utils" local FsRename = require "nvim-tree.actions.fs.rename-file" local notify = require "nvim-tree.notify" -local M = {} +local M = { + config = {}, +} function M.bulk_move() if #Marks.get_marks() == 0 then @@ -29,14 +31,14 @@ function M.bulk_move() FsRename.rename(node, to) end - if M.enable_reload then + if not M.config.filesystem_watchers.enable then require("nvim-tree.actions.reloaders.reloaders").reload_explorer() end end) end function M.setup(opts) - M.enable_reload = not opts.filesystem_watchers.enable + M.config.filesystem_watchers = opts.filesystem_watchers end return M diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index 26f463eb955..efa5246963e 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -1,9 +1,10 @@ local notify = require "nvim-tree.notify" - local log = require "nvim-tree.log" local utils = require "nvim-tree.utils" -local M = {} +local M = { + config = {}, +} local Event = { _events = {}, @@ -72,7 +73,15 @@ function Event:start() rc, _, name = self._fs_event:start(self._path, FS_EVENT_FLAGS, event_cb) if rc ~= 0 then - notify.warn(string.format("Could not start the fs_event watcher for path %s : %s", self._path, name)) + local warning = string.format("Could not start the fs_event watcher for path %s : %s", self._path, name) + if name == "EMFILE" then + M.disable_watchers( + warning, + "Please see https://github.com/nvim-tree/nvim-tree.lua/wiki/Troubleshooting#could-not-start-fs_event-for-path--emfile" + ) + else + notify.warn(warning) + end return false end @@ -154,6 +163,15 @@ end M.Watcher = Watcher +--- Permanently disable watchers and purge all state following a catastrophic error. +--- @param warning string +--- @param detail string +function M.disable_watchers(warning, detail) + notify.warn(string.format("%s Disabling watchers: %s", warning, detail)) + M.config.filesystem_watchers.enable = false + require("nvim-tree").purge_all_state() +end + function M.purge_watchers() log.line("watcher", "purge_watchers") @@ -191,4 +209,8 @@ function M.is_fs_event_capable(path) return true end +function M.setup(opts) + M.config.filesystem_watchers = opts.filesystem_watchers +end + return M