Skip to content
Open
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ https://github.com/user-attachments/assets/64c41f01-dffe-4318-bce4-16eec8de356e
view_mode = "list", -- "list" or "tree" for files under commits
},

-- Keymaps in diff view
-- Keymaps in diff view (can also be a table of keys)
keymaps = {
view = {
quit = "q", -- Close diff tab
Expand All @@ -159,7 +159,7 @@ https://github.com/user-attachments/assets/64c41f01-dffe-4318-bce4-16eec8de356e
toggle_layout = "t", -- Toggle between side-by-side and inline layout
},
explorer = {
select = "<CR>", -- Open diff for selected file
select = { "<CR>", "o" }, -- Open diff for selected file
hover = "K", -- Show file diff preview
refresh = "R", -- Refresh git status
toggle_view_mode = "i", -- Toggle between 'list' and 'tree' views
Expand Down
2 changes: 1 addition & 1 deletion lua/codediff/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ M.defaults = {
show_help = "g?", -- Show floating window with available keymaps
},
explorer = {
select = "<CR>",
select = { "<CR>", "o" },
hover = "K",
refresh = "R",
toggle_view_mode = "i", -- Toggle between 'list' and 'tree' views
Expand Down
30 changes: 16 additions & 14 deletions lua/codediff/ui/conflict/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ local tracking = require("codediff.ui.conflict.tracking")
local actions = require("codediff.ui.conflict.actions")
local diffget = require("codediff.ui.conflict.diffget")
local navigation = require("codediff.ui.conflict.navigation")
local set_keymap = require("codediff.ui.lifecycle.accessors").set_keymap
local del_keymap = require("codediff.ui.lifecycle.accessors").del_keymap

--- Setup conflict keymaps for a session
--- @param tabpage number
Expand All @@ -28,15 +30,15 @@ function M.setup_keymaps(tabpage)
if bufnr and vim.api.nvim_buf_is_valid(bufnr) then
-- Unbind normal mode do/dp from view keymaps (they don't apply in merge conflict mode)
if view_keymaps.diff_get then
pcall(vim.keymap.del, "n", view_keymaps.diff_get, { buffer = bufnr })
pcall(keymap_del, "n", view_keymaps.diff_get, { buffer = bufnr })
end
if view_keymaps.diff_put then
pcall(vim.keymap.del, "n", view_keymaps.diff_put, { buffer = bufnr })
pcall(keymap_del, "n", view_keymaps.diff_put, { buffer = bufnr })
end

-- Accept incoming
if keymaps.accept_incoming then
vim.keymap.set(
set_keymap(
"n",
keymaps.accept_incoming,
tracking.make_repeatable(function()
Expand All @@ -48,7 +50,7 @@ function M.setup_keymaps(tabpage)

-- Accept current
if keymaps.accept_current then
vim.keymap.set(
set_keymap(
"n",
keymaps.accept_current,
tracking.make_repeatable(function()
Expand All @@ -60,7 +62,7 @@ function M.setup_keymaps(tabpage)

-- Accept both
if keymaps.accept_both then
vim.keymap.set(
set_keymap(
"n",
keymaps.accept_both,
tracking.make_repeatable(function()
Expand All @@ -72,7 +74,7 @@ function M.setup_keymaps(tabpage)

-- Discard
if keymaps.discard then
vim.keymap.set(
set_keymap(
"n",
keymaps.discard,
tracking.make_repeatable(function()
Expand All @@ -84,48 +86,48 @@ function M.setup_keymaps(tabpage)

-- Accept ALL incoming
if keymaps.accept_all_incoming then
vim.keymap.set("n", keymaps.accept_all_incoming, function()
set_keymap("n", keymaps.accept_all_incoming, function()
actions.accept_all_incoming(tabpage)
end, vim.tbl_extend("force", base_opts, { buffer = bufnr, desc = "Accept ALL incoming changes" }))
end

-- Accept ALL current
if keymaps.accept_all_current then
vim.keymap.set("n", keymaps.accept_all_current, function()
set_keymap("n", keymaps.accept_all_current, function()
actions.accept_all_current(tabpage)
end, vim.tbl_extend("force", base_opts, { buffer = bufnr, desc = "Accept ALL current changes" }))
end

-- Accept ALL both
if keymaps.accept_all_both then
vim.keymap.set("n", keymaps.accept_all_both, function()
set_keymap("n", keymaps.accept_all_both, function()
actions.accept_all_both(tabpage)
end, vim.tbl_extend("force", base_opts, { buffer = bufnr, desc = "Accept ALL both changes" }))
end

-- Discard ALL
if keymaps.discard_all then
vim.keymap.set("n", keymaps.discard_all, function()
set_keymap("n", keymaps.discard_all, function()
actions.discard_all(tabpage)
end, vim.tbl_extend("force", base_opts, { buffer = bufnr, desc = "Discard ALL, reset to base" }))
end

-- Navigation
if keymaps.next_conflict then
vim.keymap.set("n", keymaps.next_conflict, function()
set_keymap("n", keymaps.next_conflict, function()
navigation.navigate_next_conflict(tabpage)
end, vim.tbl_extend("force", base_opts, { buffer = bufnr, desc = "Next conflict" }))
end

if keymaps.prev_conflict then
vim.keymap.set("n", keymaps.prev_conflict, function()
set_keymap("n", keymaps.prev_conflict, function()
navigation.navigate_prev_conflict(tabpage)
end, vim.tbl_extend("force", base_opts, { buffer = bufnr, desc = "Previous conflict" }))
end

-- Vimdiff-style diffget from incoming (2do) - only on result buffer
if keymaps.diffget_incoming and bufnr == session.result_bufnr then
vim.keymap.set(
set_keymap(
"n",
keymaps.diffget_incoming,
tracking.make_repeatable(function()
Expand All @@ -137,7 +139,7 @@ function M.setup_keymaps(tabpage)

-- Vimdiff-style diffget from current (3do) - only on result buffer
if keymaps.diffget_current and bufnr == session.result_bufnr then
vim.keymap.set(
set_keymap(
"n",
keymaps.diffget_current,
tracking.make_repeatable(function()
Expand Down
21 changes: 11 additions & 10 deletions lua/codediff/ui/explorer/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local config = require("codediff.config")
local actions_module = require("codediff.ui.explorer.actions")
local refresh_module = require("codediff.ui.explorer.refresh")
local tree_utils = require("codediff.ui.lib.tree_utils")
local set_keymap = require("codediff.ui.lifecycle.accessors").set_keymap

local M = {}

Expand All @@ -18,7 +19,7 @@ function M.setup(explorer)

-- Toggle expand/collapse or select file
if explorer_keymaps.select then
vim.keymap.set("n", explorer_keymaps.select, function()
set_keymap("n", explorer_keymaps.select, function()
local node = tree:get_node()
if not node then
return
Expand Down Expand Up @@ -52,7 +53,7 @@ function M.setup(explorer)
end

-- Double click also works for files
vim.keymap.set("n", "<2-LeftMouse>", function()
set_keymap("n", "<2-LeftMouse>", function()
local node = tree:get_node()
if not node or not node.data or node.data.type == "group" or node.data.type == "directory" then
return
Expand All @@ -63,7 +64,7 @@ function M.setup(explorer)
-- Hover to show full path (K key, like LSP hover)
local hover_win = nil
if explorer_keymaps.hover then
vim.keymap.set("n", explorer_keymaps.hover, function()
set_keymap("n", explorer_keymaps.hover, function()
-- Close existing hover window
if hover_win and vim.api.nvim_win_is_valid(hover_win) then
vim.api.nvim_win_close(hover_win, true)
Expand Down Expand Up @@ -125,49 +126,49 @@ function M.setup(explorer)

-- Refresh explorer (R key)
if explorer_keymaps.refresh then
vim.keymap.set("n", explorer_keymaps.refresh, function()
set_keymap("n", explorer_keymaps.refresh, function()
refresh_module.refresh(explorer)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Refresh explorer" }))
end

-- Toggle view mode (i key) - switch between 'list' and 'tree'
if explorer_keymaps.toggle_view_mode then
vim.keymap.set("n", explorer_keymaps.toggle_view_mode, function()
set_keymap("n", explorer_keymaps.toggle_view_mode, function()
actions_module.toggle_view_mode(explorer)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Toggle list/tree view" }))
end

-- Stage all files (S key)
if explorer_keymaps.stage_all then
vim.keymap.set("n", explorer_keymaps.stage_all, function()
set_keymap("n", explorer_keymaps.stage_all, function()
actions_module.stage_all(explorer)
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()
set_keymap("n", explorer_keymaps.unstage_all, function()
actions_module.unstage_all(explorer)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Unstage all files" }))
end

-- Restore/discard changes (X key)
if explorer_keymaps.restore then
vim.keymap.set("n", explorer_keymaps.restore, function()
set_keymap("n", explorer_keymaps.restore, function()
actions_module.restore_entry(explorer, tree)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Restore/discard changes" }))
end

-- Toggle Changes (unstaged) group visibility
if explorer_keymaps.toggle_changes then
vim.keymap.set("n", explorer_keymaps.toggle_changes, function()
set_keymap("n", explorer_keymaps.toggle_changes, function()
actions_module.toggle_group(explorer, "unstaged")
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Toggle Changes visibility" }))
end

-- Toggle Staged Changes group visibility
if explorer_keymaps.toggle_staged then
vim.keymap.set("n", explorer_keymaps.toggle_staged, function()
set_keymap("n", explorer_keymaps.toggle_staged, function()
actions_module.toggle_group(explorer, "staged")
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Toggle Staged Changes visibility" }))
end
Expand Down
9 changes: 5 additions & 4 deletions lua/codediff/ui/history/keymaps.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-- Keymaps for history panel
local config = require("codediff.config")
local tree_utils = require("codediff.ui.lib.tree_utils")
local set_keymap = require("codediff.ui.lifecycle.accessors").set_keymap

local M = {}

Expand All @@ -18,7 +19,7 @@ function M.setup(history, opts)

-- Toggle expand/collapse or select file
if history_keymaps.select then
vim.keymap.set("n", history_keymaps.select, function()
set_keymap("n", history_keymaps.select, function()
local node = tree:get_node()
if not node then
return
Expand Down Expand Up @@ -54,7 +55,7 @@ function M.setup(history, opts)
end

-- Double-click support
vim.keymap.set("n", "<2-LeftMouse>", function()
set_keymap("n", "<2-LeftMouse>", function()
local node = tree:get_node()
if not node then
return
Expand Down Expand Up @@ -91,7 +92,7 @@ function M.setup(history, opts)

-- Toggle view mode between list and tree
if history_keymaps.toggle_view_mode then
vim.keymap.set("n", history_keymaps.toggle_view_mode, function()
set_keymap("n", history_keymaps.toggle_view_mode, function()
local history_config = config.options.history or {}
local current_mode = history_config.view_mode or "list"
local new_mode = (current_mode == "list") and "tree" or "list"
Expand All @@ -116,7 +117,7 @@ function M.setup(history, opts)

-- Refresh (R key) - re-fetch commits
if history_keymaps.refresh then
vim.keymap.set("n", history_keymaps.refresh, function()
set_keymap("n", history_keymaps.refresh, function()
local refresh_module = require("codediff.ui.history.refresh")
refresh_module.refresh(history)
end, vim.tbl_extend("force", map_options, { buffer = split.bufnr, desc = "Refresh history" }))
Expand Down
3 changes: 2 additions & 1 deletion lua/codediff/ui/keymap_help.lua
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,9 @@ function M.toggle(tabpage)

-- Close keymaps
local show_help_key = keymaps.view.show_help or "g?"
local set_keymap = require("codediff.ui.lifecycle.accessors").set_keymap
for _, key in ipairs({ "q", "<Esc>", show_help_key }) do
vim.keymap.set("n", key, function()
set_keymap("n", key, function()
if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
end
Expand Down
3 changes: 2 additions & 1 deletion lua/codediff/ui/lib/tree_utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ function M.setup_fold_keymaps(opts)
for _, binding in ipairs(fold_bindings) do
local key = keymaps[binding.key]
if key then
vim.keymap.set("n", key, binding.fn, vim.tbl_extend("force", map_options, { buffer = bufnr, desc = binding.desc }))
local set_keymap = require("codediff.ui.lifecycle.accessors").set_keymap
set_keymap("n", key, binding.fn, vim.tbl_extend("force", map_options, { buffer = bufnr, desc = binding.desc }))
end
end
end
Expand Down
39 changes: 34 additions & 5 deletions lua/codediff/ui/lifecycle/accessors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -439,29 +439,58 @@ function M.set_tab_keymap(tabpage, mode, lhs, rhs, opts)
local base_opts = { noremap = true, silent = true, nowait = true }

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 }))
M.set_keymap(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = sess.original_bufnr }))
sess.keymap_buffers[sess.original_bufnr] = true
end

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 }))
M.set_keymap(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 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 }))
M.set_keymap(mode, lhs, rhs, vim.tbl_extend("force", base_opts, opts, { buffer = explorer.bufnr }))
sess.keymap_buffers[explorer.bufnr] = true
end

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 }))
M.set_keymap(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

--- Keymap set wrapper to allow lists of keys
---@param modes string|string[] Mode "short-name" (see |nvim_set_keymap()|), or a list thereof.
---@param lhs string|string[] Left-hand side |{lhs}| of the mapping, can also be a list.
---@param rhs string|function Right-hand side |{rhs}| of the mapping, can be a Lua function.
---@param opts? vim.keymap.set.Opts
function M.set_keymap(modes, lhs, rhs, opts)
if type(lhs) == "string" then
vim.keymap.set(modes, lhs, rhs, opts)
else
for _, key in ipairs(lhs) do
vim.keymap.set(modes, key, rhs, opts)
end
end
end

--- Keymap del wrapper to delete lists of keys
---@param modes string|string[]
---@param lhs string|string[]
---@param opts? vim.keymap.del.Opts
function M.del_keymap(mode, lhs, opts)
if type(lhs) == "string" then
vim.keymap.del(mode, lhs, opts)
else
for _, key in ipairs(lhs) do
vim.keymap.del(mode, key, opts)
end
end
end

--- Remove codediff keymaps from a session's buffers
function M.clear_tab_keymaps(tabpage)
local active_diffs = get_active_diffs()
Expand All @@ -476,7 +505,7 @@ function M.clear_tab_keymaps(tabpage)
end
for _, key in pairs(keys) do
if key then
pcall(vim.keymap.del, "n", key, { buffer = bufnr })
pcall(M.del_keymap, "n", key, { buffer = bufnr })
end
end
end
Expand Down
Loading