Customizing Vim

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:

Editing vimrc

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:

  • :e $MYVIMRC if you already have a vimrc file, you can use this predefined variable to open it
  • :h vimrc to find out where the vimrc file should be located for your OS
  • :source $MYVIMRC apply changes from within your current Vim session

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

defaults.vim

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.

  • source $VIMRUNTIME/defaults.vim add this to your vimrc file if you want to keep these defaults
  • :h defaults.vim-explained describes the settings provided by defaults.vim

Alternatively, you can copy only the parts you want to retain from the defaults.vim file to your vimrc file.

General Settings

info set syntax and guidelines were introduced in the Setting options section.

  • set history=200 increase default history from 50 to 200
    • as mentioned in the Command-line mode chapter, there are separate history lists for : commands, search patterns, etc
  • set nobackup disable backup files
  • set noswapfile disable swap files
  • colorscheme murphy a dark theme
    • you can use :colorscheme followed by a space and then press Tab or Ctrl+d to get a list of the available color schemes
  • set showcmd Command-line area will show partial Normal mode commands and character/line/block-selection for Visual mode
  • set wildmode=longest,list,full use bash-like tab completion
    • first tab will complete as much as possible
    • second tab will provide a list
    • third and subsequent tabs will cycle through the completion options

info :h 'history' will give you the documentation for the given option (note the use of single quotes).

info 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 the vimrc, which will be discussed in the CLI options chapter.

Further Reading

Text and Indent Settings

  • filetype plugin indent on enables loading of plugin and indent files
    • these files become active based on the type of the file to influence syntax highlighting, indentation, etc
    • :echo $VIMRUNTIME gives your installation directory (indent and plugin directories would be present in this path)
    • see :h vimrc-filetype, :h :filetype-overview and :h filetype.txt for more details
  • set autoindent copy indent from the current line when starting a new line
    • useful for files not affected by the indent setting
    • see also :h smartindent
  • set textwidth=80 guideline for Vim to automatically move to a new line with 80 characters as the limit
    • white space is used to break lines, so a line can still be greater than the limit if there's no white space
    • default is 0 which disables this setting
  • set colorcolumn=80 create a highlighted vertical bar at column number 80
  • set shiftwidth=4 number of spaces to use for indentation (default is 8)
  • set tabstop=4 width for the tab character (default is 8)
  • set expandtab use spaces for tab expansion
  • set cursorline highlight the line containing the cursor

Search Settings

  • set hlsearch highlight all matching portions
    • using :noh (short for :nohlsearch) will clear the currently highlighted portions
  • set incsearch highlights current match as you type the pattern, the screen is updated automatically as needed
    • pressing the Enter key would move the cursor to the matched portion
    • pressing the Esc key would keep the cursor at the current location
    • other matching terms will be highlighted based on the hlsearch setting

Custom mapping

Mapping 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 mapping
  • xnoremap Visual mode non-nested, non-recursive mapping
  • inoremap Insert mode non-nested, non-recursive mapping
  • inoreabbrev Insert mode non-nested, non-recursive abbreviation

The 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 mappings
  • nunmap, 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)
    • use mapclear instead of unmap to clear all the mappings for that particular mode
  • onoremap (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

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

Normal mode

  • nnoremap <F2> :w<CR> press F2 function key to save changes
    • <F2> represents the F2 function key and <CR> represents the Enter key
    • I chose F2 since it is close to the Esc key (F1 opens help page)
  • nnoremap <F3> :wq<CR> press F3 to save changes and quit
  • nnoremap <F4> ggdG press F4 to delete everything
  • nnoremap <F5> :%y+<CR> press F5 to copy everything to the system clipboard
  • nnoremap <left> <nop> do nothing when the arrow key is pressed
    • likewise, you can map the other arrow keys to do nothing
  • nnoremap Y y$ change Y to behave similarly to D and C
  • nnoremap / /\v add very magic mode modifier for forward direction search
  • nnoremap ? ?\v add very magic mode modifier for backward direction search
  • nnoremap <silent> <Space> :noh<CR><Space> press Space key to clear the currently highlighted portions
    • <silent> modifier executes the command without displaying in the Command-line area
    • Note that this mapping also retains the default behavior of the Space key
  • nnoremap <A-1> 1gt press Alt+1 to switch to the first tab
    • I prefer this to make switching tabs consistent with browser and terminal shortcuts
  • nnoremap <A-2> 2gt press Alt+2 to switch to the second tab and so on

info See :h map-which-keys to know which keys are not already Vim commands, which ones are not commonly used, etc.

info See :h key-notation for a list of keys that can be represented using the <> notation.

Map leader

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.

  • nnoremap <Leader>f gg=G if mapleader hasn't been set, using \f will auto indent the code for the whole file
  • let mapleader = ";" change the leader key to ;
    • nnoremap <Leader>f gg=G this will now require ;f since the leader key was changed

info See learnvimscriptthehardway: Leaders for more examples and details.

Insert mode

  • inoremap <F2> <C-o>:w<CR> press F2 to save changes in Insert mode as well
    • Ctrl+o is used here to execute a command and return back to Insert mode automatically
    • imap <F2> <C-o><F2> can also be used if you've already defined the Normal mode mapping
  • inoremap <C-f> <Esc>ea press Ctrl+f to move to the end of the word
    • I'd prefer Ctrl+e but that is useful to cancel autocompletion
  • inoremap <C-b> <C-Left> press Ctrl+b to move to the beginning of the word
  • inoremap <C-a> <End> press Ctrl+a to move to the end of the line
  • inoremap <C-s> <Home> press Ctrl+s to move to the start of the line
  • inoremap <C-v> <C-o>"+p press Ctrl+v to paste from the clipboard
    • If you need Ctrl+v functionality, the Ctrl+q alias can be used to insert characters like Enter key (but this alias may not work in some terminals)
  • inoremap <C-l> <C-x><C-l> press Ctrl+l to autocomplete matching lines

info Use noremap! if you want a mapping to work in both Insert and Command-line modes.

Visual mode

  • xnoremap * y/<C-R>"<CR> press * to search the visually selected text in the forward direction
    • recall that Ctrl+r helps you insert register contents in Command-line mode
  • xnoremap # y?<C-R>"<CR> press # to search the visually selected text in the backward direction

info Note that xnoremap is used here since vnoremap affects both Visual and Select modes.

Abbreviations

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

    • you can trigger the abbreviation completion using non-keyword characters such as Esc, Space and Enter keys, punctuation characters and so on
    • use Ctrl+] to expand the abbreviation without adding anything extra
    #!/usr/bin/env perl
    use strict;
    use warnings;
    
    
  • inoreabbrev py #!/usr/bin/env python3 expand py to #!/usr/bin/env python3

    • this might cause issues if you need py literally (for example, script.py)
    • you can use something like [p or @p instead
  • inoreabbrev 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

    • this one works best when you type @a followed by the Esc key to place the cursor at the end of the first line
    always @()
    begin
    end
    
  • :abbreviate or :ab list all abbreviations

info See :h 24.7 for more details about using abbreviations.

Matching Pairs

  • set matchpairs+=<:> add <> to the list of pairs matched by the % command in Normal mode

info To match keywords like if-else pairs with %, you can use the matchit.vim plugin. This supports filetypes such as HTML, Vim, LaTeX, XML, etc. See :h matchit-install for more details.

GUI options

  • set guioptions-=m remove menu bar
  • set guioptions-=T remove tool bar

info See :h guioptions for more details.

Third-party customizations

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

plugin

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 file_1.vim file_2.vim ~/.vim/plugin/python/

If you want to add plugins that should work based on a specific filetype, add them to the ftplugin directory:

$ mkdir -p ~/.vim/ftplugin
$ cp ftplugin_file.vim ~/.vim/ftplugin/

package

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.

  • packadd! matchit enable matchit package
    • this plugin comes with Vim, see :h matchit for further details
    • ! is used to prevent loading this plugin when Vim is started with the --noplugin CLI option

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

  • ysiw] will surround a word with [], for example hello to [hello]
  • cs"' will change text surrounded by double quotes to single quotes, for example "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
  • :packadd vim-surround enable this package from Command-line mode
  • packadd! vim-surround enable this package in vimrc (usually under some condition)

color scheme

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.

info See also this collection of awesome color schemes for Vim.

autocmd

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
  • augroup helps you to group related autocommands
  • autocmd! removes all autocommands within a group (pyg in the above example)
    • useful to avoid autocommands getting defined again when you source the vimrc file
  • :autocmd list all autocommands, you can provide arguments to narrow down this listing

info warning Note that in earlier versions of Vim, double quotes is used for comments as shown in the above snippet. You'll need to use the # character instead for vim9script. See vim9-conversion-aid for upgrading old scripts.

See also:

Further Reading