Vim’s screen always contains at least the following elements:

  • one tab page, containing at least…​

  • one window, displaying…​

  • one buffer.

At the root of that tree—and at the center of Vim’s design—is the buffer; then comes the window and, finally, the tab page. Vim will quit when you delete the last buffer, close the last window or close the last tab page.

Buffers

Like Microsoft Word or Adobe Photoshop, Vim lets us create, delete, switch to, and edit “buffers” (Vim’s word for “documents”). Like in Microsoft Word or Adobe Photoshop, those buffers:

  • can be associated with an actual file or not,

  • are written to disk only if you instruct Vim to do so.

Similarly, Vim will tell you when you are trying to quit without saving a currently opened buffer so, well…​ Vim is not that weird, after all.

Buffers are just abstract containers for your text so there’s not much to say about their look.

Windows

An interesting feature of Vim is the ability to split the screen in multiple windows—often called “splits”—to display different buffers or parts of a buffer. The exact mechanism is quite simple: the current window is split in two equal parts and the cursor is placed in the new window.

The purpose of a window is to provide a view into a buffer. A window can be created, moved around and closed, but it is important to remember that windows and buffers are not coupled at all. Since any buffer could end up being displayed in any window it is plain wrong to assume “switching to a window” to be the same as “switching to a buffer”, let alone “switching to a file”.

On the visual side of things, each window gets its own “status line” and, only in GVim/MacVim, its own scrollbar.

Tab pages

In the same way windows are an abstraction built on top of buffers, tab pages are an abstraction built on top of windows.

Tab pages—too often called “tabs”—have been a neverending source of confusion since their appearance in Vim 7.0. Despite their name and how the “tab line” widget is implemented, Vim’s tab pages are not like other editor’s tabs.

In other editors, “tabs” serve as proxies for documents. This means that the editor’s “tab line”—a list of tabs—is effectively a list of documents: one navigates from one tab to another and thus from one document to another. A “tab” is for all intent and purpose a document and there is no need to abstract away the tab widget from its associated “panel” and thus from the document it is associated with.

In those editors, switching to a “tab” is exactly like switching to a document.

In Vim, “tab pages” are workspaces, associated with “tab” widgets, themselves listed in a “tab line”. The “tab” and “tab line” widgets work pretty much like their counterparts in other editors but the huge difference lies in the workspace bit.

A tab page is just like a workspace: a place where you arrange one or more windows displaying one or more buffers. But we have seen earlier that buffers are global so, while it is entirely possible to have a single buffer displayed in a single window in a single tab page, it is impossible to force an actual one-to-one relationship between that buffer and that tab page without devising our own buffer/window/tab management paradigm.

Because “tab” widgets are not associated with specific buffers we simply can’t use them as document proxies.

As collections of windows, tab pages offer a pretty good way to manage workspaces. They are ideal for when we need to have multiple pairs of files displayed side-by-side, or when we suddenly need to open a file from outside the current project…​ But they are too limited to be used as document/file proxies.

Just like windows, the place of tab pages in our workflow depends largely on our needs. Using tab pages as document/file proxies is wrong, but refusing to use them altogether in the name of some imaginary purity is just as wrong. If not more.

Buffers, window, and tab pages are explored thoroughly in the following chapter.

Special Windows

Beyond the regular window described above, Vim uses a number of very useful specialized windows.

The quickfix window

The quickfix window is a special kind of window used to list the entries of the the quickfix list. The quickfix list is a handy list of addresses that we can populate and navigate at will. Each entry in the list is roughly made of:

  • a filename,

  • a line number,

  • an optional column number,

  • some text associated with the current item.

That list—and its associated window—is global so you can’t have more than one active at the same time; But it’s pefectly possible to recall up to nine previous lists with :colder.

Vim comes with a lot of commands that populate the quickfix list, like :grep or :vimgrep, used for searching text in your project, and :make, used to build your program or pass them through a syntax checker. Once the quickfix list is populated with valid entries, one can use a number of relatively intuitively named commands to navigate it:

command

description

:cfirst

jumps to the first entry

:clast

jumps to the last entry

:cnext

jumps to the next entry

:cprevious

jumps to the previous entry

or :cwindow to open the interactive “quickfix window”.

