Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 49 additions & 7 deletions lua/codediff/ui/explorer/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -245,14 +261,20 @@ 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)
if err then
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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions lua/codediff/ui/explorer/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions lua/codediff/ui/explorer/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,22 @@ 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()
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

-- 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()
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

Expand Down
14 changes: 14 additions & 0 deletions lua/codediff/ui/explorer/refresh.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ 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

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

-- 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)
Expand Down
14 changes: 12 additions & 2 deletions lua/codediff/ui/view/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,12 @@ 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()
vim.schedule(function()
navigation.next_file()
explorer_module.refresh_now(explorer)
end)
end)
return
end

Expand All @@ -252,7 +257,12 @@ 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()
vim.schedule(function()
navigation.next_file()
explorer_module.refresh_now(explorer)
end)
end)
return
end

Expand Down