designates my notes. / designates important.
Right off the bat Drew tells you not to read the book linearly, to pick at it here and there. I read it linearly. It is set up like a cookbook, which I normally don’t like at all, but there was enough elaboration with each tip and the similar tips were grouped together. Not a particularly easy task since there are so many ways you might get to the same solution with vim, none being the ‘right’ way.
Though I didn’t take the advice and read it cover to cover, I did do it slowly, over about two weeks. I tried to pick a few things that I wanted to integrate and made a point of consciously using them for a few days; many of the habits stuck. This is the best way to learn vim, bit by bit. Learn one new thing a day, or a week, and, eventually, you’ll have attained mastery, or at least competence.
On top of this strategy, I also have a list of all the stuff I’d eventually like to integrate as second nature. This prevents me from ever getting to the point where I become comfortable without having to be constantly looking for new tips. This book would be great to poke around in, there will always be something new, or at least will lead you to a more advanced understanding of something old, but I rather prefer my making one pass and compiling a TODO list. I’ll probably go through the book again though, maybe even before my list is empty.
The other key thing to realize is, reading alone is not enough. You get good at vim the same way you get to Carnegie Hall; practice, practice, practice! You should always try out new and interesting ways of doing things. By having a scratch file to work with, which apparently are available online to follow the book exactly, though I simply made up my own examples, you can fiddle with new commands without wrecking a real project.
All in all, when you hear people online saying that this is THE vim book, I think they are right. This book is highly recommended; I was very pleased with it.
gU = make all uppercase was one I had been lacking
Tim Pope’s commentary.vim plugin provides a
good example.[4] This adds a command for commenting and uncommenting lines of
code in all languages supported by Vim. The commentary command is triggered by
gc{motion}
, which toggles commenting for the specified lines.
From insert mode, command line, or bash:
Keystrokes | Effect
-------------------
`<C-h>` | Delete back one character (backspace)
`<C-w>` | Delete back one word
`<C-u>` | Delete back to start of line
Keystrokes | Effect
-----------+-------
`<C-o>` | Switch to Insert Normal mode
J
= joins current and next line (can use when I write my 5 sent abstracts that
I want on one line, but type as 5 lines.
<C-[>
=
In Insert mode, we can press <C-r>0
to paste the text that we just yanked
at the current cursor position.
The expression register is addressed by the = symbol. From Insert mode we can
access it by typing <C-r>=
. This opens a prompt at the bottom of the screen
where we can type the expression that we want to evaluate. When done, we hit
<CR>
, and Vim inserts the result at our current position in the document.
gv
| Reselect the last visual selection
o
| Go to other end of highlighted text
use >
for indenting (from visual mode instead of I
use ‘r’ instead of ‘I’ to add columns of data
yyp
then Vr{char}
to underline a line to the exact length
Append to end of ragged lines: visual block, $, A{char},
:[range]join
Join the specified lines
:{number}
= jumps to line number (useful to get to bugs in stack traces)
:{+-}{number}
= jumps to line number lines up (-) or down (+)
{number}G
= jumps to line number (useful to get to bugs in stack traces)
:h range
:t
or :co
or :copy
, combined with line numbers, useful in visual mode
:move
or :m
works much like :copy
Repeating the last Ex command is as easy as pressing @:
The :’<,’>normal .
command can be read as follows: “For each line in the
visual selection, execute the Normal mode . command.”
:%normal A;
= append a ; at the end of ever line in the file
:help @
The :read !{cmd}
command lets us direct standard output into a buffer. As
you might expect, the :write !{cmd}
does the inverse: it uses the contents of
the buffer as standard input for the specified {cmd} (see :write_c)
The effect of the :write !sh
command is that each line of the current
buffer is executed in the shell. Refer to :h rename-files
:2,$!sort -t',' -k2
The :lcd {path}
command lets us set the working directory locally for the
current window.
ea
moves to the end of current word and append, think of as end-append
Keystrokes Current | Keystrokes Current
---------------------+-------------------
`iw` word | `aw` word plus space(s)
`iW` WORD | `aW` WORD plus space(s)
`is` sentence | `as` sentence plus space(s)
`ip` paragraph | `ap` paragraph plus blank line(s)
Lowercase marks are local to each individual buffer, whereas uppercase marks are globally accessible.
`{mark} (backtick) takes you to the exact place a mark was set
'{mark}
(apostrophe) takes you to the beginning of the line a mark was set
on.
Table 10. Vim’s Automatic Marks
Keystrokes | Buffer Contents
---------- +-------------------------------------------
`“` | Position before the last jump within current file
`‘.` | Location of last change
`‘^` | Location of last insertion
`‘[` | Start of last change or yank
`‘]` | End of last change or yank
`‘<` | Start of last visual selection
`‘>` | End of last visual selection
The %
command lets us jump between opening and closing sets of parentheses
(see %). It works with (), {}, and [], <>
Even though matchit ships with the Vim distribution, it’s not enabled by default. This minimal vimrc would make Vim autoload the matchit plugin on startup:
set nocompatible
filetype plugin on
runtime macros/matchit.vim
The enhancements provided by this plugin are very useful, so I’d recommend
enabling it. Consult matchit-install
for more details.
Surround.vim
One of my favorite plugins is surround.vim by Tim Pope,[16] which makes wrapping a selection with a pair of delimiters easy. For example, we could put the words New York in quote marks:
Keystrokes | Buffer Contents
-----------+----------------------------------------
`{start}` | cities = ["London", "Berlin", New York]
`vee` | cities = ["London", "Berlin", New York]
`S"` | cities = ["London", "Berlin", "New York"]
The S"
command is provided by surround.vim, and it can be read as “Surround
the selection with a pair of double quote marks.” We could just as easily use
S)
or S}
if we wanted to wrap the selection with opening and closing
parentheses or braces.
We can also use surround.vim to change existing delimiters. For example, we
could change {London} to [London] with the cs}]
command, which can be read as
“Change surrounding {} braces to [] brackets.” Or we could go the other way
with the cs]}
command. It’s a powerful plugin—check it out.
:put {reg}
puts/pastes
Matching within delimiters:
Keystrokes | Buffer Contents
------------------------+-----------------------------------------
`{start}` | Match "quoted words"---not quote marks.
`/\v"[^"]+" <CR>` | Match "quoted words"---not quote marks.
`/\v"\zs[^"]+\ze" <CR>` | Match "quoted words"---not quote marks.
The basic pattern uses a common regex idiom: “[^”]+" . The pattern begins and ends with a quote mark and then matches one or more characters in between that are anything but a quote.
Searching:
Command | Effect
--------+----------------------------------------------------
`n` | Jump to next match, preserving direction and offset
`N` | Jump to previous match, preserving direction and offset
`/<CR>` | Jump forward to next match of same pattern
`?<CR>` | Jump backward to previous match of same pattern
`gn` | Enable character-wise Visual mode and select next search match
`gN` | Enable character-wise Visual mode and select previous search match
q/
brings up command mode with search history
//
runs the last search
If we prefix a % at the start of the substitute command, it will be executed
on every line of the file: :%s/going/rolling/g
:[range] global[!] /{pattern}/ [cmd]
The default range for the :global command is the entire file (%). That sets it apart from most other Ex commands, including :delete, :substitute, and :normal, whose range is the current line (. ) by default.
The {pattern} field integrates with search history. That means we can leave it blank and Vim will automatically use the current search pattern.
The [cmd] could be any Ex command except for another :global command.
We can invert the behavior of the :global
command either by running
:global!
or :vglobal
(mnemonic: invert). Each of these tells Vim to execute
[cmd] on each line that doesn’t match the specified pattern.
On the Etymology of Grep
Consider this abbreviated form of the :global command:
:g/re/p
:v/href/d
(:vglobal) can be read as “Delete each line that doesn’t contain
href.”
Suppose that we wanted to collect all of the TODO items in one place. We
could view them all at a glance by running this command: :g/TODO
let’s yank each line containing the word “TODO” into a register. Then we can
paste the contents of that register into another file and keep them around for
later. We’ll use the a register. First we’ll need to clear it by running
qaq
. Let’s break that down: qa
tells Vim to start recording a macro into
the a register, and then q
stops the recording. We didn’t type anything while
the macro was recording, so the register ends up empty. We can check that by
running the following:
:reg a
--- Registers ---
"a
:g/TODO/yank A
:reg a
"a // TODO: Cache this regexp for certain depths.
// TODO: No matching end code found - warn!
Here’s an alternative solution: :g/TODO/t$
It uses the :t
command, which we met in Tip 29. Rather than appending each
TODO item to a register, we simply copy it to the end of the file. After
running this command, we could jump to the end of the file to review the TODO
items. This technique is more straightforward because it avoids messing around
with registers. But it won’t work as neatly with the :argdo
and :bufdo
commands.
‘:sort’
:vimgrep TERM %
searches in the open file
:copen
brings up the matches,
:cnext
and :cprevious
cycle through matches
Trigger | Effect
----------------
`c` | Change
`d` | Delete
`y` | Yank into register
`g~` | Swap case
`gu` | Make lowercase
`gU` | Make uppercase
`>` | Shift right
`<` | Shift left
`=` | Autoindent
`!` | Filter {motion} lines through an external program
“If you’re curious about how to create your own custom motions, start by reading
:h omap-info
“From insert mode, command line, or b
Keystrokes | Effect
-----------+-------
`<C-h>` | Delete back one character (backspace)
`<C-w>` | Delete back one word
`<C-u>` | Delete back to start of line
page 39:
>G
command increases the indentation from the current line until the
end of the file.page 44:
con+cat+these+with+spaces
,f+s + <Esc> # I've remapped f to ,f
;. # so I can use f for easymotion without leader
;.
;.
con + cat + these + with + spaces
page 46:
Perform substitution :s/target/replacement
repeat -> &
or undo -> u
@:
can be used to repeat any Ex command
page 60:
10<C-a>
adds ten to the current/next number in line.page 61:
Number Formats
What follows 007? No, this isn’t a James Bond gag; I’m asking what result would you expect if you added one to 007.
If you answered 008, then you might be in for a surprise when you try using
Vim’s
If you work with octal numbers frequently, Vim’s default behavior might suit you. If you don’t, you probably want to add the following line to your vimrc:
set nrformats=
This will cause Vim to treat all numerals as decimal, regardless of whether they are padded with zeros.
Trigger | Effect
----------------
`c` | Change
`d` | Delete
`y` | Yank into register
`g~` | Swap case
`gu` | Make lowercase
`gU` | Make uppercase
`>` | Shift right
`<` | Shift left
`=` | Autoindent
`!` | Filter {motion} lines through an external program
page 65:
when an operator command is invoked in duplicate, it acts upon the current
line. So dd
deletes the current line, while >>
indents it. The gU
command
is a special case. We can make it act upon the current line by running either
gUgU
or the shorthand gUU
.
Tim Pope’s commentary.vim plugin provides a
good example.[4] This adds a command for commenting and uncommenting lines of
code in all languages supported by Vim. The commentary command is triggered by
gc{motion}
, which toggles commenting for the specified lines.
:help map-operator
:h omap-info
Keystrokes | Effect
-----------+-------
`<C-h>` | Delete back one character (backspace)
`<C-w>` | Delete back one word
`<C-u>` | Delete back to start of line
Keystrokes | Effect
-----------+-------
`<Esc>` | Switch to Normal mode
`<C-[>` | Switch to Normal mode
`<C-o>` | Switch to Insert Normal mode
page 71:
<C-r>0
to paste the text that we just yanked
at the current cursor position.<C-r>=
. This opens a prompt at the bottom of the screen
where we can type the expression that we want to evaluate. When done, we hit
<CR>
, and Vim inserts the result at our current position in the document.page 74:
We can tell Vim to insert any arbitrary character if we know its numeric
code. From Insert mode, we just have to type <C-v>{code}
, where {code} is the
address of the character that we want to insert. Vim expects the numeric code
to consist of three digits. Suppose, for example, that we wanted to insert an
uppercase “A” character. The character code is 65, so we would have to enter it
as <C- v>065
.
But what if we wanted to insert a character whose numeric code is longer than
three digits? For example, the Unicode Basic Multilingual Plane has an address
space for up to 65,535 characters. It turns out that we can enter all of these
using a four-digit hexadecimal code if we type <C-v>u{1234}
(note the u
preceding the digit this time). Let’s say we wanted to insert an inverted
question mark symbol (“¿”), which is represented by the character code 00bf.
From Insert mode, we would just have to type <C-v>u00bf
. See i_CTRL-V_digit
for more details.
If you want to find out the numeric code for any character in your document,
just place the cursor on it and trigger the ga
command.
page 75:
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
page 76:
:h digraph-table
page 82:
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
page 83:
Command | Effect
--------+-------
`o` | Go to other end of highlighted text
page 88:
page 90:
yyp
then Vr{char}
to underline a line to the exact lengthpage 93:
Keystrokes | Buffer Contents
-------------+-----------------------
{start} | var foo = 1
Normal mode | var bar = 'a'
| var foobar = foo + bar
-------------+-----------------------
<C-v>jj$ | var foo = 1
Visual-Block | var bar = ’a’
| var foobar = foo + bar
-------------+-----------------------
A; | var foo = 1;
Insert mode | var bar = 'a'
| var foobar = foo + bar
-------------+-----------------------
<Esc> | var foo = 1;
Normal mode | var bar = 'a';
| var foobar = foo + bar;
-------------+-----------------------
:[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
page 99:
:{number}
= jumps to line number (useful to get to bugs in stack traces)
:{+-}{number}
= jumps to line number lines up (-) or down (+)
{number}G
= jumps to line number (useful to get to bugs in stack traces)
page 100:
:{range}
= :{start},{end}
= do something over the range
.
in range, as in :.,{end}
, = current line
%
= all the lines in current file
use % with substitute like: :%s/Practical/Pragmatic/
page 101:
If we press the :
key now [after visually selecting], the command-line
prompt will be prepopulated with the range :’<,’>
. It looks cryptic, but you
can think of it simply as a range standing for the visual selection.
Vim also accepts a pattern as an address for an Ex command, such as the one shown here:
= > :/<html>/,/<\/html>/p
< = 2 <html>
3 <head><title>Practical Vim</title></head>
4 <body><h1>Practical Vim</h1></body>
5 </html>
page 105:
So we can read the :6copy.
command as “Make a copy of line 6 and put it
below the current line.”
We could shorten the :copy
command to only two letters, as :co
. Or we
can be even more succinct by using the :t
command, which is a synonym for
:copy. As a mnemonic, you can think of it as copy
TO. This table shows a few examples of the :t
command in action:
Command | Effect
-----------+-------
`:6t.` | Copy line 6 to just below the current line
`: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
or :m
works much like :copy
page 106:
@:
, then @@
for more
repeatspage 108:
The :’<,’>normal .
command can be read as follows: “For each line in the
visual selection, execute the Normal mode . command.”
:%normal A;
= append a ; at the end of ever line in the file
page 110:
:help @
page 117:
q:
and meet the command-line window (see cmdwin)page 118:
Command | Action
---------+-------
`q/` | Open the command-line window with history of searches
`q:` | Open the command-line window with history of Ex commands
`ctrl-f` | Switch from Command-Line mode to the command-line window
page 119:
:shell
command to start an interactive shell session (see :shell
page 120:
=> $ jobs
<= [1]+ Stopped vim
In bash, we can use the fg
command to resume a suspended job, bringing it
back into the foreground. That brings Vim back to life exactly as we left it.
The Ctrl-z
and fg
commands are quicker and easier to use than Vim’s
equivalent :shell and exit commands. For more information, run man bash and
read the section on job control.
the :read !{cmd}
command, which puts the output from the {cmd} into our
current buffer (see :read!).
The :read !{cmd}
command lets us direct standard output into a buffer. As
you might expect, the :write !{cmd}
does the inverse: it uses the contents of
the buffer as standard input for the specified {cmd} (see :write_c)
:write !sh
command is that each line of the current
buffer is executed in the shell. Refer to :h rename-filesfirst name,last name,email
john,smith,john@example.com
drew,neil,drew@vimcasts.org
jane,doe,jane@example.com
We’ll sort the records by the second field: last name. We can use the -t’,’ option to tell the sort command that fields are separated with commas, and we can use the -k2 flag to indicate that the second field is to be used for the sort.
The first line of the file contains header information. We want to leave it at the top of the file, so we’ll exclude it from the sort operation by using a range of :2,$ . This command line does what we want:
:2,$!sort -t',' -k2
first name,last name,email
jane,doe,jane@example.com
drew,neil,drew@vimcasts.org
john,smith,john@example.com
page 122:
!{motion}
operator command drops us into Command-Line mode and
prepopulates the [range] with the lines covered by the specified {motion} (see
!). For example, if we place our cursor on line 2 and then invoke !G
, Vim
opens a prompt with the :.,$! range set up for us.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 the shell with [range] lines as standard input
`:[range]!{filter}` | Filter the specified [range] through external program {filter}
page 124:
global/href/join
vglobal/ href/delete
%normal A: http:/ /vimcasts.org
%normal yi"$p
%substitute/\v^[^\>]+\>\s//g
:source
command to execute the batch.vim script (see
source). Each line of the script is executed as an Ex command, just as though
we had typed itpage 125:
:argdo source batch.vim
:args
. Can do this by
opening vim ala vim * (to open all files in directory, or match however). Can
also use :bufdo
and :argadd %
to set up the :args
.page 140:
Ex Command | Normal Command Effect
-----------+----------------------
`:clo[se]` | `<C-w>c` Close the active window
`:on[ly]` | `<C-w>o` Keep only the active window, closing all others
page 142:
The :lcd {path}
command lets us set the working directory locally for the
current window.
Note that :lcd
applies locally to the current window, not to the current
tab page. If we have a tab page containing two or more split windows, we could
set the local working directory for all of them by running :windo lcd {path}
.
Command | Effect
----------------------- +-----------------------------
`:tabe[dit] {filename}` | Open {filename} in a new tab
`<C-w>T` | Move the current window into its own tab
`:tabc[lose]` | Close the current tab page and all of its windows
`:tabo[nly]` | Keep the active tab page, closing all others
page 155:
= > : w !sudo tee % > /dev/null
< = Password:
W12: Warning: File "hosts" has changed and the buffer was
changed in Vim as well
[O]k, (L)oad File, Load (A)ll, (I)gnore All:
page 158:
:h motions
page 163:
Command | Move Cursor
--------+------------
`w` | Forward to start of next word
`b` | Backward to start of current/previous word
`e` | Forward to end of current/next word
`ge` | Backward to end of previous word
page 172:
Keystrokes | Buffer Contents
-------------+-----------------
{start} | This phrase [t]akes time but
| eventually gets to the point.
|
`d /ge <CR>` | This phrase [g]ets to the point.
page 177:
Keystrokes Current | Keystrokes Current
---------------------+-------------------
`iw` word | `aw` word plus space(s)
`iW` WORD | `aW` WORD plus space(s)
`is` sentence | `as` sentence plus space(s)
`ip` paragraph | `ap` paragraph plus blank line(s)
page 178:
d{motion}
command tends to work
well with aw
, as
, and ap
, whereas the c{motion}
command works better
with iw
and similar.page 179:
Lowercase marks are local to each individual buffer, whereas uppercase marks are globally accessible.
`{mark} (backtick) takes you to the exact place a mark was set
'{mark}
(apostrophe) takes you to the beginning of the line a mark was set
on.
page 180:
Keystrokes | Buffer Contents
---------- +-------------------------------------------
`“` | Position before the last jump within current file
`‘.` | Location of last change
`‘^` | Location of last insertion
`‘[` | Start of last change or yank
`‘]` | End of last change or yank
`‘<` | Start of last visual selection
`‘>` | End of last visual selection
page 181:
%
command lets us jump between opening and closing sets of parentheses
(see %). It works with (), {}, and [], <>page 182:
Keystrokes | Buffer Contents
---------- +------------------------------------
`{start}` | cities = %w{London Berlin New\ York}
`dt{` | cities = {London Berlin New\ York}
`%` | cities = {London Berlin New\ York}
`r]` | cities = {London Berlin New\ York]
```` | cities = {London Berlin New\ York]
`r[` | cities = [London Berlin New\ York]
page 183:
set nocompatible
filetype plugin on
runtime macros/matchit.vim
The enhancements provided by this plugin are very useful, so I’d recommend
enabling it. Consult matchit-install
for more details.
Surround.vim
One of my favorite plugins is surround.vim by Tim Pope,[16] which makes wrapping a selection with a pair of delimiters easy. For example, we could put the words New York in quote marks:
Keystrokes | Buffer Contents
-----------+----------------------------------------
`{start}` | cities = ["London", "Berlin", @N@ew York]
`vee` | cities = ["London", "Berlin", New Yor@k@]
`S"` | cities = ["London", "Berlin", "New York"]
The S"
command is provided by surround.vim, and it can be read as “Surround
the selection with a pair of double quote marks.” We could just as easily use
S)
or S}
if we wanted to wrap the selection with opening and closing
parentheses or braces.
We can also use surround.vim to change existing delimiters. For example, we
could change {London} to [London] with the cs}]
command, which can be read as
“Change surrounding {} braces to [] brackets.” Or we could go the other way
with the cs]}
command. It’s a powerful plugin—check it out.
page 190:
= > :set path?
< = path=.,/usr/include,,
page 201:
:delete c
, and then we could paste it below the current line with
the :put c
command.page 202:
y{motion}
command, the specified text is copied not only
into the unnamed register but also into the yank register, which is addressed
by the 0 symbol (see quote0). As the name suggests, the yank register is set
only when we use the y{motion}
command.page 203:
page 204:
Keystrokes | Buffer Contents
-----------+----------------
`"+` | The X11 clipboard, used with cut, copy, and paste
`"*` | The X11 primary, used with middle mouse button
page 205:
Register | Contents
---------+---------
`"%` | Name of the current file
`"#` | Name of the alternate file
`".` | Last inserted text
`":` | Last Ex command
`"/` | Last search pattern
page 236:
Keystrokes Buffer | Contents
-------------------------+------------------
`:let i=1` | [p]artridge in a pear tree
`qa` | [p]artridge in a pear tree
`I<C-r>= i <CR> )<Esc>` | 1)[ ]partridge in a pear tree
`:let i += 1` | 1)[ ]partridge in a pear tree
`q` | 1)[ ]partridge in a pear tree
page 252:
page 256:
Keystrokes | Buffer Contents
------------------------+-----------------------------------------
`{start}` | Match "quoted words"---not quote marks.
`/\v"[^"]+" <CR>` | Match "quoted words"---not quote marks.
`/\v"\zs[^"]+\ze" <CR>` | Match "quoted words"---not quote marks.
page 259:
Escaping characters by hand is laborious, error-prone work. Fortunately, Vim script includes a library function that can do the hard work for us: escape({string}, {chars}) (see escape() i). The {chars} argument specifies which characters must be escaped with a backslash. If we’re searching forward, we could call escape(@u, ’/\’), which would prefix each / and \ character with a backslash. If we were searching backward, we could instead call escape(@u, ’?\’).
First, make sure that the URL we want to search for is still stored in the u
register. Then we’ll bring up the search prompt by pressing / or ?; either one
will work just fine. Enter the \V literal switch and then type
=> escape(@u, getcmdtype().'\')
page 263:
Command | Effect
--------+----------------------------------------------------
`n` | Jump to next match, preserving direction and offset
`N` | Jump to previous match, preserving direction and offset
`/<CR>` | Jump forward to next match of same pattern
`?<CR>` | Jump backward to previous match of same pattern
`gn` | Enable character-wise Visual mode and select next search match
`gN` | Enable character-wise Visual mode and select previous search match
page 268:
n
a couple of times, we realize that we’d prefer to place
the cursor at the end of the match. That’s no problem: we could simply run
//e<CR>
. When we leave the search field blank like this, Vim reuses the
pattern from the previous search. So this repeats the last search but with an
offset.page 273:
q/
brings up command mode with search history
//
runs the last search
visual-star.vim
xnoremap * :<C-u>call <SID>VSetSearch(' /')<CR>/<C-R>=@/<CR><CR>
xnoremap # :<C-u>call <SID>VSetSearch(' ?')<CR>?<C-R>=@/<CR><CR>
function! s:VSetSearch(cmdtype)
let temp = @s
norm! gv"sy
let @/ = '\V' . substitute(escape(@s, a:cmdtype.' \'), '\ n ' , '\\n ' , 'g' )
let @s = temp
endfunction
page 281:
n
flag suppresses the usual substitute behavior, causing the command to
report the number of occurrences that would be affected if we ran the
substitute command. Tip 86, gives an example of usage.page 282:
&
flag simply tells Vim to reuse the same flags from the previous
substitute command.Symbol | Represents
-----------------+-------------------------
`\r` | Insert a carriage return
`\t` | Insert a tab character
`\\` | Insert a single backslash
`\1` | Insert the first submatch
`\2` | Insert the second submatch (and so on, up to \9)
`\0` | Insert the entire matched pattern
`&` | Insert the entire matched pattern
`~` | Use {string} from the previous invocation of :substitute
`\={Vim script}` | Evaluate {Vim script} expression; use result as replacement {string}
page 284:
:%s/going/rolling/g
page 285:
Trigger | Effect
--------+----------------------
`y` | Substitute this match
`n` | Skip this match
`q` | Quit substituting
`l` | “last”—Substitute this match, then quit
`a` | “all”—Substitute this and any remaining matches
`<C-e>` | Scroll the screen up
`<C-y>` | Scroll the screen down
page 287:
Leaving the search field of the substitute command blank instructs Vim to reuse the most recent search pattern.
allows us to select any text in our document and then hit the *
key to
search for the selection. We could then run the substitute command with an
empty search field to replace our selection
page 288:
<C-r>/
at the command line pastes the contents of the last search
register in place.page 290:
=> :%s/Pragmatic Vim/Practical Vim/g
=> :let @/='Pragmatic Vim'
=> :let @a='Practical Vim'
=> :%s//\=@a/g
:let @/=’Pragmatic Vim’
is a programmatic way of setting the search
pattern. It has the same effect as executing the search /Pragmatic Vim<CR>
(except that running :let @/=’Pragmatic Vim’
does not create a record in the
search history).
Likewise, :let @a=’Practical Vim’ sets the contents of the a register.
page 292:
:%s//~/&
This longhand command spells out the following instruction: repeat the last substitute command using the same flags, the same replacement string, and the current search pattern, but use the % range. In other words, repeat the last substitution across the entire file.
page 294:
:&&
command. It doesn’t matter what range was used the last time. :&&
by itself
acts on the current line, :’<,’>&&
acts on the visual selection, and :%&&
acts on the entire file. As we saw already, the g&
command is a handy
shortcut for :%&&
.page 295:
&
command is a synonym for :s, which repeats the last substitution.
Unfortunately, if any flags were used, the &
command disregards them, meaning
that the outcome could be quite different from the previous substitution.
Making &
trigger the :&&
command is more useful. It preserves flags and
therefore produces more consistent results. These mappings fix the &
command
in Normal mode and create a Visual mode equivalent:nnoremap & :&&<CR>
xnoremap & :&&<CR>
page 296:
last name,first name,email
neil,drew,drew@vimcasts.org
doe,john,john@example.com
=> `/\v^([^,]*),([^,]*),([^,]*)$`
=> `:%s//\3,\2,\1`
In the pattern, [^,] matches anything that isn’t a comma. So ([^,]*) matches zero or more consecutive non-commas and captures the result as a submatch
The result of running this command looks like this:
email,first name,last name
drew@vimcasts.org,drew,neil
john@example.com,john,doe
page 298:
Arithmetic on searches:
:%s//\=submatch(0)-1/g
page 299:
=> :let swapper={"dog":"man","man":"dog"}
=> :echo swapper["dog"]
<= man
=> :echo swapper["man"]
<= dog
When we pass “dog” as a key to our swapper dictionary, it returns “man”, and vice versa.
swapping 2 (or more) words with substitute
=> /\v(<man>|<dog>)
=> :%s//\={"dog":"man","man":"dog"}[submatch(1)]/g
page 306:
The :global
command takes the following form (see :g):
:[range] global[!] /{pattern}/ [cmd]
The default range for the :global command is the entire file (%). That sets it apart from most other Ex commands, including :delete, :substitute, and :normal, whose range is the current line (. ) by default.
The {pattern} field integrates with search history. That means we can leave it blank and Vim will automatically use the current search pattern.
The [cmd] could be any Ex command except for another :global command.
We can invert the behavior of the :global
command either by running
:global!
or :vglobal
(mnemonic: invert). Each of these tells Vim to execute
[cmd] on each line that doesn’t match the specified pattern.
On the Etymology of Grep
Consider this abbreviated form of the :global command:
:g/re/p
re stands for regular expression, and p is short for :print, which is the default [cmd]. If we ignore the / symbols, we find the word “grep.”
page 308:
Just like with the :substitute command, we can leave the search field of the :global command blank, and Vim will reuse the last search pattern
:v/href/d
(:vglobal) can be read as “Delete each line that doesn’t contain
href.”
page 309:
:g/TODO
page 310:
qaq
. Let’s break that down: qa
tells Vim to start recording a macro into
the a register, and then q
stops the recording. We didn’t type anything while
the macro was recording, so the register ends up empty. We can check that by
running the following::reg a
--- Registers ---
"a
:g/TODO/yank A
:reg a
"a TODO: Cache this regexp for certain depths.
TODO: No matching end code found - warn!
The trick here is that we’ve addressed our register with an uppercase A. That tells Vim to append to the specified register
Here’s an alternative solution: :g/TODO/t$
It uses the :t
command, which we met in Tip 29. Rather than appending each
TODO item to a register, we simply copy it to the end of the file. After
running this command, we could jump to the end of the file to review the TODO
items. This technique is more straightforward because it avoids messing around
with registers. But it won’t work as neatly with the :argdo
and :bufdo
commands.
page 312:
page 313:
:g/{/ .+1,/}/-1 sort
The { pattern matches the first line of each {} block. For every line that matches, the :sort command is executed on a [range] that terminates at the end of the {} block. The end result is that all CSS properties are alphabetized within each block of rules.
A generalized form of this :global command goes like this: :g/{start}/ .,{finish} [cmd]
We can read this as “For each range of lines beginning with {start} and ending with {finish}, run the specified [cmd].”
page 317:
page 337:
‘:compiler’ and ‘:make’ Are Not Just for Compiled Languages
The words make and compile have particular meanings in the context of a compiled programming language. But in Vim, the corresponding :make and :compile commands have more flexible definitions, making them just as applicable for interpreted languages and markup formats.
For example, when working on a LaTeX document, we can configure Vim so that the :make command compiles our .tex file into a PDF. Or if we’re working with an interpreted language such as JavaScript, we can have :make run our source code through JSLint or some other (less opinionated) syntax checker. Alternatively, we could set up :make so that it runs the test suite.
In Vim’s terminology, a compiler is any external program that does something with our document and produces a list of errors or warnings. The :make command simply invokes the external compiler and then parses the output to construct a navigable quickfix list from them.
page 345:
vimgrep
:vimgrep /TERM/ %
searches in the open file
:vimgrep /TERM/g %
matches beyond the first per line (global)
:copen
brings up the matches,
:cnext
and :cprevious
cycle through matches
page 346:
This is the format of the :vimgrep command (:vimgrep): :vim[grep][!] /{pattern}/[g][j] {file}
As well as being able to use * and ** wildcards, we can use the ## symbol, which is expanded to represent the names of each file in the argument list (cmdline-special i). This allows for an alternative workflow. First, we populate the argument list with the files we want to inspect. Then we run :vimgrep across each of the files in the argument list:
=> :args *.txt
=> :vim /going/g ##
:set ignorecase&