Vim Reference Guide is intended as a concise learning resource for beginner to intermediate level Vim users. It has more in common with cheatsheets than a typical text book. Most features are presented using a sample usage. Topics like Regular Expressions and Macros have more detailed explanations and examples due to their complexity.
The features covered in this guide are shaped and limited by my own experiences since 2007. Fourteen years would seem a long time to have already become an expert, but I'm not there yet (nor do I have a pressing need for such expertise). The earlier version of this guide was written five years back and I still took more than three months to get it fit for publication. A large portion of that time was spent correcting my understanding of Vim commands, going through user and reference manuals, getting good at using built-in help, learning more features and so on.
I do give a brief introduction to get started with using Vim, but having prior experience would be ideal before using this resource. As a minimum requirement, you should be able to use vimtutor
on your own.
See my Vim curated list for links to tutorials, books, interactive resources, cheatsheets, tips, tricks, forums and so on.
git
command, click the Code button on the webpage to get the files.I would highly appreciate if you'd let me know how you felt about this book, it would help to improve this book as well as my future attempts. Also, please do let me know if you spot any error or typo.
Issue Manager: https://github.com/learnbyexample/vim_reference/issues
E-mail: learnbyexample.net@gmail.com
Twitter: https://twitter.com/learn_byexample
Sundeep Agarwal is a lazy being who prefers to work just enough to support his modest lifestyle. He accumulated vast wealth working as a Design Engineer at Analog Devices and retired from the corporate world at the ripe age of twenty-eight. Unfortunately, he squandered his savings within a few years and had to scramble trying to earn a living. Against all odds, selling programming ebooks saved his lazy self from having to look for a job again. He can now afford all the fantasy ebooks he wants to read and spends unhealthy amount of time browsing the internet.
When the creative muse strikes, he can be found working on yet another programming ebook (which invariably ends up having at least one example with regular expressions). Researching materials for his ebooks and everyday social media usage drowned his bookmarks, so he maintains curated resource lists for sanity sake. He is thankful for free learning resources and open source tools. His own contributions can be found at https://github.com/learnbyexample.
List of books: https://learnbyexample.github.io/books/
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License
Code snippets are available under MIT License
Resources mentioned in Acknowledgements section above are available under original licenses.
1.0
See Version_changes.md to track changes across book versions.
Back in 2007, I had a rough beginning as a design engineer at a semiconductor company in terms of software tools. Linux command line, Vim and Perl were all new to me. I distinctly remember progressing from dd (delete current line) to d↓ (delete current line as well as the line below) and feeling happy that it reduced time spent on editing. Since I was learning on the job, I didn't know about count prefix or the various ways I could've deleted all the lines from the beginning of the file to the line containing a specific phrase. Or even better, I could've automated editing multiple files if I had been familiar with sed
or progressed that far with Perl.
I also remember that we got a two-sided printed cheatsheet that we kept pinned to our cabins. That was one of the ways I kept adding commands to my repertoire. But, I didn't have a good insight to Vim's philosophy and I didn't know how to apply many of the cheatsheet commands. At some point, I decided to read the Vim book by Steve Oualline and that helped a lot, but it was also too long and comprehensive for me to read it all. My memory is hazy after that, and I don't recall what other resources I used. However, I'm sure I didn't effectively utilize built-in help. Nor did I know about stackoverflow or /r/vim until after I left my job in 2014.
Still, I knew enough to conduct a few Vim learning sessions for my colleagues. That came in handy when I got chances to teach Vim as part of scripting course for college students. From 2016 to 2018, I started maintaining my tutorials on Linux command line, Vim and scripting languages as GitHub repos. As you might guess, I then started polishing these materials and published them as ebooks. This is an ongoing process, with Vim Reference Guide being the twelfth ebook.
You've probably already heard that Vim is a text editor, powerful one at that. Vim's editing features feel like a programming language and you can customize the editor using scripting languages. Apart from plethora of editing commands and support for regular expressions, you can also incorporate external commands. To sum it up, most editing tasks can be managed from within Vim itself instead of having to write a script.
Now, you might wonder, what is all this need for complicated editing features? Why does a text editor require programming capabilities? Why is there even a requirement to learn how to use a text editor? Isn't it enough to have the ability to enter text, use Backspace/Delete/Home/End/Arrow/etc, menu and toolbar, some shortcuts, a search and replace feature and so on? A simple and short answer — to reduce repetitive manual task.
What I like the most about Vim:
There's a huge ecosystem of plugins, packages and colorschemes as well, but I haven't used them much. I've used Vim for a long time, but not really a power user. I prefer using GVim, tab pages, mouse, arrow keys, etc. So, if you come across tutorials and books suggesting you should avoid using them, remember that they are subjective preferences.
Here are some more opinions by those who enjoy using Vim:
Should everybody use Vim? Is it suitable for all kinds of editing tasks? I'd say no. There are plenty of other well established text editors and new ones are coming up all the time. The learning curve isn't worth it for everybody. If Vim wasn't being used at job, I probably wouldn't have bothered with it. Don't use Vim for the wrong reasons article discusses this topic in more detail.
I use the following command on Ubuntu (a Linux distribution):
sudo apt install vim vim-gui-common
See also https://github.com/vim/vim for source code and other details.
Open a terminal and follow these steps:
gvim ip.txt
opens a file named ip.txt
for editing
vim
if you prefer terminal instead of GUI, or if gvim
is not availablei
, not some alien key)cat ip.txt
— sanity check to see what you typed is saved or notPhew, what a complicated procedure to write a simple line of text, isn't it? This is the most challenging and confusing part for a Vim newbie. Here's a brief explanation of the above steps:
If you launched GVim, you'll likely have Menu and Tool bars, which would've helped with operations like saving, quitting, etc. Nothing wrong with using them, but this book will not discuss those operations. In fact, you'll learn how to configure Vim to hide them in the Customizing Vim chapter.
Don't proceed any further if you aren't comfortable with the above steps. Take help of youtube videos if you must. Master this basic procedure and you will be ready for Vim awesomeness that'll be discussed in the coming sections and chapters.
Material presented here is based on GVim (GUI), which has a few subtle differences compared to Vim (TUI). See this stackoverflow thread for more details.
Options and details related to opening Vim from the command line will be discussed in the CLI options chapter.
gvimtutor
command that opens a tutorial session with lessons to get started with Vim
vimtutor
if gvim
is not available
Next step is :h usr_02.txt, which provides enough information about editing files with Vim.
Vim comes with comprehensive user and reference manuals. The user manual reads like a text book and reference manual has more details than you are likely to need. There's also an online site with these help contents, which will be linked as appropriate throughout this book.
Help
menuHere's a neat table from :h help-context:
WHAT | PREPEND | EXAMPLE |
---|---|---|
Normal mode command | :help x |
|
Visual mode command | v_ |
:help v_u |
Insert mode command | i_ |
:help i_<Esc> |
Command-line command | : |
:help :quit |
Command-line editing | c_ |
:help c_<Del> |
Vim command argument | - |
:help -r |
Option | ' |
:help 'textwidth' |
Regular expression | / |
:help /[ |
You can go through a copy of the documentation online at https://vimhelp.org/. As shown above, all the :h hints in this book will also be linked to the appropriate online help section.
As mentioned in the Preface chapter, this Vim Reference Guide is more like a cheatsheet instead of a typical book for learning Vim. In addition to built-in features already mentioned in the previous sections, here are some resources you can use:
Tutorials
Books
Interactive
See my Vim curated list for a more complete list of learning resources, cheatsheets, tips, tricks, forums, etc.
As mentioned earlier, Vim is a modal editor. This book will mainly discuss these four modes:
This section provides a brief description for these modes. Separate chapters will discuss their features in more detail.
For a complete list of modes, see :h vim-modes-intro and :h mode-switching.
Insert mode
This is the mode where the required text is typed. There are also commands available for moving around, deleting, autocompletion, etc.
Pressing the Esc key takes you back to Normal mode.
Normal mode
This is the default mode when Vim is opened. This mode is used to run commands for operations like cut, copy, paste, recording, moving around, etc. This is also known as the Command mode.
Visual mode
Visual mode is used to edit text by selecting them first. Selection can either be done using mouse or using visual commands.
Pressing the Esc key takes you back to the Normal mode.
Command-line mode
This mode is used to perform file operations like save, quit, search, replace, execute shell commands, etc. Any operation is completed by pressing the Enter key after which the mode changes back to the Normal mode. The Esc key can be used to ignore whatever is typed and return to the Normal mode.
The space at the end of the file used for this mode is referred to as Command-line area. It is usually a single line, but can expand for cases like auto completion, shell commands, etc.
|
cursor
-- INSERT --
can be seen on the left hand side of the Command-line area-- VISUAL --
or -- VISUAL LINE --
or -- VISUAL BLOCK --
according to the visual command used
See also :h 'showmode' setting.
Commands discussed in this section will be covered again in later chapters. The idea here is to give you a brief introduction to modes and notable Vim features. See also:
- Best introduction to Vi and its core editing concepts explained as a language (this stackoverflow thread also has numerous Vim tips and tricks)
- Seven habits of effective text editing
As a programmer, I love how composable Vim commands are. For example, you can do this in Normal mode:
d
is the delete command awaiting further instructionG
is a motion command to move to the last line of the filey
is the yank (copy) command awaiting further instructionMost Normal mode commands accept a count prefix. For example:
3
to the number under the cursorThere are context aware operations too. For example:
{}
including the {}
charactersIf you are a fan of selecting text before editing them, you can use the Visual mode. There are several commands you can use to start Visual mode. If enabled, you can even use mouse to select the required portions.
1
for the first line, by 2
for the second line, by 3
for the third line and so onThe Command-line mode is useful for file level operations, search and replace, changing Vim configurations, talking to external commands and so on.
call
animal
with mammal
only for the lines containing cat
3
to 8
(uses external command sort
)Changes to Vim configurations from the Command-line mode are applicable only for that particular session. You can use the vimrc
file to load the settings at startup.
8
)teh
to the
in Insert modeThere are many more Vim features that'd help you with text processing and customizing the editor to your needs, some of which you'll get to know in the coming chapters.
Finally, you can apply your Vim skills elsewhere too. Vim-like features have been adopted across a huge variety of applications and plugins, for example:
See Where Vim Came From if you are interested in knowing Vim's history that traces back to the 1960s with qed
, ed
, etc.
Here's the list of remaining chapters:
This is the mode where the required text is typed. There are also commands available for moving around, deleting, autocompletion, etc.
Documentation links:
Recall that you need to add
i_
prefix for built-in help on Insert mode commands, for example :h i_CTRL-P.
You can use the
whichwrap
setting (ww
for short) to allow ← and → arrow keys to cross lines. For example, :set ww+=[,] tells Vim to allow left and right arrow keys to move across lines in Insert mode (+=
is used here to preserve existing options for thewhichwrap
setting).
If more than one word matches, they are displayed using a popup menu. You can use ↑/↓ arrow keys or Ctrl+p/Ctrl+n to move through this list.
With multiple matches, you'll notice that the first match is automatically inserted and moving through the list doesn't change the text that was inserted. You'll have to press Ctrl+y or Enter key to choose a different completion text. If you were satisfied with the first match, typing any character will make the popup menu disappear and insert whatever character you had typed. Or press Esc to select the first match and go to Normal mode.
If more than one line matches, they are displayed using a popup menu. You can use ↑/↓ arrow keys or Ctrl+p/Ctrl+n to move through this list. You can also use Ctrl+l to move up the list.
See :h ins-completion for more details and other autocomplete features. See :h 'complete' setting for customizing autocomplete commands.
Indentation depends on the
shiftwidth
setting. See :h 'shiftwidth' for more details.
"a
register1024
2022/02/02
From :h 24.6:
If the register contains characters such as
<BS>
or other special characters, they are interpreted as if they had been typed from the keyboard. If you do not want this to happen (you really want the<BS>
to be inserted in the text), use the commandCTRL-R CTRL-R {register}
.
Registers will be discussed in more details in the Normal mode chapter. See :h usr_41.txt to get started with Vim script.
^[
^M
You'll see a practical usage of this command in Macro chapter. You can also specify the character using decimal, octal or hexadecimal formats. See :h 24.8 for more details.
¥
You can use :digraphs to get a list of combinations and their respective characters. You can also define your own combinations using the :digraph command. See :h 24.9 for more details.
Make sure you are in Normal mode before trying out the commands in this chapter. Press Esc key to return to Normal mode from other modes. Press Esc again if needed.
Documentation links:
The four arrow keys can be used in Vim to move around, just like other text editors. Vim also maps them to four characters in Normal mode.
Vim offers plenty of other motion commands. Several sections will discuss them later in this chapter.
You can use the
whichwrap
setting to allow ← and → arrow keys to cross lines. For example, :set ww+=<,> tells Vim to allow left and right arrow keys to move across lines in Normal and Visual modes. Addh
andl
to this comma separated list if want those commands to cross lines as well.
There are various ways to delete text. All of these commands can be prefixed with a count value. d
and c
commands can accept any motion commands. Only arrow motion examples are shown in this section, many more variations will be discussed later in this chapter.
whichwrap
setting as discussed earlierautoindent
settingautoindent
setting
You can also select text (using mouse or visual commands) and then press d or x or c or s to delete the selected portions. Example usage will be discussed in the Visual mode chapter.
The deleted portions can also be pasted elsewhere using the paste command (discussed later in this chapter).
There are various ways to copy text using the yank command y
.
You can also select text (using mouse or visual commands) and then press y to copy them.
The put (paste) command p
is used after cut or copy operations.
See :h 32.3 for details on g- and g+ commands that you can use to undo branches.
Often, you just need to change one character. For example, changing i
to j
, 2
to 4
and so on.
j
y
aaa
To replace multiple characters with different characters, use R
.
lion
R
commandThe advantage of r
and R
commands is that you remain in the Normal mode, without needing to switch to Insert mode and back.
2dd
5x
123
and go back to Normal modeFrom :h 4.3:
The . command works for all changes you make, except for u (undo), CTRL-R (redo) and commands that start with a colon (
:
).
See :h repeat.txt for complex repeats, using Vim scripts, etc.
Indentation of the new line depends on
autoindent
,smartindent
andcindent
settings.
Moving within long lines that are spread over multiple screen lines:
See :h left-right-motions for more details.
These commands allow you to move based on single character search, within the current line only.
(
b
"
;
x
a
a
f
or F
or t
or T
motion in the same directionf
or F
or t
or T
motion in the opposite direction
Note that the previously used count prefix wouldn't be repeated with ; or , commands, but you can use a new count prefix. If you pressed a wrong motion command, use the Esc key to abandon the search instead of continuing with the wrongly chosen command.
Definitions from :h word and :h WORD are quoted below to explain the difference between word and WORD.
word A word consists of a sequence of letters, digits and underscores, or a sequence of other non-blank characters, separated with white space (spaces, tabs,
<EOL>
). This can be changed with theiskeyword
option. An empty line is also considered to be a word.
WORD A WORD consists of a sequence of non-blank characters, separated with white space. An empty line is also considered to be a WORD.
192.1.168.43;hello
is considered as a single WORD, but has multiple words
All of these motions will work across lines. For example, if the cursor is on the last word of a line, pressing w will move to the start of the first word in the next line.
More such text objects will be discussed later under the Context editing section. See :h object-motions for a complete list of such motions.
()
, {}
and []
matchpairs
option to customize the matching pairs. For example, :set matchpairs+=<:> will match <>
as well
It is also possible to match a pair of keywords like HTML tags, if-else, etc with %. See :h matchit-install for details.
See :h 'scrolloff' option if you want to always show context around the current line.
d
or y
ip
later in the Context editing section)
Indentation depends on the
shiftwidth
setting. See :h shift-left-right, :h = and :h 'shiftwidth' for more details.
You can indent/unindent the same selection multiple times using a number prefix in the Visual mode.
a
a
a
A
(this will work for any file where the mark was set)a
d
, y
, >
, etc
Motion commands that take you across lines (for example, 10G) will automatically save the location you jumped from in the default
`
mark. You can move back to that exact location using``
or the first non-blank character using'`
. Note that the arrow and word motions aren't considered for the default mark even if they move across lines.
See :h mark-motions for more ways to use marks.
This is helpful if you are moving around often while editing a large file, moving between different buffers, etc. From :h jump-motions:
The following commands are jump commands:
'
,`
,G
,/
,?
,n
,N
,%
,(
,)
,[[
,]]
,{
,}
,:s
,:tag
,L
,M
,H
and the commands that start editing a new file.When making a change the cursor position is remembered. One position is remembered for every change that can be undone, unless it is close to a previous change.
o
as in old)i
and o
are usually next to each other)
Use :jumps and :changes to view the jump and change lists respectively. See :h jump-motions for more details.
From :h usr_03.txt:
You first type an operator command. For example, d is the delete operator. Then you type a motion command like 4l or w. This way you can operate on any text you can move over.
a
()
, {}
, []
, etcc
in the same lineFrom :h usr_03.txt:
Whether the character under the cursor is included depends on the command you used to move to that character. The reference manual calls this "exclusive" when the character isn't included and "inclusive" when it is. The $ command moves to the end of a line. The d$ command deletes from the cursor to the end of the line. This is an inclusive motion, thus the last character of the line is included in the delete operation.
You have seen examples for combining motions such as w
, %
and f
with editing commands like d
, c
and y
. Such combination of commands require precise positioning to be effective.
Vim also provides a list of handy context based options to make certain editing use cases easier using the i
and a
text object selections. You can easily remember the difference between these two options by thinking i
as inner and a
as around.
()
and change to Insert mode
{}
including the {}
characters
You can use a count prefix for nested cases. For example, c2i{ will clear the inner braces (including the braces, and this could be nested too) and then only the text between braces for the next level.
See :h text-objects for more details.
You can use lowercase alphabets a-z
to save some content for future use. You can also append some more content to those registers by using the corresponding uppercase alphabets A-Z
at a later stage.
"a
register"a
register
"a
register"a
register"e
register
You can use :reg (short for
:registers
) to view the contents of the registers. Specifying one or more characters (next to each other as a single string) will display contents only for those registers.
The named registers are also used for saving macros (will be discussed in the Macro chapter). You can record an empty macro to clear the contents, for example qbq clears the
"b
register.
Vim has nine other types of registers for different use cases. Here are some of them:
"
all yanked/deleted text is stored in this register
"0
yanked text is stored in this register
"1
to "9
deleted contents are stored in these registers and get shifted with each new deletion
"+
this register is used to work with the system clipboard contents
"*
this register stores visually selected text
"_
black hole register, when you want to delete something without saving it anywhereFurther reading
the
, you'll also get matches for them
, lather
, etc
You can also provide a count prefix to these commands.
<EOL>
character is replaced with a space (unless there are trailing spaces or the next line starts with a )
character)<EOL>
character is deleted (space character won't be added)
![]()
joinspaces
,cpoptions
andformatoptions
settings will affect the behavior of these commands. See :h J and scroll down for more details.
You can also provide a count prefix to these commands.
3
to the number1000
from the number
Numbers prefixed with
0
,0x
and0b
will be treated as octal, hexadecimal and binary respectively (you can also use uppercase forx
andb
).
Decimal numbers prefixed with
-
will be treated as negative numbers. For example, using Ctrl+a on-100
will give you-99
. While this is handy, this trips me up often when dealing with date formats like 2021-12-07.
rot13
transformation
hello
word will change it to uryyb
uryyb
word will change it to hello
Normal to Insert mode
autoindent
settingNormal to Command-line mode
Normal to Visual mode
See :h mode-switching for a complete table.
Any operation in Command-line mode is completed by pressing the Enter key after which the mode changes back to the Normal mode. Press Esc key to ignore whatever is typed and return to the Normal mode.
Documentation links:
Recall that you need to add
:
orc_
prefix for built-in help on Command-line mode, for example :h :w and :h c_CTRL-R. Use single quotes around options, :h 'autoindent' for example.
:w
is short for :write
)w!
to create a new file if it doesn't exist:wa
is short for :wall
)
Appending
!
forces Vim to override errors, provided you have the appropriate permissions. For example, if you have edited a read-only file, :w will result in an error and :w! will save the changes. Another case where you'll get an error is :w filename if the file already exists. Using :w! filename will override the error.
By default, entire file content is used for these commands. You can use a range (discussed later in this chapter) to work with selective lines.
:q
is short for :quit
)
:qa
is short for :quitall
)
Append
!
to discard unsaved changes and quit.
Append
!
to override errors. Not all errors can be skipped, for example unsaved changes on a file that hasn't been named yet.
Multiple files can be opened in Vim within the same tab page and/or in different tabs. From :h windows-intro:
- A buffer is the in-memory text of a file.
- A window is a viewport on a buffer.
- A tab page is a collection of windows.
:e
is short for :edit
)e
and #
):bn
is short for :bnext
)
:bp
is short for :bprevious
)
Use :set hidden if you want to switch to another buffer even if there are unsaved changes in the current buffer. Instead of this setting, you can also use :hide edit filename to hide the current unsaved buffer. You'll still get an error if you try to quit Vim without saving such buffers, unless you use the
!
modifier.
See :h 'autowrite' option if you want to automatically save changes when moving to another buffer.
See :h 22.4 and :h buffer-hidden for user and reference manuals on working with buffer list.
:tabe
is short for :tabedit
)
filename
isn't specified, you'll get an unnamed empty window:tabn
is short for :tabnext
)
:tabp
is short for :tabprevious
)
:tabr
is short for :tabrewind
)
:tabl
is short for :tablast
)N
tabs from the start (:tabm
is short for :tabmove
)
N
positions to the rightN
positions to the left
Buffer list includes all the files opened in all the tabs.
You can also use the mouse to switch/move tabs in GVim.
hjkl
or arrow keys, switch in the respective directionHJKL
(uppercase), moves the current split to the farthest possible location in the respective direction
If filename is not provided, the current one is used.
Vim adds a highlighted horizontal bar containing the filename for each split.
If multiple buffers are open and you want to apply a common editing task for all of them, one option is to use the bufdo
command.
silent
skips displaying normal messages!
skips error messagessed
, awk
and perl
instead.
Further reading
From :h options.txt:
Vim has a number of internal variables and switches which can be set to achieve special effects. These options come in three forms:
- boolean can only be on or off
- number has a numeric value
- string has a string value
Here are examples for each of these forms:
+=
allows you to append to an existing string valueUsage guidelines:
set {option}
switch on the given boolean setting
set {option}!
toggle the given boolean setting
set inv{option}
can also be usedset no{option}
switch off the given boolean setting
set {option}?
get the current value of the given option (works for all three forms)
expandtab
or noexpandtab
depending on whether it is switched on or offset {option}
get the current value of number or string option
See :h options.txt for complete list of usage guidelines and available options.
/
for searching, n will move in the forward direction?
for searching, n will move in the backward directionBy default, the cursor is placed at the starting character of the match. There are various options to place the cursor at other locations:
b
(begin) instead of s
, but it'll change to s
after the command is executed2
characters after the start of the match (i.e. third character of the match)2
characters before the start of the match4
characters after the end of the match4
characters before the end of the match3
lines below the match3
lines above the matchHighlight settings:
hlsearch
settings:noh
is short for :nohlsearch
)
Using an empty pattern will repeat the last searched pattern. So, you can use something like //s+3 to repeat the last search with this new offset. Empty pattern can be used with substitution command as well (discussed later in this chapter). See :h last-pattern for more details.
You can prefix a count value to
/
,?
,n
andN
commands. Also, searching will automatically wrap around when it reaches the top or bottom of the file contents, unless you set thenowrapscan
option.
Characters like
.
,^
,$
, etc have special meaning in thesearchpattern
. These will be discussed in detail in the Regular Expressions chapter.
By default, certain commands like :d
and :s
apply to the current line whereas commands like :w
and :perldo
apply to the entire file. You can use range to change the lines that are acted upon.
:d
is short for :delete
command).
) to the given filename
:w
works on the entire file$
):m
is short for :move
command)
m
is the line number after which you want to place the lines specified by the range:t
(or :co
or :copy
) command if you want to copy instead of moving%
is a shortcut for 1,$
range)/
is used)
?pattern?
to find a match in the backward directionpat1
as well as the line after (total 2
lines)
;
will set the line matched by the first pair of the range as the current line for the second pairpat1
as well as two lines before (total 3
lines)pat1
after the fifth line
;
again here, the search will be based on the current cursor line if you use ,
instead of ;
a
to the line marked by b
If you press : after a visual selection, you'll automatically get
:'<,'>
as the visual range. If you prefix a number before pressing :, you'll get a range with that many lines — for example 10: will give you:.,.+9
as the range.
See :h 10.3 and :h cmdline-ranges for more details.
See :h ex-cmd-index for a complete list of
:
commands.
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
General syntax for s
command (short for substitute
) is shown above. Space between the range
and s
is optional, which you can use for readability.
a
with b
on the current line only
.
represents the current line)apple
with Mango
on the second line only
i
flag matches the searchpattern
case insensitivelycall
with jump
on lines 3
to 6
g
flag performs search and replace for all the matching occurrencescall
with jump
from the fifth line to the end of the filecall
in the file with jump
%
is a shortcut for the range 1,$
You can leave the
searchpattern
as empty to reuse the previously searched pattern, which could be from/
,?
,*
,s
command, etc. See :h last-pattern for more details.
See Regular Expressions chapter for more details on the substitute command.
:[range]g[lobal]/{pattern}/[cmd]
General syntax for g
command (short for global
) is shown above. This command is used to edit lines that are first filtered based on a searchpattern
. You can use g!
or v
to act on lines not satisfying the filtering condition.
call
d
Normal mode command, the deleted contents will be saved to the default "
register"a
register#
to the start of the filecall
only for the first five linesjump
animal
with mammal
only for the lines containing cat
20
lines only if the line starts with #
normal
when you need to use Normal mode commands on the filtered linesnormal!
if you don't want user defined mappings to be considered
In addition to the
/
delimiter, you can also use any single byte character other than alphabets,\
,"
or|
.
See :h :g for more details.
You can also use shell commands from within Vim (assuming you have access to these commands).
!
waits for motion similar to d
and y
commands, !G will give :.,$!%
is a shortcut for the range 1,$
:sort
command3
to 8
!
is not used here since there is no shell commandHelp
in the current file
%
here refers to current file contentsexit
command to quit the sessionsplitbelow
option is setsplitright
option is setN
here)
Depending on your shell, you can use the
exit
command to end the terminal session.Ctrl+d
might work too.
There are lot of features in this mode, see :h terminal.txt for more details.
0
, lines above and below the current line are assigned 1
, two lines above and below are assigned 2
and so on
See :h 5.9 for user manual about often used options.
sessionoptions
settingproj.vim
file
vim -S proj.vim
restore a session from the command line when launching Vim
See :h 21.4, :h views-sessions and :h 'sessionoptions' for more details.
See stackoverflow: How to save and restore multiple different sessions in Vim? for custom settings to automate the save and restore process and other tips and tricks. See also Learn-Vim: Views, Sessions, and Viminfo.
From :h 21.3:
After editing for a while you will have text in registers, marks in various files, a command line history filled with carefully crafted commands. When you exit Vim all of this is lost. But you can get it back! The
viminfo
file is designed to store status information:
- Command-line and Search pattern history
- Text in registers
- Marks for various files
- The buffer list
- Global variables
Each time you exit Vim it will store this information in a file, the
viminfo
file. When Vim starts again, theviminfo
file is read and the information restored.
The :mksession
command doesn't save the viminfo
file. You'll have to save and restore this file separately:
!
isn't used, you'll get a merged output based on the current internal Viminfo contents and the file contentsproj.viminfo
file
!
overwrites any existing internal settingsvim -i proj.viminfo
restore Viminfo from the command line when launching Vim
See :h viminfo-read-write for more details.
Once you are in Command-line mode (after typing :
or /
or ?
), you can use the commands discussed below. Many of these commands are similar to those available in the Insert mode.
"a
register1024
2022/02/02
wildmode
settingcpoptions
setting
See :h usr_20.txt for a nice tutorial on working effectively in the Command-line mode. See :h cmdline-editing and :h cmdline-completion for more details.
There are separate history lists for :
commands, searchpattern
, etc. These lists make it easy to reuse (after modifications if necessary) previously used commands.
See :h cmdline-history for more details. You can change the number of entries that are remembered using the
history
setting.
You can also view, edit and execute history of commands using a special Command-line window. You can open this special window from Normal mode as well as Command-line mode. This window will be in Normal mode by default, which will allow you to move around easily. You can also edit any of the history commands if you wish.
:
commands (from Normal mode):
or search pattern windows automatically, any text you've typed so far will be preserved as the most recent command
See :h cmdline-window for more details. You can change the number of entries that are remembered using the
history
setting.
Visual mode allows you to perform editing tasks on selected portions of text. There are various visual commands to select the text of interest. If enabled, you can also use your mouse to select the desired portions.
Documentation links:
Recall that you need to add
v_
prefix for built-in help on Visual mode commands, for example :h v_o.
Pressing $ in block selection will select until the end of lines for the selected area, even if the lines have different number of characters. This will continue to be the case if you extend the selection with up/down motions.
"
register
a
g
, s
, !
, normal
, etc on the selected text
Press Ctrl+c if you've typed text after using I or A but don't want to replicate the text across all the lines.
See :h visual-operators for complete list of commands.
c
c
with Normal mode motion, you'll have to first use n (or N depending on the direction) and then use the . command to repeat the change
Searching will automatically wrap around when it reaches the top or bottom of the file contents, unless you set the
nowrapscan
option.
Consider the following unindented code:
for(i=1; i<5; i++)
{
for(j=i; j<10; j++)
{
statements
}
statements
}
Here's the result after applying vip= (you can also use =ip if you prefer Normal mode).
for(i=1; i<5; i++)
{
for(j=i; j<10; j++)
{
statements
}
statements
}
For block selection, space will be inserted before the starting column of the block.
Indentation depends on the
shiftwidth
setting. See :h shift-left-right, :h = and :h 'shiftwidth' for more details.
1
5
1
1
for the first line, by 2
for the second line, by 3
for the third line and so on2
for the first line, by 4
for the second line, by 6
for the third line and so on (i.e. repeat the process specified by the count prefix)1
for the first line, by 2
for the second line, by 3
for the third line and so on
The visual selection should cover the numeric portion you wish to increment or decrement. If there are multiple numbers in a visually selected line, only the first number will be affected.
Example for g followed by Ctrl+a:
# before
item[0]
item[0]
item[0]
# after
item[1]
item[2]
item[3]
Example for g followed by Ctrl+x:
# before
item[12]
item[16]
item[22]
# after
item[11]
item[14]
item[19]
Example for 3g followed by Ctrl+a:
# before
item[12]
item[16]
item[22]
# after
item[15]
item[22]
item[31]
This chapter will discuss regular expressions (regexp) and related features in detail. As discussed in earlier chapters:
/searchpattern
search the given pattern in the forward direction?searchpattern
search the given pattern in the backward direction:range s/searchpattern/replacestring/flags
search and replace
:s
is short for :substitute
commandreplacestring
is optional if you are not using flagsDocumentation links:
:substitute
command
Recall that you need to add
/
prefix for built-in help on regular expressions, :h /^ for example.
g
replace all occurrences within a matching line
c
ask for confirmation before each replacementi
ignore case for searchpattern
I
don't ignore case for searchpattern
These flags are applicable for the substitute command but not /
or ?
searches. Flags can also be combined, for example:
s/cat/Dog/gi
replace every occurrence of cat
with Dog
Cat
, cAt
, CAT
, etc will also be replacedi
doesn't affect the case of the replacement string
See :h s_flags for a complete list of flags and more details about them.
By default, regexp will match anywhere in the text. You can use line and word anchors to specify additional restrictions regarding the position of matches. These restrictions are made possible by assigning special meaning to certain characters and escape sequences. The characters with special meaning are known as metacharacters in regular expressions parlance. In case you need to match those characters literally, you need to escape them with a \
(discussed in Escaping metacharacters section later in this chapter).
^
restricts the match to the start-of-line
^This
matches This is a sample
but not Do This
$
restricts the match to the end-of-line
)$
matches apple (5)
but not def greeting():
^$
match empty line\<pattern
restricts the match to the start of a word
\<his
matches his
or to-his
or history
but not this
or _hist
pattern\>
restricts the match to the end of a word
his\>
matches his
or to-his
or this
but not history
or _hist
\<pattern\>
restricts the match between start of a word and end of a word
\<his\>
matches his
or to-his
but not this
or history
or _hist
End-of-line can be
\r
(carriage return),\n
(newline) or\r\n
depending on your system andfileformat
setting.
See :h pattern-atoms for more details.
.
match any single character other than end-of-line
c.t
matches cat
or cot
or c2t
or c^t
or c.t
or c;t
but not cant
or act
or sit
\_.
match any single character, including end-of-line
As seen above, matching end-of-line character requires special attention. Which is why examples and descriptions in this chapter will assume you are operating line wise unless otherwise mentioned. You'll later see how
\_
is used in many more places to include end-of-line in the matches.
Quantifiers can be applied to literal characters, dot metacharacter, groups, backreferences and character classes. Basic examples are shown below, more will be discussed in the sections to follow.
*
match zero or more times
abc*
matches ab
or abc
or abccc
or abcccccc
but not bc
Error.*valid
matches Error: invalid input
but not valid Error
s/a.*b/X/
replaces table bottle bus
with tXus
since a.*b
matches from the first a
to the last b
\+
match one or more times
abc\+
matches abc
or abccc
but not ab
or bc
\?
match zero or one times
\=
can also be used, helpful if you are searching backwards with the ?
commandabc\?
matches ab
or abc
. This will match abccc
or abcccccc
as well, but only the abc
portions/abc\?/X/
replaces abcc
with Xc
\{m,n}
match m
to n
times (inclusive)
ab\{1,4}c
matches abc
or abbc
or xabbbcz
but not ac
or abbbbbc
\{m,n\}
(ending brace is escaped)\{m,}
match at least m
times
ab\{3,}c
matches xabbbcz
or abbbbbc
but not ac
or abc
or abbc
\{,n}
match up to n
times (including 0
times)
ab\{,2}c
matches abc
or ac
or abbc
but not xabbbcz
or abbbbbc
\{n}
match exactly n
times
ab\{3}c
matches xabbbcz
but not abbc
or abbbbbc
Greedy quantifiers will consume as much as possible, provided the overall pattern is also matched. That's how the Error.*valid
example worked. If .*
had consumed everything after Error
, there wouldn't be any more characters to try to match valid
. How the regexp engine handles matching varying amount of characters depends on the implementation details (backtracking, NFA, etc).
See :h pattern-overview for more details.
If you are familiar with other regular expression flavors like Perl, Python, etc, you'd be surprised by the use of
\
in the above examples. If you use\v
very magic modifier (discussed later in this chapter), the\
won't be needed.
Non-greedy quantifiers match as minimally as possible, provided the overall pattern is also matched.
\{-}
match zero or more times as minimally as possible
s/t.\{-}a/X/g
replaces that is quite a fabricated tale
with XX fabricaXle
tha
, t is quite a
and ted ta
s/t.*a/X/g
replaces that is quite a fabricated tale
with Xle
since *
is greedy\{-m,n}
match m
to n
times as minimally as possible
m
or n
can be left out as seen in the Greedy Quantifiers sections/.\{-2,5}/X/
replaces 123456789
with X3456789
(here .
matched 2 times)s/.\{-2,5}6/X/
replaces 123456789
with X789
(here .
matched 5 times to satisfy overall pattern)
See :h pattern-overview and stackoverflow: non-greedy matching for more details.
To create a custom placeholder for a limited set of characters, you can enclose them inside []
metacharacters. Character classes have their own versions of metacharacters and provide special predefined sets for common use cases.
[aeiou]
match any lowercase vowel character[^aeiou]
match any character other than lowercase vowels[a-d]
match any of a
or b
or c
or d
-
can be applied between any two characters\a
match any alphabet character [a-zA-Z]
\A
match other than alphabets [^a-zA-Z]
\l
match lowercase alphabets [a-z]
\L
match other than lowercase alphabets [^a-z]
\u
match uppercase alphabets [A-Z]
\U
match other than uppercase alphabets [^A-Z]
\d
match any digit character [0-9]
\D
match other than digits [^0-9]
\o
match any octal character [0-7]
\O
match other than octals [^0-7]
\x
match any hexadecimal character [0-9a-fA-F]
\X
match other than hexadecimals [^0-9a-fA-F]
\h
match alphabets and underscore [a-zA-Z_]
\H
match other than alphabets and underscore [^a-zA-Z_]
\w
match any word character (alphabets, digits, underscore) [a-zA-Z0-9_]
\W
match other than word characters [^a-zA-Z0-9_]
\s
match space and tab characters [ \t]
\S
match other than space and tab characters [^ \t]
Here are some examples with character classes:
c[ou]t
matches cot
or cut
\<[ot][on]\>
matches oo
or on
or to
or tn
as whole words only^[on]\{2,}$
matches no
or non
or noon
or on
etc as whole lines onlys/"[^"]\+"/X/g
replaces "mango" and "(guava)"
with X and X
s/\d\+/-/g
replaces Sample123string777numbers
with Sample-string-numbers
s/\<0*[1-9]\d\{2,}\>/X/g
replaces 0501 035 26 98234
with X 035 26 X
(matches numbers >=100 with optional leading zeros)s/\W\+/ /g
replaces load2;err_msg--\ant
with load2 err_msg ant
To include the end-of-line character, use
\_
instead of\
for any of the above escape sequences. For example,\_s
will help you match across lines. Similarly, use\_[]
for bracketed classes.
![]()
The above escape sequences do not have special meaning within bracketed classes. For example,
[\d\s]
will only match\
ord
ors
. You can use named character sets in such scenarios. For example,[[:digit:][:blank:]]
to match digits or space or tab characters. See :h :alnum: for full list and more details.
The predefined sets are also better in terms of performance compared to bracketed versions. And there are more such sets than the ones discussed above. See :h character-classes for more details.
Alternation helps you to match multiple terms and they can have their own anchors as well (since each alternative is a regexp pattern). Often, there are some common things among the regular expression alternatives. In such cases, you can group them using a pair of parentheses metacharacters. Similar to a(b+c)d = abd+acd
in maths, you get a(b|c)d = abd|acd
in regular expressions.
\|
match either of the specified patterns
min\|max
matches min
or max
one\|two\|three
matches one
or two
or three
\<par\>\|er$
matches whole word par
or a line ending with er
\(pattern\)
group a pattern to apply quantifiers, create a terser regexp by taking out common elements, etc
a\(123\|456\)b
is equivalent to a123b\|a456b
hand\(y\|ful\)
matches handy
or handful
hand\(y\|ful\)\?
matches hand
or handy
or handful
\(to\)\+
matches to
or toto
or tototo
and so onre\(leas\|ceiv\)\?ed
matches reed
or released
or received
There's some tricky situations when using alternation. Say, you want to match are
or spared
— which one should get precedence? The bigger word spared
or the substring are
inside it or based on something else? The alternative which matches earliest in the input gets precedence, irrespective of the order of the alternatives.
s/are\|spared/X/g
replaces rare spared area
with rX X Xa
s/spared\|are/X/g
will also give the same resultsIn case of matches starting from the same location, for example spa
and spared
, the leftmost alternative gets precedence. Sort by longest term first if don't want shorter terms to take precedence.
s/spa\|spared/**/g
replaces spared spare
with **red **re
s/spared\|spa/**/g
replaces spared spare
with ** **re
The groupings seen in the previous section are also known as capture groups. The string captured by these groups can be referred later using backreference \N
where N
is the capture group you want. Backreferences can be used in both search and replacement sections.
\(pattern\)
capture group for later use via backreferences\%(pattern\)
non-capturing group1
, second leftmost group is 2
and so on (maximum 9
groups)\1
backreference to the first capture group\2
backreference to the second capture group\9
backreference to the ninth capture group&
or \0
backreference to the entire matched portionHere are some examples:
\(\a\)\1
matches two consecutive repeated alphabets like ee
, TT
, pp
and so on
\a
refers to [a-zA-Z]
\(\a\)\1\+
matches two or more consecutive repeated alphabets like ee
, ttttt
, PPPPPPPP
and so ons/\d\+/(&)/g
replaces 52 apples 31 mangoes
with (52) apples (31) mangoes
(surround digits with parentheses)s/\(\w\+\),\(\w\+\)/\2,\1/g
replaces good,bad 42,24
with bad,good 24,42
(swap words separated by comma)s/\(_\)\?_/\1/g
replaces _foo_ __123__ _baz_
with foo _123_ baz
(matches one or two underscores, deletes one underscore)s/\(\d\+\)\%(abc\)\+\(\d\+\)/\2:\1/
replaces 12abcabcabc24
with 24:12
(matches digits separated by one or more abc
sequences, swaps the numbers with :
as the separator)
abc
since it isn't needed laters/\(\d\+\)\(abc\)\+\(\d\+\)/\3:\1/
does the same if only capturing groups are usedReferring to text matched by a capture group with a quantifier will give only the last match, not entire match. Use a capture group around the grouping and quantifier together to get the entire matching portion. In such cases, the inner grouping is an ideal candidate to use non-capturing group.
s/a \(\d\{3}\)\+/b (\1)/
replaces a 123456789
with b (789)
a 4839235
will be replaced with b (923)5
s/a \(\%(\d\{3}\)\+\)/b (\1)/
replaces a 123456789
with b (123456789)
a 4839235
will be replaced with b (483923)5
Lookarounds help to create custom anchors and add conditions within the searchpattern
. These assertions are also known as zero-width patterns because they add restrictions similar to anchors and are not part of the matched portions.
Vim's syntax is different than those usually found in programming languages like Perl, Python and JavaScript. The syntax starting with
\@
is always added as a suffix to the pattern atom used in the assertion. For example,(?!\d)
and(?<=pat.*)
in other languages are specified as\d\@!
and\(pat.*\)\@<=
respectively in Vim.
\@!
negative lookahead assertion
ice\d\@!
matches ice
as long as it is not immediately followed by a digit character, for example ice
or iced!
or icet5
or ice.123
but not ice42
or ice123
s/ice\d\@!/X/g
replaces iceiceice2
with XXice2
s/par\(.*\<par\>\)\@!/X/g
replaces par
with X
as long as whole word par
is not present later in the line, for example parse and par and sparse
is converted to parse and X and sXse
at\(\(go\)\@!.\)*par
matches cat,dog,parrot
but not cat,god,parrot
(i.e. match at
followed by par
as long as go
isn't present in between, this is an example of negating a grouping)\@<!
negative lookbehind assertion
_\@<!ice
matches ice
as long as it is not immediately preceded by a _
character, for example ice
or _(ice)
or 42ice
but not _ice
\(cat.*\)\@<!dog
matches dog
as long as cat
is not present earlier in the line, for example fox,parrot,dog,cat
but not fox,cat,dog,parrot
\@=
positive lookahead assertion
ice\d\@=
matches ice
as long as it is immediately followed by a digit character, for example ice42
or ice123
but not ice
or iced!
or icet5
or ice.123
s/ice\d\@=/X/g
replaces ice ice_2 ice2 iced
with ice ice_2 X2 iced
\@<=
positive lookbehind assertion
_\@<=ice
matches ice
as long as it is immediately preceded by a _
character, for example _ice
or (_ice)
but not ice
or _(ice)
or 42ice
![]()
![]()
You can also specify number of bytes to search for lookbehind patterns. This will significantly speed up the matching process. You have to specify the number between
@
and<
characters. For example,_\@1<=ice
will lookback only one byte beforeice
for matching purposes.\(cat.*\)\@10<!dog
will lookback only ten bytes beforedog
to check the given assertion.
As discussed earlier, both greedy and non-greedy quantifiers will try to satisfy the overall pattern by varying the amount of characters matched by the quantifiers. You can use atomic grouping if you do not want a specific sub-pattern to ever give back characters it has already matched. Similar to lookarounds, you need to use \@>
as a suffix, for example \(pattern\)\@>
.
s/\(0*\)\@>\d\{3,\}/(&)/g
replaces only numbers >= 100 irrespective of any number of leading zeros, for example 0501 035 154
is converted to (0501) 035 (154)
\(0*\)\@>
matches the 0
character zero or more times, but it will not give up this portion to satisfy overall patterns/0*\d\{3,\}/(&)/g
replaces 0501 035 154
with (0501) (035) (154)
(here 035
is matched because 0*
will match zero times to satisfy the overall pattern)
Some regexp engines provide this feature as possessive quantifiers.
Some of the positive lookbehind and lookahead usage can be replaced with \zs
and \ze
respectively.
\zs
set the start of the match (portion before \zs
won't be part of the match)
s/\<\w\zs\w*\W*//g
replaces sea eat car rat eel tea
with secret
s/\(\<\w\)\@<=\w*\W*//g
or s/\(\<\w\)\w*\W*/\1/g
\ze
set the end of the match (portion after \ze
won't be part of the match)
s/ice\ze\d/X/g
replaces ice ice_2 ice2 iced
with ice ice_2 X2 iced
s/ice\d\@=/X/g
or s/ice\(\d\)/X\1/g
As per :h \zs and :h \ze, these "Can be used multiple times, the last one encountered in a matching branch is used."
These escape sequences change certain aspects of the syntax and behavior of the search pattern that comes after such a modifier. You can use multiple such modifiers as needed for particular sections of the pattern.
\m
magic mode (this is the default setting)\M
nomagic mode
.
, *
and ~
are no longer metacharacters (compared to magic mode)\.
, \*
and \~
will make them to behave as metacharacters^
and $
would still behave as metacharacters\Ma.b
matches only a.b
\Ma\.b
matches a.b
as well as a=b
or a<b
or acd
etcThe default syntax of Vim regexp has only a few metacharacters like .
, *
, ^
and so on. If you are familiar with regexp usage in programming languages such as Perl, Python and JavaScript, you can use \v
to get a similar syntax in Vim. This will allow the use of more metacharacters such as ()
, {}
, +
, ?
and so on without having to prefix them with a \
metacharacter. From :h magic documentation:
Use of
\v
means that after it, all ASCII characters except0
-9
,a
-z
,A
-Z
and_
have special meaning
\v<his>
matches his
or to-his
but not this
or history
or _hist
a<b.*\v<end>
matches c=a<b #end
but not c=a<b #bending
\v
is used after a<b
to avoid having to escape <
\vone|two|three
matches one
or two
or three
\vabc+
matches abc
or abccc
but not ab
or bc
s/\vabc?/X/
replaces abcc
with Xc
s/\vt.{-}a/X/g
replaces that is quite a fabricated tale
with XX fabricaXle
\vab{3}c
matches xabbbcz
but not abbc
or abbbbbc
s/\v(\w+),(\w+)/\2,\1/g
replaces good,bad 42,24
with bad,good 24,42
s/\(\w\+\),\(\w\+\)/\2,\1/g
From :h magic documentation:
Use of
\V
means that after it, only a backslash and terminating character (usually/
or?
) have special meaning
\V^.*{}$
matches ^.*{}$
literally\V^.*{}$\.\*abcd
matches ^.*{}$
literally only if abcd
is found later in the line
\V^.*{}$\m.*abcd
can also be used\V\^This
matches This is a sample
but not Do This
\V)\$
matches apple (5)
but not def greeting():
These will override flags and settings, if any. Unlike the magic modifiers, you cannot apply \c
or \C
for a specific portion of the pattern.
\c
case insensitive search
\cthis
matches this
or This
or THIs
and so on
th\cis
or this\c
and so on will also result in the same behavior\C
case sensitive search
\Cthis
match exactly this
but not This
or THIs
and so on
th\Cis
or this\C
and so on will also result in the same behaviors/\Ccat/dog/gi
replaces cat Cat CAT
with dog Cat CAT
since i
flag gets overriddenThese can be used in the replacement section:
\u
Uppercases the next character\U
UPPERCASES the following characters\l
lowercases the next character\L
lowercases the following characters\e
or \E
will end further case changes\L
or \U
will also override any existing conversionExamples:
s/\<\l/\u&/g
replaces hello. how are you?
with Hello. How Are You?
\l
in the search section is equivalent to [a-z]
s/\<\L/\l&/g
replaces HELLO. HOW ARE YOU?
with hELLO. hOW aRE yOU?
\L
in the search section is equivalent to [A-Z]
s/\v(\l)_(\l)/\1\u\2/g
replaces aug_price next_line
with augPrice nextLine
s/.*/\L&/
replaces HaVE a nICe dAy
with have a nice day
s/\a\+/\u\L&/g
replaces HeLLo:bYe gOoD:beTTEr
with Hello:Bye Good:Better
s/\a\+/\L\u&/g
can also be used in this cases/\v(\a+)(:\a+)/\L\1\U\2/g
replaces Hi:bYe gOoD:baD
with hi:BYE good:BAD
From :h substitute documentation:
Instead of the
/
which surrounds the pattern and replacement string, you can use any other single-byte character, but not an alphanumeric character,\
,"
or|
. This is useful if you want to include a/
in the search pattern or replacement string.
s#/home/learnbyexample/#\~/#
replaces /home/learnbyexample/reports
with ~/reports
s/\/home\/learnbyexample\//\~\//
Certain characters like tab, carriage return, newline, etc have escape sequences to represent them. Additionally, any character can be represented using their codepoint value in decimal, octal and hexadecimal formats. Unlike character set escape sequences like \w
, these can be used inside character classes as well. If the escape sequences behave differently in searchpattern
and replacestring
portions, they'll be highlighted in the descriptions below.
\t
tab character\b
backspace character\r
matches carriage return for searchpattern
, produces newline for replacestring
\n
matches end-of-line for searchpattern
, produces ASCII NUL for replacestring
\n
can also match \r
or \r\n
(where \r
is carriage return) depending upon fileformat
setting\%d
matches character specified by decimal digits
\%d39
matches the single quote character\%o
matches character specified by octal digits
\%o47
matches the single quote character\%x
matches character specified by hexadecimal digits (max 2 digits)
\%x27
matches the single quote character\%u
matches character specified by hexadecimal digits (max 4 digits)\%U
matches character specified by hexadecimal digits (max 8 digits)
Using
\%
sequences to insert characters inreplacestring
hasn't been implemented yet. See vi.stackexchange: Replace with hex character for workarounds.
See ASCII code table for a handy cheatsheet with all the ASCII characters and conversion tables. See codepoints for Unicode characters.
To match the metacharacters literally (including character class metacharacters like -
), i.e. to remove their special meaning, prefix those characters with a \
(backslash) character. To indicate a literal \
character, use \\
. Depending on the pattern, you can also use a different magic modifier to reduce the need for escaping. Assume default magicness for the below examples unless otherwise specified.
^
and $
do not require escaping if they are used out of position
b^2
matches a^2 + b^2 - C*3
$4
matches this ebook is priced $40
\^super
matches ^superscript
(you need to escape here since ^
is at the customary position)[
and ]
do not require escaping if only one of them is used
b[1
matches ab[123
42]
matches xyz42] =
b\[123]
or b[123\]
matches ab[123] = d
[
in substitute command requires careful consideration
s/b[1/X/
replaces b[1/X/
with nothings/b\[1/X/
replaces ab[123
with aX23
\Va*b.c
or a\*b\.c
matches a*b.c
&
in replacement section requires escaping to represent it literally
s/and/\&/
replaces apple and mango
with apple & mango
The following can be used to match character class metacharacters literally in addition to escaping them with a \
character:
-
can be specified at the start or the end of the list, for example [a-z-]
^
should be other than the first character, for example [+a^.]
]
should be the first character, for example []a-z]
and [^]a]
\=
when replacestring
starts with \=
, it is treated as an expressions/date:\zs/\=strftime("%Y-%m-%d")/
appends current date
date:
to date:2022-02-17
s/\d\+/\=submatch(0)*2/g
multiplies matching numbers by 2
4 and 10
to 8 and 20
submatch()
function is similar to backreferences, 0
gives the entire matched string, 1
refers to the first capture group and so ons/\(.*\)\zs/\=" = " . eval(submatch(1))/
appends result of an expression
10 * 2 - 3
to 10 * 2 - 3 = 17
.
is the string concatenation operatoreval()
here executes the contents of first capture group as an expressions/"[^"]\+"/\=substitute(submatch(0), '[aeiou]', '\u&', 'g')/g
affects vowels only inside double quotes
"mango" and "guava"
to "mAngO" and "gUAvA"
substitute()
function works similarly to the s
commandsearchpattern
replacestring
s
commandperldo s/\d+/$&*2/ge
changes 4 and 10
to 8 and 20
perl
interface is available with your Vim installation1,$
(the s
command works only on the current line by default)
See :h usr_41.txt for details about Vim script.
See :h sub-replace-expression for more details.
See also stackoverflow: find all occurrences and replace with user input.
\%V
match inside visual area only
s/\%V10/20/g
replaces 10
with 20
only inside the visual area\%V
, the replacement would happen anywhere on the lines covered by the visual selection\%[set]
match zero or more of these characters in the same order, as much as possible
spa\%[red]
matches spa
or spar
or spare
or spared
(longest match wins)
\vspa(red|re|r)?
or \vspa(red?|r)?
and so onap\%[[pt]ly]
matches ap
or app
or appl
or apply
or apt
or aptl
or aptly
\_^
and \_$
restrict the match to start-of-line and end-of-line respectively, useful for multiline patterns\%^
and \%$
restrict the match to start-of-file and end-of-file respectively~
represents the last replacement string
s/apple/banana/
followed by /~
will search for banana
s/apple/banana/
followed by s/fig/(~)/
will use (banana)
as the replacement stringThe . repeat command repeats only the last change. And it gets overwritten with every change. The q
command allows you to record a sequence of commands and execute them later whenever you need. You can make it recursive, add a count prefix, combine it with Command-line mode commands and so on. Powerful indeed!
With so many built-in features, sometimes it isn't easy to choose. I prefer the substitute command to macros if both of them can be used for the given problem, especially if the processing doesn't require multiple lines to be considered at once for the solution. That said, macros are more flexible, having an inherent advantage of being able to easily integrate numerous Vim commands.
Documentation links:
q
and related commandsHere's a rough overview of q
command usage. Working examples will be discussed in later sections.
5
times
Command-line area will show
recording @a
after step 2 and this indicator vanishes after step 4.
Note that these registers are shared across recording, delete and yank commands. You'll see how this helps to modify a recording later, but you should also be careful not to mix them if you want separate recording and paste use cases. As mentioned earlier in Normal mode chapter, uppercase registers will append to existing content in lowercase registers.
See also vi.stackexchange: Can I repeat a macro with the "dot operator"? (one of the solutions will allow you to use . command to execute a macro immediately after recording as well).
The qwceHello^[q macro recording clears text till the end of the word and inserts Hello
. Here's a breakdown of this command sequence:
^
and [
characters"w
register using "wpAfter you've recorded the macro, you can execute this command sequence anywhere else you need it. For example, if the cursor is on the fourth character of the text Hi-there
and @w is pressed, you'll get Hi-Hello
.
As mentioned earlier, registers are shared across recording, delete and yank commands. When you call a macro using @
, the register content is treated as the sequence of commands to be executed. So, editing a register's content will automatically update the behavior of the macro as well. Knowing that you can modify a macro also helps if you make a mistake — you can choose to finish the recording and update later instead of restarting the recording.
Suppose you want to use 'Hello!'
instead of Hello
for the macro discussed in the previous section. Here's one possible way to make the changes:
"w
register
ceHello^[
"w
register after visually selecting the modified text or using motion commands in Normal modeAfter you've modified the register contents, check if it is working as expected. For example, if the cursor is on the fourth character of the text Hi-there
and @w is pressed, you should now get Hi-'Hello'!
.
In case you wish to create a new macro from scratch by just typing the required text instead of using the
q
command, you'll find Ctrl+v (or the Ctrl+q alias) useful to insert keys like Esc and Enter. To do so, press Ctrl+v followed by the required key. You'll get^[
for Esc,^M
for Enter and so on.
let @w = "ce'Hello'!^[" adding this line to
vimrc
file will load the"w
register with the given text at startup.
Suppose you forgot to add curly braces for single statement control structures in a Perl program:
# syntax error
if($word eq reverse $word)
print "$word is a palindrome\n";
# corrected code
if($word eq reverse $word)
{
print "$word is a palindrome\n";
}
qpo{^[jo}^[q is one way to do it:
p
{
character}
characterHaving a macro will help you apply this correction whenever you forget braces for single statement control structures.
Note that
{
and}
will be indented based on style settings for that particular filetype.
I used F`r[f`s]()^["*P macro to replace `:h <topic>`
with a hyperlink to the corresponding online help page for this ebook. Assume the cursor is somewhere within the :h <topic>
text portion surrounded by backticks (markdown formatting for inline code). This has to be changed to [:h <topic>](link)
(markdown formatting for hyperlinks).
[
]()
P
to paste content to the left of the cursorOnce the macro was recorded, I just had to select the url from the browser for each help topic and execute the macro. I used n to navigate in the markdown files after using :h
as the search pattern.
If you have to apply the same macro for text portions that are next to each other, you can add motion commands at the end of the macro for reaching the next text portion. The motion command could be arrow motions, searching using /
and so on. Doing so will allow you to use a count prefix to apply the macro for all the text portions in one shot. This assumes that you can easily count the number of text portions. For example, consider this Python snippet where you want to change single line definitions to multiple lines:
def square(n): return n ** 2
def cube(n): return n ** 3
def isodd(n): return n % 2 == 1
You can do a recording as usual, select these lines visually (or use a range) and then apply the macro using normal @d in Command-line mode. Or, you could add a motion to automatically go to the next line and use a count prefix as described below.
qd0f:lr^M>>o^[jq is one way to achieve this:
:
(which is a space character in the above snippet)
:
character as part of the function argumentsAfter recording, you can use 3@d on the first line to get the output as shown below:
def square(n):
return n ** 2
def cube(n):
return n ** 3
def isodd(n):
return n % 2 == 1
Suppose the Python function definitions discussed above aren't next to each other but can be found anywhere in the Python script file. In such cases, if you are able to reliably identify the lines using a regexp filter, you can use the :g
command.
0
not required since the cursor starts at the beginningSuppose it isn't easy to count the number of text portions and filtering is complicated too. In such cases, you might be able to use recursive recording that continues to execute the macro until one of the steps fails. Similar to recursive function calls, you have to call the macro from within the recording. Consider this Python snippet where you want to change single line definitions to multiple lines:
def square(n): return n ** 2
def cube(n): return n ** 3
def isodd(n): return n % 2 == 1
print(square(12))
qr0f:lr^M>>o^[j@rq is one way to achieve this. The only addition here is @r
at the end of the recording compared to the solution discussed in the previous section. For the fourth line with print()
function, the macro will stop when it doesn't find the :
character. It would've stopped even if a :
was found, provided it was the last character, since the l
motion would've failed.
Using @r
on the first line of the above snippet would give the following output:
def square(n):
return n ** 2
def cube(n):
return n ** 3
def isodd(n):
return n % 2 == 1
print(square(12))
![]()
Note that the register being used here must be empty before you start the recording, otherwise you might see some unwanted changes when you type
@r
while recording. To ensure this register is empty, you can use qrq (i.e. record an empty macro) before you record the recursive macro.
If the
:s
command is part of the recording and you do not want the macro to stop if the search pattern isn't found, you can use thee
flag.
Here are some more examples:
if
control structure and so onGiven the following text:
# Introduction
# Normal mode
# Command Line mode
# Visual mode
Use a macro (or substitute command if you prefer) to get the modified text as shown below:
* [Introduction](#introduction)
* [Normal mode](#normal-mode)
* [Command Line mode](#command-line-mode)
* [Visual mode](#visual-mode)
Settings like indentation and keyword-pairs can vary between different programming languages and file types. You might need to adapt style guides based on client requirements. Or perhaps, you wish to create or override commands to suit your preferences.
This chapter will discuss how you can customize Vim for different purposes. Some of the settings will be specific to GVim.
Documentation links:
From :h usr_41.txt and :h vimrc-intro:
The Vim script language is used for the startup vimrc file, syntax files, and many other things.
The vimrc file can contain all the commands that you type after a colon. The simplest ones are for setting options.
This chapter only covers some use cases. You'll see what some of the settings do, how to use mappings, abbreviations and so on. Not much will be discussed about the programming aspects of Vim script. Make sure you have a vimrc
file using the following details:
vimrc
file, you can use this predefined variable to open itvimrc
file should be located for your OS
To view a sample
vimrc
file, I have one on GitHub. More resources are mentioned in the Further Reading section at the end of this chapter.
If you haven't created a vimrc
file, the defaults.vim
file that comes with Vim installation will be used. This file aims to provide saner defaults like enabling syntax highlighting, filetype settings and so on.
vimrc
file if you want to keep these defaultsdefaults.vim
Alternatively, you can copy only the parts you want to retain from the defaults.vim
file to your vimrc
file.
![]()
set
syntax and guidelines were introduced in the Setting options section.
:
commands, search patterns, etcbash
like tab completion
:h 'history' will give you the documentation for the given option (note the use of single quotes).
You can use these settings from the Command-line mode as well, but will be active for the current Vim session only. Settings specified in the
vimrc
file will be loaded automatically at startup. You can also load a different file as thevimrc
, which will be discussed in the CLI options chapter.
Further Reading
plugin
and indent
files
indent
and plugin
directories would be present in this path)indent
setting80
characters as the limit
0
which disables this setting80
highlight ColorColumn
setting to customize the color for this vertical bar8
)8
)hlsearch
settingMapping helps you to create new commands or redefine existing ones. You can restrict such mappings for specific modes as well. Only the following settings will be discussed in this chapter:
nnoremap
Normal mode non-nested, non-recursive mappingxnoremap
Visual mode non-nested, non-recursive mappinginoremap
Insert mode non-nested, non-recursive mappinginoreabbrev
Insert mode non-nested, non-recursive abbreviationThe following will not be discussed, but you might find it useful to know or explore further:
nmap
, xmap
, imap
and iabbrev
allows nested and recursive mappingsnunmap
, xunmap
, iunmap
and iunabbrev
unmaps the given command (usually used from Command-line mode to temporarily disable a mapping, will be available again on startup if it was defined in vimrc
)
mapclear
instead of unmap
to clear all the mappings for that particular modeonoremap
(or omap
) map a motion or text object to be used with commands like d
or y
command
helps you create a Command-line mode command, see :h 40.2 and :h user-commands for details
:nmap, :xmap, :imap and :iab will list all the current mappings for that particular mode. You can provide an argument to display the mapping for that particular command, for example :nmap Y. See :h key-mapping and :h map-overview for reference manuals.
<F2>
represents the F2 function key and <CR>
represents the Enter key<silent>
modifier executes the command without displaying on Command-line
See :h map-which-keys to know which keys are not already Vim commands, which ones are not commonly used, etc.
See :h key-notation for a list of keys that can be represented using the
<>
notation.
Normal mode commands are already crowded, so if you are looking to create new commands, using a leader mapping can help you out. You can define a key that'll serve as a prefix for these new set of commands. By default, the backslash key is used as the leader key.
mapleader
hasn't been set, using \f
will auto indent the code for the whole file;
;f
since the leader key was changed
See learnvimscriptthehardway: Leaders for more examples and details.
Use noremap! if you want a mapping to work in both Insert and Command-line modes.
Note that
xnoremap
is used here sincevnoremap
affects both Visual and Select modes.
Abbreviations are usually used to correct typos and insert frequently used text. From :h abbreviations documentation:
An abbreviation is only recognized when you type a non-keyword character. This can also be the
<Esc>
that ends insert mode or the<CR>
that ends a command. The non-keyword character which ends the abbreviation is inserted after the expanded abbreviation. An exception to this is the character<C-]>
, which is used to expand an abbreviation without inserting any extra characters.
inoreabbrev p #!/usr/bin/env perl<CR>use strict;<CR>use warnings;<CR> expand p
to the text as shown in the code snippet below
#!/usr/bin/env perl
use strict;
use warnings;
inoreabbrev py #!/usr/bin/env python3 expand py
to #!/usr/bin/env python3
py
literally (for example, script.py
)[p
or @p
insteadinoreabbrev teh the automatically correct teh
typo to the
inoreabbrev @a always @()<CR>begin<CR>end<Esc>2k$ expand @a
to the text as shown in the code snippet below
@a
followed by Esc key to place the cursor at the end of the first linealways @()
begin
end
:abbreviate or :ab list all abbreviations
See :h 24.7 for more details about using abbreviations.
<>
to the list of pairs matched by % command in Normal mode
To match keywords like
if
-else
pairs with %, you can installmatchit.vim
plugin. This supports filetypes such as HTML, Vim, LaTeX, XML, etc. See :h matchit-install for more details.
See :h guioptions for more details.
![]()
See :h 'runtimepath' to know the path within which you can add the plugins and packages discussed in this section.
~/.vim
is commonly used on Unix/Linux systems.
Make sure to backup your directory (~/.vim
for example) and the vimrc
file, so that you can easily apply your customizations on a new machine.
Some plugins are loaded by default. Some come with Vim installation but you have to explicitly enable them. You can also write your own or add plugins written by others. From :h add-plugin:
Vim's functionality can be extended by adding plugins. A plugin is nothing more than a Vim script file that is loaded automatically when Vim starts.
There are two types of plugins:
global plugin: Used for all kinds of files
filetype plugin: Only used for a specific type of file
If you want to add a global plugin created by you or someone else, place it in the plugin
directory. If you don't have that directory yet, you can create it using the below command (assuming Unix/Linux):
$ mkdir -p ~/.vim/plugin
$ cp plugin_file.vim ~/.vim/plugin/
If you have multiple related plugin files, you can put them under a subdirectory:
$ mkdir -p ~/.vim/plugin/python
$ cp plugin_files.vim ~/.vim/plugin/python/
If you want to add plugins that should work based on specific filetype, add them to the ftplugin
directory:
$ mkdir -p ~/.vim/ftplugin
$ cp ftplugin_file.vim ~/.vim/ftplugin/
Packages make it easy to manage projects that require multiple plugins, use a version controlled repository directly and so on. See :h packages for more details. From :h add-package:
A package is a set of files that you can add to Vim. There are two kinds of packages: optional and automatically loaded on startup.
The Vim distribution comes with a few packages that you can optionally use. For example, the matchit plugin.
matchit
package
:h matchit
for further details!
is used to prevent loading this plugin when Vim is started with --noplugin
CLI optionvim-surround is used here as an example for a third-party package. Installation instructions (provided in this repository) are shown below, assuming you want to enable this package at startup:
# 'pack' is the directory for packages
# 'tpope' subdirectory is useful to group all packages by this author
# 'start' means this package will be loaded at startup
$ mkdir -p ~/.vim/pack/tpope/start
# go to the directory and clone the git repository
# you can then update the repository when new changes are needed
$ cd ~/.vim/pack/tpope/start
$ git clone https://github.com/tpope/vim-surround.git
When you start Vim after the above steps, vim-surround
will be automatically active. Couple of examples are shown below, see the repository linked above for more details.
[]
, for example hello
to [hello]
"hi bye"
to 'hi bye'
If you want to enable this package optionally, put it under opt
directory instead of start
.
# 'opt' makes it optional
$ mkdir -p ~/.vim/pack/tpope/opt
$ cd ~/.vim/pack/tpope/opt
$ git clone https://github.com/tpope/vim-surround.git
vimrc
(usually under some condition)There are different ways to add a new color scheme. The simplest is to copy the theme.vim
file to the ~/.vim/colors
directory. Or, follow the installation steps provided by the theme creators. Here are couple of solarized themes you can check out:
After installation, you can use the :colorscheme command to set the new theme. If the theme offers multiple variations, you might need additional settings like set background=dark
or set background=light
. See the installation instructions provided in the above repositories for more details.
See Where to put what section under :h packages for more details about installation directories.
See also this collection of awesome color schemes for Vim.
From :h 40.3:
An autocommand is a command that is executed automatically in response to some event, such as a file being read or written or a buffer change.
Autocommands are very powerful. Use them with care and they will help you avoid typing many commands. Use them carelessly and they will cause a lot of trouble.
Syntax from the reference manual is shown below:
:au[tocmd] [group] {event} {aupat} [++once] [++nested] {cmd}
Here's an example for Python files:
augroup pyg
autocmd!
" add Python shebang for a new buffer with .py extension
" py abbreviation was discussed earlier in this chapter
autocmd BufNewFile *.py normal ipy
" Black command is provided by a Python code formatter plugin
autocmd BufWritePre *.py Black
augroup END
autocmd BufNewFile *.py normal ipy
BufNewFile
event that triggers on editing a file that doesn't already exist*.py
filenames ending with .py
(similar to shell wildcards)normal ipy
command to be executed (normal
is needed here since by default commands are treated as Command-line mode)autocmd BufWritePre *.py Black
BufWritePre
event that triggers on writing a fileBlack
command to be executed (see black vim plugin documentation for more details)augroup
helps you to group related autocommandspyg
in the above example
vimrc
fileSee also:
version 7.3
)vimrc
reference, tips and generation
vimrc
by selecting optionsThis chapter discusses some of the options you can use when starting Vim from the command line. Examples given are based on Unix/Linux system. Syntax and features might vary for other platforms like Windows.
Documentation links:
Recall that you need to add
-
prefix for built-in help on CLI options, :h -y for example.
gvim
opens a new unnamed buffer when filename is not specifiedgvim script.py
opens script.py
script.py
doesn't exist, file will be created only after you explicitly issue write commandsgvim report.log power.log area.log
opens the specified files
report.log
here) will be the current buffergvim -- *.txt
if filenames can start with -
, use --
to prevent such files from being treated as an optiongvim -h
brief description of the options
gvim -p *.log
opens specified files as separate tab pages
10
pages, use the tabpagemax
setting if you want to change this numbergvim -o *.log
opens specified files as horizontal splitsgvim -O *.log
opens specified files as vertical splits
You can append a number to each of these options to specify how many tabs or splits you want. For example,
gvim -p3 *.py
opens three tabs irrespective of the number of input files. Empty buffers will be used if there aren't enough input files to satisfy the given number.
gvim -y
opens in Insert mode and behaves like a click-and-type editor
notepad
, gedit
, etcalias vim='vim -y'
See also novim-mode plugin, which aims to make Vim behave more like a 'normal' editor.
gvim -R
Readonly mode
gvim -M
stricter Readonly mode
gvim -Z
Restricted mode
gvim + script.py
opens script.py
and the cursor is placed on the last linegvim +25 script.py
opens script.py
and the cursor is placed on the 25th line
gvim +/while script.py
opens script.py
and the cursor is placed on the first line containing the given pattern
gvim +1 +/pattern
to force the search to start from the first line, otherwise cursor position stored in viminfo
will be used (if applicable)gvim -c
allows you to execute the Command-line mode command passed as an argumentgvim -c '%s/search/replace/g' script.py
opens script.py
and performs the given substitute operationgvim -c 'normal =G' script.py
opens script.py
and auto indents the entire file content
As per :h -c, "You can use up to 10
+
or-c
arguments in a Vim command. They are executed in the order given. A-S
argument counts as a-c
argument as well"
![]()
--cmd
option is similar to the-c
option, but executes the command before loading anyvimrc
files.
gvim -q <(grep -Hn 'search' *.py)
interactively edit the matching lines from grep
output
-H
and -n
options ensure filename and line number prefix for the matching linesgvim -q file
if you save the grep
output to that filegvim -q error.log
edit source code based on compiler output containing filenames and line numbers for the error locations
error.log
is assumed to be the filename used to save the error messages
See Vim and the quickfix list and stackoverflow: How do you use Vim's quickfix feature? to learn more about this feature.
See :h quickfix for documentation.
gvim -u file
uses the given file for initialization instead of vimrc
files
vimrc
based on which project you are working on, etcgvim -u NONE
all initializations are skippedgvim -u DEFAULTS
similar to NONE
, but defaults.vim
is loadedgvim -u NORC
similar to NONE
, but plugins are loadedgvim --noplugin
only plugins are not loadedHere's a neat table from :h --noplugin:
argument | vimrc | plugins | defaults.vim |
---|---|---|---|
(nothing) | yes | yes | yes |
-u NONE |
no | no | no |
-u DEFAULTS |
no | no | yes |
-u NORC |
no | yes | no |
--noplugin |
yes | no | yes |
gvim -S proj.vim
restore a session using the previously saved session file
gvim -i proj.viminfo
restore Viminfo from the given file
viminfo
file to save information