local map = vim.keymap.set ---------------------------------------------------------------------- -- WINDOW MANAGEMENT (w) ---------------------------------------------------------------------- map('n', 'w|', 'v', { desc = 'Split window right' }) map('n', 'w-', 's', { desc = 'Split window below' }) map('n', 'wd', 'c', { desc = '[W]indow [D]elete' }) map('n', 'wo', 'o', { desc = '[W]indow [O]nly (close others)' }) map('n', 'wm', function() if vim.t.maximized then vim.cmd('wincmd =') vim.t.maximized = false else vim.cmd('wincmd _|') vim.t.maximized = true end end, { desc = '[W]indow toggle [M]aximize' }) map('n', 'w=', '=', { desc = 'Equalize window sizes' }) map('n', '', 'resize +2', { desc = 'Increase window height' }) map('n', '', 'resize -2', { desc = 'Decrease window height' }) map('n', '', 'vertical resize -2', { desc = 'Decrease window width' }) map('n', '', 'vertical resize +2', { desc = 'Increase window width' }) ---------------------------------------------------------------------- -- BUFFER MANAGEMENT (b) ---------------------------------------------------------------------- map('n', 'bd', 'bdelete', { desc = '[B]uffer [D]elete' }) map('n', 'bD', 'bdelete!', { desc = '[B]uffer [D]elete (force)' }) map('n', 'bo', function() local current = vim.api.nvim_get_current_buf() for _, buf in ipairs(vim.api.nvim_list_bufs()) do if buf ~= current and vim.api.nvim_buf_is_loaded(buf) then vim.api.nvim_buf_delete(buf, { force = false }) end end end, { desc = '[B]uffer delete [O]thers' }) map('n', 'bb', 'b#', { desc = '[B]uffer [B]ack to alternate' }) map('n', 'b1', '1gt', { desc = 'Go to tab 1' }) map('n', 'b2', '2gt', { desc = 'Go to tab 2' }) map('n', 'b3', '3gt', { desc = 'Go to tab 3' }) map('n', 'b4', '4gt', { desc = 'Go to tab 4' }) map('n', 'b5', '5gt', { desc = 'Go to tab 5' }) map('n', 'b6', '6gt', { desc = 'Go to tab 6' }) map('n', 'b7', '7gt', { desc = 'Go to tab 7' }) map('n', 'b8', '8gt', { desc = 'Go to tab 8' }) map('n', 'b9', '9gt', { desc = 'Go to tab 9' }) map('n', '', 'bprevious', { desc = 'Previous buffer' }) map('n', '', 'bnext', { desc = 'Next buffer' }) map('n', '[b', 'bprevious', { desc = 'Previous buffer' }) map('n', ']b', 'bnext', { desc = 'Next buffer' }) ---------------------------------------------------------------------- -- TAB MANAGEMENT () ---------------------------------------------------------------------- map('n', '', 'tabnew', { desc = 'New tab' }) map('n', 'd', 'tabclose', { desc = 'Close tab' }) map('n', ']', 'tabnext', { desc = 'Next tab' }) map('n', '[', 'tabprevious', { desc = 'Previous tab' }) map('n', 'f', 'tabfirst', { desc = 'First tab' }) map('n', 'l', 'tablast', { desc = 'Last tab' }) map('n', 'o', 'tabonly', { desc = 'Close other tabs' }) map('n', '1', '1gt', { desc = 'Go to tab 1' }) map('n', '2', '2gt', { desc = 'Go to tab 2' }) map('n', '3', '3gt', { desc = 'Go to tab 3' }) map('n', '4', '4gt', { desc = 'Go to tab 4' }) map('n', '5', '5gt', { desc = 'Go to tab 5' }) map('n', '6', '6gt', { desc = 'Go to tab 6' }) map('n', '7', '7gt', { desc = 'Go to tab 7' }) map('n', '8', '8gt', { desc = 'Go to tab 8' }) map('n', '9', '9gt', { desc = 'Go to tab 9' }) ---------------------------------------------------------------------- -- TOGGLES (u) ---------------------------------------------------------------------- map('n', 'ul', function() vim.wo.number = not vim.wo.number end, { desc = 'Toggle [L]ine numbers' }) map('n', 'uL', function() vim.wo.relativenumber = not vim.wo.relativenumber end, { desc = 'Toggle relative line [L]numbers' }) map('n', 'uw', function() vim.wo.wrap = not vim.wo.wrap end, { desc = 'Toggle [W]rap' }) map('n', 'us', function() vim.wo.spell = not vim.wo.spell end, { desc = 'Toggle [S]pell' }) map('n', 'uc', function() vim.wo.conceallevel = vim.wo.conceallevel == 0 and 2 or 0 end, { desc = 'Toggle [C]onceal' }) map('n', 'ub', function() vim.o.background = vim.o.background == 'dark' and 'light' or 'dark' end, { desc = 'Toggle [B]ackground' }) map('n', 'uS', function() vim.wo.list = not vim.wo.list end, { desc = 'Toggle [S]how whitespace' }) map('n', 'uh', 'set hlsearch!', { desc = 'Toggle search [H]ighlight' }) map('n', 'ud', function() local config = vim.diagnostic.config() vim.diagnostic.config({ virtual_text = not config.virtual_text }) end, { desc = 'Toggle [D]iagnostics' }) map('n', 'ur', 'nohlsearchredraw', { desc = '[U]I [R]edraw / clear highlight' }) ---------------------------------------------------------------------- -- GIT (g) ---------------------------------------------------------------------- map('n', 'gb', function() local ok, gitsigns = pcall(require, 'gitsigns') if ok then gitsigns.blame_line({ full = true }) else vim.cmd('Git blame') end end, { desc = '[G]it [B]lame' }) map('n', 'gl', function() vim.cmd('new') vim.cmd('terminal git log --oneline -20') vim.cmd('startinsert') end, { desc = '[G]it [L]og' }) map('n', 'gL', function() vim.cmd('new') vim.cmd('terminal git log --oneline -20 -- ' .. vim.fn.expand('%')) vim.cmd('startinsert') end, { desc = '[G]it [L]og (current file)' }) map('n', 'gg', function() vim.cmd('terminal lazygit') vim.cmd('startinsert') end, { desc = '[G]it [G]ui (LazyGit)' }) map('n', 'gS', 'Git', { desc = '[G]it [S]tatus' }) map('n', 'gd', function() vim.cmd('Gvdiffsplit') end, { desc = '[G]it [D]iff' }) ---------------------------------------------------------------------- -- QUICKFIX / LOCATION LIST (x) ---------------------------------------------------------------------- map('n', 'xq', 'copen', { desc = 'Quickfix list' }) map('n', 'xl', 'lopen', { desc = 'Location list' }) map('n', 'xc', 'cclose', { desc = 'Close quickfix' }) map('n', 'xC', 'lclose', { desc = 'Close location list' }) map('n', ']q', 'cnext', { desc = 'Next quickfix item' }) map('n', '[q', 'cprevious', { desc = 'Previous quickfix item' }) map('n', ']Q', 'clast', { desc = 'Last quickfix item' }) map('n', '[Q', 'cfirst', { desc = 'First quickfix item' }) map('n', ']l', 'lnext', { desc = 'Next location item' }) map('n', '[l', 'lprevious', { desc = 'Previous location item' }) ---------------------------------------------------------------------- -- LSP / CODE (c) ---------------------------------------------------------------------- map('n', 'ca', vim.lsp.buf.code_action, { desc = '[C]ode [A]ction' }) map('x', 'ca', vim.lsp.buf.code_action, { desc = '[C]ode [A]ction' }) map('n', 'cr', vim.lsp.buf.rename, { desc = '[C]ode [R]ename' }) map('n', 'cA', function() vim.lsp.buf.code_action({ context = { only = { 'source' } }, apply = true }) end, { desc = '[C]ode [A]ction (source)' }) map('n', 'cl', 'LspInfo', { desc = '[C]ode [L]SP Info' }) map('n', 'cd', vim.diagnostic.open_float, { desc = 'Line [D]iagnostics' }) map('n', ']e', function() vim.diagnostic.goto_next({ severity = vim.diagnostic.severity.ERROR }) end, { desc = 'Next [E]rror' }) map('n', '[e', function() vim.diagnostic.goto_prev({ severity = vim.diagnostic.severity.ERROR }) end, { desc = 'Previous [E]rror' }) map('n', ']w', function() vim.diagnostic.goto_next({ severity = vim.diagnostic.severity.WARN }) end, { desc = 'Next [W]arning' }) map('n', '[w', function() vim.diagnostic.goto_prev({ severity = vim.diagnostic.severity.WARN }) end, { desc = 'Previous [W]arning' }) ---------------------------------------------------------------------- -- UTILITIES ---------------------------------------------------------------------- map({ 'i', 'x', 'n', 's' }, '', 'w', { desc = 'Save file' }) map('n', 'n', 'nzzzv', { desc = 'Next search result (centered)' }) map('n', 'N', 'Nzzzv', { desc = 'Previous search result (centered)' }) map('n', 'J', 'mzJ`z', { desc = 'Join lines (keep position)' }) map('n', '', 'm .+1==', { desc = 'Move line down' }) map('n', '', 'm .-2==', { desc = 'Move line up' }) map('i', '', 'm .+1==gi', { desc = 'Move line down' }) map('i', '', 'm .-2==gi', { desc = 'Move line up' }) map('v', '', "m '>+1gv=gv", { desc = 'Move selection down' }) map('v', '', "m '<-2gv=gv", { desc = 'Move selection up' }) map('v', '<', '', '>gv', { desc = 'Indent right' }) map('n', 'fn', 'enew', { desc = '[F]ile [N]ew' }) map('n', 'qq', 'qa', { desc = '[Q]uit [Q]all' }) map('n', 'qQ', 'qa!', { desc = '[Q]uit [Q]all (force)' }) map('n', 'K', 'norm! K', { desc = 'Keywordprg' }) map('n', 'l', 'Lazy', { desc = 'Open [L]azy' }) map('n', 'cf', function() require('conform').format({ async = true, lsp_format = 'fallback' }) end, { desc = '[C]ode [F]ormat' }) map('x', 'cf', function() require('conform').format({ async = true, lsp_format = 'fallback' }) end, { desc = '[C]ode [F]ormat' }) ---------------------------------------------------------------------- -- TERMINAL ---------------------------------------------------------------------- map('n', 'ft', function() vim.cmd('split') vim.cmd('terminal') vim.cmd('startinsert') end, { desc = '[F]ile [T]erminal' }) map('n', '', function() vim.cmd('terminal') vim.cmd('startinsert') end, { desc = 'Open terminal' }) map('t', '', 'close', { desc = 'Close terminal' }) map('t', '', 'wincmd h', { desc = 'Go to left window' }) map('t', '', 'wincmd j', { desc = 'Go to lower window' }) map('t', '', 'wincmd k', { desc = 'Go to upper window' }) map('t', '', 'wincmd l', { desc = 'Go to right window' }) return {}