269 lines
11 KiB
Lua
269 lines
11 KiB
Lua
local map = vim.keymap.set
|
|
local prefix = require('which-key').register
|
|
|
|
-- The general ideas behind these mappings:
|
|
--
|
|
-- * Leader prefix is the generally preferred way to map new things, however
|
|
-- only for those that affect all of vim of work in a supra-buffer way.
|
|
--
|
|
-- * Localleader prefix is used for mappings which only affect single buffers.
|
|
-- In other words mostly filetype specific mappings
|
|
|
|
-- backspace to switch to alternate (last) buffer
|
|
map('n', '<BS>', '<C-^>')
|
|
|
|
-- since u undoes, would it not make sense that U redoes?
|
|
map('n', 'U', '<C-r>')
|
|
|
|
-- d-motion puts the last 'deleted' thing into the default register to paste;
|
|
-- use D-motion to truly delete something into nothingness and keep whatever
|
|
-- you want in your register, ready to paste
|
|
map('n', 'D', '"_d')
|
|
|
|
-- I don't particularly need ex mode (at least, yet) but faster macro access is nice
|
|
map('n', 'Q', '@')
|
|
|
|
-- stronger versions of left,right - move all the way to beginning/end of line
|
|
map('n', 'H', '^')
|
|
map('n', 'L', '$')
|
|
|
|
-- when in softwrapped files, allow moving through the visible lines with j/k
|
|
-- but when prepending a number jump *exactly* as many lines, wrapped or not
|
|
-- This makes relative linenumbers much more useful in prose docs since they
|
|
-- are always exactly correct
|
|
local function wrap_up()
|
|
if vim.v.count == 0 then return 'gk' end
|
|
return 'k'
|
|
end
|
|
|
|
local function wrap_down()
|
|
if vim.v.count == 0 then return 'gj' end
|
|
return 'j'
|
|
end
|
|
|
|
map('n', 'k', wrap_up, { expr = true })
|
|
map('n', 'j', wrap_down, { expr = true })
|
|
|
|
-- move around between matching brackets with tab
|
|
map('n', '<Tab>', '%')
|
|
|
|
-- when in insertion mode, C-u uppercases the current word, C-l lowercases it,
|
|
map('i', '<C-u>', '<esc>gUiw`]a')
|
|
map('i', '<C-y>', '<esc>guiw`]a')
|
|
|
|
-- Add undo break-points at punctuations for plaintext editing
|
|
for _, char in pairs({ ",", ".", ";", "?", "!" }) do
|
|
map("i", char, string.format("%s<c-g>u", char))
|
|
end
|
|
|
|
-- yank current filename/filepath to f buffer
|
|
map('n', 'yp', ':let @p = expand("%")<Cr>', { desc = 'yank filename' })
|
|
map('n', 'yP', ':let @p = expand("%:p")<Cr>', { desc = 'yank filepath' })
|
|
|
|
-- repeat the last substitute command with all its flags preserved
|
|
map('n', '&', ':&&<cr>')
|
|
|
|
-- bracket pairings to go to the next/previous of:
|
|
-- (works with count prefixes)
|
|
-- Argument list
|
|
map('n', '[a', ':previous<cr>')
|
|
map('n', ']a', ':next<cr>')
|
|
-- Buffers
|
|
map('n', '[b', ':bprevious<cr>')
|
|
map('n', ']b', ':bnext<cr>')
|
|
-- Quickfix list
|
|
map('n', '[q', ':cprevious<cr>')
|
|
map('n', ']q', ':cnext<cr>')
|
|
-- Location list
|
|
map('n', '[l', ':lprevious<cr>')
|
|
map('n', ']l', ':lnext<cr>')
|
|
|
|
-- maps the leader for buffer local mappings
|
|
-- since we are (atm) using sneak to go fwd/bwd in fFtT searches, comma does
|
|
-- not do too many useful things and can be taken up as localleader
|
|
vim.g.maplocalleader = ","
|
|
|
|
-- If we mapped localleader to comma, we can still get to its original function
|
|
-- by douple-tapping it.
|
|
-- FIXME does this work still (and is it necessary)?
|
|
if vim.g.maplocalleader == ',' then
|
|
map('', ',,', ',')
|
|
vim.keymap.del('', ',,', { silent = true })
|
|
end
|
|
|
|
-- remove search highlights by pressing space+/
|
|
map('n', '<leader>/', ':noh<cr>', { desc = 'remove highlights' })
|
|
|
|
-- split buffers vertically/horizontally with the leader \ or - (mirrors my
|
|
-- tmux setup)
|
|
map('n', '<leader>-', ':sp<cr>', { desc = 'open horiz split' })
|
|
map('n', '<leader>\\', ':vsp<cr>', { desc = 'open vert split' })
|
|
-- 'open new buffer' with leader-t (opens new buffer containing current dir and switches to it)
|
|
map('n', '<leader>t', ':vsp | Vifm<cr>', { desc = 'open buffer' })
|
|
-- open actual new tab with leader-T
|
|
map('n', '<leader>T', ':tabedit | Vifm<cr>', { desc = 'open tab' })
|
|
|
|
-- select the whole buffer with <leader>-a
|
|
map('n', '<leader>a', 'ggVG', { desc = 'select all' })
|
|
|
|
-- PLUGIN: Navigator.nvim
|
|
map('n', '<c-w>h', '<CMD>lua require("Navigator").left()<cr>', { silent = true })
|
|
map('n', '<c-w>k', '<CMD>lua require("Navigator").up()<cr>', { silent = true })
|
|
map('n', '<c-w>l', '<CMD>lua require("Navigator").right()<cr>', { silent = true })
|
|
map('n', '<c-w>j', '<CMD>lua require("Navigator").down()<cr>', { silent = true })
|
|
map('n', '<c-w>p', '<CMD>lua require("Navigator").previous()<cr>',
|
|
{ silent = true })
|
|
|
|
-- PLUGIN: Vifm.vim
|
|
-- open/close file tree with leader-e
|
|
map('n', '<leader>e', ':Vifm<cr>', { desc = 'browse files' })
|
|
-- open current file tree with current file directory
|
|
map('n', '<leader>E', ':Vifm getcwd()<cr>', { desc = 'browse project' })
|
|
|
|
-- set 'v'im-related options
|
|
prefix({ ['<leader>v'] = { name = "+vim" } })
|
|
map('n', '<leader>vc', ':Vifm ' .. vim.fn.stdpath('config') .. '/lua<cr>',
|
|
{ desc = 'open config' })
|
|
map('n', '<leader>vh', ":lua require 'telescope.builtin'.help_tags()<cr>",
|
|
{ desc = 'help tags' })
|
|
map('n', '<leader>vH', ":lua require 'telescope.builtin'.man_pages()<cr>",
|
|
{ desc = 'man pages' })
|
|
map('n', '<leader>vC',
|
|
":lua require 'telescope.builtin'.colorscheme(require 'telescope.themes'.get_ivy())<cr>",
|
|
{ desc = 'colorschemes' })
|
|
map('n', '<leader>vl', ":Lazy<cr>", { desc = 'Lazy' })
|
|
map('n', '<leader>vm', ":Mason<cr>", { desc = 'Mason' })
|
|
-- Set vim to distraction free prose mode with F11
|
|
map('n', '<leader>vz', ':ZenMode<cr>', { silent = true })
|
|
|
|
|
|
-- PLUGIN: Telescope GLOBAL FUZZY FINDING
|
|
-- buffers and files in current workdir
|
|
prefix({ ['<leader>f'] = { name = '+find' } })
|
|
map('n', '<leader>fb',
|
|
":lua require 'telescope.builtin'.buffers(require 'telescope.themes'.get_ivy())<cr>",
|
|
{ desc = 'list buffers' })
|
|
-- most recently used / MRU, bound to S since it is essentially a larger
|
|
-- go-back intention than just buffers
|
|
map('n', '<leader>fo',
|
|
":lua require 'telescope.builtin'.oldfiles(require 'telescope.themes'.get_ivy())<cr>",
|
|
{ desc = 'list old files' })
|
|
-- fuzzy find files in cwd
|
|
map('n', '<leader>ff', ":lua require 'telescope.builtin'.find_files()<cr>",
|
|
{ desc = 'find files' })
|
|
-- fuzzy find hidden files in cwd
|
|
map('n', '<leader>fh',
|
|
":lua require 'telescope.builtin'.find_files({hidden=true})<cr>",
|
|
{ desc = 'find hidden files' })
|
|
-- general full-text search in cwd with rg
|
|
map('n', '<leader>fF', ":lua require 'telescope.builtin'.live_grep()<cr>",
|
|
{ desc = 'grep search' })
|
|
|
|
-- git status
|
|
map('n', '<leader>fg', ":lua require 'telescope.builtin'.git_status()<cr>",
|
|
{ desc = 'git status' })
|
|
-- git buffercommits
|
|
map('n', '<leader>fc', ":lua require 'telescope.builtin'.git_bcommits()<cr>",
|
|
{ desc = 'git buffer commits' })
|
|
-- git commitlog
|
|
map('n', '<leader>fl', ":lua require 'telescope.builtin'.git_commits()<cr>",
|
|
{ desc = 'git commit log' })
|
|
|
|
-- spell suggestions
|
|
map('n', 'z=',
|
|
":lua require 'telescope.builtin'.spell_suggest(require 'telescope.themes'.get_ivy())<cr>")
|
|
|
|
-- Format current Paragraph (esp useful in prose writing)
|
|
map('n', '<localleader>q', 'gqap',
|
|
{ silent = true, desc = 'Format current paragraph' })
|
|
map('x', '<localleader>q', 'gq', { silent = true, desc = 'Format {motion}' })
|
|
map('n', '<localleader>Q', 'vapJgqap',
|
|
{ silent = true, desc = 'Unformat then format paragraph' })
|
|
|
|
map('n', '<localleader>mp', '<Plug>MarkdownPreviewToggle',
|
|
{ desc = 'Toggle md preview' })
|
|
|
|
-- FORMAT code with
|
|
-- PLUGIN: formatter.nvim
|
|
map('n', '<localleader>f', ':FormatLock<cr>')
|
|
map('n', '<localleader>F', ':FormatWriteLock<cr>')
|
|
|
|
-- SPELL CHECKING
|
|
-- Move to the prev/next spelling error with [S ]S
|
|
-- Move to the prev/next spelling error or suggestion with [s ]s
|
|
prefix({ ['<localleader>Z'] = { name = '+Spelling' } })
|
|
map('n', '<localleader>ZZ', ':setlocal spell! spelllang=en_us,de_de<cr>',
|
|
{ desc = 'Toggle spellcheck' })
|
|
map('n', '<localleader>ZE', ':setlocal spell! spelllang=en_us<cr>',
|
|
{ desc = 'Toggle EN spellcheck' })
|
|
map('n', '<localleader>ZG', ':setlocal spell! spelllang=de_de<cr>',
|
|
{ desc = 'Toggle DE spellcheck' })
|
|
-- undo last spelling mistake from insert and normal mode
|
|
map('i', '<c-s>', '<C-G>u<Esc>[s1z=`]a<C-G>u')
|
|
map('n', '<localleader>s', 'ms[s1z=`s', { desc = 'Fix last spell error' })
|
|
|
|
-- PLUGIN: mini.nvim
|
|
prefix({ ['<leader>s'] = { name = '+show' } })
|
|
map('n', '<leader>sm', ':lua MiniMap.toggle()<cr>',
|
|
{ silent = true, desc = 'toggle minimap' })
|
|
map('n', '<leader>ss', ":lua MiniStarter.open()<cr>", { desc = 'show startpage' })
|
|
|
|
-- PLUGIN: symbols-outline.nvim
|
|
map('n', '<leader>so', '<cmd>SymbolsOutline<cr>',
|
|
{ silent = true, desc = 'toggle symbol outline' })
|
|
|
|
-- PLUGIN: easy-align
|
|
-- Start interactive EasyAlign in visual mode (e.g. vipga)
|
|
map('x', 'ga', '<Plug>(EasyAlign)')
|
|
-- Start interactive EasyAlign for a motion/text object (e.g. gaip)
|
|
map('n', 'ga', '<Plug>(EasyAlign)')
|
|
|
|
-- trim trailing whitespaces with mini.nvim trailspace
|
|
map("n", "<localleader>w", function() require("mini.trailspace").trim() end,
|
|
{ noremap = true })
|
|
|
|
-- PLUGIN: dial-increment
|
|
map("n", "<C-a>", '<Plug>(dial-increment)')
|
|
map("n", "<C-x>", '<Plug>(dial-decrement)')
|
|
map("v", "<C-a>", '<Plug>(dial-increment)')
|
|
map("v", "<C-x>", '<Plug>(dial-increment)')
|
|
map("v", "g<C-a>", 'g<Plug>(dial-increment)')
|
|
map("v", "g<C-x>", 'g<Plug>(dial-increment)')
|
|
|
|
-- PLUGIN: zettelkasten.nvim
|
|
map('n', '<cr>', [[:silent lua require 'zettelkasten'.link_follow()<cr>]])
|
|
map('v', '<cr>', [[:lua require 'zettelkasten'.link_follow(true)<cr>]])
|
|
prefix({ ['<leader>w'] = { name = '+wiki' } })
|
|
map('n', '<leader>ww', [[:lua require 'zettelkasten'.index_open()<cr> ]],
|
|
{ desc = "open wiki" })
|
|
|
|
-- PLUGIN: toggleterm.nvim
|
|
-- create a lazygit window, set up in toggleterm settings
|
|
map('n', '<leader>G', ':Lazygit<cr>')
|
|
|
|
-- PLUGIN: magma-nvim
|
|
-- Operate jupyter notebooks from within vim
|
|
map('n', '<localleader>mm', ':MagmaEvaluateLine<cr>', { silent = true })
|
|
map('n', '<localleader>M', '?^```{<cr>jV/```<cr>k:<C-u>MagmaEvaluateVisual<cr>',
|
|
{ silent = true, desc = 'Evaluate current quarto cell' })
|
|
map('x', '<localleader>m', ':<C-u>MagmaEvaluateVisual<cr>', { silent = true })
|
|
map('n', '<localleader>m', "nvim_exec('MagmaEvaluateOperator', v:true)",
|
|
{ expr = true, silent = true })
|
|
map('n', '<localleader>mr', ':MagmaReevaluateCell<cr>', { silent = true })
|
|
map('n', '<localleader>ma', ':MagmaShowOutput<cr>', { silent = true })
|
|
map('n', '<localleader>mq', ':noautocmd :MagmaEnterOutput<cr>',
|
|
{ silent = true, desc = 'MagmaEnterOutput' })
|
|
map('n', '<localleader>md', ':MagmaDelete<cr>', { silent = true })
|
|
map('n', '<localleader>ms', ':MagmaInterrupt<cr>')
|
|
map('n', '<localleader>mI', ':MagmaInit ')
|
|
map('n', '<localleader>mD', ':MagmaDeinit<cr>')
|
|
map('n', '<localleader>mR', ':MagmaRestart<cr>')
|
|
|
|
-- jump to beginning of previous/ next cell code
|
|
map('n', ']c', '/^```{<cr>}:nohl<cr>', { desc = 'Next quarto cell' })
|
|
map('n', '[c', '?^```<cr>n}:nohl<cr>', { desc = 'Previous quarto cell' })
|
|
-- insert cell header above/below
|
|
map('n', '<localleader>mo', 'o```{python}<cr><cr>```<esc>k',
|
|
{ desc = 'Insert quarto cell below' })
|
|
map('n', '<localleader>mO', 'O```{python}<cr><cr>```<esc>k',
|
|
{ desc = 'Insert quarto cell above' })
|