Complete Vim (Advanced) keyboard shortcuts reference — 296 shortcuts across 27 categories. Quick reference cheat sheet for Cross-platform.
This is the long form of Vim's command reference — the quickref that ships as :help quickref — arranged by the same headings. The basic Vim page covers the first week; this one is for the motions, registers, folds, windows and quickfix commands that make Vim worth the years. Row names use Vim's own notation: v_ marks Visual-mode commands, c_ command-line ones, and CTRL-W_ the window prefix.
| Shortcut | Action |
|---|---|
| h | left (also: CTRL-H, <BS>, or <Left> key) |
| l | right (also: <Space> or <Right> key) |
| 0 | to first character in the line (also: <Home> key) |
| ^ | to first non-blank character in the line |
| $ | to the last character in the line (N-1 lines lower) (also: <End> key) |
| g0 | to first character in screen line (differs from "0" when lines wrap) |
| g^ | to first non-blank character in screen line (differs from "^" when lines wrap) |
| g$ | to last character in screen line (differs from "$" when lines wrap) |
| gm | to middle of the screen line |
| gM | to middle of the line |
| bar | to column N (default: 1) |
| f | to the Nth occurrence of {char} to the right |
| F | to the Nth occurrence of {char} to the left |
| t | till before the Nth occurrence of {char} to the right |
| T | till before the Nth occurrence of {char} to the left |
| ; | repeat the last "f", "F", "t", or "T" N times |
| , | repeat the last "f", "F", "t", or "T" N times in opposite direction |
| Shortcut | Action |
|---|---|
| k | up N lines (also: CTRL-P and <Up>) |
| j | down N lines (also: CTRL-J, CTRL-N, <NL>, and <Down>) |
| - | up N lines, on the first non-blank character |
| + | down N lines, on the first non-blank character (also: CTRL-M and <CR>) |
| _ | down N-1 lines, on the first non-blank character |
| G | goto line N (default: last line), on the first non-blank character |
| gg | goto line N (default: first line), on the first non-blank character |
| N% | goto line N percentage down in the file; N must be given, otherwise it is the % command |
| gk | up N screen lines (differs from "k" when line wraps) |
| gj | down N screen lines (differs from "j" when line wraps) |
| Shortcut | Action |
|---|---|
| w | N words forward |
| W | N blank-separated WORDs forward |
| e | forward to the end of the Nth word |
| E | forward to the end of the Nth blank-separated WORD |
| b | N words backward |
| B | N blank-separated WORDs backward |
| ge | backward to the end of the Nth word |
| gE | backward to the end of the Nth blank-separated WORD |
| ) | N sentences forward |
| ( | N sentences backward |
| } | N paragraphs forward |
| { | N paragraphs backward |
| ]] | N sections forward, at start of section |
| [[ | N sections backward, at start of section |
| ][ | N sections forward, at end of section |
| [] | N sections backward, at end of section |
| [( | N times back to unclosed ' |
| [{ | N times back to unclosed '{' |
| [m | N times back to start of method (for Java) |
| [M | N times back to end of method (for Java) |
| ]) | N times forward to unclosed ')' |
| ]} | N times forward to unclosed '}' |
| ]m | N times forward to start of method (for Java) |
| ]M | N times forward to end of method (for Java) |
| [# | N times back to unclosed "#if" or "#else" |
| ]# | N times forward to unclosed "#else" or "#endif" |
| [star | N times back to start of comment "/*" |
| ]star | N times forward to end of comment "*/" |
| Shortcut | Action |
|---|---|
| /<CR> | repeat last search, in the forward direction |
| ?<CR> | repeat last search, in the backward direction |
| n | repeat last search |
| N | repeat last search, in opposite direction |
| star | search forward for the identifier under the cursor |
| # | search backward for the identifier under the cursor |
| gstar | like "*", but also find partial matches |
| g# | like "#", but also find partial matches |
| gd | goto local declaration of identifier under the cursor |
| gD | goto global declaration of identifier under the cursor |
| Shortcut | Action |
|---|---|
| % | find the next brace, bracket, comment, or "#if"/ "#else"/"#endif" in this line and go to its |
| H | go to the Nth line in the window, on the first non-blank |
| M | go to the middle line in the window, on the first non-blank |
| L | go to the Nth line from the bottom, on the first non-blank |
| go | go to Nth byte in the buffer |
| :go | go to [off] byte in the buffer |
| Shortcut | Action |
|---|---|
| CTRL-E | window N lines downwards (default: 1) |
| CTRL-D | window N lines Downwards (default: 1/2 window) |
| CTRL-F | window N pages Forwards (downwards) |
| CTRL-Y | window N lines upwards (default: 1) |
| CTRL-U | window N lines Upwards (default: 1/2 window) |
| CTRL-B | window N pages Backwards (upwards) |
| z<CR> | redraw, current line at top of window |
| z. | redraw, current line at center of window |
| z- | redraw, current line at bottom of window |
| zh | scroll screen N characters to the right |
| zl | scroll screen N characters to the left |
| zH | scroll screen half a screenwidth to the right |
| zL | scroll screen half a screenwidth to the left |
| Shortcut | Action |
|---|---|
| a | append text after the cursor (N times) |
| A | append text at the end of the line (N times) |
| i | insert text before the cursor (N times) (also: <Insert>) |
| I | insert text before the first non-blank in the line (N times) |
| gI | insert text in column 1 (N times) |
| o | open a new line below the current line, append text (N times) |
| O | open a new line above the current line, append text (N times) |
| v_b_I | insert the same text in front of all the selected lines |
| v_b_A | append the same text after all the selected lines |
| Shortcut | Action |
|---|---|
| x | delete N characters under and after the cursor |
| <Del> | delete N characters under and after the cursor |
| X | delete N characters before the cursor |
| d | delete the text that is moved over with {motion} |
| v_d | delete the highlighted text |
| dd | delete N lines |
| D | delete to the end of the line (and N-1 more lines) |
| J | join N-1 lines (delete <EOL>s) |
| v_J | join the highlighted lines |
| gJ | like "J", but without inserting spaces |
| v_gJ | like "{visual}J", but without inserting spaces |
| :d | delete [range] lines [into register x] |
| Shortcut | Action |
|---|---|
| quote | use register {char} for the next delete, yank, or put |
| :reg | show the contents of all registers |
| y | yank the text moved over with {motion} into a register |
| v_y | yank the highlighted text into a register |
| yy | yank N lines into a register |
| Y | yank N lines into a register |
| p | put a register after the cursor position (N times) |
| P | put a register before the cursor position (N times) |
| ]p | like p, but adjust indent to current line |
| [p | like P, but adjust indent to current line |
| gp | like p, but leave cursor after the new text |
| gP | like P, but leave cursor after the new text |
| Shortcut | Action |
|---|---|
| r | replace N characters with {char} |
| gr | replace N characters without affecting layout |
| R | enter Replace mode (repeat the entered text N times) |
| gR | enter virtual Replace mode: Like Replace mode but without affecting layout |
| c | change the text that is moved over with {motion} |
| v_c | change the highlighted text |
| cc | change N lines |
| S | change N lines |
| C | change to the end of the line (and N-1 more lines) |
| s | change N characters |
| v_b_c | in Visual block mode: Change each of the selected lines with the entered text |
| v_b_C | in Visual block mode: Change each of the selected lines until end-of-line with the entered text |
| ~ | switch case for N characters and advance cursor |
| v_~ | switch case for highlighted text |
| v_u | make highlighted text lowercase |
| v_U | make highlighted text uppercase |
| < | move the lines that are moved over with {motion} one shiftwidth left |
| << | move N lines one shiftwidth left |
| > | move the lines that are moved over with {motion} one shiftwidth right |
| >> | move N lines one shiftwidth right |
| gq | format the lines that are moved over with {motion} to 'textwidth' length |
| Shortcut | Action |
|---|---|
| == | filter N lines through 'equalprg' |
| & | Repeat previous ":s" on current line without options |
| Shortcut | Action |
|---|---|
| v_aw | Select "a word" |
| v_iw | Select "inner word" |
| v_aW | Select "a WORD" |
| v_iW | Select "inner WORD" |
| v_as | Select "a sentence" |
| v_is | Select "inner sentence" |
| v_ap | Select "a paragraph" |
| v_ip | Select "inner paragraph" |
| v_ab | Select "a block" (from "[(" to "])") |
| v_ib | Select "inner block" (from "[(" to "])") |
| v_aB | Select "a Block" (from "[{" to "]}") |
| v_iB | Select "inner Block" (from "[{" to "]}") |
| v_a> | Select "a <> block" |
| v_i> | Select "inner <> block" |
| v_at | Select "a tag block" (from <aaa> to </aaa>) |
| v_it | Select "inner tag block" (from <aaa> to </aaa>) |
| v_a' | Select "a single quoted string" |
| v_i' | Select "inner single quoted string" |
| v_a` | Select "a backward quoted string" |
| v_i` | Select "inner backward quoted string" |
| Shortcut | Action |
|---|---|
| . | repeat last change (with count replaced with N) |
| q | record typed characters into register {a-z} |
| @ | execute the contents of register {a-z} (N times) |
| :@ | execute the contents of register {a-z} as an Ex command |
| :@@ | repeat previous :@{a-z} |
| gs | goto Sleep for N seconds |
| Shortcut | Action |
|---|---|
| :shell | start a shell |
| :! | execute {command} with a shell |
| K | lookup keyword under the cursor with 'keywordprg' program (default: "man") |
| Shortcut | Action |
|---|---|
| :cc | display error [nr] (default is the same again) |
| :cnext | display the next error |
| :cprevious | display the previous error |
| :clist | list all errors |
| :cfile | read errors from the file 'errorfile' |
| :cgetbuffer | like :cbuffer but don't jump to the first error |
| :cgetfile | like :cfile but don't jump to the first error |
| :cgetexpr | like :cexpr but don't jump to the first error |
| :caddfile | add errors from the error file to the current quickfix list |
| :caddexpr | add errors from an expression to the current quickfix list |
| :cbuffer | read errors from text in a buffer |
| :cexpr | read errors from an expression |
| :cquit | quit without writing and return error code (to the compiler) |
| :make | start make, read errors, and jump to first error |
| :grep | execute 'grepprg' to find matches and jump to the first one |
| Shortcut | Action |
|---|---|
| CTRL-L | clear and redraw the screen |
| CTRL-G | show current file name (with path) and cursor position |
| ga | show ascii value of character under cursor in decimal, hex, and octal |
| g8 | for utf-8 encoding: show byte sequence for character under cursor in hex |
| g_CTRL-G | show cursor column, line, and character position |
| CTRL-C | during searches: Interrupt the search |
| :version | show version information |
| :mode | set screen mode to N (obsolete) |
| Q | switch to "Ex" mode |
| :redir | redirect messages to {file} |
| :silent | execute {command} silently |
| :confirm | quit, write, etc., asking about unsaved changes or read-only files |
| :browse | open/read/write file, using a file selection dialog |
| Shortcut | Action |
|---|---|
| c_CTRL-D | list all names that match the pattern in front of the cursor |
| c_CTRL-A | insert all names that match pattern in front of cursor |
| c_CTRL-L | insert longest common part of names that match pattern |
| c_CTRL-N | after 'wildchar' with multiple matches: go to next match |
| c_CTRL-P | after 'wildchar' with multiple matches: go to previous match |
| Shortcut | Action |
|---|---|
| -vim | start editing with an empty buffer |
| -file | start editing one or more files |
| -- | read file from stdin |
| -tag | edit the file associated with {tag} |
| -qf | start editing in QuickFix mode, display the first error |
| Shortcut | Action |
|---|---|
| :args | print the argument list, with the current file in "[]" |
| :all | open a window for every file in the arg list |
| :wn | write file and edit next file |
| :wN | write file and edit previous file |
| Shortcut | Action |
|---|---|
| :w | write to the current file |
| :w_f | write to {file}, unless it already exists |
| :w_a | append to the current file |
| :w_c | execute {cmd} with [range] lines as standard input |
| :up | write to current file if modified |
| :wall | write all changed buffers |
| :q | quit current buffer, unless changes have been made; Exit Vim when there are no other non-help |
| :qa | exit Vim, unless changes have been made |
| :cq | quit without writing and return error code |
| :wq | write the current file and exit |
| :xit | like ":wq" but write only when changes have been made |
| ZZ | same as ":x" |
| ZQ | same as ":q!" |
| :stop | suspend Vim or start new shell; if 'aw' option is set and [!] not given write the buffer |
| Shortcut | Action |
|---|---|
| :rviminfo | read info from viminfo file [file] |
| :wviminfo | add info to viminfo file [file] |
| modeline | In the first and last lines of the file (see 'ml' option), {set-arg} is given as an argument |
| Shortcut | Action |
|---|---|
| CTRL-W_s | split window into two parts |
| :split_f | split window and edit {file} in one of them |
| :vsplit | same, but split vertically |
| :vertical | make {cmd} split vertically |
| :sfind | split window, find {file} in 'path' and edit it |
| :terminal | open a terminal window |
| CTRL-W_] | split window and jump to tag under cursor |
| CTRL-W_f | split window and edit file name under the cursor |
| CTRL-W_^ | split window and edit alternate file |
| CTRL-W_n | create new empty window |
| CTRL-W_q | quit editing and close window |
| CTRL-W_c | make buffer hidden and close window |
| CTRL-W_o | make current window only one on the screen |
| CTRL-W_j | move cursor to window below |
| CTRL-W_k | move cursor to window above |
| CTRL-W_CTRL-W | move cursor to window below (wrap) |
| CTRL-W_W | move cursor to window above (wrap) |
| CTRL-W_t | move cursor to top window |
| CTRL-W_b | move cursor to bottom window |
| CTRL-W_p | move cursor to previous active window |
| CTRL-W_r | rotate windows downwards |
| CTRL-W_R | rotate windows upwards |
| CTRL-W_x | exchange current window with next one |
| CTRL-W_= | make all windows equal height & width |
| CTRL-W_- | decrease current window height |
| CTRL-W_+ | increase current window height |
| CTRL-W__ | set current window height (default: very high) |
| CTRL-W_< | decrease current window width |
| CTRL-W_> | increase current window width |
| CTRL-W_bar | set current window width (default: widest possible) |
| Shortcut | Action |
|---|---|
| :buffers | list all known buffer and file names |
| :ball | edit all args/buffers |
| :unhide | edit all loaded buffers |
| :badd | add file name {fname} to the list |
| :bunload | unload buffer [N] from memory |
| :bdelete | unload buffer [N] and delete it from the buffer list |
| Shortcut | Action |
|---|---|
| :syn-on | start using syntax highlighting |
| :syn-off | stop using syntax highlighting |
| :syntax | list current syntax items |
| :syn-clear | clear all syntax info |
| :highlight | clear all highlight info |
| :filetype | switch on file type detection, without syntax highlighting |
| Shortcut | Action |
|---|---|
| :gui | UNIX: start the GUI |
| :menu | list all menus |
| :tmenu | add tooltip to menu {mpath} |
| :unmenu | remove menu {mpath} |
| Shortcut | Action |
|---|---|
| zf | operator: Define a fold manually |
| :fold | define a fold for {range} lines |
| zd | delete one fold under the cursor |
| zD | delete all folds under the cursor |
| zo | open one fold under the cursor |
| zO | open all folds under the cursor |
| zc | close one fold under the cursor |
| zC | close all folds under the cursor |
| zm | fold more: decrease 'foldlevel' |
| zM | close all folds: make 'foldlevel' zero |
| zr | reduce folding: increase 'foldlevel' |
| zR | open all folds: make 'foldlevel' max |
| zn | fold none: reset 'foldenable' |
| zN | fold normal set 'foldenable' |
| zi | invert 'foldenable' |
| Shortcut | Action |
|---|---|
| ci" | Change inside quotes |
| di{ | Delete inside braces |
| gg=G | Indent all |
| Ctrl + V | Block visual |
| :%s/foo/bar/gc | Confirm replace |
| q[register] | Record macro |
| @[register] | Play macro |
f and t jump to or just before a character on the line, and ; repeats the jump; with a count they skip ahead. % bounces between matching brackets, } and { move by paragraph, ) and ( by sentence, and [{ and [( go back to the unclosed brace or paren you are inside, which is the fastest way out of a nested block. H, M and L move to the top, middle and bottom of the window without scrolling, while z., z<CR> and z- scroll the window so the current line is centred, top or bottom. gd jumps to the local declaration of the word under the cursor and star (the * key) searches for it.
Every delete and yank goes to a register; quote (the " key) followed by a letter chooses one — "ayy yanks a line into a, "ap puts it back — and :reg shows them all, which is how you recover text you deleted three edits ago. ]p puts while adjusting indent to the current line. The text objects v_iw, v_ip, v_i', v_it and their a forms work after any operator, so ci" and di{ in the Additional group are just c and d applied to an object. . repeats the last change, q records a macro into a register and @ plays it; & repeats the last substitution on the current line.
zf creates a fold over a motion, zo and zc open and close one, zR and zM open and close all, and zi toggles folding entirely. Windows are on the Ctrl + W prefix: CTRL-W_s splits, :vsplit splits vertically, CTRL-W_j and its siblings move between windows, CTRL-W_o keeps only the current one and CTRL-W_= equalises sizes; :terminal opens a shell in a window. The quickfix list turns compiler output into a navigable list: :make or :grep fills it, :cnext and :cprevious step through errors, :clist shows them all and :cfile loads a saved error file.
They are Vim's help notation. v_iw means the iw text object in Visual mode (or after an operator); c_CTRL-D means Ctrl + D on the command line.
Deleted text rotates through registers 1 to 9. :reg shows them; "3p puts the third most recent deletion.
Run :grep pattern files (or :vimgrep), then :cnext and :cprevious to move between matches and :copen to see the list.
zM closes all folds, then zv or zo opens the one at the cursor. zR reopens everything.
Open your assistant with this page preloaded as the source — great for follow-up questions like "which of these work in other apps?"