From 9b3a9ece1ea2630cf912b9202a06cc7e05d9f7d7 Mon Sep 17 00:00:00 2001 From: Martin Larsson Date: Mon, 13 Jan 2025 12:08:07 +0100 Subject: [PATCH] Add a way to cache default keymaps, impl function for adding temporary keymaps (i.e keymaps during debugging) which saves original keymaps if it overrides them at restores them upon deletion. --- home/.config/nvim/lua/plugs/nvim-dap.lua | 2 +- home/.config/nvim/lua/utils.lua | 90 ++++++++++++++++++------ 2 files changed, 71 insertions(+), 21 deletions(-) diff --git a/home/.config/nvim/lua/plugs/nvim-dap.lua b/home/.config/nvim/lua/plugs/nvim-dap.lua index 4103114..ea09c95 100644 --- a/home/.config/nvim/lua/plugs/nvim-dap.lua +++ b/home/.config/nvim/lua/plugs/nvim-dap.lua @@ -79,7 +79,7 @@ return { local function enter_debug_mode() dapui.open() if not are_stepping_keymaps_active then - utils.add_keymaps(stepping_keymaps) + utils.add_temporary_keymaps(stepping_keymaps) are_stepping_keymaps_active = true end diff --git a/home/.config/nvim/lua/utils.lua b/home/.config/nvim/lua/utils.lua index 17c5e32..ff806ba 100644 --- a/home/.config/nvim/lua/utils.lua +++ b/home/.config/nvim/lua/utils.lua @@ -1,5 +1,7 @@ local M = {} +local overridden_default_keymaps = {} + local function is_single_keymap_table(map_table) assert(map_table) return map_table.n or map_table.t or map_table.i or map_table.v or map_table.x or map_table.o @@ -73,44 +75,92 @@ function M.add_opts_to_all_mappings(mappings, opts) end end +local function pass_keymap_tbl_to_fn(maps, fn) + if is_single_keymap_table(maps) then + fn(maps) + else + for _, map_table in pairs(maps) do + fn(map_table) + end + end +end + +local function get_keymaps(mode, buffer) + if buffer then + return vim.api.nvim_buf_get_keymap(buffer, mode) + end + + return vim.api.nvim_get_keymap(mode) +end + +function M.add_temporary_keymaps(maps) + assert(maps) + + pass_keymap_tbl_to_fn(maps, function(map_table) + for mode, entries in pairs(map_table) do + -- We make an assumptino here which is that all the entries are buffers, or not buffers. + -- Meaning, we only check the first entry and trust that the rest are the same. + local result = get_keymaps(mode, (function() + for _, entry in pairs(entries) do + -- nil buffer is treated as a global keymap + return entry.buffer + end + end)()) + + for code, _ in pairs(entries) do + for _, map in ipairs(result) do + if map.lhs == code then + if not overridden_default_keymaps[mode] then + overridden_default_keymaps[mode] = {} + end + + overridden_default_keymaps[mode][code] = { + cmd = map.callback or map.rhs, + opts = { + noremap = map.noremap == 1, + expr = map.expr == 1, + silent = map.silent == 1, + nowait = map.nowait == 1, + script = map.script == 1, + buffer = type(map.buffer) == "number" and map.buffer or nil, + }, + } + end + end + end + end + end) + + M.add_keymaps(maps) +end + function M.add_keymaps(maps) assert(maps) - local function set_keymaps(map_table) + pass_keymap_tbl_to_fn(maps, function(map_table) for mode, entries in pairs(map_table) do for code, info in pairs(entries) do vim.keymap.set(mode, code, info.cmd, info.opts) end end - end - - if is_single_keymap_table(maps) then - set_keymaps(maps) - else - for _, map_table in pairs(maps) do - set_keymaps(map_table) - end - end + end) end function M.remove_keymaps(maps) assert(maps) - local function del_keymaps(map_table) + pass_keymap_tbl_to_fn(maps, function(map_table) for mode, entries in pairs(map_table) do + local overriden_mode = overridden_default_keymaps[mode] for code, _ in pairs(entries) do vim.keymap.del(mode, code) + + if overriden_mode and overriden_mode[code] then + vim.keymap.set(mode, code, overriden_mode[code].cmd, overriden_mode[code].opts) + end end end - end - - if is_single_keymap_table(maps) then - del_keymaps(maps) - else - for _, map_table in pairs(maps) do - del_keymaps(map_table) - end - end + end) end function M.is_buf_filetype(bufnr, filetype)