Skip to content
Merged
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
15 changes: 2 additions & 13 deletions lua/codediff/ui/explorer/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,8 @@ function M.setup(explorer)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Restore/discard changes" }))
end

-- Navigate to next file (uses view keymaps)
if config.options.keymaps.view.next_file then
vim.keymap.set("n", config.options.keymaps.view.next_file, function()
render_module.navigate_next(explorer)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Next file" }))
end

-- Navigate to previous file (uses view keymaps)
if config.options.keymaps.view.prev_file then
vim.keymap.set("n", config.options.keymaps.view.prev_file, function()
render_module.navigate_prev(explorer)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Previous file" }))
end
-- Note: next_file/prev_file keymaps are set via view/keymaps.lua:setup_all_keymaps()
-- which uses set_tab_keymap to set them on all buffers including explorer
end

return M
15 changes: 2 additions & 13 deletions lua/codediff/ui/history/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,8 @@ function M.setup(history, opts)
end
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Select file" }))

-- Navigate to next file (uses view keymaps)
if config.options.keymaps.view.next_file then
vim.keymap.set("n", config.options.keymaps.view.next_file, function()
opts.navigate_next(history)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Next file" }))
end

-- Navigate to previous file (uses view keymaps)
if config.options.keymaps.view.prev_file then
vim.keymap.set("n", config.options.keymaps.view.prev_file, function()
opts.navigate_prev(history)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Previous file" }))
end
-- Note: next_file/prev_file keymaps are set via view/keymaps.lua:setup_all_keymaps()
-- which uses set_tab_keymap to set them on all buffers including history panel

-- Toggle view mode between list and tree
if history_keymaps.toggle_view_mode then
Expand Down
125 changes: 28 additions & 97 deletions lua/codediff/ui/lifecycle/accessors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -399,34 +399,6 @@ function M.confirm_close_with_unsaved(tabpage)
end
end

--- Find and save an existing buffer-local keymap before overwriting
--- @param bufnr number Buffer number
--- @param mode string Keymap mode
--- @param lhs string Left-hand side of the keymap
--- @return table|nil The saved keymap data, or nil if no existing keymap
local function save_existing_keymap(bufnr, mode, lhs)
if not vim.api.nvim_buf_is_valid(bufnr) then
return nil
end
local keymaps = vim.api.nvim_buf_get_keymap(bufnr, mode)
for _, map in ipairs(keymaps) do
if map.lhs == lhs then
return {
lhs = map.lhs,
rhs = map.rhs,
callback = map.callback,
expr = map.expr == 1,
noremap = map.noremap == 1,
nowait = map.nowait == 1,
silent = map.silent == 1,
script = map.script == 1,
desc = map.desc,
}
end
end
return nil
end

--- Set a keymap on all buffers in the diff tab (both diff buffers + explorer + result)
--- This is the unified API for setting tab-wide keymaps
--- @param tabpage number Tab page ID
Expand All @@ -442,109 +414,68 @@ function M.set_tab_keymap(tabpage, mode, lhs, rhs, opts)
return false
end

-- Initialize saved keymaps storage if needed
sess.saved_keymaps = sess.saved_keymaps or {}
-- Track all buffers that have keymaps set (for cleanup on close)
sess.keymap_buffers = sess.keymap_buffers or {}

opts = opts or {}
local base_opts = { noremap = true, silent = true, nowait = true }

-- Helper to save existing keymap before setting new one
local function set_with_save(bufnr)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
-- Save existing keymap (only if not already saved for this buffer/lhs)
local key = bufnr .. ":" .. mode .. ":" .. lhs
if sess.saved_keymaps[key] == nil then
local existing = save_existing_keymap(bufnr, mode, lhs)
-- Store even if nil (marks that we've checked this keymap)
sess.saved_keymaps[key] = existing or false
end
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = bufnr }))
if vim.api.nvim_buf_is_valid(sess.original_bufnr) then
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = sess.original_bufnr }))
sess.keymap_buffers[sess.original_bufnr] = true
end

set_with_save(sess.original_bufnr)
set_with_save(sess.modified_bufnr)
if vim.api.nvim_buf_is_valid(sess.modified_bufnr) then
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = sess.modified_bufnr }))
sess.keymap_buffers[sess.modified_bufnr] = true
end

local explorer = sess.explorer
if explorer and explorer.bufnr then
set_with_save(explorer.bufnr)
if explorer and explorer.bufnr and vim.api.nvim_buf_is_valid(explorer.bufnr) then
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = explorer.bufnr }))
sess.keymap_buffers[explorer.bufnr] = true
end

if sess.result_bufnr then
set_with_save(sess.result_bufnr)
if sess.result_bufnr and vim.api.nvim_buf_is_valid(sess.result_bufnr) then
vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = sess.result_bufnr }))
sess.keymap_buffers[sess.result_bufnr] = true
end

return true
end

--- Remove codediff keymaps from a session's buffers and restore original keymaps
--- Remove codediff keymaps from a session's buffers
function M.clear_tab_keymaps(tabpage)
local active_diffs = session.get_active_diffs()
local sess = active_diffs[tabpage]
if not sess then
return
end

-- Guard: If already cleared, don't run again (prevents double-cleanup from deleting restored keymaps)
if not sess.saved_keymaps then
return
end

local saved_keymaps = sess.saved_keymaps

-- Helper to restore a single keymap
local function restore_keymap(bufnr, mode, lhs)
local function del_buf_keymaps(bufnr, keys)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
local key = bufnr .. ":" .. mode .. ":" .. lhs
local saved = saved_keymaps[key]

-- First, delete the codediff keymap
pcall(vim.keymap.del, mode, lhs, { buffer = bufnr })

-- Then restore the original keymap if one existed
if saved and saved ~= false then
local restore_opts = {
buffer = bufnr,
expr = saved.expr,
noremap = saved.noremap,
nowait = saved.nowait,
silent = saved.silent,
desc = saved.desc,
}
local rhs = saved.callback or saved.rhs or ""
pcall(vim.keymap.set, mode, lhs, rhs, restore_opts)
for _, key in pairs(keys) do
if key then
pcall(vim.keymap.del, "n", key, { buffer = bufnr })
end
end
end

-- Helper to restore keymaps for a buffer from a keymap config table
local function restore_buf_keymaps(bufnr, keys)
if not vim.api.nvim_buf_is_valid(bufnr) then
return
end
for _, lhs in pairs(keys) do
if lhs then
restore_keymap(bufnr, "n", lhs)
end
-- Delete keymaps from ALL buffers that ever had them set (not just current ones)
if sess.keymap_buffers then
for bufnr, _ in pairs(sess.keymap_buffers) do
del_buf_keymaps(bufnr, config.options.keymaps.view)
end
end

restore_buf_keymaps(sess.original_bufnr, config.options.keymaps.view)
restore_buf_keymaps(sess.modified_bufnr, config.options.keymaps.view)

-- Also handle explorer keymaps separately (explorer buffer uses both view and explorer keymaps)
if sess.explorer and sess.explorer.bufnr then
restore_buf_keymaps(sess.explorer.bufnr, config.options.keymaps.view)
restore_buf_keymaps(sess.explorer.bufnr, config.options.keymaps.explorer or {})
end

if sess.result_bufnr then
restore_buf_keymaps(sess.result_bufnr, config.options.keymaps.view)
del_buf_keymaps(sess.explorer.bufnr, config.options.keymaps.explorer or {})
end

-- Clear saved keymaps
sess.saved_keymaps = nil
sess.keymap_buffers = nil
end

--- Setup auto-sync on file switch: automatically update diff when user edits a different file in working buffer
Expand Down
Loading