Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Advanced Vim: splits, macros, plugins

By updated

Improve this page

You master the Vim basics, modes, motions, substitution, and you want to turn it into a real working environment. This guide goes beyond the certification corridor to cover what makes Vim productive day to day: working on several files side by side, automating repetitive tasks with macros, and extending the editor with plugins. By the end, you will have a complete .vimrc and an ecosystem comparable to a lightweight IDE. The commands and the configuration were replayed on Vim 9.1, the one shipped by Debian 13.

What you will learn

  • Organise several files with buffers, splits and tabs
  • Record and replay macros for repetitive tasks
  • Use the :g command to apply an action to every line matching a pattern
  • Install plugins with vim-plug
  • Set up a complete .vimrc that stays maintainable
  • Use 12 essential plugins that turn Vim into a terminal IDE

In which context?

The features in this guide are outside the certification core (LFCS/RHCSA). They come into play when Vim becomes your main editor: development, writing long-lived scripts, comparing configuration files, reshaping a CSV export. They assume a personal workstation where you can configure your environment, not a throwaway SSH session on a customer's server.

SituationUseful feature
Compare two versions of a configuration fileVertical splits (:vsp)
Reformat 100 lines of a CSV identicallyMacros (qa ... q then 100@a)
Add a prefix to every line containing "debug"Global command (:g/debug/normal I# )
Navigate a project of 200 filesfzf plugin (:Files)
Comment/uncomment a block of codevim-commentary plugin (gcc)
See Git changes in the marginvim-gitgutter plugin

Working with several files

As a sysadmin or developer, you rarely edit a single file. You often need to compare two configurations, read one file while changing another, or jump quickly between several scripts. Vim handles this with three complementary mechanisms: buffers, splits and tabs.

Buffers: keep several files in memory

When you open a file with :e, Vim loads it into a buffer (an area of memory). Think of buffers as a browser's hidden tabs: the files are open, but you only see one at a time.

CommandWhat it does
:e fileOpens a file in a new buffer
:lsLists every open buffer
:b2Switches to buffer no. 2
:bnMoves to the next buffer
:bpMoves to the previous buffer
:bdCloses the current buffer (without quitting Vim)

Splits: show several files side by side

Splits divide your screen to show several files at the same time. It is like having two sheets of paper open next to each other on your desk, each in its own window.

CommandWhat it does
:vsp fileVertical split (side by side)
:sp fileHorizontal split (one above the other)

To move between windows, the combination is always the same: Ctrl+w followed by the direction.

ShortcutNavigation
Ctrl+w hGo to the left window
Ctrl+w lGo to the right window
Ctrl+w jGo to the window below
Ctrl+w kGo to the window above
Ctrl+w =Equalise the size of every window
Ctrl+w cClose the current window
Ctrl+w oKeep only the current window

Here is an example with three open files, a Python script, a YAML file and a Bash script, all visible at the same time:

Three files open side by side in Vim with vertical and horizontal splits

This layout is very handy to compare two configuration files or to edit code while reading the documentation in the neighbouring window.

Tabs: separate work contexts

Tabs group sets of splits. If splits are the windows on your desk, tabs are virtual desktops. Useful to separate contexts: one tab for the code, one for configurations, one for logs.

CommandWhat it does
:tabnew fileOpens a file in a new tab
gtMoves to the next tab
gTMoves to the previous tab
:tabsLists every open tab
:tabcloseCloses the current tab

Automate with macros

Say you have a CSV file of 100 lines and you must reformat every line the same way: add a prefix, remove a column, change a separator. Doing it by hand would take hours. Vim macros let you record a sequence of actions and replay it as many times as needed.

Record and replay a macro

A macro is stored in a register (a memory slot identified by a letter).

  1. Start recording: press q followed by a letter to choose the register. For example, qa records into register a. You see recording @a appear at the bottom of the screen.

  2. Perform the actions: everything you type (moves, changes, insertions) is recorded. Work on a single line as a model.

  3. Stop recording: press q. The recording message disappears.

  4. Replay the macro: type @a to run the macro in register a. Type @@ to replay the last macro used.

Apply an action to a range of lines

The most direct way (without a macro) to comment lines 4 to 8:

:4,8normal I#

This command tells Vim: "on lines 4 to 8, run the normal command I#" (insert # at the start of the line). The normal keyword means that the keys that follow are read as in normal mode. To get # followed by a space, type a space after the #: it is invisible on screen, but Vim inserts it, as checked on Vim 9.1.

Apply an action to every line matching a pattern

You want to comment every line that contains the word debug:

:g/debug/normal I#

The :g/pattern/ command (for global) selects every line matching the pattern, then applies the action that follows. It is extremely powerful: you can, for example, delete every empty line with :g/^$/d.

Repeat a macro N times

To run macro a ten times in a row:

10@a

You do the work once by hand, then Vim repeats it 10, 100 or 1,000 times. For the repetitions to move forward, the macro must end with a move to the next line, otherwise they all apply to the same line.

Save a macro in .vimrc

Macros are lost when you close Vim. To keep one, add it to your .vimrc file between double quotes:

let @a="I# \<Esc>j"

This line pre-fills register a with the macro "insert # at the start of the line, go back to normal mode, move down one line". The double quotes are essential: between single quotes, Vim does not translate \<Esc>, and the macro inserts the text # \<Esc>j literally instead of leaving insert mode, as measured on Vim 9.1.

Customise Vim with .vimrc

The ~/.vimrc file is the heart of your Vim configuration. It is read at every launch. Each line matches a command you could type by hand, but which is applied automatically.

Think of .vimrc as your shell's .bashrc: it is where you define the settings that match your way of working.

Structure of a complete .vimrc

Here is a solid starting point with an explanation for each block. The set command accepts a comment at the end of the line, introduced by ": not every command does, as the Leader key shows further down.

" === Appearance ===
set number " Line numbers on the left
set relativenumber " Distance from the current line
set cursorline " Highlight the cursor line
set showmatch " Briefly highlight the matching bracket
set laststatus=2 " Status line always shown
" === Indentation ===
set tabstop=4 " A tab is worth 4 spaces
set shiftwidth=4 " Automatic indentation shifts by 4 spaces
set expandtab " Tab inserts spaces (not \t)
set autoindent " Keep the previous line's indentation
set smartindent " Add a level after { or if
" === Search ===
set incsearch " Real-time results while typing
set hlsearch " Highlight every match
set ignorecase " Case-insensitive search
set smartcase " UNLESS you type an uppercase letter
" === Comfort ===
set encoding=utf-8 " UTF-8 encoding
set scrolloff=8 " 8 lines visible around the cursor
set wildmenu " Completion menu on :e <Tab>
set mouse=a " Mouse on (click, scroll, selection)
set clipboard=unnamedplus " System clipboard integration

Persistent undo

By default, when you close a file and reopen it, the undo history is lost. Persistent undo saves that history to disk:

" === Persistent undo ===
set undofile
set undodir=~/.vim/undodir

Create the folder once and for all. Vim does not create it, and when it is missing, it writes no undo file without showing the slightest message: the history is lost on close as if the option were absent, which makes the failure hard to notice (measured on Vim 9.1):

Terminal window
mkdir -p ~/.vim/undodir

The Leader key

The Leader key is a prefix you choose to create custom shortcuts that do not get in the way of any existing Vim command. By convention, the Space key is ideal: easy to reach and unused in normal mode.

" === Leader key ===
let mapleader = " " " Space = Leader
" Space+w → save
nnoremap <leader>w :w<CR>
" Space+q → quit
nnoremap <leader>q :q<CR>
" Space+h → clear the highlighting
nnoremap <leader>h :nohlsearch<CR>

Here the comments go above the nnoremap lines, never at the end of the line: for a mapping command, everything that follows is part of the shortcut. Measured on Vim 9.1, a line nnoremap <leader>w :w<CR> " Space+w records a shortcut that types :w, confirms, then replays the spaces and the comment text in normal mode. :verbose nmap <leader>w shows what was really recorded.

The Space h shortcut is very handy: after a search, every match stays highlighted. Space h removes the highlighting without losing the search, which n keeps walking through.

Adapt indentation to the file type

A Python file uses 4 spaces, a YAML file uses 2. Vim can adjust automatically thanks to FileType autocommands:

filetype plugin indent on
autocmd FileType python set tabstop=4 shiftwidth=4 expandtab
autocmd FileType yaml set tabstop=2 shiftwidth=2 expandtab
autocmd FileType json set tabstop=2 shiftwidth=2 expandtab
autocmd FileType sh set tabstop=2 shiftwidth=2 expandtab

Apply changes without restarting

After editing your .vimrc, there is no need to close and reopen Vim:

:source ~/.vimrc

This command rereads the configuration file and applies the changes straight away. The autocmd lines are then registered a second time: without an augroup group, each :source adds a duplicate, with no visible effect here since each duplicate applies the same setting again.

Install plugins with vim-plug

So far, you have a well-configured but "bare" Vim. Plugins add features Vim does not have out of the box: a file explorer, Git integration, fuzzy search, modern colour schemes.

vim-plug is the most popular plugin manager (more than 35,000 stars on GitHub, 35,775 recorded on 1 October 2026). It downloads, installs and updates your plugins in one command.

Install vim-plug

The following command downloads vim-plug, pinned to the commit of its version 0.14.0 rather than to the tag, which a maintainer can move, then checks its SHA-256 checksum before Vim runs it. You only have to do it once; the file lands in ~/.vim/autoload/, which Vim loads on demand:

Terminal window
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/d80f495fabff8446972b8695ba251ca636a047b0/plug.vim
echo "20b4c895f98d13848204698068c4dd031730d4e7c9c4b630d6273b9b9afcdcdb $HOME/.vim/autoload/plug.vim" \
| sha256sum --check

The check must answer OK, recorded on 2026-10-01 against the 0.14.0 tag.

Declare plugins in .vimrc

Each Plug line matches one plugin. The quoted name is the GitHub repository (author/name), and the lines go between plug#begin and plug#end:

" === Plugins (vim-plug) ===
call plug#begin('~/.vim/plugged')
" Navigation and files
Plug 'preservim/nerdtree' " Tree file explorer
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } " Fuzzy search
Plug 'junegunn/fzf.vim' " fzf commands for Vim
" Editing
Plug 'tpope/vim-commentary' " Comment/uncomment with gcc
Plug 'tpope/vim-surround' " Change quotes/brackets
Plug 'tpope/vim-repeat' " Make . work with plugins
Plug 'jiangmiao/auto-pairs' " Automatic closing of (, [, {, "
" Git
Plug 'tpope/vim-fugitive' " Git commands from Vim
Plug 'airblade/vim-gitgutter' " +/~/- markers in the gutter
" Appearance
Plug 'morhetz/gruvbox' " Pleasant colour scheme
Plug 'itchyny/lightline.vim' " Coloured status line
Plug 'yggdroot/indentline' " Visual indentation guides
call plug#end()

Install the plugins

Save the .vimrc, restart Vim, then type:

:PlugInstall

vim-plug downloads and installs each plugin in parallel. The window shows the progress and a "Done!" message:

Installation of the 12 plugins with vim-plug, every plugin downloaded in parallel

Manage plugins day to day

Four commands cover a plugin's whole life cycle, from installation to clean-up; they all read the list declared in the .vimrc:

CommandWhat it does
:PlugInstallInstalls the new plugins added to .vimrc
:PlugUpdateUpdates every installed plugin
:PlugCleanRemoves the plugins whose Plug line was deleted
:PlugStatusShows the state of each plugin

To remove a plugin: delete its Plug line from .vimrc, then run :PlugClean.

The essential plugins in detail

The 12 plugins declared above cover common needs. Here is what each one brings, with the commands to know.

Gruvbox: a readable colour scheme

Problem solved: by default, Vim's scheme has little contrast. Gruvbox offers a palette of balanced warm colours, pleasant for long sessions. Keywords, strings, comments and functions each get a distinct colour.

Add these lines to your .vimrc after the plug#end() block:

" === Gruvbox scheme ===
set background=dark
colorscheme gruvbox
set noshowmode " Hide -- INSERT -- since lightline shows it

Vim with the Gruvbox scheme, Python syntax highlighting and line numbers

NERDTree: browse your files

Problem solved: without a plugin, to open a file you must type its full path with :e /path/to/file. NERDTree shows a tree on the left-hand side, as in VS Code.

" === NERDTree ===
nnoremap <leader>n :NERDTreeToggle<CR>

Press Space n to show or hide the explorer:

NERDTree showing a project tree with Python, YAML and Bash files

Useful keys in NERDTree:

KeyWhat it does
o or EnterOpen the file or expand the folder
sOpen in a vertical split
iOpen in a horizontal split
tOpen in a new tab
RRefresh the tree
mOpen the menu (create, rename, delete)
IShow/hide hidden files
qClose NERDTree

fzf.vim: find files instantly

Problem solved: on a project with hundreds of files, finding the right one by typing its full path is tedious. fzf (fuzzy finder) lets you type a few approximate letters and finds the file for you.

" === fzf ===
" Find a file by name
nnoremap <leader>f :Files<CR>
" Browse open files
nnoremap <leader>b :Buffers<CR>
" Search text across the whole project
nnoremap <leader>r :Rg<CR>

Fuzzy file search with fzf in Vim

The :Rg command (Ripgrep) searches content inside files, like an ultra-fast grep built into Vim, and shows the matches in a filterable list.

vim-fugitive: use Git without leaving Vim

Problem solved: to run a git status, you normally have to leave Vim, type the command, then come back. vim-fugitive brings Git straight into Vim, with commands named after their shell equivalent:

CommandShell equivalentWhat it does
:Git or :Ggit statusInteractive summary of the changes
:Git diffgit diffCompares with the last commit
:Git blamegit blameWho changed each line, and when
:Git loggit logCommit history
:Gwritegit add fileStages the current file
:Greadgit checkout fileDiscards the local changes

vim-gitgutter: see changes in the gutter

Problem solved: when you edit a versioned file, it is hard to know which lines changed. vim-gitgutter shows coloured markers in the gutter (the thin column left of the line numbers):

vim-gitgutter showing change markers in the gutter

MarkerColourMeaning
+GreenAdded line
~YellowChanged line
-RedDeleted line

The quick navigation shortcuts only exist in a file tracked by Git: the plugin creates them buffer by buffer, when a versioned file is opened.

ShortcutWhat it does
]cJumps to the next change
[cJumps to the previous change
<leader>hpPreviews the change
<leader>huUndoes the local change

vim-surround: handle quotes and brackets

Problem solved: changing single quotes into double ones, or wrapping a word in brackets, normally takes several steps. vim-surround does it in a single command, and every row of the table was replayed on Vim 9.1:

SituationCommandBeforeAfter
Change the quotescs"'"hello"'hello'
Turn into an HTML tagcs'<p>'hello'<p>hello</p>
Remove the quotesds""hello"hello
Add quotes around a wordysiw"hello"hello"
Wrap the line in bracketsyss(hello world( hello world )

The syntax follows the principle action + s + old + new. cs"' = change surround " into '. The opening bracket ( adds spaces inside; the closing one ) leaves them out.

vim-commentary: comment with one key

Problem solved: commenting code means knowing the right character for each language (# in Python, // in JavaScript, " in vimscript). vim-commentary detects the language automatically:

CommandWhat it does
gccComment/uncomment the current line
gcapComment the whole paragraph
gc3jComment the current line and the next 3
visual selection + gcComment the whole selection

lightline.vim: an informative status line

Problem solved: Vim's default status line is hard to read. lightline replaces it with a coloured line that shows the mode (NORMAL, INSERT, VISUAL…), the file name, the encoding and the position.

" === Lightline ===
let g:lightline = { 'colorscheme': 'gruvbox' }

auto-pairs: automatic closing of delimiters

Problem solved: when you type (, you have to type ) later. auto-pairs adds it automatically and puts the cursor between the two. It works with [, {, ", ', `. To prevent the closing in a given case, type Ctrl+v before the character, which is then inserted as is.

indentLine: visualise indentation

Problem solved: in YAML or Python files, indentation is significant: one space too many changes the meaning of the file. indentLine shows thin vertical lines at each indentation level to help you align correctly.

Complete .vimrc summary

Here is the complete configuration that gathers every setting and plugin presented, followed by a quick installation in five commands. It was loaded as is in a Debian 13 container: the 12 plugins install and colorscheme answers gruvbox.

" ============================================
" .vimrc: complete Vim configuration
" ============================================
" === Appearance ===
set number
set relativenumber
set cursorline
set showmatch
set laststatus=2
set noshowmode
" === Indentation ===
set tabstop=4
set shiftwidth=4
set expandtab
set autoindent
set smartindent
filetype plugin indent on
" === Search ===
set incsearch
set hlsearch
set ignorecase
set smartcase
" === Behaviour ===
set encoding=utf-8
set scrolloff=8
set wildmenu
set mouse=a
set clipboard=unnamedplus
" === Persistent undo ===
set undofile
set undodir=~/.vim/undodir
" === Leader key ===
let mapleader = " "
nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>h :nohlsearch<CR>
" === Plugins (vim-plug) ===
call plug#begin('~/.vim/plugged')
Plug 'preservim/nerdtree'
Plug 'tpope/vim-commentary'
Plug 'itchyny/lightline.vim'
Plug 'tpope/vim-fugitive'
Plug 'airblade/vim-gitgutter'
Plug 'tpope/vim-surround'
Plug 'tpope/vim-repeat'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'jiangmiao/auto-pairs'
Plug 'morhetz/gruvbox'
Plug 'yggdroot/indentline'
call plug#end()
" === Scheme ===
set background=dark
colorscheme gruvbox
" === NERDTree ===
nnoremap <leader>n :NERDTreeToggle<CR>
" === fzf ===
nnoremap <leader>f :Files<CR>
nnoremap <leader>b :Buffers<CR>
nnoremap <leader>r :Rg<CR>
" === Lightline ===
let g:lightline = { 'colorscheme': 'gruvbox' }
" === Per file type configuration ===
autocmd FileType python set tabstop=4 shiftwidth=4 expandtab
autocmd FileType yaml set tabstop=2 shiftwidth=2 expandtab
autocmd FileType json set tabstop=2 shiftwidth=2 expandtab
autocmd FileType sh set tabstop=2 shiftwidth=2 expandtab

Leader shortcuts summary

Once your .vimrc is in place with the plugins, here are all the available shortcuts with the Leader key (Space). :nmap <leader> lists them from Vim, with their exact definition:

ShortcutAction
Space wSave
Space qQuit
Space hClear search highlighting
Space nOpen/close NERDTree
Space fFuzzy file search
Space bBrowse buffers
Space rText search across the project

Troubleshooting

Most failures of an enriched .vimrc come down to a plugin not installed, a Vim binary built without a feature, or a misplaced line in the file. The table follows that order.

SymptomLikely causeSolution
The Gruvbox scheme does not showPlugin not installed:PlugInstall then restart Vim
E185: Cannot find color scheme 'gruvbox'First launch, before :PlugInstallInstall the plugins, then restart Vim
E492: Not an editor command: PlugInstallvim-plug missingRerun the installation curl command
System copy and paste do not workVim built without +clipboardsudo apt install vim-gtk3
fzf :Rg finds nothingripgrep not installedsudo apt install ripgrep
NERDTree does not openPlugin not installedCheck the Plug line and rerun :PlugInstall
The Space+... shortcut does nothingLeader misplacedlet mapleader = " " must come before the nnoremap lines
A shortcut does strange things after its actionComment at the end of an nnoremap lineMove the comment above, check with :verbose nmap
A saved macro inserts \<Esc> literallylet @a='…' between single quotesWrite let @a="…"
E518: Unknown option: undodirVim too oldUpgrade to Vim 7.3+
u no longer undoes anything after reopening, without any messageMissing undodir folder, which Vim does not reportmkdir -p ~/.vim/undodir

Key points

  • Buffers (:ls, :bn, :bp) keep several files in memory, much faster than reopening them each time.
  • Splits (:vsp, :sp, Ctrl+w navigation) let you see several files side by side.
  • Macros (qa ... q then @a or 10@a) automate repetitive tasks; in .vimrc, you freeze them with let @a="…", between double quotes.
  • The global command :g/pattern/action applies an action to every line matching a pattern, extremely powerful on log or configuration files.
  • An nnoremap accepts no comment at the end of the line: the text would become part of the shortcut.
  • vim-plug installs and manages plugins in one line; the 12 plugins presented cover everyday needs (files, Git, search, editing, appearance).
  • The .vimrc is built gradually: start minimal and add options when you feel the need.
  • Keep your .vimrc in a Git repository (dotfiles) to find it on every machine.

Knowledge check

Check that the essentials of this guide are acquired. The questions only cover what has just been explained here.

Knowledge check

Check what you have learned with this interactive quiz

6 questions
6 min
70% to pass

How it works

  • The timer starts when you click Start
  • Multiple choice, true/false and short answer questions
  • You can move between questions
  • Detailed results are shown at the end

Starts the quiz and the timer

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn