Vim Features Overview
About
This is my overview of some of the Vim features created as a part of learning about these features.
The Vim config is here: https://github.com/serebrov/vimrc (careful, here be dragons).
Essential resources:
Normal mode - dot to repeat the last command
. (dot) - repeat the last normal-mode command, automatic mini-macro.
Normal mode operators, motions and text objects
Operators
[operator]{motion} - apply
:h operator to
the text defined by motion.
For example: >G - shift everything until the end of file to the right (> -
shift right operator, G - end of file motion), gg=G - format the
whole file (gg - jump to the top, = - format operator, G - end of
file motion).
Operators:
c- changed- deletey- yank into register (does not change the text)J- join lines,gJ- join lines without adding a space between them~- swap case (only if 'tildeop' is set)g~- swap case, visual mode~gu- make lowercase, visual modeugU- make uppercase, visual modeU!- filter through an external program=- text indenting, usingequalprgor internal functiongq- text formatting, usingformatexprorformatprgor internal functiong?- ROT13 encoding>- shift right (in visual mode>, in normal mode>>)<- shift left (in visual mode<, in normal mode<<)zf- define a foldg@- call function set with the 'operatorfunc' option
More info: how to define your own operator, :h :map-operator, how to define your own motion, :h omap-info.
Motions
Horizontal (left-right) motions
Imagine we have the following line in the buffer where * is the cursor position:
Pudding—Alice: Alice—Pudding.
┆ ┆ ┆*┆ ┆ ┆ ┆
┆ ┆ ┆ ┆ ┆ ┆ ┆
0 ^ h l gm 25| g_ $
With h / l we can move one character left or right (it can
also take count, 5h moves 5 characters to the left).
0 jumps to line start and so on.
^ jumps to the first non-space character (so the first P).
g_ jumps to the last non-space and $ to the end of the line (assuming that we
have some spaces at the end in the example above).
The [count]| moves to the specified column (25 in this case, which is the second P).
When the line is wrapped, g^ moves to the start of the screen line. The
gm depends on the window width and moves to the center of the screen
line.
Jump to the character: f / t, F / T
f jumps forward to the character given after it, so fc jumps to the next c.
t jumps forward "till" the character (stops just before it).
F and T do the same backwards.
Pudding-Alice: Alice-Pudding. | * | | Fu fc tP TP
Words and WORDs
"Word"s are sequences of letters, digits and underscores (can be configured with 'iskeyword')
and "WORD"s are any non-blank characters.
We can use the following motions (the cursor is at the * position):
Words and WORDs
┌┈┈┈┈┈┈┈┈┐ ┌┈┈┈┈┈┈┈┐ ┌┈┈┈┈┈┈┐ ┌┈┈┈┈┈┈┈┈┐ - WORDs
┌┈┈┈┈┈┐┌┈┐ ┌┈┈┈┐┌┈┈┐ ┌┈┈┈┐┌┈┐ ┌┈┈┈┈┈┐┌┈┐ - words
Pudding--- Alice:::: Alice--- Pudding...
┆ ┆ * ┆ ┆
┆ ┆ w W ┈┈┈┈┈┈ next word / WORD
┆ ┆
B b - prev word / WORD
Pudding--- Alice:::: Alice--- Pudding...
┆ ┆ ┆ * ┆ ┆
┆ ┆ ┆ e E ┈┈┈┈┈┈ end of the word / WORD
┆ ┆ ┆
┆ ┆ ge/gE ┈┈┈┈┈┈┈┈┈┈┈ end of the prev word / WORD
┆ ┆
2gE 2ge ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ two words / WORDs back
Vertical (up-down) motions
Vertical motions (the cursor is at *):
Up-down motions ... ┈┈┈ gg ... But the Red Queen looked sulky, and growled ┈┈┈ k - line up, `-` - up and move to the start 'Pudding—Alice: Alice—Pudding. * Remove the pudding!' ┈┈┈ j - line down, `+` - down and move to the start and the waiters took it away so quickly ┈┈┈ :+3 - range is a motion, c:+2, d:107 that Alice couldn't return its bow. ┈┈┈ /bow - search is a motion, c/bow ... ... ┈┈┈ G
Note that : (which lets you run a command from the Vim command line) can be used
as a motion: d:call search('f') will delete until the next 'f' found by the
search() function.
There is also [count]_ motion which moves count-1 lines down and
jumps to the start of the line. It is like a ^ motion, but with count.
If there is no count or count=1 it moves to the current line start, with count > 1
moves down and jumps to the start.
The [N]% jumps to the N% of the file, :[range]go[to] [count] and
[count]go jump to the count byte in the file.
Text object motions / various motions
Matching pair () {} [] - % - move to the matching pair, make sure to enable the
/**/ matchit.vim (standard plugin), ":h matchit.txt"
<tag></tag> "matching" things can be html tags, if/else statements
if/else/endif and you don't have to be at the pair item for % to work
etc for example, in "my text (something)", you can use % when
cursor is at the start of the line.
A next / prev sentence. - ) / ( - [count] sentences, like y3) - yank 3 sentences
A paragraph of text. - } / { - [count] paragraphs
Unmatched ( - [( / ]( - prev/next unmatched (
Unmatched { - [{ / ]{ - prev/next unmatched {
Unmatched #if / #else - [# / ]# - prev/next unmatched #if / #else
A method of the class - [m / ]m, and [M / ]M move to the end of the method
A block comment /* */ - [*, [/ / ]*, ]/ - prev / next comment mark
[n] lines from the top - [n]H
[n] lines from the bottom - [n]L
Middle line - M
A section - ]] / [[ - [count] sections, see ":h section",
can be redefined by filetype plugins, like move between
classes / methods in python.
End of the section - ][ / [] - [count] end of section
Each of them can be used as an operator target.
For example c% - change until the matching pair:
if (x and y or something(b, c))
*
|
c% - from here it will find the parens pair around "b, c"
and will jump to the end paren
if (x and y or ▓) - as a result, we are changing the whole "something(b, c)"
with just one motion
link_to("text", my_p(sing("one"), plu(fn("two"))))
* A B
|
c% --- from here will change until B
%c% --- will change the A-B, including brackets
%ci( --- here will change inside the A-B
See also Vim's life-changing c%.
Text object selection
Text objects allow specifying which part of the text we want to operate on.
There are usually "around" objects which include surrounding elements (such as "a(" includes the surrounding parens) and "inner" objects which only include what's inside (such as "i(" that only selects text inside the parens).
A simple way to try text objects is to use them with the "v" (visual mode) motion. For example, "vaw" will select the "around word" and "viw" will select the "inner word".
word, word_two - aw / iw (regular / inner "word" text object)
WORD, word--%4- - aW / iW ("WORD" object)
'string' - a' / i'
"string" - a" / i"
`string` - a` / i`
A sentence. - as / is
A paragraph of
text. It also has a
text object. - ap / ip
[ block ] - a[, a] / i[, i]
( block ) - a(, a), ab / i(, i), ib
< block > - a<, a> / i<, i>
{ block } - a{, a}, aB / i{, i}, iB
<tag>value</tag> - at / it
Plugins that add more text objects: wellle/targets.vim, indent object, column object.
The quotes text objects (a', a", etc) look forward if the cursor is not
inside the quoted string. For example, if cursor is on the * position in
text [*] text 'quote', the ya' will yank (copy) the quoted word. The
wellle/targets.vim makes other text objects also look forward (and then also backward
if there is no object forward).
Inner text objects (iw, iB, etc) do not include the surrounding
marks. For words this is trailing space, for blocks - brackets.
"aw" vs "iw" vs "w"
┌┈┈┈┈┈┈┐ - yaw - yank word with trailing space - "Pudding "
┌┈┈┈┈┈┐ - yiw - yank only word - "Pudding"
Pudding Alice
Note: motions like yw and yaw do the same and yank the word with the
trailing space (same for daw, caw, etc), but it will be a bit
different in visual mode. The vaw will also select the first letter of
the next word (because w actually moves to there). It works in a
similar way for other objects, like sentences. See also :h exclusive.
Motions and operators
There are 3 types of the effects of operators: characterwise,
linewise, blockwise.
And *wise can be varied by operator and motion:
dw- characterwise - delete a word>j- linewise - indent 2 linesdj- linewise - delete 2 lines
It is possible to force *wise with the following keys:
v- characterwiseV- linewise<C-v>- blockwise
Usage: {operator}{*wise-specifier}{motion}, see
:h o_v:
dvj- characterwisedVj- linewised<C-v>j- blockwise
See also: operator, the true power of Vim.
Marks
a-z- local marks (inside the buffer), reset when buffer is deletedA-Z- global (across files)0-9- automatically set from .viminfo, '0 - cursor position on last exit from Vim, '1 - previous exit, and so on, see :h viminfo-file-marks
Set the mark with m{a-zA-Z}.
Jump to the mark:
'{a-z} `{a-z}- jump to mark in the current buffer, with ' - to the first non-blank char of the mark line, with ` - to the exact mark location'{A-Z0-9} `{A-Z0-9}- jump to mark in the file (may be another file, not a motion in this case)
Jump to the mark is a motion (can be used with operators).
List of marks - :marks.
Delete marks with :delm:
:delm a - delete mark `a` :delm a b or :delm ab - delete marks `a` and `b` :delm p-z - delete all marks from `p` to `z` :delm! - delete all marks for the current buffer (only a-z, not A-Z and 0-9)
Normal mode - jump list and change list
Jump list is a very powerful way to navigate files in Vim. It is similar to the browser
back / forward navigation button. After you use a motion or a command like gf to open another
file, you can use C-o to go back and C-i to go forward again.
The change list lets you move across edits in a similar way.
Jump list
<C-O>/<C-I>- move back / forward in the jump list,:jumps''/``- jump to the previous place you jumped here fromgf- open file under cursorgd/gD- local / global variable definitionC-]- jump to the tagC-^- switch between two recent files[num]<C-^>- switch to 'num' file (see file numbers in :buffers)
Change list
g;/g,- move back / forward the change list, view the list:changesgi- jump to last edit and start the insert mode (uses'^mark)'.- jump to last edit position
Special marks
Vim also provides a set of special marks that can be used to quickly jump around:
'[ `[ / '] `] - first / last char of last changed / yanked text '< `< / '> `> - first / last char of last visual selected text '' `` - previous jump position '" `" - position before exiting the buffer (useful when you reopen it) '^ `^ - last insert mode position '. `. - last edit position [' [` / ]' ]` - [count] previous / next lowercase mark
Insert and command mode: editing shortcuts
Some shortcuts that are useful in the command and insert mode:
<C-H>- delete previous character<C-W>- delete previous word<C-U>- delete current line, this is often used in mappings to clear the command line, for example to remove the automatic'<,'>when there is a visual selection
Insert mode: editing shortcuts
And some editing shortcuts for the insert mode (everything can be done by switching to normal mode, changing the text and switching back to insert, but it may be faster to do a small edit operation while staying in the insert mode):
<C-T>/<C-D>- indent / un-indent, useful for markdown lists<C-Y>/<C-E>- insert char above / below the cursor<C-A>/<C-X>(normal mode) - increment/decrement number under the cursorg<C-A>in visual mode - sequentially increment values in a column
1 1 1 1 -- select --> |1| -- g<C-A> --> 2 1 |1| 3
This one is special as it does switch to the normal mode, but only for one command:
<C-O>- execute normal command and get back to insert mode
Insert and command mode: insert from the register
<C-R><r> inserts the text from the register.
Examples:
<C-R>0(zero) - paste yanked text<C-R>"- paste the text from the unnamed register
If we have "Hello" in the a register and "World" in the b, we can
insert them like this: "ap"bp from normal mode.
But it is easy to do from the insert mode <C-R>a<C-R>b and change will
be repeatable with dot.
See also: Vim: The useful Ctrl-R
Insert and command mode: calculate the expression and insert the result
<C-R>= - prompt for the expression and insert it
<C-R>=3*0.65 -- will insert 1.95
Insert mode: insert the last inserted text
<C-A> - Insert the last text added in the insert mode.
Example:
"some_text(...) ct(new_text" - change "some_text" to "new_text" till the ( "some_text, ... - now we need to do the same change, but till the comma ct,<C-A> - we enter the new command `ct,` and then use Ctrl-A to insert new_text
There is also <C-@> to insert the last inserted text and stop the insert mode.
Insert mode autocompletion
Completion shortcuts for the insert mode:
<C-N>/<C-P>- generic completion, :h i_CTRL-N<C-X><C-O>- omni-completion, :h compl-omni<C-X><C-L>- lines<C-X><C-F>- file names, based on:pwd<C-X><C-]>- tags<C-X><C-K>- dictionary<C-X><C-N>- keywords in current file- there are more, see :h ins-completion
Work with autocomplete menu:
<C-N>/<C-P>- use the next / prev match from the word list<C-Y>- accept the currently selected match (yes)<C-E>- revert to the originally typed text (exit from autocompletion)<BS>(and<C-H>) - delete one character from current match<C-L>- add one character from current match
Open the popup without selecting the first item: <C-N><C-P> (will actually select
the first item and then un-select it).
Insert mode: complete whole lines
Complete whole lines with <C-X><C-L>:
- type some text, do
<C-X><C-L> - if there are a few suggestions - type a bit more and
<C-L> - now you are at the end of the line, and complete mode is still active
- press
<C-X><C-L>a few more times to get more lines which follow the line you've got
See also: Let Vim Do the Typing.
Similarly it is possible to complete sentences word-by-word with <C-X><C-P>.
Command line window
The command line window is a larger view of the command line.
It is very useful to edit long commands, or search patterns because we can use the normal
mode for editing (the normal command line, : only has insert mode).
q:- opens a command-line window.q/- opens a search history window.
From the command line / search prompt - press <C-F> to switch to the
command-line window.
So don't re-map the q:! (as people often map it to nop because they accidentally
open the command line window meaning to do :q).
If you often invoke it accidentally, you probably have a problem with
entering :q correctly. In this case either remap the :q to
something else (for example, to <Leader>q) or type it like this:
- left pinky -
Shift - right pinky -
: - left pinky -
q
(there is no chance to type it backwards this way).
Visual mode
In normal mode v, V, <C-V> start the char-, line-, block-wise visual mode.
Same keys in visual mode switch between char/line/block modes.
In normal mode gv re-selects the last visual selection (very useful).
In visual mode:
o- move to other end of the selection (also very useful when you need to adjust the selection on the other end of the visual block)gv- switch current and previous visual selectionc- change the selection (can re-paste after the change with<C-R>", convenient for wrapping)d- delete the selectionr- replace each character in the selection with entered character
In the visual block mode:
O- move to other corner on the same line$- select until the end of line, will work for all lines even if the length is differentA/I- append / prepend the block with entered text
Visual block + $ - selects a non-rectangular block. Then use A to append to the end of lines.
This is a very handy operation that often saves a lot of time.
Alternative: do A on one line, then select a block and repeat with :'<,'>normal ..
Select function body (between { and }): vaBV - select "a block" and
then change the selection mode to line-wise. To select 2 levels up -
v2aBV (when inside other {} block inside function) or vaBaB (repeat
aB to move to the next block). A mapping to work from any level inside
the function: :map t ? function <CR>f{vaBV (search backwards for
function, move to the { and then do vaBV).
Show full file name and stats
<C-G>- normal mode, show current file name and path and cursor positiong<C-G>- show file stats (number of columns, lines, words, bytes)
Calculator: expression register
In insert mode, Ctrl-R= will prompt for the expression and insert the
result into the document.
It can also be convenient to have the expression in the document, then
copy it and insert when prompted. The insert operation will be in
command-line mode and we can do it using Ctrl-R" (in cmd mode, Ctrl-R
inserts the given register value).
For example:
Document: 5+5*2 | ^ v $ y - go to start, select until end, copy 5+5*2= | A = Ctrl-R = - append, enter =, Ctrl-R = to invoke prompt Command line: = | Ctrl-R " - insert the copied expression =5+5*2 | Enter Document: 5+5*2=15 cos(1.57)=7.963267e-4
See :help i_CTRL-R_=, :help c_CTRL-R, :help registers.
Digraphs and special chars
<C-K>{char1}{char2}- insert a digraph (normal mode)- digraph table
<C-V><key>- insert the key literally (like<C-V><Tab>always inserts a tab, regardless of 'expandtab' option).<C-V>{code}- insert the unicode char literally by decimal code<C-V>u{code}- insert by hex codega- show ascii value of char under cursorg8- show utf-8 byte sequence for char under cursor
:dig - show digraphs
Manage Files
Some commands to manage files from Vim command line:
set path.,**= - set path to recursively look through the sub-directories.:find **/filenameor:e **/filename- search for the file and open it.:find **/filename<TAB>- display the list of matching files and move through them:saveas new_name- make a copy withnew_nameand switch to that copy:saveas Ctrl-R %- will insert the current file name, useful if new file name is similar to the current file name (also the following can be useful to edit the new name in the command-line window):w new_name- make a copy, but don't switch to it:drop file_name- open file or jump to already opened version:set switchbuf +useopen= +:sbuffer path/to/file- with 'useopen' option will also search for already open buffer and jump to it (also affects quickfix):hardcopy- print the file
The 'tpope/vim-eunuch' adds more commands to manage files (like Remove, Move, Chmod, Find, SudoWrite, and others).
Netrw
Netrw is the standard Vim file manager:
<F1>- open netrw help (use<C-^>to get back)-- go to the parent dir,<CR>- open a fileR- rename filed- create dirmf- mark file,mF- unmark file,mu- unmark all files,qF- mark quickfix files:MF pattern- mark files by pattern,mr- query for pattern and mark filesmt- mark target dir (or:MP dir), mark files,mc- copy files (mm- move)mg- vimgrep marked,mz- compress / decompress,mx- apply shell command,md- diff,mp- printqf- file info<del>,D- delete file or dir (marked files if there are any, visual selection if any)gh- hide / unhide dot filesi- switch view mode (thin / long / wide / tree)s- sorting stylep- preview the filex- view the file with an associated program (gxin any buffer)X- execute the filemb- bookmark the directory,gb- go to bookmarked dir,qb- list bookmarks and history:Ex */pattern- search in current dir:Ex **/pattern- search in current dir and sub-directories:Ex **//pattern- search in dir and sub-dirs inside files with vimgrep
Easter Eggs
- :help 42
- :help!
- :help holy-grail
- :help UserGettingBored
- :help quotes
- :Ni!
- :set rightleft (revert with :set norightleft or :set rightleft!)
- :help map-modes (see comment below the table about :nunmap)
- :help showmatch (read the note)
- :help bar