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 (
:wis 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 (
:wais 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 (
:qis 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 (
:qais 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 (
:eis 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
eand#)
- :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 (
:bnis short for:bnext)- opens the first buffer if you are on the last buffer
- :bp open the previous file in the buffer list (
:bpis 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 (
:tabeis short for:tabedit)- if
filenameisn'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 (
:tabnis 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 (
:tabpis 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 (
:tabris short for:tabrewind)- :tabfirst can also be used
- :tabl switch to the last tab (
:tablis short for:tablast) - :tabm N move the current tab to after
Ntabs from the start (:tabmis 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
Npositions to the right - :tabm -N move the current tab
Npositions 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
hjklor 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
silentskips 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,awkandperlinstead.- 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
expandtabornoexpandtabdepending 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 tosafter the command is executed
- /searchpattern/s+2 place the cursor
2characters after the start of the match (i.e. the third character of the match) - /searchpattern/s-2 place the cursor
2characters before the start of the match - /searchpattern/e place the cursor at the end of the match
- /searchpattern/e+4 place the cursor
4characters after the end of the match - /searchpattern/e-4 place the cursor
4characters before the end of the match - /searchpattern/+3 place the cursor
3lines below the match - /searchpattern/-3 place the cursor
3lines 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
hlsearchsettings - 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 (
:nohis 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
/,?,nandNcommands. Also, searching will automatically wrap around when it reaches the top or bottom of the file contents, unless you set thenowrapscanoption.
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 (
:dis short for the:deletecommand) - :.w filename save the current line (represented by
.) to the given filename- recall that by default
:wworks 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 (
:mis short for the:movecommand)- the number following
mis the line number after which you want to place the lines specified by the range - use
:t(or:coor: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
pat1as well as the line after (total2lines)- 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
pat1as well as two lines before (total3lines) - :5;/pat1/d delete from the fifth line to a line matching
pat1after 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
ato 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:.,.+9as 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
awithbon 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
applewithMangoon the second line onlyiflag matches thesearchpatterncase insensitively
- :3,6 s/call/jump/g replace all the occurrences of
callwithjumpon lines3to6gflag performs search and replace for all the matching occurrences
- :5,$ s/call/jump/g replace all the occurrences of
callwithjumpfrom the fifth line to the end of the file - :% s/call/jump/g replace all the occurrences of
callin the file withjump- recall that
%is a shortcut for the range1,$
- recall that
You can leave the
searchpatternas empty to reuse the previously searched pattern, which could be from/,?,*,scommand, 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
dNormal 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
"aregister - :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
callonly 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
animalwithmammalonly for the lines containingcat - :.,.+20 g/^#/ normal >> indent the current line and the next
20lines only if the line starts with#- Note the use of
normalwhen 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 thedandycommands, !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
:sortcommand
- recall that
- :3,8! sort sort only lines
3to8 - :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
Helpin the current file%here refers to the current file contents
- :sh open a shell session within Vim
- use the
exitcommand 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
splitbelowoption 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
splitrightoption 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
Nhere)- 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
exitcommand to end the terminal session.Ctrl+dmight 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 assigned2and 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
sessionoptionssetting - 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.vimfilevim -S proj.vimrestore 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
viminfofile 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
viminfofile. When Vim starts again, theviminfofile 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.viminfofile!overwrites any existing internal settingsvim -i proj.viminforestore 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
"aregister
- 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
wildmodesetting
- 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
cpoptionssetting
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
historysetting.
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
historysetting.