Series notes on Practical Vim by D. Neil:
- Practical Vim: Modes
- Practical Vim: Files
- Practical Vim: Getting Around Faster
- Practical Vim: Registers
Contents
- Chap 1 - The Vim Way
- Chap 2 - Normal Mode
- Chap 3 - Insert Mode
- Chap 4 - Visual Mode
- Chap 5 - Command-Line Mode
- Tip 27: Meet Command Line
- Tip 28: Execute a Command on One or More Consecutive Lines
- Tip 29: Duplicate or Move Lines Using
:t
and:m
Commands - Tip 30: Run Normal Mode Command Across a Range
- Tip 31: Repeat the Last Ex Command
- Tip 32: Tab-Complete Ex Commands
- Tip 33: Insert the Current Word at the Command Prompt
- Tip 34: Recall Commands from History
- Tip 35: Run Command in the Shell
Chap 1 - The Vim Way
Tip 1: Repeat with Dot Command
.
: Repeat last change
>G
: indent lines until the end of file
Tip 2: Append line and repeat
A
: append to the end of current line
C
= c$
: delete until the end of line, into Insert mode
s
= cl
: delete the character at right, into Insert mode
Tip 3: Forward scan and repeat
f+
: forward scan line for character +
;
: forward scan line for latest forward-scanned character
;.
: forward scan line for latest forward-scanned character, repeat lately executed change
Tip 4: Repeat and Reverse
Intent | Act | Repeat | Reverse |
---|---|---|---|
make a change | {edit} | . |
u |
scan line for next char | f{char} /t{char} |
; |
, |
scan line for previous char | F{char} /T{char} |
; |
, |
scan document for next match | /pattern<CR> |
n |
N |
scan document for previous match | ?pattern<CR> |
n |
N |
perform substitution | :s/target/replacement | & |
u |
execute a sequence of changes | qx{changes}q |
@x |
u |
Tip 5: Find and replace by hand
*
: find the next string matched to the word below cursor
n
: find the next matched string searched lately, which can follow the /
or *
command
cw
: delete to the end of the word, into Insert mode.
n.
: go to next matched string searched lately, repeat the lately executed change
Tip 6: Revisit the Dot Formula
The Ideal: One Keystroke to Move, One Keystroke to Execute
Chap 2 - Normal Mode
Tip 8: Chunk Your Undos
i{insert some text}<Esc>
constitutes a change that can be undone by a u
stroke.
Therefore, in Insert Mode, when openning a new line, try pressing <Esc>o
instead of <CR>
to keep the granularity in the change flow.
Special case: If we use the <Up>
, <Down>
, <Left>
, or <Right>
cursor keys while in Insert mode, a new undo chunk is created.
It’s just as though we had switched back to Normal mode to move around with the h
, j
, k
, or l
commands, except that we don’t have to leave Insert mode.
This also has implications on the operation of the dot command.
Tip 9: Compose Repeatable changes
aw
: a word
daw
: delete a whole word (this daw
can be repeated as one step using .
)
Tip 10: Use Counts to Do Simple Arithmetic
The <C-a>
and <C-x>
commands perform addition and subtraction on numbers (at or after the cursor).
18<C-a>
will add 18 to the number. When run without a count, they increment by one.
Tip 11: Count vs Repeat
Repeat over Count: dw.
may be better than 2dw
or d2w
in:
- counting is tedious
- it can be undone by
u
with one word in one step; u
and.
commands have more granularity
Count over Repeat:
- if you want to change 3 words to another series of characters,
c3w
followed by those characters would be better thandw..
andi
and those characters - a clean and coherent undo history
Tip 12: Combine and Conquer
Operator + Motion = Action:
The d{motion}
commands can be like
dl
delete a characterdaw
delete a whole worddap
delete an entire paragraph
The same goes for c{motion}
, y{motion}
, etc. Find a complete list of operators by :h operator
.
Some of them are:
Trigger | Effect |
---|---|
c |
change |
d |
delete |
y |
yank into register (copy) |
g~ |
swap case |
gu |
make lowercase |
gU |
make uppercase |
> |
shift right |
< |
shift left |
= |
autoindent |
! |
filter {motion} lines though an external program |
One more rule: invoking an operator in duplicate would act upon the current line, like
dd
deletes the current line>>
indents the current linegUgU
orgUU
make the current line all uppercase
Custom Operators
Check by :h :map-operator
Chap 3 - Insert Mode
Tip 13: Corrections in Insert Mode
Keystrokes | Effect |
---|---|
<C-h> |
delete back one character (backspace) |
<C-w> |
delete back one word |
<C-u> |
delete back to start of line |
These commands can also be used in Vim’s command line as well as in the bash shell.
Tip 14: Back to Normal Mode
Keystrokes | Effect |
---|---|
<Esc> |
to Normal mode |
<C-[> |
to Normal mode |
<C-o> |
to Insert Normal mode |
Insert Normal mode is s special version of Normal mode. It allows one command to execute, after which it will return to Insert mode immediately.
For example, the zz
command redraws the screeen with the current line in the middle of the window.
Thus, in Insert mode, <C-o>zz
helps to move our input flow into the middle of the window.
Tip 15: Paste without Leaving Insert Mode
<C-r>{register}
paste those in {register} in Insert mode.
<C-r><C-p>{register}
is smarter, which inserts text literally and fixes any unintended indentation.
But it’s a bit of handful. When pasting a register containing multiple lines of text, consider switching to Normal mode.
Tip 16: Do Calculations in Place
The expression register allows us to perform calculations directly. It is addressed by the =
symbol.
In Insert mode, <C-r>=
6*35<CR>
will insert 210 directly in the text.
Tip 17: Insert Unusual Characters by Character Code
In Insert mode, <C-v>{code}
can input the character whose address is {code}.
<C-v>u{00bf}
will insert the character whose unicode address is 00bf.
It should be a four-digit hexadecimal code.
ga
outputs a message showing the address of the character under cursor.
Keystrokes | Effect |
---|---|
<C-v>{123} |
insert character by decimal code |
<C-v>u{1234} |
insert character by hexadecimal code |
<C-v>{nondigit} |
insert nondigit literally |
<C-k>{char1}{char2} |
insert character represented by {char1}{char2} digraph |
Tip 18: Insert Unusual Characters by Digraph
<C-k>?I
: the ¿ character.
<C-k>12
: the ½ character.
<C-k>>>
: the » character.
<C-k>sa
: the さ character.
Get help by :h digraphs-default
or :h digraph-table
.
Tip 19: Overwrite Existing Text with Replace Mode
In Normal mode, R
triger Replace mode.
In Insert mode, the <Insert>
key in common keyboards can toggle between Insert and Replace mode.
gR
triggers Virtual Replace mode, which treats the tab character as though it consisted of spaces.
r
gr
provide the single-shot versions of Replace and Virtual Replace mode.
Chap 4 - Visual Mode
Tip 20: Grok Visual Mode
Commands that work the same as Normal mode in Visual:
h
j
k
l
to move cursorf{char}
to jump to a character;
,
to repeat or reverse the jump byf{char}
- search commands (together with
n
/N
) to jump to pattern matches c
to change text and go into Insert mode (after selection)
Tip 21: Define a Visual Selection
Enable Visual mode from Normal mode
Command | Effect |
---|---|
v |
enable character-wise Visual mode |
V |
enable line-wise Visual mode |
<C-v> |
enable block-wise Visual mode |
gv |
reselect the last visual selection |
Switching between Visual modes
Command | Effect |
---|---|
<Esc> /<C-[> |
switch to Normal mode |
v /V /<C-v> |
switch to Normal mode (when used from character-, line-, or block-wise Visual mode, respectively |
v |
switch to character-wise Visual mode |
V |
switch to line-wise Visual mode |
<C-v> |
switch to block-wise Visual mode |
o |
go to the other end of highlighted text |
Tip 22: Repeat Line-Wise Visual Commands
To make the <
>
commands work properly:
:set shiftwidth=4 softtabstop=4 expandtab
Vj
: select two lines
>.
/2>
: indent the selected lines twice. If over shoot, u
can undo it.
Tip 23: Prefer Operators to Visual Commands Where Possible
Suppose we have the 3 html lines below, and would like to make the 3 words inside the tags uppercase:
<a href="#">one</a>
<a href="#">two</a>
<a href="#">three</a>
Using a Visual Operator
vit
to visually select inside the tag;U
to convert the selected characters to uppercase;j.
to repeat the above operations in the next line.
However, this set of commands will give such results:
<a href="#">ONE</a>
<a href="#">TWO</a>
<a href="#">THRee</a>
A repeated Visual command affects the same range of text (in this case, only three characters).
Using a Normal Operator
gUit
j.
j.
give good results:
<a href="#">ONE</a>
<a href="#">TWO</a>
<a href="#">THREE</a>
Tip 24: Edit Tabular Data with Visual-Block Mode
Keystrokes | Meanings |
---|---|
<C-v>3j |
select a vertical column in 4 lines |
x... |
delete that column; delete 3 more columns |
gv |
reselect the last visually selected column |
r| |
replace each character in that column with | |
yyp |
duplicate a line |
Vr- |
trigger line-wise Visual mode, and replace every character in that line with - |
Tip 25: Change Columns of Text
Use Visual-Block mode to insert text into several lines simultaneously.
Keystrokes | Meanings |
---|---|
<C-v>jje |
trigger Visual-Block mode, select blocks across three lines, whose width decided by the word in the 3rd line |
c |
delete the selected text; into Insert mode |
{text} | insert {text}; only changes of the topmost line can be seen |
<Esc> |
back to Normal mode, changes in all lines can be seen |
Tip 26: Append After a Ragged Visual Block
Visual-Block mode is not limited to rectangular regions.
Keystrokes | Meanings |
---|---|
<C-v>jj$ |
trigger Visual-Block mode; select across 3 lines, all until the end of lines |
A; |
append ; in the end; only changes in the topmost line can be seen |
<Esc> |
back to Normal mode, changes in all lines can be seen |
Note: in Visual-Block mode, I
or A
places the cursor at the start or end of the selection.
Chap 5 - Command-Line Mode
Vim traces its ancestry back to vi; vi traces its ancestry back to a line editor called ex, which is why we have Ex commands.
Tip 27: Meet Command Line
:
to get into Command-Line mode.
Command | Effect |
---|---|
:[range]delete [x] | delete specified lines [into register x] |
:[range]yank [x] | yank specified lines [into register x] |
:[line]put [x] | put the text from register x after the specified line |
:[range]copy {address} | copy the specified lines to below the line specified by {address} |
:[range]move {address} | move the specified lines to below the line specified by {address} |
:[range]join | join the specified lines |
:[range]normal {commands} | execute Normal mode {commands} on each specified line |
:[range]substitute/{pattern}/{string}/[flags] | replace occurrences of {pattern} with {string} on each specified line |
:[range]global/{pattern}/[cmd] | execute the Ex command [cmd] on all specified lines where the {pattern} matches |
<C-v>
<C-k>
<C-r>{register}
work in Command-Line mode like in Insert mode.
Tip 28: Execute a Command on One or More Consecutive Lines
:1
: specify line 1
:$
: specify the last line
:2,5p
: specify line 2 to line 5; and print them
:.
: specify the current line
:.,$p
: specify from the current line to the last line; and print them
:%
: specify the all lines in the current file
:%s/Pratical/Pragmatic/
: replace the first occurrence of “Practical” with “Pragmatic” on each line
We can also use visaul selection to specify lines.
:/<html>/,/<\/html>/
: specify the range of lines beginning with a line containing <html>
and ending with a line containing </html>
.
:{address}+n
: specify by the address adding with an offset.
:/<html>/+1,/<\/html>/-1
: specify the range of lines, whose beginning line is one line below the line containing <html>
, and whose ending line is one line above the line containing </html>
.
Special addresses:
Symbol | Address |
---|---|
1 | first line of the file |
$ | last line of the file |
0 | virtual line above the first line of the file |
. | line where the cursor is placed |
'm |
line containing mark m |
'< |
start of visual selection |
'> |
end of visual selection |
% | the entire file (shorthand for :1,$ ) |
Here line 0 is useful in the :copy {address}
or :move {address}
commands when we want to copy or move a range of lines to the top of a file.
Tip 29: Duplicate or Move Lines Using :t
and :m
Commands
:copy
= :co
= :t
. Think of it as copy TO.
Command | Effect |
---|---|
:t6 | copy the current line to just below line 6 |
:t. | duplicate the current line (similar to Normal mode yyp |
:t$ | copy the current line to the end of the file |
:'<,'>t0 |
copy the visually selected lines to the start of the file |
:move
= :m
. It functions analogously to :t
, but in ‘move’ rather than ‘copy’ way.
Tip 30: Run Normal Mode Command Across a Range
Use :normal
to run Normal mode command on a range of lines.
:'<,'>normal .
: for each line in the visual selection, execute the Normal mode dot command.
:%normal A;
: append a ;
at the end of every line of the file.
:%normal i//
: add //
in the beginning of every line of the file.
Tip 31: Repeat the Last Ex Command
@:
: repeat the last ex command.
Tip 32: Tab-Complete Ex Commands
<C-d>
: in Command mode, to reveal a list of possible completions
<Tab>
: cycle through the possible completions
Customize the completion behaviors with the ‘wildmode’ option. :h 'wildmode'
to get help.
Tip 33: Insert the Current Word at the Command Prompt
<C-r><C-w>
copies the word under the cursor and inserts it at the command line prompt.
Tip 34: Recall Commands from History
Use up arrow key to get the previous command; down arrow in the opposite direction.
Arrow keys can be avoided for recalling command history, by custom mappings:
cnoremap <C-p> <Up>
cnoremap <C-n> <Down>
:write | !python %
: join the commands :write
and :!python %
q:
in Normal mode to meet the Command-Line window.
Command | Action |
---|---|
q/ |
open the command-line window with history of searches |
q: |
open the command-line window with history of Ex commands |
<C-f> |
switch from Command-Line mode to the command-line window |
Tip 35: Run Command in the Shell
:!python %
: execute the current file using python
:shell
: hang the current Vim session, into a shell interface
$ exit
: exit the shell and back to Vim
If we already run Vim in Bash, <C-z>
in Vim and fg
in Bash achieve the same function as :shell
in Vim and exit
in shell.
The position of !
matters:
:write !sh
: pass the contents of the buffer as input to the externalsh
:write ! sh
: same as above:write! sh
: write the contents of the buffer to a file calledsh
by calling the:write!
command.
Filtering the Contents Through an External Command
Suppose we have a csv file:
first name,last name,email
john,smith,john@example.com
drew,neil,drew@vimcasts.org
jane,doe,jane@example.com
We can sort the namelist by the last name using this command:
:2,$!sort -t',' -k2
Here :2,$
specify the line range; sort
is the external filtering command; the -t','
option assigns that fields are separated with commas, and the k2
flag indicates that the second field is to be used for the sort.
Command | Effect |
---|---|
:shell |
start a shell (return to Vim by typing exit |
:!{cmd} |
execute {cmd} with the shell |
:read !{cmd} |
execute {cmd} in the shell and insert its standard output below the cursor |
:[range]write !{cmd} |
execute {cmd} in shell with [range] lines as standard input |
:[range]!{filter} |
filter the specified [range] through external program {filter} |