Files
nvim/lua/core/keymap.lua
T
2026-05-10 03:26:28 +02:00

237 lines
7.5 KiB
Lua

-- Tab mappings ---
vim.keymap.set("n", "tn", vim.cmd.tabnew)
vim.keymap.set("n", "tq", vim.cmd.tabclose)
-- Clipboard
if vim.env.TMUX ~= nil and vim.fn.executable("tmux") == 1 then
vim.keymap.set(
{ "n", "x" },
"<leader>y",
"\"+y:call system('tmux load-buffer -w -', @+)<CR>"
)
else
vim.keymap.set({ "n", "x" }, "<leader>y", '"+y')
end
vim.keymap.set({ "n", "x" }, "<leader>p", '"+p')
vim.keymap.set({ "n", "x" }, "<leader>P", '"+P')
vim.keymap.set({ "n", "x" }, "<leader>+", ":call setreg('+', @\")<CR>")
-- Exit insert mode in terminal using <ESC>
vim.keymap.set("t", "<Esc>", "<C-\\><C-n>")
-- Feed ESC in terminal mode using <C-\>
vim.keymap.set("t", "<C-\\>", function()
vim.api.nvim_feedkeys(
vim.api.nvim_replace_termcodes("<Esc>", true, false, true),
"n",
false
)
end)
-- Enable <C-w> window commands in terminal mode
vim.keymap.set("t", "<C-w>", "<C-\\><C-n><C-w>")
-- Use :diffput/get instead of normal one to allow staging visual selection
vim.keymap.set({ "n", "x" }, "<leader>dp", ":diffput<CR>")
vim.keymap.set({ "n", "x" }, "<leader>do", ":diffget<CR>")
local close_pum = function()
if vim.fn.pumvisible() ~= 0 then
return "<cmd>pclose<cr>"
end
for _, winid in pairs(vim.api.nvim_tabpage_list_wins(0)) do
if vim.api.nvim_win_get_config(winid).relative ~= "" then
return "<cmd>fclose<cr>"
end
end
end
vim.keymap.set({ "n", "i" }, "<C-c>", function()
return close_pum()
end, { expr = true })
---@param force boolean
local function delete_buffer(force)
local buffers =
vim.split(vim.fn.execute("buffers t"), "\n", { trimempty = true })
if #buffers < 2 then
return
end
local b1 = buffers[1] --[[@as -nil]]
local b2 = buffers[2] --[[@as -nil]]
local current = tonumber(b1:match("^%s*(%d+)")) --[[@as integer?]]
local previous = tonumber(b2:match("^%s*(%d+)")) --[[@as integer?]]
if not current or not previous then
return
end
if not force and vim.bo[current].modified then
vim.api.nvim_echo(
{ { "Buffer has unsaved changes", "ErrorMsg" } },
false,
{}
)
return
end
vim.api.nvim_set_current_buf(previous)
vim.api.nvim_buf_delete(current, { force = force })
end
vim.keymap.set("n", "<C-q>", function()
delete_buffer(false)
end)
vim.keymap.set("n", "<M-q>", function()
delete_buffer(true)
end)
vim.keymap.set("n", "<C-Space>", ":b#<CR>")
-- Allow (de)indenting without deselecting
vim.keymap.set({ "x" }, "<", "<gv")
vim.keymap.set({ "x" }, ">", ">gv")
-- Remove default mappings
vim.keymap.set("", "<C-LeftMouse>", "")
vim.keymap.set("n", "gr", "<Nop>")
-- Remove right-click menu items
vim.cmd.aunmenu({ "PopUp.-1-" })
vim.cmd.aunmenu({ "PopUp.How-to\\ disable\\ mouse" })
-- Insert-mode Emacs bindings
vim.keymap.set("i", "<C-a>", "<C-o>^")
vim.keymap.set("i", "<C-e>", function()
return vim.fn.pumvisible() ~= 0 and "<C-e>" or "<C-o>$"
end, { expr = true, replace_keycodes = true })
-- vim.keymap.set('i', '<C-d>', '<C-o>x') -- Overrides de-indent
vim.keymap.set("i", "<M-f>", "<C-o>w")
vim.keymap.set("i", "<M-b>", "<C-o>b")
vim.keymap.set("i", "<M-d>", "<C-o>dw")
vim.keymap.set("i", "<M-BS>", "<C-o>db")
-- Command-mode Emacs bindings
vim.keymap.set("c", "<C-a>", "<Home>")
vim.keymap.set("c", "<C-e>", "<End>")
vim.keymap.set("c", "<C-d>", "<Delete>")
vim.keymap.set("c", "<C-n>", "<Down>")
vim.keymap.set("c", "<C-p>", "<Up>")
vim.keymap.set("c", "<M-f>", "<C-Right>")
vim.keymap.set("c", "<M-b>", "<C-Left>")
vim.keymap.set("c", "<M-d>", "<C-Right><C-w>")
vim.keymap.set("c", "<M-BS>", "<C-w>")
vim.keymap.set("n", "<leader>ve", function()
if vim.o.virtualedit == "all" then
vim.o.virtualedit = "block"
else
vim.o.virtualedit = "all"
end
end)
-- Replace all occurrences of word
vim.keymap.set("n", "<Leader>r", function()
local word = vim.fn.expand("<cword>")
local replacement = vim.fn.input('Replace "' .. word .. '" by? ')
if replacement ~= "" then
local cursor_pos = vim.api.nvim_win_get_cursor(0)
vim.cmd(":%s/\\<" .. word .. "\\>/" .. replacement .. "/g")
vim.api.nvim_win_set_cursor(0, cursor_pos)
end
end)
vim.keymap.set("n", "[d", function()
vim.diagnostic.jump({ count = -1, float = true })
end)
vim.keymap.set("n", "]d", function()
vim.diagnostic.jump({ count = 1, float = true })
end)
vim.keymap.set("n", "gD", vim.lsp.buf.declaration)
vim.keymap.set("n", "<C-k>", function()
vim.lsp.buf.hover({ max_width = 80 })
end)
vim.keymap.set({ "i", "s" }, "<C-s>", function()
local winid = vim.b.lsp_floating_preview
if winid and vim.api.nvim_win_is_valid(winid) then
vim.api.nvim_win_close(winid, false)
return
end
vim.lsp.buf.signature_help({ max_width = 80 })
end)
---@param mode string | string[]
---@param key string
---@param direction "up" | "down"
---@param count integer
---@param fallback? string
local function hover_scroll_map(mode, key, direction, count, fallback)
vim.keymap.set(mode, key, function()
local winid = vim.b.lsp_floating_preview
if not winid or not vim.api.nvim_win_is_valid(winid) then
return fallback or key
end
vim.schedule(function()
local scroll_key = direction == "down" and vim.keycode("<C-e>")
or vim.keycode("<C-y>")
vim.api.nvim_win_call(winid, function()
vim.cmd.normal({
args = { count .. scroll_key },
bang = true,
})
end)
end)
return ""
end, { expr = true, replace_keycodes = true })
end
hover_scroll_map({ "n", "s" }, "<C-f>", "down", 5)
hover_scroll_map({ "n", "s" }, "<C-b>", "up", 5)
hover_scroll_map("i", "<C-f>", "down", 5, "<Right>")
hover_scroll_map("i", "<C-b>", "up", 5, "<Left>")
---@param key string
---@param dir 1 | -1
local function snippet_jump_map(key, dir)
vim.keymap.set({ "i", "s" }, key, function()
if vim.snippet.active({ direction = dir }) then
return string.format("<cmd>lua vim.snippet.jump(%d)<CR>", dir)
end
return key
end, { expr = true, replace_keycodes = true })
end
snippet_jump_map("<Tab>", 1)
snippet_jump_map("<S-Tab>", -1)
vim.keymap.set({ "n", "i" }, "<C-h>", vim.lsp.buf.document_highlight)
vim.keymap.set({ "n", "x" }, "<leader>lf", vim.lsp.buf.format)
vim.keymap.set("n", "grl", function()
require("lsp.codelens").toggle()
end)
vim.keymap.set("n", "<leader>ld", function()
vim.diagnostic.enable(
not vim.diagnostic.is_enabled({ bufnr = 0 }),
{ bufnr = 0 }
)
end)
vim.keymap.set({ "n", "i" }, "<C-l>", function()
vim.lsp.buf.clear_references()
vim.cmd.nohlsearch()
vim.schedule(vim.cmd.diffupdate)
vim.snippet.stop()
return "<C-l>"
end, { expr = true })
vim.keymap.set("n", "<leader>fd", vim.diagnostic.setloclist)
vim.keymap.set("n", "<leader>fD", vim.diagnostic.setqflist)
vim.keymap.set("n", "grt", vim.lsp.buf.type_definition)
vim.keymap.set("n", "gd", vim.lsp.buf.definition)
vim.keymap.set("n", "<leader>gd", "<Plug>(git-diff-vertical)")
vim.keymap.set("n", "<leader>gD", "<Plug>(git-diff-vertical-head)")
vim.keymap.set("n", "<leader>gh", "<Plug>(git-diff-horizontal)")
vim.keymap.set("n", "<leader>gH", "<Plug>(git-diff-horizontal-head)")
vim.keymap.set("n", "<leader>gg", "<Plug>(git-status-toggle)")
vim.keymap.set("n", "<leader>gc", "<Plug>(git-commit)")
vim.keymap.set("n", "<leader>ga", "<Plug>(git-commit-amend)")
vim.keymap.set("n", "<leader>gl", "<Plug>(git-log)")