Command-line mode
An 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:
- :h usr_05.txt — set your settings
- :h usr_07.txt — editing more than one file
- :h usr_08.txt — splitting windows
- :h usr_10.txt — making big changes
- :h usr_21.txt — go away and come back
- :h 3.8 — simple searches
- :h cmdline.txt — reference manual for Command-line mode
- :h windows.txt — reference manual for Editing with multiple windows and buffers
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.
Save changes
- :w save changes (
:w
is short for:write
) - :w filename provide a filename if it is a new file or if you want to save to another file
- :w >> filename append to an existing file (
w!
will create a new file if it doesn't exist) - :wa save all the changed buffers (
: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, the entire file content is used for these commands. You can use a range (discussed later in this chapter) to work with selective lines.
Quit Vim
- :q quit the current window (
:q
is short for:quit
)- if other windows/tabs are present, they will remain open
- you will get an error message if there are unsaved changes
- :qa quit all (
:qa
is short for:quitall
)- you will get an error message if there are unsaved changes
- :confirm qa similar to quit all, but prompts for every file that has unsaved changes
Append
!
to discard unsaved changes and quit.
Combining Save and Quit
- :wq save changes and quit
- :wqa save changes for all files 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.
Working with buffers and tabs
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.
Buffers
- :e refreshes the current buffer (
:e
is short for:edit
) - :e filename open a particular file by its path, in the same window
- :e # switch back to the previous buffer, won't work if that buffer is not named
- :e# can also be used (no space between
e
and#
)
- :e# can also be used (no space between
- Ctrl+6 switch back to the previous buffer, works even if that buffer is not named
- Ctrl+^ can also be used
- :e #1 open the first buffer
- :e #2 open the second buffer, and so on
- :buffers show all buffers
- :ls or :files can also be used
- :bn open the next file in the buffer list (
:bn
is short for:bnext
)- opens the first buffer if you are on the last buffer
- :bp open the previous file in the buffer list (
:bp
is short for:bprevious
)- opens the last buffer if you are on the first buffer
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 lists.
Tabs
- :tabe filename open the given file in a new tab (
:tabe
is short for:tabedit
)- if
filename
isn't specified, you'll get an unnamed empty window - by default, the new tab is opened to the right of the current tab
- :0tabe open as the first tab
- :$tabe open as the last tab
- see :h :tabe for more details and features
- if
- :tabn switch to the next tab (
:tabn
is short for:tabnext
)- if tabs to the right are exhausted, switch to the first tab
- gt and Ctrl+Page Down can also be used
- 2gt switch to the second tab (the number specified is absolute, not relative)
- :tabp switch to the previous tab (
:tabp
is short for:tabprevious
)- if tabs to the left are exhausted, switch to the last tab
- gT and Ctrl+Page Up can also be used
- :tabr switch to the first tab (
:tabr
is short for:tabrewind
)- :tabfirst can also be used
- :tabl switch to the last tab (
:tabl
is short for:tablast
) - :tabm N move the current tab to after
N
tabs from the start (:tabm
is short for:tabmove
)- :tabm 0 move the current tab to the beginning
- :tabm move the current tab to the end
- :tabm +N move the current tab
N
positions to the right - :tabm -N move the current tab
N
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.
Splitting
- :split filename open file for editing in a new horizontal window, above the current window
- you can also use :sp instead of :split
- :set splitbelow open horizontal splits below the current window
- :vsplit filename open file for editing in a new vertical window, to the left of the current window
- you can also use :vs instead of :vsplit
- :set splitright open vertical splits to the right of the current window
- Ctrl+w followed by w switch to the below/right window for horizontal/vertical splits respectively
- Ctrl+w followed by Ctrl+w also performs the same function
- switches to the first split if you are on the last split
- Ctrl+w followed by W switch to the above/left window for horizontal/vertical splits respectively
- switches to the last split if you are on the first split
- Ctrl+w followed by
hjkl
or arrow keys, switch in the respective direction - Ctrl+w followed by t or b switch to the top (first) or bottom (last) window
- Ctrl+w followed by
HJKL
(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.
Edit all buffers
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! bufdo %s/search/replace/g | update perform substitution across all the buffers
silent
skips displaying normal messages!
skips error messages
- It is not an efficient way to open buffers just to search and replace a pattern across multiple files. Use tools like
sed
,awk
andperl
instead.- See my book list if you'd like to learn about such tools.
- See :h :bufdo, :h :windo and :h :silent for more details.
Further reading
- How to change multiple files
- stackoverflow: Effectively work with multiple files
- When to use Buffers and when to use Tabs
- :h argument-list — for working only with the files provided as Vim CLI arguments
Setting options
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:
- :set cursorline highlight the line containing the cursor
- :set history=200 increase default history from 50 to 200
- :set ww+=[,] allow left and right arrow keys to move across lines in Insert mode
+=
allows you to append to an existing string value
Usage guidelines:
set {option}
switch on the given boolean setting- :set expandtab use spaces for tab expansion
set {option}!
toggle the given boolean setting- :set expandtab! if previously tabs were expanded, it will be turned off and vice versa
set inv{option}
can also be used
set no{option}
switch off the given boolean setting- :set noexpandtab disable expanding tab to spaces
set {option}?
get the current value of the given option (works for all three forms)- :set expandtab? output will be
expandtab
ornoexpandtab
depending on whether it is switched on or off
- :set expandtab? output will be
set {option}
get the current value of number or string option- for example, try :set history or :set ww
See :h options.txt for a complete list of usage guidelines and available options.
Search
- /searchpattern search the given pattern in the forward direction
- ?searchpattern search the given pattern in the backward direction
- Esc ignore the currently typed pattern and return to Normal mode
- n move to the next match in the same direction as the last search
- if you used
/
for searching, n will move in the forward direction - if you used
?
for searching, n will move in the backward direction
- if you used
- N move to the next match in the opposite direction of the last search
- / followed by Enter repeat the last search in the forward direction
- ? followed by Enter repeat the last search in the backward direction
- Ctrl+c cancel the search if it is taking too long
By default, the cursor is placed at the starting character of the match. There are various options to place the cursor at other locations:
- /searchpattern/s place the cursor at the start of the match
- same as /searchpattern or /searchpattern/s+0
- you can also use
b
(begin) instead ofs
, but it'll change tos
after the command is executed
- /searchpattern/s+2 place the cursor
2
characters after the start of the match (i.e. the third character of the match) - /searchpattern/s-2 place the cursor
2
characters before the start of the match - /searchpattern/e place the cursor at the end of the match
- /searchpattern/e+4 place the cursor
4
characters after the end of the match - /searchpattern/e-4 place the cursor
4
characters before the end of the match - /searchpattern/+3 place the cursor
3
lines below the match - /searchpattern/-3 place the cursor
3
lines above the match
Highlight settings:
- :set hlsearch highlight the matched patterns
- :set nohlsearch do not highlight matched patterns
- :set hlsearch! toggle the highlight setting
- :set hlsearch? check what is the current highlight setting
- :set incsearch highlights current match as you type the pattern, the screen is updated automatically as needed
- other matching portions will be highlighted based on
hlsearch
settings - if you press Esc instead of Enter, you'll end up where you originally started before the search
- other matching portions will be highlighted based on
- :noh clear the currently highlighted patterns, if any (
: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 the
/
,?
,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.
Range
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 prefix a range to change the lines that are acted upon.
- :d delete the current line (
:d
is short for the:delete
command) - :.w filename save the current line (represented by
.
) to the given filename- recall that by default
:w
works on the entire file
- recall that by default
- :5d delete the fifth line
- :$d delete the last line (represented by
$
) - :25m0 move the twenty-fifth line to the start of the file (
:m
is short for the:move
command)- the number following
m
is the line number after which you want to place the lines specified by the range - use
:t
(or:co
or:copy
) command if you want to copy instead of moving
- the number following
- :2,10d delete the second to tenth lines (comma is used here to separate the start and end ranges)
- :5,$d delete the fifth line to the last line
- :5,$-1d delete the fifth line to the last but one line
- :%d delete all the lines (
%
is a shortcut for the1,$
range) - :/pat1/,/pat2/d delete the matching range of lines in the forward direction from the current cursor position (forward because
/
is used)- if there are multiple matches, only the first such range will be deleted
- use
?pattern?
to find a match in the backward direction - you can also mix these two types of direction if needed
- :/pat1/;+1d delete the line matching
pat1
as well as the line after (total2
lines)- using
;
will set the line matched by the first pair of the range as the current line for the second pair
- using
- :/pat1/;-2d delete the line matching
pat1
as well as two lines before (total3
lines) - :5;/pat1/d delete from the fifth line to a line matching
pat1
after the fifth line- note the use of
;
again here, the search will be based on the current cursor line if you use,
instead of;
- note the use of
- :'a,'bd delete from the line marked by
a
to the line marked byb
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.
Search and Replace
:[range]s[ubstitute]/{pattern}/{string}/[flags] [count]
General syntax for the s
command (short for substitute
) is shown above. Space between the range
and s
is optional, which you can use for readability.
- : s/a/b/ replace the first occurrence of
a
withb
on the current line only- you can also use :. s/a/b/ (recall that
.
represents the current line) - the delimiter after the replacement string is optional in this case
- you can also use :. s/a/b/ (recall that
- :2 s/apple/Mango/i replace the first occurrence of
apple
withMango
on the second line onlyi
flag matches thesearchpattern
case insensitively
- :3,6 s/call/jump/g replace all the occurrences of
call
withjump
on lines3
to6
g
flag performs search and replace for all the matching occurrences
- :5,$ s/call/jump/g replace all the occurrences of
call
withjump
from the fifth line to the end of the file - :% s/call/jump/g replace all the occurrences of
call
in the file withjump
- recall that
%
is a shortcut for the range1,$
- recall that
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 the Regular Expressions chapter for more details on the substitute command.
Editing lines filtered by a pattern
:[range]g[lobal]/{pattern}/[cmd]
General syntax for the 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.
- :g/call/d delete all lines containing
call
- similar to the
d
Normal mode command, the deleted contents will be saved to the default"
register - :g/call/d a in addition to the default register, the deleted content will also be stored in the
"a
register - :g/call/d _ deleted content won't be saved anywhere, since it uses the black hole register
- similar to the
- :g/^#/t0 copy all lines starting with
#
to the start of the file - :1,5 g/call/d delete all lines containing
call
only for the first five lines - :v/jump/d delete all lines not containing
jump
- same as :g!/jump/d
- :g/cat/ s/animal/mammal/g replace
animal
withmammal
only for the lines containingcat
- :.,.+20 g/^#/ normal >> indent the current line and the next
20
lines only if the line starts with#
- Note the use of
normal
when you need to use Normal mode commands on the filtered lines - Use
normal!
if you don't want user defined mappings to be considered
- Note the use of
In addition to the
/
delimiter, you can also use any single byte character other than alphabets,\
,"
or|
.
See :h :g for more details.
Shell commands
You can also use shell commands from within Vim (assuming you have access to these commands).
- :!ls execute the given shell command and display its output
- the results are displayed as part of an expanded Command-line area, doesn't change contents of the file
- :.! date replace the current line with the output of the given command
- pressing !! in Normal mode will also result in :.!
!
waits for motion similar to thed
andy
commands, !G will give :.,$!
- :%! sort sort all the lines
- recall that
%
is a shortcut for the range1,$
- note that this executes an external command, not the built-in
:sort
command
- recall that
- :3,8! sort sort only lines
3
to8
- :r! date insert output of the given command below the current line
- :r report.log insert contents of the given file below the current line
- Note that
!
is not used here since there is no shell command
- Note that
- :.!grep '^Help ' % replace the current line with all the lines starting with
Help
in the current file%
here refers to the current file contents
- :sh open a shell session within Vim
- use the
exit
command to quit the session
- use the
Terminal mode
- :terminal open a new terminal window as a horizontal split
- the terminal window opens above the current window unless
splitbelow
option is set - you can then use shell commands as you would normally do from a terminal
- the terminal window opens above the current window unless
- :vertical :terminal open a new terminal window as a vertical split
- the terminal window opens to the left of the current window unless
splitright
option is set
- the terminal window opens to the left of the current window unless
- Ctrl+w followed by w or Ctrl+w move to the next window
- helps you to easily switch back and forth if you have one text editing window and one terminal window
- see the Splitting section discussed earlier in this chapter for more such commands
- Ctrl+w followed by N goes to Terminal-Normal mode which will help you to move around using Normal mode commands, copy text, etc (note that you need to use uppercase
N
here)- Ctrl+\ followed by Ctrl+n another way to go to Terminal-Normal mode
- :tnoremap <Esc> <C-w>N map Esc key to go to Terminal-Normal mode (use of maps will be discussed in more detail in the Customizing Vim chapter)
- Ctrl+w followed by : go to Command-line mode from terminal window
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.
Line number settings
- :set number prefix line numbers
- this is a visual guideline, doesn't modify the text
- see :h 'numberwidth' for setting the width of the prefix
- :set number! toggle number setting
- :set nonumber don't use line number prefix
- :set relativenumber prefix line numbers relative to the current line
- current line is assigned
0
, lines above and below the current line are assigned1
, two lines above and below are assigned2
and so on - useful visual guide for commands like 11yy, 6>>, 9j, etc
- current line is assigned
- :set relativenumber! toggle relative number setting
- :set norelativenumber don't use relative line number prefix
See :h 5.9 for user manual about often used options.
Sessions
- :mksession proj.vim save the current Vim session with details like cursor position, file list, layout, etc
- you can customize things to be saved using the
sessionoptions
setting - for example, :set sessionoptions+=resize will save resized window information as well
- you can customize things to be saved using the
- :mksession! proj.vim overwrite existing session
- :source proj.vim restore Vim session from
proj.vim
filevim -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.
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:
- :wviminfo! proj.viminfo save the current internal Viminfo contents to the given file
- if
!
isn't used, you'll get a merged output based on the current internal Viminfo contents and the file contents
- if
- :rviminfo! proj.viminfo restore Viminfo from
proj.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.
Motion, editing and completion commands
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.
- ← and → move the cursor left and right respectively by one character
- you can also use the mouse to position the cursor
- Ctrl+← and Ctrl+→ move the cursor left and right respectively by one WORD
- you can also use the Shift key instead of Ctrl
- Note that in Insert mode this command moves by word, not WORD
- Ctrl+b or Home move to the beginning
- Ctrl+e or End move to the end
- Ctrl+w delete word before the cursor
- Ctrl+u delete all characters before the cursor
- Ctrl+r insert register contents
- Ctrl+r followed by % inserts the current file name
- Ctrl+r followed by a inserts the content of
"a
register
- Ctrl+r followed by = allows you to insert the result of an expression
- Ctrl+r followed by =12+1012 and then Enter key inserts
1024
- Ctrl+r followed by =strftime("%Y/%m/%d") and then Enter key inserts the current date, for example
2022/02/02
- Ctrl+r followed by =12+1012 and then Enter key inserts
- Ctrl+d show completions based on the characters typed so far
- Tab autocomplete based on the characters typed so far, pressing this key multiple times will cycle through the completions
- behavior can be customized using the
wildmode
setting
- behavior can be customized using the
- Ctrl+c cancel and go back to Normal mode
- Esc cancel and go back to Normal mode, depends on
cpoptions
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.
Command-line history
There are separate history lists for :
commands, searchpattern
, etc. These lists make it easy to reuse (after modifications if necessary) previously executed commands.
- ↑ and ↓ move through the history lists
- if you have already typed some characters, you will get only the commands starting with those characters
See :h cmdline-history for more details. You can change the number of entries that are remembered using the
history
setting.
Command-line window
You can also view, edit and execute the 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.
- q: window for
:
commands (from Normal mode) - q/ and q? window for search patterns (from Normal mode)
- Ctrl+f use this shortcut if you are already in the Command-line mode, opens appropriate
:
or search pattern windows automatically, any text you've typed so far will be preserved as the most recent command - Enter to execute the command under the cursor
- Ctrl+c continue editing the command under the cursor in the usual Command-line area, the window will still be visible
- :q quit the window and go to Normal mode
See :h cmdline-window for more details. You can change the number of entries that are remembered using the
history
setting.