local g = vim.g local set = vim.keymap.set local f = string.format g.mapleader = ' ' g.maplocalleader = '\\' -- Disable arrow key movement -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for _, key in ipairs({ '<DOWN>', '<UP>', '<LEFT>', '<RIGHT>' }) do set({ 'n', 'i' }, key, '<NOP>') end -- Better up/down -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for dir, key in pairs({ Down = 'j', Up = 'k' }) do set( { 'n', 'x' }, key, f("v:count == 0 ? 'g%s' : '%s'", key, key), { desc = dir, expr = true, silent = true } ) end -- Resize windows -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for key, dir in pairs({ Up = 'increase', Down = 'decrease', Left = 'decrease', Right = 'increase', }) do local sign = (dir == 'increase') and '+' or '-' set( { 'n' }, f('<C-%s>', key), f('<CMD>resize %s4<CR>', sign), { desc = f('%s window height', dir) } ) end -- Buffers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for key, dir in pairs({ ['<S-H>'] = 'previous', ['<S-L>'] = 'next', ['[b'] = 'previous', [']b'] = 'next', }) do -- previous -> prev local prettyDir = dir:sub(1, 4) set( { 'n' }, key, f('<CMD>b%s<CR>', dir), { desc = f('%s buffer', prettyDir) } ) end set({ 'n' }, '<LEADER>bD', '<CMD>bd<CR>', { desc = 'delete buffer and window' }) -- Clear search & refresh -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set( { 'n', 'i' }, '<ESC>', '<CMD>noh<CR><ESC>', { desc = 'escape and clear hlsearch' } ) set( { 'n' }, '<LEADER>ur', '<CMD>nohlsearch<BAR>diffupdate<BAR>normal! <C-l><CR>', { desc = 'redraw / clear hlsearch / diff update' } ) -- Better n & N -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for _, mode in ipairs({ 'n', 'x', 'o' }) do local zv = (mode == 'n') and ".'zv'" or '' set( { mode }, 'n', f("'Nn'[v:searchforward]%s", zv), { desc = 'next search result', expr = true } ) set( { mode }, 'N', f("'nN'[v:searchforward]%s", zv), { desc = 'previous search result', expr = true } ) end -- Undo break-points -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for _, char in ipairs({ ',', '.', ';' }) do set({ 'i' }, char, f('%s<C-g>u', char)) end -- Search docs (keywordprog) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- https://til.codeinthehole.com/posts/about-how-to-use-keywordprg-effectively/ set( { 'n' }, '<LEADER>K', '<CMD>norm! K<CR>', { desc = 'search <KEYWORDPROG> for word' } ) -- Better indenting -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for _, char in ipairs({ '<', '>' }) do local desc = 'indent ' .. (char == '<' and 'left' or 'right') set({ 'v' }, char, f('%sgv', char), { desc = desc }) end -- Commenting -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for key, dir in pairs({ o = 'below', O = 'above' }) do set( { 'n' }, f('gc%s', key), f('%s<ESC>Vcx<ESC><CMD>normal gcc<CR>fxa<BS>', key), { desc = f('add comment %s', dir) } ) end -- New files -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set({ 'n' }, '<LEADER>fn', '<CMD>enew<CR>', { desc = 'new file' }) -- Locations/quickfixes -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set({ 'n' }, '<LEADER>xl', '<CMD>lopen<CR>', { desc = 'location list' }) set({ 'n' }, '<LEADER>xq', '<CMD>copen<CR>', { desc = 'quickfix list' }) for key, dir in pairs({ ['['] = 'previous', [']'] = 'next' }) do -- previous -> prev local cmd = dir:sub(1, 4) set( { 'n' }, f('%sq', key), f('<CMD>c%s<CR>', cmd), { desc = f('%s quickfix', dir) } ) end -- Diagnostics -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set({ 'n' }, '<LEADER>cd', function() vim.diagnostic.open_float() end, { desc = 'line diagnostics' }) local function goto_diagnostic(next, severity) local go = next and vim.diagnostic.goto_next or vim.diagnostic.goto_prev severity = severity and vim.diagnostic.severity[severity] or nil return function() go({ severity = severity }) end end for key, sev in pairs({ d = { nil, 'diagnostic' }, e = { 'ERROR', 'error' }, w = { 'WARN', 'warning' }, }) do set( { 'n' }, f(']%s', key), goto_diagnostic(true, sev[1]), { desc = f('next %s', sev[2]) } ) set( { 'n' }, f('[%s', key), goto_diagnostic(false, sev[1]), { desc = f('previous %s', sev[2]) } ) end -- Quit -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set({ 'n' }, '<LEADER>qq', '<CMD>qa<CR>', { desc = 'quit all' }) -- Inspect -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set({ 'n' }, '<LEADER>ui', vim.show_pos, { desc = 'inspect position' }) -- Window management -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- set({ 'n' }, '<LEADER>w', '<C-w>', { desc = 'windows', remap = true }) set({ 'n' }, '<LEADER>-', '<C-w>s', { desc = 'split below', remap = true }) set({ 'n' }, '<LEADER>|', '<C-w>v', { desc = 'split right', remap = true }) set({ 'n' }, '<LEADER>wd', '<C-w>c', { desc = 'delete window', remap = true }) -- Tab management -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for key, act in pairs({ l = 'last', o = 'only', f = 'first', ['<TAB>'] = 'new', [']'] = 'next', d = 'close', ['['] = 'previous', }) do local desc = (act == 'only') and 'close other tabs' or f('%s tab', act) set( { 'n' }, f('<LEADER><TAB>%s', key), f('<CMD>tab%s<CR>', act:lower()), { desc = desc } ) end