diff --git a/.github/workflows/lint_code.yml b/.github/workflows/lint_code.yml index ebf3a1a94..622cbbd4c 100644 --- a/.github/workflows/lint_code.yml +++ b/.github/workflows/lint_code.yml @@ -7,4 +7,4 @@ jobs: - uses: actions/checkout@v3 - uses: lunarmodules/luacheck@v1 with: - args: . --std luajit --globals vim _toggle_lazygit _command_panel _lspkeymap_loaded_bufnr --max-line-length 150 --no-config + args: . --std luajit --globals vim _toggle_lazygit _command_panel _debugging --max-line-length 150 --no-config diff --git a/lua/core/event.lua b/lua/core/event.lua index e88d74e85..db579fef4 100644 --- a/lua/core/event.lua +++ b/lua/core/event.lua @@ -14,14 +14,10 @@ function autocmd.nvim_create_augroups(definitions) end local mapping = require("keymap.completion") -_G._lspkeymap_loaded_bufnr = {} vim.api.nvim_create_autocmd("LspAttach", { group = vim.api.nvim_create_augroup("LspKeymapLoader", { clear = true }), callback = function(event) - if not _lspkeymap_loaded_bufnr[event.buf] then - mapping.lsp(event.buf) - _lspkeymap_loaded_bufnr[event.buf] = true - end + mapping.lsp(event.buf) end, }) diff --git a/lua/modules/configs/tool/dap/dap-keymap.lua b/lua/modules/configs/tool/dap/dap-keymap.lua index 495ef5cb2..bdaf08d32 100644 --- a/lua/modules/configs/tool/dap/dap-keymap.lua +++ b/lua/modules/configs/tool/dap/dap-keymap.lua @@ -1,78 +1,21 @@ local M = {} local bind = require("keymap.bind") -local map_cr = bind.map_cr local map_cmd = bind.map_cmd local did_load_debug_mappings = false -local keymap_info_debug = { - n = { K = false }, - v = { K = false }, -} -local keymap_info_original = { - n = { K = true }, - v = { K = false }, -} local debug_keymap = { ["nv|K"] = map_cmd("lua require('dapui').eval()") :with_noremap() :with_nowait() - :with_desc("debug: Evaluate expression under cursor"), -} -local original_keymap = { - ["n|K"] = map_cr("Lspsaga hover_doc"):with_noremap():with_silent():with_desc("lsp: Show doc"), - ["v|K"] = map_cmd(":m '<-2gv=gv"), + :with_desc("Evaluate expression under cursor"), } -local function del_keymap(mappings, keymap_info) - for key in pairs(mappings) do - local modes, keymap = key:match("([^|]*)|?(.*)") - for _, mode in ipairs(vim.split(modes, "")) do - if vim.fn.maparg(keymap, mode, false) ~= "" then - if keymap_info[mode][keymap] == true then - vim.api.nvim_buf_del_keymap(0, mode, keymap) - else - vim.api.nvim_del_keymap(mode, keymap) - end - end - end - end -end - -local function load_keymap(mappings, keymap_info) - for key, value in pairs(mappings) do - local modes, keymap = key:match("([^|]*)|?(.*)") - if type(value) == "table" then - for _, mode in ipairs(vim.split(modes, "")) do - local rhs = value.cmd - local options = value.options - if keymap_info[mode][keymap] == true then - for buf in pairs(_G._lspkeymap_loaded_bufnr) do - -- Restore lsp keymaps - vim.api.nvim_buf_set_keymap(buf, mode, keymap, rhs, options) - end - else - vim.api.nvim_set_keymap(mode, keymap, rhs, options) - end - end - end - end -end - -function M.load() +function M.load_extras() if not did_load_debug_mappings then - del_keymap(original_keymap, keymap_info_original) - load_keymap(debug_keymap, keymap_info_debug) + require("modules.utils.keymap").amend("Debugging", "_debugging", debug_keymap) did_load_debug_mappings = true end end -function M.restore() - if did_load_debug_mappings then - del_keymap(debug_keymap, keymap_info_debug) - load_keymap(original_keymap, keymap_info_original) - did_load_debug_mappings = false - end -end - return M diff --git a/lua/modules/configs/tool/dap/init.lua b/lua/modules/configs/tool/dap/init.lua index 489f0dc9b..8fff15a4e 100644 --- a/lua/modules/configs/tool/dap/init.lua +++ b/lua/modules/configs/tool/dap/init.lua @@ -8,16 +8,15 @@ return function() local mappings = require("tool.dap.dap-keymap") -- Initialize debug hooks - local _debugging = false + _G._debugging = false local function debug_init_cb() - _debugging = true - mappings.load() + _G._debugging = true + mappings.load_extras() dapui.open({ reset = true }) end local function debug_terminate_cb() if _debugging then - _debugging = false - mappings.restore() + _G._debugging = false dapui.close() end end diff --git a/lua/modules/utils/keymap.lua b/lua/modules/utils/keymap.lua new file mode 100644 index 000000000..033e1686a --- /dev/null +++ b/lua/modules/utils/keymap.lua @@ -0,0 +1,150 @@ +local M = {} + +---Shortcut for `nvim_replace_termcodes`. +---@param keys string +---@return string +local function termcodes(keys) + return vim.api.nvim_replace_termcodes(keys, true, true, true) +end + +---Returns if two key sequence are equal or not. +---@param a string +---@param b string +---@return boolean +local function keymap_equals(a, b) + return termcodes(a) == termcodes(b) +end + +---Get map +---@param mode string +---@param lhs string +---@return table +local function get_map(mode, lhs) + for _, map in ipairs(vim.api.nvim_buf_get_keymap(0, mode)) do + if keymap_equals(map.lhs, lhs) then + return { + lhs = map.lhs, + rhs = map.rhs or "", + expr = map.expr == 1, + callback = map.callback, + noremap = map.noremap == 1, + script = map.script == 1, + silent = map.silent == 1, + nowait = map.nowait == 1, + buffer = true, + } + end + end + + for _, map in ipairs(vim.api.nvim_get_keymap(mode)) do + if keymap_equals(map.lhs, lhs) then + return { + lhs = map.lhs, + rhs = map.rhs or "", + expr = map.expr == 1, + callback = map.callback, + noremap = map.noremap == 1, + script = map.script == 1, + silent = map.silent == 1, + nowait = map.nowait == 1, + buffer = false, + } + end + end + + return { + lhs = lhs, + rhs = lhs, + expr = false, + callback = nil, + noremap = true, + script = false, + silent = true, + nowait = false, + buffer = false, + } +end + +---Returns the function constructed from the passed keymap object on call of +---which the original keymapping will be executed. +---@param map table keymap object +---@return function +local function get_fallback(map) + return function() + local keys, fmode + if map.expr then + if map.callback then + keys = map.callback() + else + keys = vim.api.nvim_eval(map.rhs) + end + elseif map.callback then + map.callback() + return + else + keys = map.rhs + end + keys = termcodes(keys) + fmode = map.noremap and "in" or "im" + vim.api.nvim_feedkeys(keys, fmode, false) + end +end + +---@param cond string +---@param mode string +---@param lhs string +---@param rhs function +---@param opts? table +local function amend(cond, mode, lhs, rhs, opts) + local map = get_map(mode, lhs) + local fallback = get_fallback(map) + local options = vim.deepcopy(opts) or {} + options.desc = table.concat({ + "[" .. cond, + (options.desc and ": " .. options.desc or ""), + "]", + (map.desc and " / " .. map.desc or ""), + }) + vim.keymap.set(mode, lhs, function() + rhs(fallback) + end, options) +end + +---Amend the existing keymap. +---@param cond string +---@param mode string | string[] +---@param lhs string +---@param rhs function +---@param opts? table +local function modes_amend(cond, mode, lhs, rhs, opts) + if type(mode) == "table" then + for _, m in ipairs(mode) do + amend(cond, m, lhs, rhs, opts) + end + else + amend(cond, mode, lhs, rhs, opts) + end +end + +---@param cond string +---@param global_flag string +---@param mapping table +function M.amend(cond, global_flag, mapping) + for key, value in pairs(mapping) do + local modes, keymap = key:match("([^|]*)|?(.*)") + if type(value) == "table" then + local rhs = value.cmd + local options = value.options + modes_amend(cond, vim.split(modes, ""), keymap, function(fallback) + if _G[global_flag] then + local fmode = options.noremap and "in" or "im" + vim.api.nvim_feedkeys(termcodes(rhs), fmode, false) + else + fallback() + end + end, options) + end + end +end + +return M