From 1c08e96ddd4f387edb4ce9d305e528dec7695352 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 17 Jul 2022 14:50:50 +1000 Subject: [PATCH 1/4] feat(watcher): fs_poll -> fs_event --- lua/nvim-tree/git/init.lua | 6 +++--- lua/nvim-tree/watcher.lua | 32 ++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index c1eb094835e..761677d042e 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -29,8 +29,8 @@ function M.reload_project(project_root, path) return end - if path and not path:match("^" .. project_root) then - path = nil + if path and path:find(project_root, 1, true) ~= 1 then + return end local git_status = Runner.run { @@ -43,7 +43,7 @@ function M.reload_project(project_root, path) if path then for p in pairs(project.files) do - if p:match("^" .. path) then + if p:find(path, 1, true) == 1 then project.files[p] = nil end end diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index 15ebeb90296..79a95981a13 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -9,6 +9,13 @@ local M = { local Watcher = {} Watcher.__index = Watcher +local FS_EVENT_FLAGS = { + -- inotify or equivalent will be used; fallback to stat has not yet been implemented + stat = false, + -- recursive is not functional in neovim's libuv implementation + recursive = false, +} + function Watcher.new(opts) for _, existing in ipairs(M._watchers) do if existing._opts.absolute_path == opts.absolute_path then @@ -35,26 +42,27 @@ function Watcher:start() local rc, _, name - self._p, _, name = uv.new_fs_poll() - if not self._p then - self._p = nil + self._e, _, name = uv.new_fs_event() + if not self._e then + self._e = nil utils.warn( - string.format("Could not initialize an fs_poll watcher for path %s : %s", self._opts.absolute_path, name) + string.format("Could not initialize an fs_event watcher for path %s : %s", self._opts.absolute_path, name) ) return nil end - local poll_cb = vim.schedule_wrap(function(err) + local event_cb = vim.schedule_wrap(function(err, filename, events) if err then - log.line("watcher", "poll_cb for %s fail : %s", self._opts.absolute_path, err) + log.line("watcher", "event_cb for %s fail : %s", self._opts.absolute_path, err) else + log.line("watcher", "event_cb '%s' '%s' %s", self._opts.absolute_path, filename, vim.inspect(events)) self._opts.on_event(self._opts) end end) - rc, _, name = uv.fs_poll_start(self._p, self._opts.absolute_path, self._opts.interval, poll_cb) + rc, _, name = self._e:start(self._opts.absolute_path, FS_EVENT_FLAGS, event_cb) if rc ~= 0 then - utils.warn(string.format("Could not start the fs_poll watcher for path %s : %s", self._opts.absolute_path, name)) + utils.warn(string.format("Could not start the fs_event watcher for path %s : %s", self._opts.absolute_path, name)) return nil end @@ -63,12 +71,12 @@ end function Watcher:stop() log.line("watcher", "Watcher:stop '%s'", self._opts.absolute_path) - if self._p then - local rc, _, name = uv.fs_poll_stop(self._p) + if self._e then + local rc, _, name = self._e:stop() if rc ~= 0 then - utils.warn(string.format("Could not stop the fs_poll watcher for path %s : %s", self._opts.absolute_path, name)) + utils.warn(string.format("Could not stop the fs_event watcher for path %s : %s", self._opts.absolute_path, name)) end - self._p = nil + self._e = nil end end From 054da049c72629f92b1a5f813a81f69caaf02b08 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 17 Jul 2022 15:06:56 +1000 Subject: [PATCH 2/4] feat(watcher): stop destroyed node's watchers --- lua/nvim-tree/explorer/watch.lua | 3 ++- lua/nvim-tree/watcher.lua | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lua/nvim-tree/explorer/watch.lua b/lua/nvim-tree/explorer/watch.lua index 2243df2ada8..9864f0d9009 100644 --- a/lua/nvim-tree/explorer/watch.lua +++ b/lua/nvim-tree/explorer/watch.lua @@ -46,12 +46,13 @@ function M.create_watcher(absolute_path) end log.line("watcher", "node start '%s'", absolute_path) - Watcher.new { + return Watcher.new { absolute_path = absolute_path, interval = M.interval, on_event = function(opts) log.line("watcher", "node event scheduled '%s'", opts.absolute_path) utils.debounce("explorer:watch:" .. opts.absolute_path, M.debounce_delay, function() + log.line("watcher", "node refreshing '%s'", absolute_path) refresh_path(opts.absolute_path) end) end, diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index 79a95981a13..cc83de00d5a 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -78,6 +78,12 @@ function Watcher:stop() end self._e = nil end + for i, w in ipairs(M._watchers) do + if w == self then + table.remove(M._watchers, i) + break + end + end end M.Watcher = Watcher From 263e3fe09977506efcc6a6d3e13f89853219aa5c Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 17 Jul 2022 16:00:24 +1000 Subject: [PATCH 3/4] feat(watcher): destroy nodes / watchers --- lua/nvim-tree/core.lua | 2 +- lua/nvim-tree/explorer/common.lua | 10 ++++++++++ lua/nvim-tree/explorer/init.lua | 17 ++++++----------- lua/nvim-tree/explorer/reload.lua | 7 ++++++- lua/nvim-tree/watcher.lua | 6 +++--- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lua/nvim-tree/core.lua b/lua/nvim-tree/core.lua index 83f3db92877..a61fea72743 100644 --- a/lua/nvim-tree/core.lua +++ b/lua/nvim-tree/core.lua @@ -10,7 +10,7 @@ local first_init_done = false function M.init(foldername) if TreeExplorer then - TreeExplorer:_clear_watchers() + TreeExplorer:destroy() end TreeExplorer = explorer.Explorer.new(foldername) if not first_init_done then diff --git a/lua/nvim-tree/explorer/common.lua b/lua/nvim-tree/explorer/common.lua index 14cef92b92a..e3c3e76d32a 100644 --- a/lua/nvim-tree/explorer/common.lua +++ b/lua/nvim-tree/explorer/common.lua @@ -43,6 +43,16 @@ function M.update_git_status(node, parent_ignored, status) end end +function M.node_destroy(node) + if not node then + return + end + + if node.watcher then + node.watcher:destroy() + end +end + function M.setup(opts) M.config = { git = opts.git, diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 5578331f67c..6b9a8c9e5cc 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -2,6 +2,7 @@ local uv = vim.loop local git = require "nvim-tree.git" local watch = require "nvim-tree.explorer.watch" +local common = require "nvim-tree.explorer.common" local M = {} @@ -33,22 +34,16 @@ function Explorer:expand(node) self:_load(node) end -function Explorer.clear_watchers_for(root_node) +function Explorer:destroy() local function iterate(node) - if node.watcher then - node.watcher:stop() + common.node_destroy(node) + if node.nodes then for _, child in pairs(node.nodes) do - if child.watcher then - iterate(child) - end + iterate(child) end end end - iterate(root_node) -end - -function Explorer:_clear_watchers() - Explorer.clear_watchers_for(self) + iterate(self) end function M.setup(opts) diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index e26a68b0a92..5d9299b7830 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -69,7 +69,12 @@ function M.reload(node, status) node.nodes = vim.tbl_map( update_status(nodes_by_path, node_ignored, status), vim.tbl_filter(function(n) - return child_names[n.absolute_path] + if child_names[n.absolute_path] then + return child_names[n.absolute_path] + else + common.node_destroy(n) + return nil + end end, node.nodes) ) diff --git a/lua/nvim-tree/watcher.lua b/lua/nvim-tree/watcher.lua index cc83de00d5a..3ab7a42d8b2 100644 --- a/lua/nvim-tree/watcher.lua +++ b/lua/nvim-tree/watcher.lua @@ -69,8 +69,8 @@ function Watcher:start() return self end -function Watcher:stop() - log.line("watcher", "Watcher:stop '%s'", self._opts.absolute_path) +function Watcher:destroy() + log.line("watcher", "Watcher:destroy '%s'", self._opts.absolute_path) if self._e then local rc, _, name = self._e:stop() if rc ~= 0 then @@ -90,7 +90,7 @@ M.Watcher = Watcher function M.purge_watchers() for _, watcher in pairs(M._watchers) do - watcher:stop() + watcher:destroy() end M._watchers = {} end From 4e7c5d7a832006b5524e711cac7f9922742f0bca Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 17 Jul 2022 16:07:25 +1000 Subject: [PATCH 4/4] feat(watcher): destroy nodes / watchers --- lua/nvim-tree/explorer/watch.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/nvim-tree/explorer/watch.lua b/lua/nvim-tree/explorer/watch.lua index 9864f0d9009..79b50fc57c0 100644 --- a/lua/nvim-tree/explorer/watch.lua +++ b/lua/nvim-tree/explorer/watch.lua @@ -52,7 +52,6 @@ function M.create_watcher(absolute_path) on_event = function(opts) log.line("watcher", "node event scheduled '%s'", opts.absolute_path) utils.debounce("explorer:watch:" .. opts.absolute_path, M.debounce_delay, function() - log.line("watcher", "node refreshing '%s'", absolute_path) refresh_path(opts.absolute_path) end) end,