From 0ba56f199ef554063b631ab5dcd883ba06f5212d Mon Sep 17 00:00:00 2001 From: Rodrigo Santa Cruz Date: Tue, 17 Mar 2026 05:18:11 +0000 Subject: [PATCH 1/2] feat: refresh explorer immediately after user git operations --- lua/codediff/ui/explorer/actions.lua | 56 ++++++++++++++++++++++++---- lua/codediff/ui/explorer/init.lua | 1 + lua/codediff/ui/explorer/keymaps.lua | 8 +++- lua/codediff/ui/explorer/refresh.lua | 16 ++++++++ lua/codediff/ui/view/keymaps.lua | 8 +++- 5 files changed, 78 insertions(+), 11 deletions(-) diff --git a/lua/codediff/ui/explorer/actions.lua b/lua/codediff/ui/explorer/actions.lua index acb7acce..40700735 100644 --- a/lua/codediff/ui/explorer/actions.lua +++ b/lua/codediff/ui/explorer/actions.lua @@ -193,8 +193,9 @@ end -- @param git_root: git repository root -- @param file_path: relative path to file -- @param group: "staged", "unstaged", or "conflicts" +-- @param on_success: optional callback invoked when git operation succeeds -- @return boolean: true if operation was initiated -function M.toggle_stage_file(git_root, file_path, group) +function M.toggle_stage_file(git_root, file_path, group, on_success) if not git_root then vim.notify("Stage/unstage only available in git mode", vim.log.levels.WARN) return false @@ -216,6 +217,11 @@ function M.toggle_stage_file(git_root, file_path, group) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) elseif group == "unstaged" then @@ -225,6 +231,11 @@ function M.toggle_stage_file(git_root, file_path, group) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) elseif group == "conflicts" then @@ -234,6 +245,11 @@ function M.toggle_stage_file(git_root, file_path, group) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) end @@ -245,7 +261,8 @@ end -- @param git_root: git repository root -- @param dir_path: relative directory path -- @param group: "staged" or "unstaged" -local function toggle_stage_directory(git_root, dir_path, group) +-- @param on_success: optional callback invoked when git operation succeeds +local function toggle_stage_directory(git_root, dir_path, group, on_success) if group == "staged" then -- Unstage directory git.unstage_file(git_root, dir_path, function(err) @@ -253,6 +270,11 @@ local function toggle_stage_directory(git_root, dir_path, group) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) elseif group == "unstaged" then @@ -262,13 +284,19 @@ local function toggle_stage_directory(git_root, dir_path, group) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) end end -- Stage/unstage toggle for the selected entry in explorer (file or directory) -function M.toggle_stage_entry(explorer, tree) +-- @param on_success: optional callback invoked when git operation succeeds +function M.toggle_stage_entry(explorer, tree, on_success) if not explorer or not explorer.git_root then vim.notify("Stage/unstage only available in git mode", vim.log.levels.WARN) return @@ -286,19 +314,21 @@ function M.toggle_stage_entry(explorer, tree) -- Directory uses dir_path, not path local dir_path = node.data.dir_path if dir_path then - toggle_stage_directory(explorer.git_root, dir_path, group) + toggle_stage_directory(explorer.git_root, dir_path, group, on_success) end else -- File uses path local path = node.data.path if path then - M.toggle_stage_file(explorer.git_root, path, group) + M.toggle_stage_file(explorer.git_root, path, group, on_success) end end end -- Stage all files -function M.stage_all(explorer) +-- @param explorer: explorer object +-- @param on_success: optional callback invoked when git operation succeeds +function M.stage_all(explorer, on_success) if not explorer or not explorer.git_root then vim.notify("Stage all only available in git mode", vim.log.levels.WARN) return @@ -309,12 +339,19 @@ function M.stage_all(explorer) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) end -- Unstage all files -function M.unstage_all(explorer) +-- @param explorer: explorer object +-- @param on_success: optional callback invoked when git operation succeeds +function M.unstage_all(explorer, on_success) if not explorer or not explorer.git_root then vim.notify("Unstage all only available in git mode", vim.log.levels.WARN) return @@ -325,6 +362,11 @@ function M.unstage_all(explorer) vim.schedule(function() vim.notify(err, vim.log.levels.ERROR) end) + return + end + + if on_success then + on_success() end end) end diff --git a/lua/codediff/ui/explorer/init.lua b/lua/codediff/ui/explorer/init.lua index cd8c7c91..2a8e1d73 100644 --- a/lua/codediff/ui/explorer/init.lua +++ b/lua/codediff/ui/explorer/init.lua @@ -15,6 +15,7 @@ M.show_welcome_page = render.show_welcome_page -- Delegate to refresh module M.setup_auto_refresh = refresh.setup_auto_refresh M.refresh = refresh.refresh +M.refresh_now = refresh.refresh_now -- Delegate to actions module M.navigate_next = actions.navigate_next diff --git a/lua/codediff/ui/explorer/keymaps.lua b/lua/codediff/ui/explorer/keymaps.lua index 4256c023..daa34d1f 100644 --- a/lua/codediff/ui/explorer/keymaps.lua +++ b/lua/codediff/ui/explorer/keymaps.lua @@ -140,14 +140,18 @@ function M.setup(explorer) -- Stage all files (S key) if explorer_keymaps.stage_all then vim.keymap.set("n", explorer_keymaps.stage_all, function() - actions_module.stage_all(explorer) + actions_module.stage_all(explorer, function() + refresh_module.refresh_now(explorer) + end) end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Stage all files" })) end -- Unstage all files (U key) if explorer_keymaps.unstage_all then vim.keymap.set("n", explorer_keymaps.unstage_all, function() - actions_module.unstage_all(explorer) + actions_module.unstage_all(explorer, function() + refresh_module.refresh_now(explorer) + end) end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Unstage all files" })) end diff --git a/lua/codediff/ui/explorer/refresh.lua b/lua/codediff/ui/explorer/refresh.lua index 1c679a8e..ef429206 100644 --- a/lua/codediff/ui/explorer/refresh.lua +++ b/lua/codediff/ui/explorer/refresh.lua @@ -4,6 +4,22 @@ local M = {} local config = require("codediff.config") local tree_module = require("codediff.ui.explorer.tree") local welcome = require("codediff.ui.welcome") + +function M.refresh_now(explorer) + if not explorer or not explorer.tabpage then + return + end + + vim.schedule(function() + if not vim.api.nvim_tabpage_is_valid(explorer.tabpage) or explorer.is_hidden then + return + end + + M.refresh(explorer) + require("codediff.ui.auto_refresh").sync_mutable_buffers(explorer.tabpage) + end) +end + -- Setup auto-refresh triggers for explorer -- Returns a cleanup function that should be called when the explorer is destroyed function M.setup_auto_refresh(explorer, tabpage) diff --git a/lua/codediff/ui/view/keymaps.lua b/lua/codediff/ui/view/keymaps.lua index 546bef0c..1fd8a205 100644 --- a/lua/codediff/ui/view/keymaps.lua +++ b/lua/codediff/ui/view/keymaps.lua @@ -230,7 +230,9 @@ function M.setup_all_keymaps(tabpage, original_bufnr, modified_bufnr, is_explore if explorer.bufnr and current_buf == explorer.bufnr then -- Delegate to explorer action (handles files and directories) local explorer_module = require("codediff.ui.explorer") - explorer_module.toggle_stage_entry(explorer, explorer.tree) + explorer_module.toggle_stage_entry(explorer, explorer.tree, function() + explorer_module.refresh_now(explorer) + end) return end @@ -252,7 +254,9 @@ function M.setup_all_keymaps(tabpage, original_bufnr, modified_bufnr, is_explore end local explorer_module = require("codediff.ui.explorer") - explorer_module.toggle_stage_file(explorer.git_root, file_path, group) + explorer_module.toggle_stage_file(explorer.git_root, file_path, group, function() + explorer_module.refresh_now(explorer) + end) return end From 7062846f4b6e6212dee7b029d41e0acbaaac3223 Mon Sep 17 00:00:00 2001 From: Rodrigo Santa Cruz Date: Wed, 18 Mar 2026 03:39:58 +0000 Subject: [PATCH 2/2] feat: navigate next after stage/unstage --- lua/codediff/ui/explorer/keymaps.lua | 8 ++++++-- lua/codediff/ui/explorer/refresh.lua | 12 +++++------- lua/codediff/ui/view/keymaps.lua | 10 ++++++++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lua/codediff/ui/explorer/keymaps.lua b/lua/codediff/ui/explorer/keymaps.lua index daa34d1f..feb68a12 100644 --- a/lua/codediff/ui/explorer/keymaps.lua +++ b/lua/codediff/ui/explorer/keymaps.lua @@ -141,7 +141,9 @@ function M.setup(explorer) if explorer_keymaps.stage_all then vim.keymap.set("n", explorer_keymaps.stage_all, function() actions_module.stage_all(explorer, function() - refresh_module.refresh_now(explorer) + vim.schedule(function() + refresh_module.refresh_now(explorer) + end) end) end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Stage all files" })) end @@ -150,7 +152,9 @@ function M.setup(explorer) if explorer_keymaps.unstage_all then vim.keymap.set("n", explorer_keymaps.unstage_all, function() actions_module.unstage_all(explorer, function() - refresh_module.refresh_now(explorer) + vim.schedule(function() + refresh_module.refresh_now(explorer) + end) end) end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Unstage all files" })) end diff --git a/lua/codediff/ui/explorer/refresh.lua b/lua/codediff/ui/explorer/refresh.lua index ef429206..07ddbe12 100644 --- a/lua/codediff/ui/explorer/refresh.lua +++ b/lua/codediff/ui/explorer/refresh.lua @@ -10,14 +10,12 @@ function M.refresh_now(explorer) return end - vim.schedule(function() - if not vim.api.nvim_tabpage_is_valid(explorer.tabpage) or explorer.is_hidden then - return - end + if not vim.api.nvim_tabpage_is_valid(explorer.tabpage) or explorer.is_hidden then + return + end - M.refresh(explorer) - require("codediff.ui.auto_refresh").sync_mutable_buffers(explorer.tabpage) - end) + M.refresh(explorer) + require("codediff.ui.auto_refresh").sync_mutable_buffers(explorer.tabpage) end -- Setup auto-refresh triggers for explorer diff --git a/lua/codediff/ui/view/keymaps.lua b/lua/codediff/ui/view/keymaps.lua index 1fd8a205..9ae36e22 100644 --- a/lua/codediff/ui/view/keymaps.lua +++ b/lua/codediff/ui/view/keymaps.lua @@ -231,7 +231,10 @@ function M.setup_all_keymaps(tabpage, original_bufnr, modified_bufnr, is_explore -- Delegate to explorer action (handles files and directories) local explorer_module = require("codediff.ui.explorer") explorer_module.toggle_stage_entry(explorer, explorer.tree, function() - explorer_module.refresh_now(explorer) + vim.schedule(function() + navigation.next_file() + explorer_module.refresh_now(explorer) + end) end) return end @@ -255,7 +258,10 @@ function M.setup_all_keymaps(tabpage, original_bufnr, modified_bufnr, is_explore local explorer_module = require("codediff.ui.explorer") explorer_module.toggle_stage_file(explorer.git_root, file_path, group, function() - explorer_module.refresh_now(explorer) + vim.schedule(function() + navigation.next_file() + explorer_module.refresh_now(explorer) + end) end) return end