diff --git a/init.lua b/init.lua index 20102502..21ad5050 100644 --- a/init.lua +++ b/init.lua @@ -314,6 +314,13 @@ require('lazy').setup({ { 's', group = '[S]earch', mode = { 'n', 'v' } }, { 't', group = '[T]oggle' }, { 'h', group = 'Git [H]unk', mode = { 'n', 'v' } }, + { 'w', group = '[W]indow' }, + { 'b', group = '[B]uffer' }, + { 'u', group = '[U]I/Toggle' }, + { 'g', group = '[G]it' }, + { 'x', group = 'Quickfi[X]/Location' }, + { 'c', group = '[C]ode' }, + { '', group = '[Tab]s' }, }, }, }, @@ -865,5 +872,7 @@ require('lazy').setup({ }, }) +require('custom.keymaps') + -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et diff --git a/lua/custom/keymaps.lua b/lua/custom/keymaps.lua new file mode 100644 index 00000000..c09a91c3 --- /dev/null +++ b/lua/custom/keymaps.lua @@ -0,0 +1,193 @@ +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 {}