One can navigate around the buffer displayed in that window with regular commands like /foo or 5j and jump to the current entry with:

command

description

<CR>

jumps to the current entry in the window above the quickfix window

<C-w><CR>

jumps to the current entry in a new window

(gifcast)

The quickfix list and quickfix window have close cousins called “location list” and “location window” that pretty much work the same way except for these two differences:

  • unlike the quickfix list, the location list is local to a window so you can have as many location lists and location windows as you have windows,

  • the commands start with an l instead of a c: :lfirst, :lwindow, etc.

Using the location list can be useful if you are heavily into windows and tab pages but the quickfix list is probably a simpler choice.

Reference

:help quickfix
:help map_bar

The preview window

The preview window is a small window used to preview something, typically the signature of a function while we are working on its usage. It is a lot like a normal window except for these differences:

  • opening the preview window doesn’t steal the focus from the current window,

  • there is only one preview window per tab page,

  • it can be closed even if it is not focused.

This window can be opened with a bunch of commands, among which these ones:

command

description

:ptag foo

open tag 'foo' in a preview window

<C-w>}

open tag under the cursor in a preview window

:psearch bar

use include search to find 'bar' and open it in a preview window

And closed with: :pclose or <C-w>z.

Here is the preview window in action:

(gifcast)

Reference

:help preview-window

The Command-line window

The command-line is a handy way to input commands but it is not that good when it comes to editing the current command or recalling an old one and changing its parameters. This is not a design flaw or an implementation issue, though: only sane separation of concerns that should appeal to anyone used to the concept of modal editing.

You use insert mode to insert text and normal mode to edit text.

You use command-line mode to issue commands and the command-line window to edit the current command and command history.

Simple.

Opening the command-line window from the current command-line mode is done with <C-f>. This will open the relevant command history in the command-line window, with the current command ready for you to edit on the last line.

From normal mode, you can use q: to open the command-line history or q//q? to open the search history, with the cursor in an empty line. Press <CR> in normal mode to run the current command or :q to quit that window.

Here is the command-line window in action:

(gifcast)

Some hardcore Ex command users like to use the command-line window instead of the usual command-line. This can be done by overriding : in normal mode:

nnoremap : q:i

I don’t recommend doing that, actually, but I think it is an interesting example of customization.

Reference

:h cmdline-window

Various UI elements

In addition to windows, we have many UI elements at our disposal for displaying information and/or interacting with one feature or another.

The tab line

(picture)

The tab line is a list of "tabs" working as proxies for tab pages. Each tab shows some information on its associated tab page:

  • the name of the buffer currently displayed in the currently focused window,

  • the number of windows contained in the tab page when there is more than one,

  • a + if one of the buffers displayed in one of the windows is "dirty".

If you have enabled mouse support in your vimrc and your terminal emulator supports that feature, you can use your mouse to switch to a tab page, reorder the tabs or close the current tab page by clicking on the X at the end of the tab line.

When to show a tab line can be defined with the showtabline option and what information to display depends on the tabline option.

While Vim’s tab pages are definitely not equivalent to other editor’s tabs, Vim’s tab line looks and works a lot like its counterparts and suffers from the same usability issues.

The main issue is that tabs are used to display filenames and filenames take up a lot of horizontal space. An horizontal space that is physically limited and thus incapable of displaying more than a few tabs. Many solutions exist to remedy that problem: wrapping the tab line to form a second one, adding scrolling widgets at both ends of the tab line, grouping tabs, truncating filenames…​ The harsh reality is that none of those "solutions" is free of annoying side effects which, ultimately, can turn an otherwise good idea into an unusable gyzmo.

The tab line and tab pages still have their use, mind you, but it is important to not think about them as you would in other editors.

Reference

:help 'showtabline'
:help 'tabline'
:help setting-tabline

The status line

(picture)

The status line is that “bar”, at the bottom of windows, used to show information on the window itself or the buffer currently displayed in that window. It can also be used to resize windows vertically if mouse support is enabled.

By default, the status line is shown only when there is more than one window but this can be changed with the laststatus option:

set laststatus=2

The default content of the status line—the filename and a status indicator—is not exactly thrilling but it’s possible to beef it up by enabling the ruler option that shows the line and colum of the cursor and tells how much of the buffer is currently visible.

