mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-06 03:38:16 +00:00
feat(explorer): file watcher when explorer is open
This commit is contained in:
parent
6149a7babb
commit
6936c1491d
1 changed files with 74 additions and 0 deletions
74
lua/snacks/explorer/watch.lua
Normal file
74
lua/snacks/explorer/watch.lua
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local uv = vim.uv or vim.loop
|
||||||
|
|
||||||
|
---@alias snacks.explorer.Watcher fun(path:string, opts:vim._watch.watch.Opts?, callback:vim._watch.Callback):fun()
|
||||||
|
|
||||||
|
---@return snacks.explorer.Watcher?
|
||||||
|
function M.watcher()
|
||||||
|
if not vim._watch then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if vim.fn.has("win32") == 1 or vim.fn.has("mac") == 1 then
|
||||||
|
return vim._watch.watch
|
||||||
|
elseif vim.fn.executable("inotifywait") == 1 then
|
||||||
|
return vim._watch.inotify
|
||||||
|
end
|
||||||
|
return vim._watch.watchdirs
|
||||||
|
end
|
||||||
|
|
||||||
|
local running = {} ---@type table<string, fun()>
|
||||||
|
|
||||||
|
function M.abort()
|
||||||
|
for _, abort in pairs(running) do
|
||||||
|
abort()
|
||||||
|
end
|
||||||
|
running = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param cwd string
|
||||||
|
function M.watch(cwd)
|
||||||
|
if running[cwd] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local Tree = require("snacks.explorer.tree")
|
||||||
|
local watch = M.watcher()
|
||||||
|
if not watch then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
M.abort()
|
||||||
|
|
||||||
|
local timer = assert(uv.new_timer())
|
||||||
|
local cancel = watch(cwd, {
|
||||||
|
uvflags = { recursive = true },
|
||||||
|
}, function(path)
|
||||||
|
-- handle deletes
|
||||||
|
while not uv.fs_stat(path) do
|
||||||
|
local p = vim.fs.dirname(path)
|
||||||
|
if p == path then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
path = p
|
||||||
|
end
|
||||||
|
Tree:refresh(path)
|
||||||
|
|
||||||
|
-- batch updates and give explorer the time to update before the watcher
|
||||||
|
timer:start(100, 0, function()
|
||||||
|
local picker = Snacks.picker.get({ source = "explorer" })[1]
|
||||||
|
if picker and Tree:is_dirty(picker:cwd(), picker.opts) then
|
||||||
|
if not picker.list.target then
|
||||||
|
picker.list:set_target()
|
||||||
|
end
|
||||||
|
picker:find()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
running[cwd] = function()
|
||||||
|
if not timer:is_closing() then
|
||||||
|
timer:close()
|
||||||
|
end
|
||||||
|
cancel()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
Loading…
Add table
Add a link
Reference in a new issue