-- unmap arrow keys in non-insert modes Map({ 'n', 'v' }, '', '') Map({ 'n', 'v' }, '', '') Map({ 'n', 'v' }, '', '') Map({ 'n', 'v' }, '', '') -- tab management / navigation Map('n', '', 'enew', { desc = 'create a new buffer' }) Map('n', '', 'bnext', { desc = 'move to next buffer' }) Map('n', '', 'bprevious', { desc = 'move to previous buffer' }) Map('n', '', 'bd', { desc = 'close buffer' }) Map('n', '', 'bd', { desc = 'close buffer' }) -- for help exiting certain modes Map({ 'n', 'i' }, '', 'nohlsearch', { desc = 'cancel search highlighting and escape' }) Map('t', '', '', { desc = 'exit terminal mode' }) -- window management Map('n', '', 'wincmd s', { desc = 'horizontal split' }) Map('n', '', 'wincmd v', { desc = 'vertical split' }) Map('n', '', 'wincmd h', { desc = 'move focus to the left window' }) Map('n', '', 'wincmd l', { desc = 'move focus to the right window' }) Map('n', '', 'wincmd j', { desc = 'move focus to the lower window' }) Map('n', '', 'wincmd k', { desc = 'move focus to the upper window' }) Map('n', '', 'wincmd H', { desc = 'move window to left' }) Map('n', '', 'wincmd L', { desc = 'move window to right' }) Map('n', '', 'wincmd K', { desc = 'move window to top' }) Map('n', '', 'wincmd J', { desc = 'move window to bottom' }) -- diagnostic / lsp key bindings Map('n', 'K', vim.lsp.buf.hover, { desc = 'symbol hover' }) Map('n', '', vim.lsp.buf.rename, { desc = 'rename symbol' }) Map('n', 'lm', vim.diagnostic.open_float, { desc = 'view line\'s diagnostic messages' }) Map('n', 'q', vim.lsp.buf.code_action, { desc = 'view quickfix list' }) Map('n', 'gd', vim.lsp.buf.definition, { desc = "Go to the definition" }) Map('n', 'gr', vim.lsp.buf.references, { desc = "Go to the reference" }) -- smart tabulation Map('i', '', function() local _, col = unpack(vim.api.nvim_win_get_cursor(0)) -- get cursor position local ln = vim.api.nvim_get_current_line():sub(1, col) local isindent = ln:match('^%s*$') local tabexpnd = vim.bo.expandtab local tabwidth = vim.bo.shiftwidth > 0 and vim.bo.shiftwidth or vim.bo.tabstop if not tabexpnd and isindent then return '\t' else -- Compute the amount of spaces needed for the line. local i = col while i >= 1 do if ln:sub(i, i) == '\t' then break end i = i - 1 end local spaces = tabwidth - (col - i) % tabwidth return string.rep(' ', spaces == 0 and tabwidth or spaces) end end, { expr = true, desc = "smart tabulation" }) -- set the keybind for appending in front of a comment, rather than behind. Map('n', 'A', function() local ts = vim.treesitter -- get reference to treesitter local buf = vim.api.nvim_get_current_buf() -- get the current buffer id local row, col = unpack(vim.api.nvim_win_get_cursor(0)) -- get cursor position -- ensure the parser exists local res = nil repeat -- get the parser if not ts.language.get_lang(vim.bo[buf].filetype) then break end local parser = ts.get_parser(buf, nil, { error = false }) if not parser then break end -- query the buffer using the parser local root = parser:parse()[1]:root() local ok, dat = pcall(ts.query.parse, parser:lang(), [[(comment) @comment]]) if not ok or not dat then break end -- set the result res = { query = dat, root = root } until true -- check if we successfully made a query if res then -- loop through the captures from the query for _, node in res.query:iter_captures(res.root, buf, row - 1, row) do -- ensure the comment is on the same row as the cursor and after the cursor's column local srow, scol, _, _ = node:range() -- extract the starting row and starting column if srow ~= row - 1 or col >= scol then goto continue end -- get the line text and remove trailing whitespace local txt = vim.api.nvim_buf_get_lines(buf, srow, srow + 1, true)[1]:sub(0, scol) txt = txt:gsub("%s*$", "") local len = txt:len() -- check if we found a match if len > 0 then vim.api.nvim_win_set_cursor(0, { row, len }) vim.cmd [[startinsert]] return end ::continue:: -- lua is stupid end end -- no comment start was found, behave like normal (moves cursor to the end of the line) vim.cmd [[startinsert!]] end, { desc = 'append end of line' })