diff --git a/lua/oil/init.lua b/lua/oil/init.lua index 30215b6..207ff50 100644 --- a/lua/oil/init.lua +++ b/lua/oil/init.lua @@ -955,6 +955,14 @@ M.setup = function(opts) elseif v == "--trash" then trash = true table.remove(args.fargs, i) + elseif v == "--progress" then + local mutator = require("oil.mutator") + if mutator.is_mutating() then + mutator.show_progress() + else + vim.notify("No mutation in progress", vim.log.levels.WARN) + end + return else i = i + 1 end diff --git a/lua/oil/mutator/init.lua b/lua/oil/mutator/init.lua index d76413a..83e71cc 100644 --- a/lua/oil/mutator/init.lua +++ b/lua/oil/mutator/init.lua @@ -364,6 +364,8 @@ M.enforce_action_order = function(actions) return ret end +local progress + ---@param actions oil.Action[] ---@param cb fun(err: nil|string) M.process_actions = function(actions, cb) @@ -390,11 +392,12 @@ M.process_actions = function(actions, cb) end local finished = false - local progress = Progress.new() + progress = Progress.new() local function finish(err) if not finished then finished = true progress:close() + progress = nil vim.api.nvim_exec_autocmds( "User", { pattern = "OilActionsPost", modeline = false, data = { err = err, actions = actions } } @@ -455,6 +458,12 @@ M.process_actions = function(actions, cb) next_action() end +M.show_progress = function() + if progress then + progress:restore() + end +end + local mutation_in_progress = false ---@return boolean diff --git a/lua/oil/mutator/progress.lua b/lua/oil/mutator/progress.lua index 1372c4e..58e8587 100644 --- a/lua/oil/mutator/progress.lua +++ b/lua/oil/mutator/progress.lua @@ -8,13 +8,11 @@ local Progress = {} local FPS = 20 function Progress.new() - local bufnr = vim.api.nvim_create_buf(false, true) - vim.bo[bufnr].bufhidden = "wipe" return setmetatable({ lines = { "", "" }, count = "", spinner = "", - bufnr = bufnr, + bufnr = nil, winid = nil, min_bufnr = nil, min_winid = nil, @@ -25,6 +23,15 @@ function Progress.new() }) end +---@private +---@return boolean +function Progress:is_minimized() + return not self.closing + and not self.bufnr + and self.min_bufnr + and vim.api.nvim_buf_is_valid(self.min_bufnr) +end + ---@param opts nil|table --- cancel fun() function Progress:show(opts) @@ -32,20 +39,24 @@ function Progress:show(opts) if self.winid and vim.api.nvim_win_is_valid(self.winid) then return end - self.closing = false - self.cancel = opts.cancel + local bufnr = vim.api.nvim_create_buf(false, true) + vim.bo[bufnr].bufhidden = "wipe" + self.bufnr = bufnr + self.cancel = opts.cancel or self.cancel local loading_iter = loading.get_bar_iter() local spinner = loading.get_iter("dots") - self.timer = vim.loop.new_timer() - self.timer:start( - 0, - math.floor(1000 / FPS), - vim.schedule_wrap(function() - self.lines[2] = string.format("%s %s", self.count, loading_iter()) - self.spinner = spinner() - self:_render() - end) - ) + if not self.timer then + self.timer = vim.loop.new_timer() + self.timer:start( + 0, + math.floor(1000 / FPS), + vim.schedule_wrap(function() + self.lines[2] = string.format("%s %s", self.count, loading_iter()) + self.spinner = spinner() + self:_render() + end) + ) + end local width, height = layout.calculate_dims(120, 10, config.progress) self.winid = vim.api.nvim_open_win(self.bufnr, true, { relative = "editor", @@ -89,6 +100,16 @@ function Progress:show(opts) vim.keymap.set("n", "M", minimize, { buffer = self.bufnr, nowait = true }) end +function Progress:restore() + if self.closing then + return + elseif not self:is_minimized() then + error("Cannot restore progress window: not minimized") + end + self:_cleanup_minimized_win() + self:show() +end + function Progress:_render() if self.bufnr and vim.api.nvim_buf_is_valid(self.bufnr) then util.render_text( @@ -139,6 +160,14 @@ function Progress:_cleanup_main_win() self.bufnr = nil end +function Progress:_cleanup_minimized_win() + if self.min_winid and vim.api.nvim_win_is_valid(self.min_winid) then + vim.api.nvim_win_close(self.min_winid, true) + end + self.min_winid = nil + self.min_bufnr = nil +end + function Progress:minimize() if self.closing then return @@ -160,6 +189,7 @@ function Progress:minimize() self.min_bufnr = bufnr self.min_winid = winid self:_render() + vim.notify_once("Restore progress window with :Oil --progress") end ---@param action oil.Action @@ -187,11 +217,7 @@ function Progress:close() self.timer = nil end self:_cleanup_main_win() - if self.min_winid and vim.api.nvim_win_is_valid(self.min_winid) then - vim.api.nvim_win_close(self.min_winid, true) - end - self.min_winid = nil - self.min_bufnr = nil + self:_cleanup_minimized_win() end return Progress diff --git a/tests/manual_progress.lua b/tests/manual_progress.lua new file mode 100644 index 0000000..bb838e2 --- /dev/null +++ b/tests/manual_progress.lua @@ -0,0 +1,28 @@ +-- Manual test for minimizing/restoring progress window +local Progress = require("oil.mutator.progress") + +local progress = Progress.new() + +progress:show({ + cancel = function() + progress:close() + end, +}) + +for i = 1, 10, 1 do + vim.defer_fn(function() + progress:set_action({ + type = "create", + url = string.format("oil:///tmp/test_%d.txt", i), + entry_type = "file", + }, i, 10) + end, (i - 1) * 1000) +end + +vim.defer_fn(function() + progress:close() +end, 10000) + +vim.keymap.set("n", "R", function() + progress:restore() +end, {})