Vim keybindings

From wikinotes

Examples

" bind 'gy' in normal mode
:nnormap gy :let @" = expand('%:p')

" binding multiple commands to a single mapping
:nnoremap gy :let @" = expand('%:p') \| let @* = expand('%:p') \| let @+ = expand('%:p')

Mapping Keys

OS notes

macvim:
  - use `set macmeta` to allow binding 'Alt/Meta' within macvim

Map Creation Keywords

Concepts

modes

vim has a different set of hotkeys for different modes. When binding your keys, you map to a specific mode.

recursive mappings

Vim keymaps can also be recursive.
If you overwrite <c-w> in one mapping,
and refer to <c-w> in another,
the second keybinding will execute the first.

" https://vim.fandom.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_1)
:map <F2>  :echo 'Current time = ' . strftime('%c')<CR>
:map <F3> <F2>  " <F3> now also prints current time

Keywords

" non-recursive mappings (executes vim's default keybindings, if applicable)
:nnoremap " bind in normal mode
:vnoremap " bind in visual mode
:inoremap " bind in insert mode

" recursive mappings (executes your overridden keybindings, if applicable)
:nmap   " bind in normal mode
:vmap   " bind in visual mode (selection)
:imap   " bind in insert mode

Buffer Maps

You can create keybindings that are localized to a specific buffer.

:map <buffer> <leader>foo :call Foo()<CR>

Binding Behaviours

feedkeys

Feedkeys enters arbitrary keys

nnoremap DoThing :call feedkeys("abc")      " enters 'abc' at cursor
nnoremap DoThing :call feedkeys("\<Down>")  " a 'down' keypress (special keys escaped with '\')

SID commands

" <SID> commands refer to vim's private methods
" they can only be accessed within the script they are defined in.
func s:DoThing()
    " ...
endfunc

nnoremap DoThing :call <SID>:DoThing()<CR>

Plug commands

" <Plug> commands must not use 'noremap' methods
" <Plug> commands are only available within modes they were defined for
imap <c-j> <Plug>snipMateShow

" bind to command
command Foo execute "normal \<Plug>(some-command)"

Mode-Sensitive Commands

normal mode

inoremap <leader>abc <c-o>call DoThing()      " executes single command in normal, returns to insert
inoremap <leader>abc <esc>call DoThing()<CR>  " change mode to normal, run commands

insert mode

" If you'd like to execute a command from within a vim-mode,
" you can wrap it in a plug command
func! DoThingInInsert()
    " ...
endfunc

" bind a '<Plug>' command
inoremap <silent> <Plug>DoThingInInsert <C-R>=DoThingInInsert()<CR>

" create your keybinding
imap <leader>abc <Plug>DoThingInInsert

Finding Available Keys

Not all combinations of keys can be bound in vim when it is run within a terminal. You can test keycodes to see if they are possible with/without modifiers with the command cat, then trying different keycombos to see if they are unique.

vim can make use of two types of keycodes:

  • terminal keycodes (specific to your terminal)
  • vim keycodes (global across all platforms, but may not always work based on the availability of terminal keycodes)

You can also check if a mapping is already being used with:

map <key-mapping> " passing key-sequence to :map will list bindings with that key-sequence
:Map              " fzf.vim lets you search mappings

Listing all mappings

" list all mappings (scroll in vim)
:map                 " list all keymappings (also nmap, imap, ...)
:map <key-sequence>  " list all keymappings beginning with key-sequence

" if fzf.vim installed, search keybindings
:Map

" otherwise, dump all mappings to a buffer
:redir @b|sil map|redir end     " capture output from 'map' (press 'q' to quit)
:(ctrl + p) b                   " paste output into buffer

terminal keycodes

cat            ## type keysequences.
               ## ctrl-d to escape

vim keycodes

:set termcap   " print all vim keycodes

Default Keybindings

modes

i               "insert mode (type freely)
<esc>, <c-]>    "normal mode (navigation)
:               "command-mode
v               "interactive character-range selection
<c-v>           "interactive character-range selection (bounding-box style)
V               "interactive line-range selection

navigation

code centric

h           "left
l           "right
k           "up
j           "down

0           "jump to beginning of line
$           "jump to end of line

w, e, b     "skip word forward/backwards (until symbol)
W, E, B     "skip word forwards/bacwards (until space)

{, }        "jump to beginning/end of paragraph
[, ]        "jump to beginning/end of scope

f<anychar>  "jump to next occurrenct of whatever the next character is on line
;           "repeat last command (ex: dd) forwards
,           "repeat last command (ex: dd) backwards

@:          " repeat last command-mode command (ex: :OrgArchive)
@@          " repeat last repeated command-mode command

:<line-num> "goto that line-number

screen centric

<c-p>, <c-n>     "next tab, previous tab
<c-w><c-[hjkl]>  "select window to the left,down,up,right
H                "move cursor to top of screen
M                "move cursor to middle of screen
L                "move cursor to bottom of screen

text-insertion

a             "jump to after cursor-char, enter insert mode
A             "jump to end of line, enter insert mode
d             "delete (something)
dd            "delete current line, or selected lines

o             "create line below current line, and enter insert mode
O             "create line above current line, and enter insert mode

x             "delete character under cursor
J             "add the line direectly underneath currentline to currentline

~             "toggle upper-case/lower-case

splits

:vs          "open new vertical split with current file
:sp          "open new horizontal split with current file
:e           "open a new file

:vs /path/to/file   "open a specific file in a new vertical split

tabs

:tabnew       "create a new tab
:tabnew %     "create a new tab with current file in it

<c-p>         "jump to next tab
<c-n>         "jump to previous tab
gt<num>       "jump to tab with the number N