It is very common, though, to customize it a bit further by playing with the statusline option that gives more control over the status line’s content and appearance.

This is how I define the status line shown in the picture above, the explanation for each item can be found in :help 'statusline':

set statusline=%<\ %f\ %m%r%y%w%=\ L:\ \%l\/\%L\ C:\ \%c\
                                                         |
                                                         +-- there's a space, here

It is also possible to define colors for specific parts or use functions to display dynamic information not provided by Vim but I recommend measure, here: the status line is an information device, not a decorative widget.

Reference

:help 'laststatus'
:help 'ruler'
:help 'statusline'

Line numbers

Showing line numbers is a fairly straightforward feature that doesn’t deserve much explanation. One enables it with :set number, disables it with :set nonumber and decides how much room it takes with :set numberwidth=6.

In most editors or IDEs, line numbers are only used directly by users in two ways: to communicate with other people who work on the same code and to jump to a specific line.

In addition, Vim allows us to use line numbers as prefix for many normal mode commands or to define the range and/or the address for many Ex commands:

command

description

33G

go to line 33

V13G

linewise visual selection from here to line 13

:2t24

copy line 2 after line 24

:m12

move current line after line 12

:8,17d

delete lines 8 to 17

:46put=@f

put content of register f after line 46

But we are not limited to absolute line numbers: we can use relative line numbers to see how far a line is from the current line.

(screenshot)

Relative numbers can be enabled with set relativenumber and used in the same way as absolute line numbers:

command

description

6j

go down 6 lines

V5k

linewise visual selection from here to 5 lines above

:-2,+6m45

move lines from 2 lines above to 6 lines below after line 45

Reference

:help 'number'
:help 'numberwidth'
:help 'relativenumber'

The fold column

(picture)

The “fold column” is disabled by default but can be enabled by setting the foldcolumn option to a number between 1 and 12. It is used to show information about the folds in your buffer and to let you open and close them with the mouse if mouse support is enabled.

Open folds are marked with a clickable -, lines belonging to a fold are marked with a | and closed folds are marked with a clickable +.

Reference

:h fold-foldcolumn
:h 'foldcolumn'

The sign column

(picture)

The “sign column” can’t be shown or hidden easily. Actually, only plugin authors have to manage signs so they are not really the most interesting feature to explore. Vim shows the sign column when you have one or more signs in your buffer, removes it when there’s no sign anymore and that’s about it.

The color and content of individual signs is usually defined by plugin authors whereas the background of the column is the responsibility of your colorscheme.

Reference

:help signs

The vertical split

(picture)

The “vertical split” is the vertical bar that separates two windows. Like the status line, it can be dragged with the mouse to resize windows and…​ that’s about it.

It’s style is defined by the VertSplit highlight group and the character used to draw it can be changed with the fillchars option. In the example below, a simple space is used instead of the original “pipe” character:

:set fillchars+=vert:\
                      |
                      +-- there's a space, here

Reference

:help hl-vertsplit
:help 'fillchars'

The completion menu

(picture)

The completion menu comes up when you press one of the many key-combinations affected to insert mode completion and there is at least one or more possible completions. In pure "modal" fashion, once the menu is displayed, some keys acquire a new meaning to allow cursor movement and selection but the general pattern stays consistent with the general Vim UI and works more or less how we expect.

problems and solutions (to be written)

Reference

:help ins-completion-menu

The command-line

(picture)

The command-line is Vim’s main interface. Like the prompt of your computer’s shell, it is used to send commands to Vim and for feedback if necessary.

Reference

Glossary

Let’s finish this chapter with a hopefully complete glossary.

Buffer

qsmdgqsldhfqsld

Window

qsdqsdsqdsqdqsdqsdqsd

Tab page
Status line
Tab line
Preview window
Quickfix list
Quickfix window
Location list
Location window
Vertical split
Line numbers
Fold column
Sign column
Completion menu
Command-line
Command-line window

sdfksgdfsd

Function
Custom function
Ex command
Custom command
Mapping
Abbreviation
Motion
Operator
Text-object
Register
Macro
Recording
Yank and put

sdhflsyd

Conclusion

(to be written)

Written by Romain Lafourcade, with help from Barry Arthur and the #vim community.

Copyleft 2015