Command-line mode

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:

info Recall that you need to add : or c_ 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
    • use w! to create a new file if it doesn't exist
  • :wa save all changed buffers (:wa is short for :wall)

info 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.

info 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.

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 provides a prompt for every file that has unsaved changes

info Append ! to discard unsaved changes and quit.

Combining Save and Quit

  • :wq save changes and quit
  • :wqa save changes for all files and quit

info 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 #)
  • 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

info 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.

info See :h 'autowrite' option if you want to automatically save changes when moving to another buffer.

info See :h 22.4 and :h buffer-hidden for user and reference manuals on working with buffer list.

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
  • :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

info Buffer list includes all the files opened in all the tabs.

info 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

info If filename is not provided, the current one is used.

info 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 and perl instead.
  • See :h :bufdo, :h :windo and :h :silent for more details.

Further reading

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 or noexpandtab depending on whether it is switched on or off
  • set {option} get the current value of number or string option
    • for example, try :set history or :set ww

info See :h options.txt for complete list of usage guidelines and available options.

  • /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
  • N move to the next match in the opposite direction as 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 of s, but it'll change to s after the command is executed
  • /searchpattern/s+2 place the cursor 2 characters after the start of the match (i.e. 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
  • :noh clear currently highlighted patterns, if any (:noh is short for :nohlsearch)

info 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.

info You can prefix a count value to /, ?, n and N commands. Also, searching will automatically wrap around when it reaches the top or bottom of the file contents, unless you set the nowrapscan option.

info Characters like ., ^, $, etc have special meaning in the searchpattern. 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 use range to change the lines that are acted upon.

  • :d delete the current line (:d is short for :delete command)
  • :.w filename save the current line (represented by .) to the given filename
    • recall that by default :w works on the entire file
  • :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 :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
  • :2,10d delete second to tenth lines (comma is used here to separate start and end ranges)
  • :5,$d delete fifth line to the last line
  • :5,$-1d delete fifth line to the last but one line
  • :%d delete all the lines (% is a shortcut for 1,$ 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 (total 2 lines)
    • using ; will set the line matched by the first pair of the range as the current line for the second pair
  • :/pat1/;-2d delete the line matching pat1 as well as two lines before (total 3 lines)
  • :5;/pat1/d delete from 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 ;
  • :'a,'bd delete from the line marked by a to the line marked by b

info 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.

info See :h 10.3 and :h cmdline-ranges for more details.

info See :h ex-cmd-index for a complete list of : commands.

Search and Replace

:[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.

  • : s/a/b/ replace the first occurrence of a with b 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
  • :2 s/apple/Mango/i replace the first occurrence of apple with Mango on the second line only
    • i flag matches the searchpattern case insensitively
  • :3,6 s/call/jump/g replace all the occurrences of call with jump on lines 3 to 6
    • g flag performs search and replace for all the matching occurrences
  • :5,$ s/call/jump/g replace all the occurrences of call with jump from the fifth line to the end of the file
  • :% s/call/jump/g replace all the occurrences of call in the file with jump
    • recall that % is a shortcut for the range 1,$

info 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.

info See Regular Expressions chapter for more details on the substitute command.

Editing lines filtered by a pattern

:[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.

  • :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
  • :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 with mammal only for the lines containing cat
  • :.,.+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

info In addition to the / delimiter, you can also use any single byte character other than alphabets, \, " or |.

info 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 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 d and y commands, !G will give :.,$!
  • :%! sort sort all the lines
    • recall that % is a shortcut for the range 1,$
    • note that this executes an external command, not the built-in :sort command
  • :3,8! sort sort only lines 3 to 8
  • :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
  • :.!grep '^Help ' % replace the current line with all the lines starting with Help in the current file
    • % here refers to current file contents
  • :sh open a shell session within Vim
    • use exit command to quit the session

info See :h :!, :h :sh and :h :r for more details.

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
  • :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
  • 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 Customizing Vim chapter)
  • Ctrl+w followed by : go to Command-line mode from terminal window

info Depending on your shell, you can use the exit command to end the terminal session. Ctrl+d might work too.

info 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 number 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 assigned 1, two lines above and below are assigned 2 and so on
    • useful visual guide for commands like 11yy, 6>>, 9j, etc
  • :set relativenumber! toggle relative number setting
  • :set norelativenumber don't use relative line number prefix

info 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
  • :mksession! proj.vim overwrite existing session
  • :source proj.vim restore Vim session from proj.vim file
    • vim -S proj.vim restore a session from the command line when launching Vim

info See :h 21.4, :h views-sessions and :h 'sessionoptions' for more details.

info 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, the viminfo 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
  • :rviminfo! proj.viminfo restore Viminfo from proj.viminfo file
    • ! overwrites any existing internal settings
    • vim -i proj.viminfo restore Viminfo from the command line when launching Vim

info 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
    • if available, 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 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+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
  • Ctrl+c cancel and go back to Normal mode
  • Esc cancel and go back to Normal mode, depends on cpoptions setting

info 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 used commands.

  • and move through the history lists
    • if you have already typed some characters, you will get only the commands starting with those characters

info 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 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

info See :h cmdline-window for more details. You can change the number of entries that are remembered using the history setting.