Practical Vim
<>denotes combinations of keys to be pressed together.{}indicates a list of valid keystrokes to follow the preceding command-indicates keys to be pressed together
Commands
@:repeats the last command:s/target/replacementreplaces the next instance oftargetwithreplacementand is repeatable with&(but only on the current line)
Global
:g/{pattern}/{command} executes command on all lines that match pattern. Can be inverted with :g! (or just :v, which executes command on all lines that don’t match pattern.
Remember commands typically take a range as well, so you can do something like :g/{start}/.,{end}/{cmd} to execute cmd on all lines between start and end.
For example, to delete html tags on all lines, you’d use :g/\v<\/?\w+>/d. If you wanted to delete all lines of a html file without links, you’d use :v/href/d.
You could also use it to yank all TODO/FIXME in a file to a register. First empty the register with q{reg}q, then :g/\vTODO|FIXME/yank {capital_reg}. It’s important to use the capital version of a register so each line is appended, rather than overwriting the preceding line. You could also just use t$ rather than the yank command to dump them all at the end of the file.
Copying
:reg(or for me, just hitting backtick) shows you all registers and their contentsYcopies to the end of the current line
Registers
Delete, yank and change all go to the unnamed register (""). Yanks also go to the yank register ("0) at the same time.
Addressing a register with a lowercase letter overwrites it, while an uppercase letter appends to the register.
Sending anything to the black hole register ("_) discards it completely.
"{register}{motion}lets you delete/yank/change to or put from a register
Deleting
dawuses a text object to delete the entire word the cursor is in and its whitespace; whilecawdoes the same and drops you into insert modedbdeletes from cursor to word start;dwfrom cursor to word endSdeletes to the end of a line from the cursor
Dot Command
Repeats the last change. But what is a ‘change’?
Everything from when you enter insert mode to when you exit it is a single change, unless you interrupt the action by moving around with the arrow keys. Each time you press an arrow key it creates a new undo chunk.
Using motions which drop you into insert mode like A or dw includes them in the change, making them replay-able along with any changes you make in insert mode.
Generally the pattern you want to aim for is one key to move, then one key to execute.
Formatting
>{num lines}increases indentation one step from the current position for the number of lines given by the next inputgc{motion}comments the lines covered bymotion.gcccomments the current line andgcin visual mode comments the selected linesgu{motion}orgU{motion}downcase or up case the selection covered bymotionOadds the newline above the current line rather than below. Useful for avoidingko
Lists
Change List
Let’s you jump through the history of changes for the current buffer
:changesshows the change listg;goes back,g,goes forward- The
backtick.mark always stores the last change as well gitakes you to the last insertion and switches to insert mode
Jump List
:jumpsshows the jump list, which is kept per tabCtrl-ojumps back, whileCtrl-ijumps forward
LSP
]dand[dgo to the next and previous diagnostics respectivelyKin normal mode brings up the definition of whatever’s under the cursor
Macros
You can execute macros in parallel on a selection with :normal @q. This means if there’s a line in the middle which the macro would usually fail on, that failure won’t prevent the macro acting on valid lines after it.
If you record a macro using qq and realise you need to append something to it (like moving to the next line) you can append to it with qQ.
Since macros are just saved into a register, if you want to edit them you can put them into a buffer from that register, then yank the macro back in once edited. When yanking it back into a register, be sure not to yank the whole line so you don’t get trailing newline characters in your macro.
Golden rule is ‘when recording a macro, ensure every command is repeatable’.
-
Start by normalizing the cursor position
-
Macros fail if any of their motions do, consider this a feature rather than a bug
- Lets you do something like
100@qif your motion is targeted enough
- Lets you do something like
-
Macros can also capture find & dot commands, so repeating something like
;.is valid -
@@invokes the most recently invoked macro
Modes
Insert Mode
Ctrl-r{register}pastes at the cursor in insert modeCtrl-v{code}allows you to insert an arbitrary character by code (ASCII) orCtrl-vu{code}for unicodegagives you the code for the character under your cursor
Ctrl-k{char1}{char2}inserts the digraph made by the two chars. For exampleCtrl-k>>would produce »
Visual Mode
Repeating actions taken in visual mode with the dot command repeats them on a selection of the same length as the initial one.
Visual block mode is triggered with ctrl-v, and works much the same but in columns rather than lines
Motions
,reverts anf{char}search, while;repeats it%jumps to the end of the next matching parentheses, then toggles between ends of themt{char}is a variant off{char}which stops before{char}rather than on it. Remember it astlike ‘till’.
gj&gkmove down/up one ‘display’ line, motions like$and^can also be prefixed withgto do the sameCtrl-aincrements the number under the cursor or the next number on the line, whileCtrl-xdecrements it.- Both can prefixed with a number to increment/decrement that many times
m{char}sets a mark at the cursor position to{char}. You can then usebacktick{char}to jump to that mark, or'{char}for the start if the line.- lowercase chars as marks are limited to the file they’re created in, while uppercase chars are global
- if you use an uppercase
{char}, it persists through sessions so can always be used to jump to that file
Operators
Can all be combined with a motion to specify the range they apply to.
cchangeddeleteyyank to registergccommentsg~swap casegumake lowercasegUmake uppercase<indent left or>right!filter through an external program
Patterns
Matched text can be referenced with \{number} after the regex. \0 captures the whole match, which \n captures the nth capture group (in ()). This can then be referenced in a substitute command like %s/\1/replacement.
Remember backslashes always need to be escaped to be treated as literals, even with \V. Same for / if searching forward and ? for back.
<and>are word boundary characters, so/\vthe>will not match ‘there’ or ‘their’.\wmatches any word character, while\Wmatches any non-word character\zsand\zecan be used to indicate only part if a pattern should be capturede as the match./Practical \zsVimwill find all instances of ‘Practical Vim’, but only highlight the ‘Vim’ part- Useful when part of the pattern is critical for finding the match, but shouldn’t actually be operated on. e.g. text in quotes
Search
You can browse your search history with the up & down arrow keys.
While searching incrementally, Ctrl-r Ctrl-w autofills the full word the current incremental search result is hovering over.
Appending /e to a search places your cursor at the end of the match rather than the start. If you wanna add the offset after already searching, just run a blank search with /e appended like //e, as the last pattern will automatically be reused.
*searches for the word under the cursor and can be incremented/decremented like/?Is a backward search, inverse of/- You can reverse search direction by starting a blank search in the opposite direction, as the previous pattern is used by default
nfor next occurrence,Nfor previous occurrencegnis a motion to apply the change to the next match,gNfor previous
f{char}searches the line for the next instance of{char},;for next occurrence,,for previous occurrence,F{char}searches backwardscappended to a:%ssearch will ask you for confirmation before making each change
Substitution
The first arg to :s, which is usually % for me, is the (vertical) range to act on. Can be a visual selection if one is active when :s invoked.
When using the /c flag to confirm substitutions, a substitutes all remaining matches while q quits.
The replacement arg can be \n to substitute the nth match, or \0 to substitute the whole match. You can use this to switch the order of words, for example :s/\v(for) (example)/\2 \1 will switch ‘for example’ to ‘example for’.
You can use the contents of a register as the replacement value, e.g. :%s/pattern/\=@"/g to replace with the contents of the default register.
g& repeats the last substitution, but with % as the range. && repeats the last substitute command with the curent range (current line by default).
Using \={vimscript} in a substitution will execute the given vimscript, e.g. to increment a matched number :%s/{pattern}/\=submatch(0)+1/g. submatch is needed to refer to capture groups when evaluating vimscript, rather than the usual \n.
Switches
- Adding a
\canywhere in your pattern will ignore case.\Cwill force case sensitivity. \Vforces the search to be literal, soa.k.awill match literally that string, not a, k and a separated by any 2 chars.\vdoes the opposite.- The backslash (escape character) retains its function though.
Settings
hlsearchtoggles search match highlighting- In my config it’s turned on, and you can hit
escin normal mode to dismiss it
- In my config it’s turned on, and you can hit
Selection
gvreselects the previous selectionotoggles the ‘free end’ of the selectionvitselects within tags
Text Objects
v/d/caacts around the text object, replacingidoew the same within ita{surround_char}gives a text object around the nearest instances of{surround_char}, whilei{surround_char}gives the same but inside the{surround_char}pair.tselects around and within tags- works with paired brackets, quotes, etc. Not with random letters.
- works when outside the specified text object, by jumping to the nearest one
w&bmove forward/backward to the start of the next/previous word, whileeandgedo the same to the endsacts on a sentence,pfor paragraphs- Their capitalized variants move to the start/end of the next/previous WORD, skipping over slashes/hyphens etc.
- WORD motions also work with change and delete motions