mastering vim damian conway

2020-09-04 06:24

seeking help

By name, by completion, by search


:help TOPIC

:help TOP<TAB>

:helpgrep PATTERN               | " Note no slashes needed

You can actually use this functionality more generally. The following command provides a unix grep-like utility for arbitrary files and directories that puts the information in a stack of vim buffers with :cnext, :cnfile functionality

:vimgrep /PATTERN/ FILES...

Suggestion: Get better by learning your alphabet

Look at each character on the keyboard and workout what they do.

As of time of writing - Sun 18/08/19 11:10

a - append
b - previous word
c - change
d - delete
e - end of word
f - character on line
g - random commands
h - left
i - insert
j - down
k - up
l - right
m - set mark
n - next search
o - insert one line below
p - paste
q - new macro
r - replace
s - delete character under cursor and insert
t - till nex character
u - undo
v - visual mode
w - next word
x - delete character
y - yank
z - random commands

~ - capitalize
` - goto row in mark line
\ - usually leader?
/ - search ahead
- - goto above line first nonblank char
+ - goto below line first nonblank char
_ - ???
= - ???
[ - ???
] - ???
( - top of sentence
) - bottom of sentence
{ - top of paragraph
} - bottom of paragraph
' - mark line
" - register select
? - search behind
> - indent
< - unindent
. - repeat
, - prev f/t char
; - ahead f/t char
! - ???
: - command
@ - ???
# - ???
$ - EOLD
% - ???
^ - first nonblank char
& - ???
* - ???


\ - usually leader
_ - motion: move downward N lines to nonblank char
= - filtering with configurable program
[ - random tag stuff
] - tag stuff
! - filter through external program
@ - execute register contents
* - search for word under cursor
# - * but searches backwards
% - jump to matching [{()}]
& - repeat last substitute AKA :s

IDEA: download the new knowledge into your fingertips

:help normal-index
:help insert-index

Learning to Move Around More Effectively

hklj - move one character at a time

word motions

w  - next word
b  - start of previous word
e  - end of word
ge - end of previous word

“word” is configurable and includes underscores. Use these for whitespace words

W  - whitespace word
B  - whitespace word
E  - whitespace word
gE - whitespace word

0 - beginning of line
$ - end of current line
^ - start of first word on current line
+ - start of first word one line below
- - start of first word one line above
<cr> - start of next line

paragraphs -

} - jump to next paragraph (uses blank spaces)
{ - jump to top of paragraph

file -

gg - top of file
G - end of file
<N>G - goto line number N
<N>gg - goto line number N
<N>% - goto percent N through file

matching constructs

% bounces between brackets under the cursor [{()}]

append some new constructs with:

set matchpairs+=<:>,<<:>>

i.e. for c-like languages bounce between assignment and terminating semicolon

set matchpairs+==:;

(note += append operator)

see also: matchit.vim

motions are designed to be repeated

4} - 4 paragraphs

Suggestion: Fix your deletions

Default vim backspace behavior is frustrating

set backspace=start
set backspace=indent
set backspace=eol

set backspace=eol,indent,start

insert control codes: improving the efficiency of insert mode

<c-y> duplicates the above line character by character
<c-e> same but from below

<c-a> re-inserts the last inserted thing

<c-r> inserts from a register

<c-r>= evaluates an experession and inserts the result

e.g. The amount of seconds in one day is (=606024) 86400

<c-t> tabs over
<c-d> tabs back
<c-v> inserts verbatim character (i.e. 


<c-w> deletes the previous word when you screw up

<c-o> takes you to normal for one command

advanced searching with more powerful regexes

regexes in vim are sed-ish with perl-like complexity/power

:help regex

very magic mode

Be aware of the meta-syntax defaults!

. and * are the most obvious exceptions. Everything else needs to be escaped


avoid this madness by defaulting to very magic mode)


nnoremap / /\v

useful metasyntax

& is the AND that corresponds to | OR Note that the position must also match! This by default is not super useful, but you can do something like this instead:


< and > match the start and end of words. Useful since / for would ignore “for” or (for)

/\<for\> will match "for" but not "wherefor" or "enforce"

on’t forget * and # for searching for words under the cursor

:set ignorecase

Note that this will effect some vimscript

set ignorecase smartcase

i.e. case insensitive for lowercase entries, but case sensitively if you capitalize anything

You can also change sensitivity on the fly with insensitive) or (sensitive)

More powerful find/replace

You may be familiar with


But you can also specify relative and absolute ranges



Semi-colon changes to relative to the first number



. is current line, $ is EOF


Shortcut: enter N: to get


Another shortcut: % expands to:


find and replace with regexes




You can also start behind


find and replace with offsets

“look backwards in the file for lines with foo in them, then start on the next line going to 10 lines from the end of the file”


! Note that most other colon commands can use these ranges as well

substitution flags

Multiple matches (global):


Confirm flag:


This presents the following options:


yes  - substitute
no   - skip
last - substitute and quit
quit - stop susbtituting
all  - substitue this and all remaining
^E   - scroll down
^Y   - scroll up

You can re-substitute easily:


Muliples or full file:


the global command

:g /pattern/ colon command

e.g. “I want to indent every line that already is indented”

:g /^\s/ :center

Global with normal commands

e.g. “Convert everything in ISBN lines to uppercase”

:g /<ISBN>/ :normal gUU

Ranges in ranges:

e.g. convert to ms word friendly format

:g /./ :.;/^$/join

i.e. "Globally, for all lines (.) from the current line (.) to (;) the next line matching a blank line (/^$/) run the :join command

Or add gaps

:g /./ :.;/^$/-1 join

copying smarter

you can yank from searches


yank “around” a text object


yanking to letters


yanking in programming blocks


yanking in text objects


understanding undo trees

vi - the u key bounces between the undoing and redoing the last change vim - the u key always takes you backwards in time ( to redo )

version 7 introduced the idea of multiple branching undo timelines for if you undo a few times and make some more changes

—- = making changes …. = undoed changes

0 70 100 120 125 130 ——————————————–…………………………….
___________ flip back to the final state of the previous timeline


flip to the next timeline


Since no visualization is provided, this makes very little sense to use the g+ and g- commands

The other mechanism is by time units

:earlier <TIME-OFFSET.

:later   <TIME-OFFSET.


:earlier 10m

:later 30s

Note that these are always relative moves. Vim will automatically flip you to the active timeline during those changes

persistant undo timelines

Since this is a pretty recent change you should be a little careful

if has('persistent_undo')
    set undofile

Note that this is directory specific. But you can change that to have a lone file:

set undodir=$HOME/.VIM_UNDO_FILES

Although this comes with an “all eggs in one basket” problem and is limited to 1000 commands. Change it with:

set undolevels=5000

more efficient command-line usage

Navigate through history with and

But you can also filter this by typing something and then flip up and down

You can also edit this history of commands:


Same rules apply to searches as well:


Command line also features TAB autocompletion

<c-a> will insert all possibilities
<c-n> is next possiblity
<c-p> is previous possibility

Configuring completions:

This will show all possiblities but not insert any

set wildmode=list

You can also have vim type out the largest common prefix

:set wildmode=list:longest

Completion will also work for vim commands, shell commands, options

Alternatively you can just use wildcards

:read ~/Desktop/*.md

Or use expansion

:write %.bak

A pound sign specifies the “other” file

:read # :n #

There’s also the muiltilevel wildcard:


This matches:

*, */*, */*/*, ...


:next **/filename.txt

(Be careful about speed in the root directory)

text completion

Also accessible in insert or replace mode


Then you have quite a few options:

CTRL-L   Whole lines
CTRL-N   keywords in the current file
CTRL-K   keywords in 'dictionary'
CTRL-T   keywords in 'thesaurus', thesaurus-style
CTRL-I   keywords in the current and included files
CTRL-]   tags
CTRL-F   file names
CTRL-D   definitions or macros (C preprocessor symbols)
CTRL-V   Vim command-line
CTRL-U   User defined completion
CTRL-O   omni completion
s        Spelling suggestions

change the CTRL-D to be more useful for non-C programming languages. e.g. perl subroutine statments:

:set define=^\\s*sub

use CTRL-N for keywords found in the file. This is changeable! e.g. fixing the c identifiers

:set iskeyword=a-z,A-Z,48-57,_,.,-,>

se CTRL-I for included files (e.g. from #include statements in C)

of course you can also use omni-completion CTRL-O to attempt “intellisense”-type behavior. Vimscript is used for contextual smarts

<head la

<head lang="EN"

This attempts to figure out what would be syntactically valid. This needs some help with configuration files.

installation happens at:


You will probably also need to use a program to generate tags (e.g. exuberant ctags for c)

You will also need to turn on filetype detection:

:filetype plugin on

Or you can turn it on manually:

:set omnifunc=javascriptcomplete#CompleteJS

This is great for learning notes, etc.

Or if you’re a badass you can write your own.

:help complete-functions

editing visually

Vim is based on the following logically order:

operation -> apply to what

You can also do things in reverse in a little more intuitive manner:

select something -> do operation

Three options:

v     - visual mode
V     - visual line mode
<c-v> - visual block mode

Visual block is probably the most useful. It selects rectangular blocks within the lines. Useful for tabular data


Specials Commands:

I - insert (since i is the "in" motion)
A - append (since a is the "around" motion)
c - change every line
r - replace every character

e.g. vipJ

enhancing the visual modes

Sometimes you want to remain in visual mode instead of being popped out into normal mode.

reselct what you previously selected:


visual guides

You can use colorcolumn to set a ruler on the right margin, but this can get annoying. Alternatively you can use the matchadd function to restrict to only the text that crosses the line.

highlight ColorColumn ctermbg=magenta
call matchadd('ColorColumn', '\%81v', 100)

highlight ColorColumn ctermbg=magenta
call matchadd('ColorColumn', '\%>81v', 100)




zo - open
zc - close
zn - unfold everit
zi - invert folds
zd - delete a fold
ze - eliminate all

zm - increase fold
zM - maximize folding
zr - reduce folding
zR - show all folds

Automate it:

:set foldmethod=indent
:syntax enable
:set foldmethod=syntax

If you are a badass:

:set foldexpr=strlen(matchstr(getline(v:lnum),'^-*'))
:set foldmethod=expr

“fold based on the length of dashed lines”