vim9script # autocomplete with and when plugins are not available def OnWhitespace(): bool return col('.') == 1 || getline('.')->strpart(0, col('.') - 1) =~ '\s$' enddef inoremap OnWhitespace() ? "\" : "\" inoremap OnWhitespace() ? "\" : "\" # Y mapping, more natural but not vi compatible map Y y$ # map gm to go to middle of line instead of middle of screen nnoremap gm gM # When softwrap happens move by screen line instead of file line nnoremap j gj nnoremap k gk # Jump lines faster (use with H, M, L) nnoremap j 5j vnoremap j 5j nnoremap k 5k vnoremap k 5k # g* selects foo in foobar while * selects , <> is word boundary. make * behave like g* # nnoremap * g* # nnoremap # g# # Resize window using arrow keys nnoremap :resize +2 nnoremap :resize -2 nnoremap :vertical resize -2 nnoremap :vertical resize +2 # alternative to 'packadd nohlsearch' nnoremap :nohls # nnoremap h :bprevious # nnoremap l :bnext # Replace [[ ]] mappings that get redefined by ftplugin/vim.vim # autocmd FileType * nnoremap [[ :bprevious # autocmd FileType * nnoremap ]] :bnext # Note: ]" [" may hop comments (:verbose nmap ][) # See /opt/homebrew/Cellar/vim/9.0.1550/share/vim/vim90/ftplugin/vim.vim # Buffer navigation nnoremap [b :bprevious nnoremap ]b :bnext nnoremap [B :bfirst nnoremap ]B :blast # quickfix list nnoremap [c :cprevious nnoremap ]c :cnext # nnoremap [C :cfirst # nnoremap ]C :clast nnoremap [C :colder nnoremap ]C :cnewer # location list (buffer local quickfix list) nnoremap [l :lprevious nnoremap ]l :lnext nnoremap [L :lfirst nnoremap ]L :llast # file list -> load buffers using :args * :args **/*.js **/*.css nnoremap [f :previous nnoremap ]f :next nnoremap [F :first nnoremap ]F :last # Map C-/ to do search within visually selected text # (C-_ produces the same hex code as C-/) vnoremap /\%V # Emacs C-s C-w like solution: hightlight in visual mode and then type * or # # `cgn` to replace text # https://vonheikemen.github.io/devlog/tools/how-to-survive-without-multiple-cursors-in-vim/ xnoremap * : call VSetSearch('/')/=@/ xnoremap # : call VSetSearch('?')?=@/ # SID means script local function; 'call' is optional in vim9script. def VSetSearch(cmdtype: string) var temp = getreg('s') # 's' is some register norm! gv"sy setreg('/', '\V' .. substitute(escape(@s, cmdtype .. '\'), '\n', '\\n', 'g')) setreg('s', temp) # restore whatever was in 's' enddef # NOTE: Use gp and gP for default purpose # gp Just like "p", but leave the cursor just after the new text. # gP Just like "P", but leave the cursor just after the new text. # [p To paste with correct indentation # visually select recent pasted (or typed) text # remember `] takes you to end of pasted buffer, or use 'gp' to paste nnoremap gs `[v`] # Type %% on Vim’s command-line prompt, it expands to the path of the active buffer # cnoremap %% getcmdtype() == ':' ? expand('%:h') .. '/' : '%%' # mappings nnoremap b b#| # alternate buffer nnoremap d bw| # :bwipeout to purge, :bdelete still leaves buffer in unlisted state (:ls!) nnoremap h hide| # hide window # nnoremap u unhidew| # unhide = one window for each loaded buffer (splits horizontally, not useful) tnoremap h :hide| # hide window (when terminal window is active) # nnoremap t !tree more # nnoremap t term nnoremap t tabnew nnoremap T tabclose nnoremap vt tab term # nnoremap w w nnoremap w update nnoremap q qa nnoremap Q qa! nnoremap n only nnoremap - s| # horizontal split # nnoremap \| v| # vertical split nnoremap \ v| # vertical split nnoremap o w| # next window in CCW direction nnoremap r registers nnoremap m marks # align vnoremap A :!column -t| # align columns vnoremap a :s/\v(.*)=(.*)/\=printf("%-16s %s", submatch(1), submatch(2)) # Toggle group nnoremap vs :set spell!:echo "Spell Check: " .. strpart("OffOn", 3 * &spell, 3) # nnoremap vt call text#Toggle() # nnoremap vc empty(filter(getwininfo(), 'v:val.quickfix')) ? ':copen' : ':cclose' # nnoremap vl empty(filter(getwininfo(), 'v:val.loclist')) ? ':lopen' : ':lclose' # Vim group nnoremap vr :new \| exec "nn q :bd!\" \| r ! | # redirect shell command, use :il /foo to filter lines nnoremap vR :enew \| exec "nn q :bd!\" \| put = execute('map')| # redirect vim cmd, use fi to filter # nnoremap vl set buflisted! nnoremap vm messages # nnoremap vd GitDiffThisFile nnoremap ve e $MYVIMRC # nnoremap vz FoldingToggle # Following not needed: use 1 for absolute path, or for relative path # nnoremap vp echo expand('%') nnoremap vi ShowImage # open netrw file browser nnoremap vf 35Lex # ---------------------------------------- # Make work in tab with terminal def SwitchTab(dir: string) if &buftype == 'terminal' :exec "normal! \\" :exec (dir == 'up' ? "tabNext" : "tabnext") else :exec (dir == 'up' ? "tabNext" : "tabnext") endif enddef tnoremap SwitchTab('up') tnoremap SwitchTab('down') # # ---------------------------------------- # import '../autoload/text.vim' # # surround ', ", and ` # vnoremap ' text.Surround('''') # vnoremap " text.Surround('"') # vnoremap ` text.Surround('`') # nnoremap ' text.Surround('''') # nnoremap " text.Surround('"') # nnoremap ` text.Surround('`') # # simple text objects # # ------------------- # # i_ i. i: i, i; i| i/ i\ i* i+ i- i# i # # a_ a. a: a, a; a| a/ a\ a* a+ a- a# a # for char in [ '_', '.', ':', ',', ';', '', '/', '', '*', '+', '-', '#', '' ] # execute 'xnoremap i' .. char .. ' text.Obj("' .. char .. '", 1)' # execute 'xnoremap a' .. char .. ' text.Obj("' .. char .. '", 0)' # execute 'onoremap i' .. char .. ' :normal vi' .. char .. '' # execute 'onoremap a' .. char .. ' :normal va' .. char .. '' # endfor # (:h emacs-keys) For Emacs-style editing on the command-line: # Default keys are in :h cmdline-editing # start of line :cnoremap # back one character :cnoremap # delete character under cursor :cnoremap # end of line :cnoremap # forward one character :cnoremap # recall newer command-line :cnoremap # recall previous (older) command-line :cnoremap # XXX: key combination causes delay in dismissing ':' command # # esc-b is backward-one-word # :cnoremap b # # esc-f is forward-one-word # :cnoremap f # # back one word, Alt-B -> not used to using this # :cnoremap â # :cnoremap ∫ # :cnoremap ļ # # forward one word, Alt-F -> not used to using this # :cnoremap æ # :cnoremap ƒ # :cnoremap ń :cnoremap :cnoremap ## ## Following keybindings are useful when not using scope.vim ## # # Open the first file in the popup menu when is entered # augroup SelectFirstChoice | autocmd! # def SelectFirstChoice() # var context = getcmdline()->matchstr('\v\S+\ze\s') # if context =~ '\v^(fin|find|e|ed|edit)!{0,1}$' # var prefix = getcmdline()->matchstr('\v\S+\s+\zs.+') # if !prefix->empty() # var choices = getcompletion(prefix, 'file_in_path') # if !choices->empty() # setcmdline($'{context} {choices[0]}') # endif # endif # elseif context =~ '\v^(b|bu|buf|buffer)!{0,1}$' # var prefix = getcmdline()->matchstr('\v\S+\s+\zs.+') # if !prefix->empty() # var choices = getcompletion(prefix, 'buffer') # if !choices->empty() # setcmdline($'{context} {choices[0]}') # endif # endif # endif # enddef # autocmd CmdlineLeave : SelectFirstChoice() # augroup END nnoremap :fin **/ # ':e' automatically closes popup and selects if only one option is present; not ideal # nnoremap :e **/ # find file in the parent git root directory nnoremap ff :fin =system("git rev-parse --show-toplevel 2>/dev/null \|\| true")->trim()/**/ nnoremap fv :fin $HOME/.vim/**/ nnoremap fV :fin $VIMRUNTIME/**/ # zsh files start with a number (01-foo.zsh), so the extra '*' at the end nnoremap fz :fin $HOME/.zsh/**/** # note: , , etc. move the cursor nnoremap fG :vim /\v/gj ** # # nnoremap vG :vim /\<=expand("")\>/gj ** # case sensitive grep # nnoremap fG :vim /\v\C/gj ** # # send output of g// to quickfix # - following solution does not open qf automatically # g//caddexpr expand("%") . ":" . line(".") . ":" . getline(".") # - instead of above, use vimgrep nnoremap fg :vim /\v/gj % # grep equivalents (-E is like \v magic in Vim; no need to escape |, (, ), ., ?, etc. Ex. egrep "import|more" # to make it case sensitive, remove '-i' # to search specific directory, and for C files, do /**/*.c # you can exclude directories or files using '~' (see zsh config file) # ':cw[indow]' opens (toggles) quickfix list only when it is non-empty nnoremap g :cgetexpr system('grep -EInsi "" **/*')\|cw nnoremap G :cgetexpr system('grep -EInsi =expand("") **/*')\|cw nnoremap :b **/ # highlight groups ([-1] forces empty string as return value of setqflist()) nnoremap fh :=setqflist([], ' ', #{title: 'highlight', items: execute("hi")->split("\n")->mapnew('{"text": v:val}')})[-1]copen # others nnoremap fk :=setqflist([], ' ', #{title: 'keymap', items: execute("map")->split("\n")->mapnew('{"text": v:val}')})[-1]copen nnoremap fm :=setqflist([], ' ', #{title: 'marks', items: execute("marks")->split("\n")->mapnew('{"text": v:val}')})[-1]copen nnoremap fr :=setqflist([], ' ', #{title: 'registers', items: execute("registers")->split("\n")->mapnew('{"text": v:val}')})[-1]copen nnoremap fq chistory