Introduction to Vim

NOTE: This a straight copy of Vim notes I keep on my computer. The notes were created and are maintained for my own reference and are idiosyncratic to my needs.

What is Vim?

Vim is a popular and powerful text editor written for efficient, mouseless writing, editing, and manipulation of text, e.g. prose and code.

Vim differs from most text editors in that there are different modes for writing (e.g. insert mode) and editing (e.g. normal mode)1. A normal session involves frequent switching between insert and normal modes depending on the task, e.g. write text in insert mode, switch to normal mode to delete the current sentence using the quick ‘das’ key sequence, then switch back to insert mode to continue typing.

Variants of Vim

There are graphical versions of Vim and terminal versions of Vim, and many integrated developer environments (IDEs) or analysis environments even have Vim-modes for code editing. Examples:

  • Vim (vim): Traditional, terminal-based Vim. macOS comes with a system version, but it isn’t kept up to date. A current version, installed through Homebrew, is recommended.
  • GVim: Graphical Vim.
  • MacVim (mvim): macOS graphical Vim. Comes with an executable script mvim2 that can be used to invoke MacVim from the command line.
  • NeoVim (nvim): Modern fork of Vim with improved architecture. Installed using Homebrew. See ‘Differences betwen Vim and Neovim’ for further information.

Other Vim-based editors I have used:

  • VimR: NeoVim GUI for macOS. The program is still in alpha development, but it has many promising features including Markdown preview and a file browser.

Programs with Vim-mode editing:

  • RStudio

Differences between Vim and NeoVim

  • Location of temporary swap files (e.g. .swp files): in Vim they’re located in the same directory of the edited file; in NeoVim, they’re located in ~/.local/share/nvim/swap.

Launching Vim via the terminal

Note: Substitute your preferred Vim, e.g. gvim, vim, or nvim, for mvim in the table below. See ‘Variants of Vim’ below for a description of the variants.

Cmd Description
mvim Open a single file
mvim file1 file2 ... Open multiple files. Buffers are created for each file, but only the first file file1 is displayed in the window. To switch to another opened file, see buffers.
mvim -p file1 file2 ... Open multiple files. Each file is opened in a seperate tab. Only applicable to graphical Vim (e.g. MacVim)
mvim -d file1 file2 Open two files in vimdiff mode: both files are opened in a seperate vertical split, the differences between the files are highlighted, and the files are coupled such that scrolling in one file also scrolls in the other file (i.e. the current lines in both files are the same).

Modes

Basic Modes

Vim has six basic modes.

  • Normal (n): Command mode. Mode in which you can enter all the regular commands. Cursor appears as a square. You can end Insert Mode and go to Normal Mode by by pressing <esc> or <Ctrl>-[.
  • Insert (i): Typing mode. The text you type is insert in the file (current buffer). If in Normal Mode, Insert Mode can be accessed by pressing a or i.
  • Visual (v): Similar to Insert Mode, but you can select the text over which the commands apply using movement commands.
  • Command-line mode (c): Type in and execute a single expression from the bottom of the main Vim window. Command-line mode is accessed from Normal or Visual mode by pressing :. Enter the command and then execute it by hitting <Enter>. The mode will return to Normal mode after completion of the command.
  • Ex mode (e): Type in and execute multiple expressions. Like Command-line mode, except you remain remain in Ex mode after entering a command. Infrequently used mode.

Additional Modes

Vim has six additional modes. These are variants of the basic modes.

  • Operator-pending (o): Similar to Normal mode. You’ve started an Operator command, but are still waiting for a {motion} to specify the text that the operator will work on.
  • Replace (r): Like Insert mode, but you overwrite rather than add text. Replace mode is accessed by entering R in Normal mode.

Repeating commands

Most commands can be optionally prefaced by an integer N to repeat the command N times. For example, 2dw for delete two words.

The column N? shows if this is possible and makes sense, i.e. exhibits the expected behavior.

Table Key

The following symbols have special meaning in the Cmd column for all document tables.

  • N: Integer. Reserved for repeating part or whole of a command. Whole commands can be repeated (see repeating commands below) or it might show up in the middle of command as part of, for example, a movement (see reformat a line or paragraph).
  • n: Integer. General use.
  • x: Single character
  • s: String
  • C: Command
  • []: Optional component

Each command (under Description) has been given a usefulness score that appears at the end of each Description entry.

  • [3]: Very useful. Used every session.
  • [2]: Useful. Used often, but perhaps not every session.
  • [1]: Worth knowing. Used, but infrequently.

Exiting Vim

Start with the most important question first: how do I exit Vim?

These commands must be entered in normal mode. If you see a blinking, square-block cursor (“ █ ”) , you’re in normal mode. If you see a blinking line cursor (“ │ ”), you’re in insert mode. To go from insert mode to normal mode, hit the escape (Esc) key.

To quit a buffer instead of a window, see Sec. ‘Closing buffers’. See Sec. ‘Buffers’ for the difference between buffers and windows. Note that tabs count as different windows.

Cmd N? Description
:quit or :q N Quit the current window (not just the current buffer). If the current window is the only window, exit Vim. Quit fails if an opened buffer has unsaved changes or if there is an unnamed buffer (a new buffer that isn’t associated with a file). If the current window is the only open window, close the window and exit Vim. [3]
:quit! or :q! N Quit the current window (like :quit), but quit even if there are buffers with unsaved changes. [3]
:qall or :qa N Quit all windows, not just the current window and exit Vim. Exiting Vim fails if there are buffers with unsaved changes. [2]
:qall! or :qa! N Quit all windows and exit Vim. Always exit. Any unsaved changes or unnamed buffers are discarded. [3]
:wq N Write to (save) the current buffer and quit the current window. Quit fails if the current buffer is unnamed, or if there are other buffers with unsaved changes. [3]
:wq! N Write to (save) the current buffer, even if it’s marked read-only, and quit the current window. Quit fails there are unnamed buffers with unsaved changes. If there are other buffers with unsaved changes, discard them.
:wqall or :wqa N Write to (save) all named buffers, quit all windows, and exit Vim. [3]
:wqall or :wqa N Write to (save) all named buffers, quit all windows, and exit Vim. [3]

Normal-mode movement

Navigate within the text or between windows.

Most commands can be repeated N times if prefaced by an integer. If possible, this is indicated in the N? column.

Move forwards and backwards by word

Cmd N? Description
b Yes Move back a word, cursor placed at front of the word. [3]
B Yes Move back a word, cursor placed at front of the word. Consider special characters as part of word. [3]
ge Yes Move back a word, cursor placed at the end of the word. [2]
gE Yes Move back a word, cursor placed at the end of the word. Consider special characters as part of the word. [2]
w Yes Move forward a word, cursor placed at the front of the word. [3]
W Yes Move forward a word, cursor placed at the front of the word. Consider special characters as part of word. [3]
e Yes Move forward a word, cursor placed at the end of word. [3]
E Yes Move forward a word, cursor placed at the end of word. Consider special characters as part of word. [3].

Move left, right, up, or down by character or line

Cmd N? Description
h Yes Move left one character. [3]
l Yes Move right one character. [3]
j Yes Move down one line. [3]
k Yes Move up one line. [3]
gj Yes Move down one display line. Differs from ‘j’ when lines are too long for the current window and are soft-wrapped to the next line. ‘gj’ will move to the line displayed below the current line, the ‘j’ command will skip over all word-wrapped lines to the next physical line. [3]
gk Yes Move up one display line. See ‘gj’ for additional detail. [3]

Move/search forwards or backwards to a specific character in the current line

Cmd N? Description
f x Yes Move (find) forwards to character x. Place cursor on character. [2]
F x Yes Move (find) backwards to character x. Place cursor on character. [2]
t x Yes Move (find) forwards to character x. Place cursor before character. [1]
T x Yes Move (find) backwards to character x. Place cursor after character. [1]
; Yes Repeat last f, F, t, or T command. [2]

Move forwards or backwards to a specific location in the current line

Cmd N? Description
0 No Move to the absolute beginning of the line (column 1). [3]
| Yes (Alternative) Move to the absolute beginning of the line (column 1). [3]
^ No Move to relative beginning of the line (wherever the text starts; could be offset from column 1 if there’s leading white space) [**3]
$ No Move to end of line (very end of line, including any trailing white space) [3]
g_ No Move to the last non-blank character of the line [2]
n | Yes Go to column number n. If no number is provided, jump to the start of the line. [1]

Move forwards or backwards by sentence

A sentence is defined by a period (.).

Cmd N? Description
( Yes Move forward a sentence [3]
) Yes Move backwards a sentence [3]

Move forwards of backwards by paragraph

Cmd N? Description
} Yes Move forward a paragraph (i.e. next group of one or more blank lines) [3]
{ Yes Move backward a paragraph (i.e. previous group of one or more blank lines) [3]

Move forwards or backwards by section

Cmd N? Description
]] Yes Move forward a section [2]
[[ Yes Move backward a section [2]
][ Yes Move forward a section. Put cursor at the end of the section. [1]
[] Yes Move backward a section. Put cursor at the end of the section [1]

Move to the top, middle, or bottom of the current window

Cmd N? Description
H No Move to top of page [2]
M No Move to middle of page [2]
L No Move to bottom of page [*2]

Move to a given character or string

See search and move to a given character or string.

Move to a specific location (line number, etc.) in the complete document

Cmd N? Description
G No Go to the end of the file [3]
n G Yes Go to line number n. If no number is provided, jump to the end of the file. [3]
gg No Jump to the top of the file [3]
n gg Yes Go to line number n (alternative to nG). If no number is provided, jump to the top of the file. [2]

Move to previous (jump) locations within the document (jump list)

Vim-help link: jump motions

Vim keeps tracks of landing locations when making specific jumps in the document. This is called Vim’s jump list. You can use this history to retrace previous views within the file.

What constitutes a jump?

  • Jump to marker location: 'x
  • Jump to line: *n*G
  • Jump to next/previous paragraph (blank line): } and {
  • Jump to beginning/end of current block: [{ and ]}
  • Jump to beginning/end of current sentence: ( and )
  • Jump to beginning/end of section: [[ and ]]
  • Jump to top/middle/bottom of window: H, M, and L
  • Jump to matching delimiter: %
  • Jump to specific tag: :tag s
  • Jump to older tag: <Cntrl>-t
  • Jump to tag definition: <Cntrl>-]
Cmd N? Description
`` N Go to previous location before your last jump [1]
:jumps or :ju N Show jump list [1]
:clearjumps or :cle N Clear jump list [1]
<Ctrl>-o N Go backward through previous (older) jump locations [2]
<Ctrl>-i or <Tab> N Go forward through next (newer) jump locations [2]

Move to previously modified location (change list)

Vim-help link: jump motions (scroll down for change list jumps sub-section).

Vim keeps track of locations where text was previously modified (changed, added, etc.) in a change list.

You can see and step through the list using the following commands.

Cmd N? Description
:changes No Show the change list [1]
'. No Move to the last edited line [2]
`. No Move to the cursor position of the last edit in the last edited line [2]
g; Yes Go to previous (older) cursor position in the change list [3]
g, Yes Go to next (newer) position in the change list [3]
gi Yes Go into Insert Mode in the same position that Insert Mode was last exited [2]

Move the window to position the current line at the top, middle, or bottom of the screen

Cmd N? Description
zt No Position current line at top of the screen [2]
zz No Position current line at middle of the screen [2]
zb No Position current line at the bottom of the screen [2]

Create and move to a marker

See markers.


Select, cut/delete, copy, and paste

All commands are assumed to be in normal mode unless explicitly noted.

Visually select text under cursor

Methods for visually selecting the current word, paragraph, bracket-enclosed content, and so forth. Current refers to whatever is under the cursor.

Visually selecting text puts Vim into Visual Mode (see modes).

Cmd N? Description
viw No Visually select current word [3]
viW No Visually select current word. Include special characters as part of word [3]
vaw No Visually select the current word. Include all blank spaces after the word. [2]
viW No Visually select current word. Include special characters as part of word. Include all blank spaces after the word. [2]
vis No Visually select the current sentence. [3]
vas No Visually select the current sentence. Include the blank spaces after the sentence. [2]
vip No Visually select current paragraph [3]
vap No Visually select current paragraph. Include the empty lines after the paragraph. [2]
vib No Visually select everything between parentheses-enclosed text. Do not include the parentheses as part of the selection. This command does not work with other matched bracket types such as square [ ] and curly { } brackets. [3]
viB No Visually select everything between brackets. Do not include the brackets as part of the selection. This command works with all bracket types: parentheses (), square brackets [ ], and curly brackets { }. [3]
vab No Visually select everything between parentheses-enclosed. Include the parentheses as part of the selection. This command does not work with other matched bracket types such as square [ ] and curly { } brackets. [3]
vaB No Visually select everything between brackets. Include the brackets as part of the selection. This command works with all bracket types: parentheses (), square brackets [ ], and curly brackets { }. [3]
vi' No Visually select everything within enclosing single quotes. Do not include the quotes as part of the selection. [2]
va' No Visually select everything within enclosing single quotes. Include the quotes as part of the selection. [2]
vi" No Visually select everything within enclosing double quotes. Do not include the quotes as part of the selection. [2]
va" No Visually select everything within enclosing double quotes. Include the quotes as part of the selection. [2]
v% No Visually select from the current bracket to its starting/ending partner. Include the bracket. [3]
gv No Re-do last visual selection [3]

Move within selected text (visual mode)

These commands assume a block of text has already been selected.

Cmd N? Description
o No (Visual mode) Move cursor to the start of the selected text. Do not change the extend of the selected text. [1]
O No (Visual mode) Move cursor to the end of the selected text. Do not change the extent of the selected text. [1]

Delete (cut) text

General form

Deletion commands follow the general Vim pattern: [command] + [movement]. For example:

  • dw: Delete to end of the word ([delete] + [move to end of word])
  • d$: Delete to end of the line ([delete] + [move to end of line])

Using this pattern, we can improvise any number of deletion commands. For example:

  • d5j: Delete the next five lines, including the current line ([delete] + [move 5 lines down])

There are special deletion commands: di for delete inside and da for delete all. They have the general form [da/di] + [boundary]. The boundary is a character that characterizes the extent of the environment of what we want to delete: ( or b for a matching pair of parentheses, [ for a matching pair of square brackets, s for a sentence, w for a word, and so forth.

  • di commands delete the text inside the boundary
  • da commands delete the text inside the boundary and the boundary indicators (e.g. delete the text and the brackets)

Delete to register

Deleted (or yanked) text automatically goes into the unnamed (default) register ". This is what Vim uses when you paste text using p.

To see the named registers, type :reg.

Delete one or more characters

Cmd N? Description
x Yes Delete the current character [2]
X Yes Delete previous character. [1]

Delete one or more words

Cmd N? Description
dw Yes Delete to end of word. To delete an entire word, cursor must be at the front of the word. [2]
dW Yes Delete to end of word. To delete an entire word, cursor must be at the front of the word. Consider special characters as part of the word. [2]
diw Yes Delete a word. Cursor can be anywhere within the word. Do not include trailing whitespace. [*2]
diW Yes Delete a word. Cursor can be anywhere within the word. Do not include trailing whitespace. Consider special characters as part of word. [*2]
daw Yes Delete a word. Cursor can be anywhere within the word. Include trailing whitespace as part of the word. [3]
daW Yes Delete a word. Cursor can be anywhere within the word. Include trailing whitespace as part of the word. Consider special characters as part of the word. [3]
<Ctrl>-w No (Insert-mode) Delete current word, i.e. delete from the current insert cursor position through the beginning of the word. This is a quick way to delete the current word if there’s a mistake without existing insert-mode. [3]

Delete one or more sentences or paragraphs

Cmd N? Description
d) Yes Delete to end of sentence. Deletes an entire sentence if the cursor is at or before (preceeding whitespace) the start of the sentence. [2]
d) Yes Delete to beginning of sentence. Delete an entire sentence if the cursor is at the end of the sentence or in the trailing whitespace. [2]
das Yes Delete an entire sentence and its trailing whitespace. Cursor can be anywhere within the sentence. Includes both the sentence and the trailing whitespace. [3]
dis Yes Delete an entire sentence. Do not include trailing whitespace. Cursor can be anywhere within the sentence. [2]
d} Yes Delete to end of paragraph. Deletes an entire paragraph if the cursor is at or before (preceeding whitespace) the start of the paragraph. [1]
d{ Yes Delete to start of paragraph. Deletes an entire paragraph if the cursor is at the end or in the trailing whitespace of the paragraph. [1]
dap Yes Delete an entire paragraph and the trailing whitespace. Cursor can be anywhere within the paragraph. [3]
dip Yes Delete entire paragraph. Do not delete the trailing whitespace. Cursor can be anywhere within the paragraph. [3]

Delete all or part of the current line

Cmd N? Description
dd Yes Delete current line [3]
D Yes Delete to end of line. If repeated N times, the command deletes to the end of the current line and then the next N - 1 lines. [3]
d$ No Delete to the end of line (alternative) [2]
d0 No Delete to beginning of line [2]
<Ctrl>-u No (Inert mode) Delete to start of current line. [2]

Delete inside a block

Cmd N? Description
dit Yes Delete inside tag. Delete the text within a set of tags (e.g. HTML tags).
dat Yes Delete around tag. Delete the text within a set of tags and the tags themselves.
d% No Delete to matching bracket (or tag if using the vim-surround plugin).

Delete to mark (easy deletion of large segments)

Deleting to a mark is a useful and quick way of deleting a large chuck of text. Quick steps:

  1. Place a mark (see markers) using **m**x (where x is the mark).
  2. Move to a new location (e.g. the next section, end of a block, etc.)
  3. Then delete backwards to that mark using **d'**x

Copy (yank) text

Cmd N? Description
yy No Yank current line
Y No Yank current line (alternative)
y$ No Yank to end of current line (alternative)
yiw No Yank current word, excluding surrounding whitespace
yaw No Yank current word, including leading or trailing whitespace

Paste text

For additional information on pasting from a register, see registers.

Cmd N? Description
p Yes Paste last deleted or yanked item after cursor
P Yes Paste last deleted or yanked item before cursor
" xp Yes Paste from register x after cursor (see registers for available registers)
" xP Yes Paste from register x after cursor (see registers for available registers)

Paste while in insert mode

Pasting can be done from insert mode. Hit <Ctrl>-r then <regname>, where <rename> is any of the registers from the register list table.


Editing and formatting

Entering insert mode

Cmd N? Description
i No Enter insert mode before cursor
a No Enter insert mode after cursor
I No Enter insert mode at the start of the line
A No Enter insert mode at the end of the line
o No Insert a new line below the current line and enter insert mode.
O No Insert a new line above the current line and enter insert mode.

See also overwrite and replace text for the change commands (e.g. S, cc, C)

Overwrite and replace text

Cmd N? Description
rx No Replace current (single) character with x.
Rs No Enter Replace Mode. Overwrite characters with string s until the mode is escaped.
~ No Change the case of the current character.
["x ] S No Change entire line. Delete entire line and place cursor in insert mode at the beginning of the line (column 1). Equivalent to cc. Optionally delete contents into register x.
["x ] cc No Change entire line. Equivalent to S. Optionally delete contents into register x.
["x] C No Change to the end of the line, i.e. delete from the current position to the end of the line and switch to insert mode. Cursor position does not change. Equivalent to c$.
ciw No Change (replace) entire word. Delete word and change to insert mode.

Reformat a line or paragraph

Formatting includes auto word-wrap and indentation.

Cmd N? Description
gqq No Format current line.
gqj No Format the current line
gq Nj No Format the next N lines (including the current line)
gwip No Format current paragraph and keep the cursor in the same location
gqip No Format current paragraph and move to the next line
gqap No Format current paragraph and move to the next paragraph
J No Joint current and next paragraph, but do not reformat.

Format (e.g indent and de-indent) code blocks

Cmd N? Description
> Yes (Visual mode) Indent select code block or text by shiftwidth.
< Yes (Visual mode) De-indent selected code block or text by shiftwidth.
>> Yes Indent current line by shiftwidth
<< Yes De-indent selected line by shiftwidth
= yes (Visual mode) Reformat selected code
== Yes Reformat current line of code

Working with surround environments, e.g. quotation marks, brackets or tags

Functionality added via the surround-vim plugin. See:

Spelling

Vim uses two main dictionaries3 when checking and marking a buffer for misspelled words: a default, main dictionary for the current language and region (for me the spelllang is en_us; this can be changed if needed), and a spellfile, a supplementary dictionary that contains a list of words that Vim should treat as correctly spelled even though they aren’t recognized by the default dictionary.

A spellfile is just a list of words. They can be directly edited. For me, they are located at ~/vim/spell/en.utf-8.add (for Vim) and ~/.config/nvim/spell/en.utf-8.add (for NeoVim).

You can create new spellfiles. This is very useful when working on projects that have a lot of project-specific words that you don’t want to add to a common dictionary. For example, in my Deorcost D&D campaign, I have a lot of character and monster names that are aren’t English words, but that I don’t want to mark as incorrectly spelled. So I created a new spellfile called deorcost.utf-8.add

To set the location of the spellfile:

:set spellfile=~/path/to/spellfile/mydictname.utf-8.add

In addition to the regular dictionary and the spellfile, a third source for valid words, an internal word list dictionary can be used. The internal word list is a temporary dictionary that only exists for the current buffers. The dictionary vanishes once Vim is exited. Words are added to the internal word list using the command zG.

Vim, by default, marks words it finds misspelled with an underline.

Cmd N? Description
:set spell No Turn on spell checking. [3]
:set nospell No Turn off spell checking [3]
]s Yes Move to the next mispelled word [3]
]S Yes Move to the next mispelled word. Only stop at bad words, not rare words (in the default English dictionary, only the word “vim” is marked as rare) or words that are valid in another region (same language but different region, e.g. American English versus UK English). [1]
[s Yes Move to the previous mispelled word [3]
[S Yes Move to the previous mispelled word. Only stop at bad words, not rare words or words from another region.
z= No For the misspelled word under the cursor, suggest correct spellings [3]
zg No Add the word under the cursor to the dictionary as a good word [3]
zG No Add the word under the cursor to a temporary dictionary (the internal word list) as a good word. This will prevent the word from being marked as incorrect for the current session only. As soon as the Vim exited, the internal word list is discarded. [3]
zw No Remove the word under the cursor from the dictionary as a good word. Useful if one has accidentally added a bad word the current spellfile and needs to remove it. [2]

Search, find, and replace

Search and move to a given character or string

Cmd N? Description
/ s No Search forward and move to string s. If the string is not found, do not move.
? s No Search backward and move to string s. If the string is not found, do not move.
% No Move to matching (i.e. opening or closing) bracket
\* No Search and move to the next exact occurance of the word under the cursor.
# No Search and move to the previous exact occurance of the word under the cursor.
g\* No Search and move to the next occurance of the word under the cursor, even if the word is contained within a larger word (i.e. search-moving for the word move will find the words movement and remove).
g# No Search and move to the previous occurance of the word under the cursor, even if the word is contained within a larger word.

Repeat previous movement searches

Cmd N? Description
n Yes Repeat the last search command (e.g. ‘/’, ’?``, '*', '#`’).
N Yes Repeat the last search command (e.g. ‘/’, ’?``, '*', '#`’) in the opposite direction.

Find and replace text

:s/searchstr/<repplacestr>/g

where searchstr and replacestr are the text one is searching for an

Miscellaneous search commands

Cmd N? Description
[I No Show all lines maching word under cursor

Set important search variables

Cmd N? Description
:nohlsearch No Turn off matched-word highlighting until the next search.
:noh No Turn off matched-word highlighting until the next search. Alternative.
q/ No Open a history of previous searches. Hit <Enter> close the window.
q? No Open a history of previous searchers. Hit <Enter> to close the window. Alternative.

Buffers and registers

Buffers

A buffer is the in-memory text of a file, this could be a file we’ve loaded or new content that we haven’t yet written to disk. Many files may be loaded into memory (many buffers) while just one is displayed (single window).

Buffers allow us to quickly jump between different files.

Showing buffers

Buffers are shown using the :ls command. The output shows:

  • Column 1: The buffer. This number indicates how the buffer should be addressed. E.g. :b 2 opens buffer 2 in the current session.
  • Column 2: Which buffer is active (%a), which buffers are hidden (h), the previously accessed buffer (#h) for the current window.
  • Column 3: If a file has been edited but not yet saved, there will be a + in this column. Otherwise it will be empty.
  • Column 4: The file and filepath relative to the current working directory. If the file content hasn’t been written to disk, it will be listed as "[No Name]".
Cmd N? Description
:ls N List all buffers

Example output:

:ls
  1  h   "vim.md"                       line 155
  2  h + "git.md"                       line 1
  3  h   "[No Name]"                    line 1
  3 #h   "root_analysis.py"             line 22
  4 %a   "root_analysis.sql"            line 1

A buffer can only be in the background if it hasn’t been modified, but the restriction can be removed by the :set hidden command. This is set in my vimrc file so that I don’t have enter it each time.

Troubleshooting: Long file paths in :ls

The listed file paths in :ls are relative to the current working directory (:pwd), which is set by the first loaded file. If buffers don’t share the same working directory, hidden files with different working directories will use their full file path relative to the user home (~). This can give unfortunately long paths in the :ls command that wrap to the next line.

To fix the issue for the currently active buffer, use a working directory that is common to other buffers using the :cd <newpath> command. <newpath> can be relative, e.g. cd .. works. Unfortunately this must be done per buffer.

Switching buffers

Switching buffers is easiest using :b <fname> with tab completion. The tab completion works on file names and paths. For example, if one of my buffers corresponds to file ~/git-projects/grav/pages/04.deorcost/episode-26/item.md, I can type :b 26<tab> (the 26 is from episode-26) and it will expand to the full file path.

This is easier than remembering which buffer number corresponds to which file. Buffer numbers associated with each file can’t be reassigned and may change when re-opening a session.

Cmd N? Description
:buffer n No Switch to buffer n [3]
:b n No Alternative to :buffer n. There does not need to be a space between :b and n. Both :b 1 and :b1 are equivalent. [3]
:b <fname> No Swith to buffer with filename <fname>. The filename accepts tab-completion if :set wildmenu has been enabled (a typical default in one’s .vimrc or init.vim). Auto-completion works on any part of the filename. [3]
<Ctrl>-6 No Switch to the last used buffer. Easy way to switch between buffers. [3]
:bnext No Switch to the next buffer [1]
:bn No Alternative to :bnext [2]
:bprevious No Switch to the previous buffer [1]
:bp No Alternative to :bprevious [2]

Creating Buffers

Cmd N? Description
:edit No Open a new buffer in the current window. [1]
:e No Alternative to :edit [2]
:edit <fname> No Open file <fname> into a new buffer in the current window. [1]
:e <fname> No Alternative to :e <fname> [*2]
:badd <fname> No Open file <fname> into a new background buffer [3]
:new No Split window horizontally into half and open a new, empty buffer in the newly created window. The new viewport is created above the current viewport.
:new No Split window horizontally in half and load file <fname> into the new buffer in the new window. The new window is created above the current window.
:vnew No Split the active window vertically in half and open a new, empty buffer in the newly created window. The new window created to the left of the current window.
:vnew No Split the active window vertically in half and load file <fname> into the new buffer in the new window. The new viewport is created to the left of the current viewport.

Comparing buffers

To add

Closing buffers

To close a window see, Exiting Vim

Cmd N? Description
:bdelete N Close the current buffer and remove it from the buffer list. This fails if the buffer has unsaved changes.
:bd N Alternative to :bdelete
:bdelete n N Close buffer n.
:bd n N Alternative to :bd:

Registers

Registers are special scratch spaces for saving and recalling text and actions.

  • Cut and copied text is automatically placed to special default registers, or can be specifically placed into named registers for longer-term recall.
  • Macros are saved to named registers.
  • The latest command and other useful information are saved to special default registers.

Registers are accessed, for both getting and putting content, using the double quote " character.

To see all registers and their contents use :reg or :registers.

Register list table

Register Content
0 - 9 Yanked (copied) text registers. Vim automatically populates the numbered registers, 0 - 9, with yanked text. Deleted (cut) text does not populate these registers. The latest yank goes to register 0; the second to last goes to register 1; and so forth.
a - z Named registers. Deleted or yanked text can be explicitly saved to any one of these named registers for later recall. They won’t be explicitly overwritten.
0 Last yanked text register. For additional information, see Registers 0 - 9 above.
" Last deleted or yanked text register (on macOS systems). Stores the last deleted or yanked text. p (paste) is equivalent to ""p.
\* System clipboard
% Current file path, relative to the file path where Vim was opened. (read-only register)
/ Last search command (read-only register)
. Last inserted text (read-only register)
# Name of the last edited file (read-only register)
: Most recently executed command. To execute the last command (e.g. a substitution on a particular line) again use @:
_ Black hole register

Copying or cut to a register

  • Any delete (cut) command (e.g. d, D, x, X) or yank command is automatically saved to the " register
  • Any yank (copy) command is saved to both the " and the 0 register. See the register list table table above for how to access previously yanked text (e.g. 2, 3 copies ago)
  • Yank or delete to a specific register using "<regname><cmd> before a delete or yank command <cmd>, e.g. ("kY, yank current line to register k; "kD delete to end of line and save contents to register k)

Pasting from a register

You paste from a register in a similar way to cutting or copying to a register: "<regname><pastecmd>. The paste command is either p for paste after, or P for paste before. Examples: "kP paste contents of register k before the cursor.

Command examples

Any yank, delete, or paste command can be used after specifying the register. The below table is is a limited sample of available commands.

Cmd N? Description
:reg or :registers No View all registers
" np Yes Paste from one of the numbered registers n.
" xp Yes Paste the contents of register x
" xP Yes Paste the contents of register x above the current line
" xyy No Yank the current line to register x. Named registers can be between a and z (26 total)
" xdd No Delete the current line to register x. Named registers can be between a and z (26 total)

Insert-mode commands

Cmd N? Description
<Ctrl>-r, then <regname> No Paste from register <regname>.
<Ctrl>-w No Delete the word before the cursor
<Ctrl>-n No Auto-completion
<Ctrl>-p No Auto-completion

Windows and tabs

Windows

Scroll a window forward or backward

Cmd N? Description
<Ctrl>-f No Scroll window forward one screen
<Ctrl>-b No Scroll window backward one screen
<Ctrl>-d No Scroll window forward one-half screen
<Ctrl>-u No Scroll window backward one-half screen
<Ctrl>-e No Scroll window up one line
<Ctrl>-y No Scroll window down one line

Split a vim window into sub-windows and move between them

Cmd Description
:sp or :split Split the Vim window horizontally (same file)
:vsp or :vsplit Split the Vim window vertically (same file)
:new Split window horizontally and open a new buffer in the new viewport (above). See also: creating buffers.
:vnew Split the active window vertically and open a new buffer in the new viewport (left). See also: creating buffers
<Ctrl>-w <Ctrl>-w Move between Vim viewports
<Ctrl>-w j Move to the viewport below
<Ctrl>-w k Move to the viewport above
<Ctrl>-w h Move to the viewport to the right
<Ctrl>-w l Move to the viewport to the left
<Cnrl-w> q Close the active viewport

Move, rotate, and re-order windows

Cmd N? Description
<Ctrl>-w R No Rotate windows up/left.
<Ctrl>-w r No Rotate windows down/right.
<Ctrl>-w L No Move the current window to the “far right”
<Ctrl>-w H No Move the current window to the “far left”
<Ctrl>-w J No Move the current window to the “very bottom”
<Ctrl>-w K No Move the current window to the “very top”

Scroll multiple windows simultaneously

You can scroll and edit multiple windows simultaneously (e.g. two vertical windows) if they’re bound together. The steps:

  1. Set scrollbind in window 1: :set scrollbind (equiv. :set scb)
  2. Move to the next window using <Ctrl>-w <Ctrl>-w
  3. Set scrollbind in window 2: :set scrollbind (equiv. :set scb)
  4. And so forth, depending on how many windows you’d like bound together

Change a window’s width and height

These commands do not effect the size of the main (terminal or program) window, and thus don’t work if only a single window is open. You can only steal or add space to neighboring windows in a multi-window environment.

The equalize window size command, i.e. <Ctrl>-w=, is probably the most useful command in the table below.

Cmd N? Description
<Ctrl>-w= No Equalize the width and height of all windows
n <Ctrl>-w + No Increase the windows height by n lines
n <Ctrl>-w - No Decrease the window height by n lines
n <Ctrl>-w _ No Set window height at n
n <Ctrl>-w | No Set window width at n

Tabs

Create new tabs and move between them

Cmd N? Description
:tabnew No Create a new tab
:tabnew <fname> No Create a new tab with open file <fname>
gt Yes Go to next tab. If N is provided, jump N tabs to the right.
gT Yes Go to the previous tab. If N is provided, jump N tabs to the left.

Folds and Markers

Folds

Cmd N? Description
zo No Open one fold under the cursor (assumes a closed fold under the cursor).
zO No Open all folders under the cursor, recursively (assumes a closed fold under the cursor). Folds hierarchies that don’t contain the cursor line are unchanged.
zR No Open all folds in the document.
zc No Close one fold under the cursor.
zC No Close all folds under the cursor, recursively. Fold hierarchies that don’t contain the cursor line are unchanged.
zM No Close all folds in the document.
za No Toggle the current fold (open the fold if closed; close the fold if open)

Markers

A marker is a remembered cursor position. They can be used to navigate a document or to mark locations for actions, e.g. delete between marks or yank text between marks.

Cmd N? Description
:marks No List all marks and their details
:marks s No List all marks and their details listed in string s. For example, to get information about markers a and b, enter :marks ab.
mx No Create and save a marker to character x [a-z].
'x No Jump to the line of the marker, i.e. jump to the first non-blank character in the line defined by marker x.
` x No Jump to the exact marker location, i.e. both the exact line number and column number.

Miscellaneous

Macros

Cmd N? Description
@@ Yes Repeat the last macro

Sessions

It’s inconvenient to re-open the same buffers and window configuration for a project every time Vim is opened. Fortunately your entire configuration, i.e. your session, can be saved using the :mksession command.

That session can then be loaded within an open Vim window (using :source <sname.ses>) or at Vim launch using mvim -S <sname.ses>.

Cmd N? Description
:mksession N Save a Vim session to file Session.ses [2]
:mks N Short form of :mksession (above) [2]
:mksession {sname.ses} N Save a Vim session to disk to filename <sname.ses>. The file must have the .ses extension. [2]
:mks {sname.ses} N Short form of :mksession <sname.ses> (above) [2]
:mksession! N Overwrite the current Session.ses file [2]
mks! N Short form of :mksession (above) [2]
:mksession! {sname.ses} N Overwrite the current <sessionname.ses> file [2]
:mks! {sname.ses} N Short form of :mksession <sname.ses> (above) [2]
:source {sname.ses} N Load a Vim session from within Vim [1]

To launch Vim with a saved session (instead of launching Vim then using :source), use:

vim -S sessionname.ses

Get or set or change the working directory

Cmd N? Description
:pwd No Print the current directory name [1]
cd {path} No Change the current directory to {path}. This applies to all open buffers. [1]
:lcd {path} No Set the current directory for the current window only. The current directory for other windows is not changed. [1]
:tcd {path} No Set the current directory for the current tab only. The current directory for other tabs is not changed. [1]

Control-key commands

Commands are for normal mode unless otherwise indicated.

Cmd N? Description
<Ctrl>-a No Increment integer under cursor [1]
<Ctrl>-x No Decrement integer under cursor [1]
<Ctrl>-[ No Escape [1]

Syntax highlighting

Assuming a normally configured ~/.vimrc with syntax enable and filetype plugin on and the correct syntax plugins installed, a displayed file should have syntax highlighting.

Sometimes, often with large files, highlighting can break. A few problems and solutions are found below.

Problem: No syntax highlighting

Check if a syntax file4 has been loaded. Run,

:setlocal syntax?

If the command returns with no associated file (i.e. the command returns syntax= with nothing after the equals sign) or an unexpected filetype, you can manually associate a new or different syntax file with the document.

For markdown files, because I have the vim-pandoc and vim-pandoc-syntax, plugins the syntax filetype should be pandoc, i.e. 

:setlocal syntax=pandoc

Setting syntax=markdown may also work.

Problem: Syntax highlighting is broken or malformed

The first thing to check is that your code or text is correct. Usually syntax highlighting are broken because of a misplaced closing tag or bracket or character.

If you’re convinced that there’s nothing wrong with the content of your document, there are a few commands you can run to try and fix highlighting.

  • Adjust the minimum number of lines Vim goes back to find the start of the environment (e.g. an opening tag or bracket) for the current syntax highlight

    syntax sync minlines=20

    Larger values will improve accuracy, but slow down highlighting

  • Re-do highlighting of the document, starting from the start

    :syntax sync fromstart
  • Increase the amount of time Vim has to draw a screen of text. If this limit is hit before Vim is finished calculating the correct syntax highlighting for the current screen, syntax highlighting will fail.

    set redrawtime=10000

Plugins

Useful details and commands about installed plugins.

List of Plugins

  • csv.vim: Improve display, navigation, and editing of delimited files
  • nvim-r: Plugin to turn Vim into a full-featured R IDE (like RStudio)
  • vim-obsession: Improve Vim’s recording of session files
  • vim-pandoc: Support for Pandoc Markdown writing and conversion
  • vim-pandoc-syntax: Syntax support for the vim-pandoc plugin
  • vim-pencil: Tweak Vim to improve the writing of prose
  • vim-matchit: Expand % from single characters (matching parentheses) to include opening and closing tags.
  • vim-repeat: Extend the repeat command . to support the full command map instead of just the last native command inside the command. Works with vim-surround.
  • vim-rmarkdown: RMarkdown support for Vim
  • vim-surround: Quoting and parenthesizing made simple
  • python-mode: Plugin to turn Vim into a full-featured Python IDE
  • nvim-r: Plugin to turn Vim into a full-featured R IDE

Checking for installed plugins

List all sourced script names, in the order they were first sourced.

Command Description
:set runtimepath? List loaded plugins
:scriptnames List all plugins

vim-pandoc

Pandoc integration and utilities for Vim. See GitHub project documentation.

Key Bindings

General Comments
  • In ~/.vimrc and init.vim, <localleader> has been set to space (<space>).
  • Commands only work in certain modes. They are indicated in the description:
    • [vn]: Visual and Normal modes
    • [n]: Normal mode only
    • [vo]: Visual and Operator Pending modes
Table of Keyboard Bindings

Bug: All of the commands involving jumps to headers (e.g. <ll>hn, <ll>hb, <ll>hh, <ll>hp) or to different sections incorrectly jump to tables’ header rows because they look similar to setext-style, level-two headers (text underlined by dashes).

Command Description
<ll>i Toggle emphasis [vn]
<ll>b Toggle bold [vn]
<ll>' Toggle verbatim. Note the command uses a single quote (') not a backtick (`). [vn]
<ll>~~ Toggle strikeout [vn]
<ll>^ Toggle superscript [vn]
<ll>_ Toggle subscript [vn]
[N]<ll># Apply ATX header. Accepts an optional count [N] for the depth of the header, e.g. 3<ll>#, otherwise it defaults to 1. Command only places the header hashmarks in front of the header text, (e.g., # My Header) not both sides (e.g., # My Header #) [vn].
<ll>hd Remove header [n]
<ll>hn Move to next header. [n]
<ll>hb Move to previous header. [n]
<ll>hh Go to current header. [n]
<ll>hp Go to current header’s parent. [n]
<ll>hsn Move to next sibling header. [n]
<ll>hsb Move to previous sibling header. [n]
<ll>hcf Move to first child header. [n]
<ll>hcl Move to last child header. [n]
[N]<ll>hcn Move to the [N]th child header. If N is ommitted, it is assumed to be 1 (move to the 1st child header). [n]
aS Select a section, including the header [vo]
iS Select a section, excluding the header [vo]
<ll>nr Insert a reference definition after this paragraph [n]
<ll>rg Go to reference definition [n]
<ll>rb Go back to reference label [n]
<ll>gl Go to current link in current window
<ll>sl Go to current link in split window
<ll>gb Go back from link
<ll>gB Go back from link to the previous file
<ll>ln Move to next list item [n]
<ll>lp Move to previous list item [n]
<ll>ll Move to the current list item [n]
<ll>llp Move to parent of the current list item [n]
<ll>lsn Move to the next list item sibling [n]
<ll>lsp Move to the previous list item sibling [n]
<ll>lcf Move to the first list item child [n]
<ll>lcl Move to the last list item child [n]
<ll>lcn Move to the [count] nth list item child [n]

vim-pencil

Tweak Vim to improve the writing of prose.

Useful for writing text, markdown, mail, rst, tex, textile, and asciidoc files.

Cmd Description
:Pencil Enable vim-pencil. Auto-detect word-wrap mode.
:HardPencil Enable vim-pencil with hard word wrap.
:SoftPencil Enable vim-pencil with soft word wrap.
:PencilOff Disable vim-pencil.

vim-repeat

Improves Vim’s repeat (.) command for plugins by repeating the entire plugin map instead of just the native (non-plugin) commands within the map. Works with the following plugins: surround.vim, speeddating.vim, abolish.vim, unimpaired.vim, commentary.vim, vim-easyclip.

No special commands are associated with the Plugin.

vim-surround

Add a surrounding character, bracket, or tag

Surrounding parentheses can be created with and without surrounding space, e.g. ( mytext ) versus (mytext).

  • To add brackets with padding, supply the opening bracket, e.g. S(.
  • To omit space, supply the closing bracket, e.g. S).
Cmd N? Description
yss s No Surround the current line with quotation mark, bracket, or tag s.
ysiw s No Surround the current word with quotation mark, bracket, or tag s. Automatically close the tag if s is a tag. Example (cursor may be anywhere within the word): bold → <em>bold</em>
ysaw s No Alternative to ysiws.
ysiW s No Surround the current word with quotation mark, bracket, or tag s. Treat special caracters as part of word. Otherwise behaves similarly to ysiws.
ysaW s No Alternative to ysiWs.
S x No (On selected text - visual mode) Add surrounding character x. If x is a bracket, insert surrounding brackets. If the opening bracket is used, add padding. If the closing bracket is used, omit padding. See the note before the table.
Sb No (On selected text - visual mode) Add surrounding parentheses (with padding).

Delete a surrounding character, bracket, or tag

Cmd N? Description
dsx No Delete a surrounding character x (e.g. single or double quote) or bracket, e.g. ds', ds", ds(
dst No Delete surrounding tag (e.g. delete the emphasis tags around <em>my text</em>). Span may be more than a single word.

Change a surrounding character, bracket, or tag

Cmd N? Description
cs xy No Change surrounding character from x to y. Span may be more than a single word.

Delete within (and including) surrounding brackets, parentheses, or tags

Cmd N? Description
dab Yes Delete within the current bracket, including the bracket.
da x Yes Delete (cut) text between matching matching brackets and the matching brackets too. x is the bracket type, e.g. [, {, etc.
di x Yes Delete (cut) text inside matching brackets, but do not delete the brackets. x is the bracket type, e.g. [, {, etc.
dit No Delete within the enclosing tag (e.g. <em>stuff I want to delete</em>)
dat No Delete within the enclosing tag and the tags

nvim-r

Vim plugin to work with R

Installed using vim-plug.

Typical workflow

Opening the environment

  1. Open the file
  2. Launch the R console (<localeader>rf). It will automatically open in a new viewport below.
  3. Open the object browser (<localleader>ro). It will automatically open in a new viewport to the right.
  4. Switch between windows using <Cntrl-W> {j,k,l,m}, where {j,k,l,m} stands for one of the four directional movement, e.g. <Ctrl-w> j for move to the viewport below

Select and run code

  • Send and run the current line using <localleader>l
  • Visually select and then run the selected code using<localleader>ss
  • Run the current function using <localleader>ff
  • Run the current block using <localleader>bb

Investigate data

  • View a dataframe using <localleader>rv

Key bindings

Key-bindings have been copied and pasted from the help file (see either online or :help nvim-r forms) .

In the tables below, <ll> is the local leader. My local leader is currently set to <space> (by default it’s ‘\’).

Start / Close
Menu Entry Default Shortcut
Start R (default) <ll>rf
Start R (custom) <ll>rc
Close R (no save) <ll>rq
Stop R :RStop
Send
Menu Entry Default Shortcut
File <ll>aa
File (echo) <ll>ae
File (open .Rout) <ll>ao
Block (cur) <ll>bb
Block (cur, echo) <ll>be
Block (cur, down) <ll>bd
Block (cur, echo and down) <ll>ba
Chunk (cur) <ll>cc
Chunk (cur, echo) <ll>ce
Chunk (cur, down) <ll>cd
Chunk (cur, echo and down) <ll>ca
Chunk (from first to here) <ll>ch
Function (cur) <ll>ff
Function (cur, echo) <ll>fe
Function (cur and down) <ll>fd
Function (cur, echo and down) <ll>fa
Selection <ll>ss
Selection (echo) <ll>se
Selection (and down) <ll>sd
Selection (echo and down) <ll>sa
Selection (evaluate and insert output in new tab) <ll>so
Paragraph <ll>pp
Paragraph (echo) <ll>pe
Paragraph (and down) <ll>pd
Paragraph (echo and down) <ll>pa
Line <ll>l
Line (and down) <ll>d
Line (and new one) <ll>q
Left part of line (cur) <ll>r<Left>
Right part of line (cur) <ll>r<Right>
Line (evaluate and insert the output as comment) <ll>o
Command
Menu Entry Default Shortcut
List space <ll>rl
Clear console <ll>rr
Remove objects and clear console <ll>rm
Print (cur) <ll>rp
Names (cur) <ll>rn
Structure (cur) <ll>rt
View data.frame (cur) <ll>rv
Run dput(cur) and show output in new tab <ll>td
Run print(cur) and show output in new tab <ll>tp
Arguments (cur) <ll>ra
Example (cur) <ll>re
Help (cur) <ll>rh
Summary (cur) <ll>rs
Plot (cur) <ll>rg
Plot and summary (cur) <ll>rb
Set working directory (cur file path) <ll>rd
Sweave (cur file) <ll>sw
Sweave and PDF (cur file) <ll>sp
Sweave, BibTeX and PDF (cur file) (Linux/Unix) <ll>sb
Knit (cur file) <ll>kn
Knit, BibTeX and PDF (cur file) (Linux/Unix) <ll>kb
Knit and PDF (cur file) <ll>kp
Knit and Beamer PDF (cur file) <ll>kl
Knit and HTML (cur file, verbose) <ll>kh
Knit and ODT (cur file) <ll>ko
Knit and Word Document (cur file) <ll>kw
Markdown render (cur file) <ll>kr
Spin (cur file) (only .R) <ll>ks
Open attachment of reference (Rmd, Rnoweb) <ll>oa
Open PDF (cur file) <ll>op
Search forward (SyncTeX) <ll>gp
Go to LaTeX (SyncTeX) <ll>gt
Build tags file (cur dir) :RBuildTags
Edit

Table Note: The “Hit _ to insert <-” shortcut can be disabled by adding let R_assign = 0 to one’s ~/.vimrc or init.vim configuration file. If the shortcut has been enabled, an underscore can be entered by hitting ‘_’ twice.

Menu Entry Default Shortcut
Insert “<-” (currently disabled) _
Complete object name <Ctrl-x> <Ctrl-o>
Indent (line) ==
Indent (selected lines) =
Indent (whole buffer) gg=G
Toggle comment (line, sel) <ll>xx
Comment (line, sel) <ll>xc
Uncomment (line, sel) <ll>xu
Add/Align right comment (line, sel) <ll>;
Go (next R chunk) <ll>gn
Go (previous R chunk) <ll>gN
Object Browser
Menu Entry Default Shortcut
Open/Close <ll>ro
Expand (all lists) <ll>r=
Collapse (all lists) <ll>r-
Toggle (cur) Enter
Help (plugin)
Menu Entry Default Shortcut
Help (R) :Rhelp

Configuration

vimrc

Cmd Description
map Character mapping for all modes.
nmap Character mapping for normal mode only.
vmap Character mapping for visual mode only.
imap Character mapping for insert mode only.

Each map command (map, nmap, vmap, imap) has a noremap equivalent (noremap, nnoremap, vnoremap, inoremap). These ignore other mappings, and therefore avoid recursion problems. Always* use these forms instead.

Cmd Description
mnoreap Character mapping, no re-all modes
nnoremap Character mapping, normal mode only
vnoremap Character mapping, visual mode only
inoremap Character mapping, insert mode only

Silly Vim

Useless but interesting things.

Command Description
N gs Put vim to sleep for N seconds

Glossary

buffer
File currently in memory; an open isntance of a file. A file may be open but not displayed. See buffers.
mark
A remembered cursor position
mode
One of Vim’s modes. Vim is a modal editor. See modes.
register
Place to store and retreive snippets of text or commands

session

tab
A collection of windows
viewport
A view of a buffer. Equivalent to window. A file can be in multiple windows simultaneously.
window
A view of a buffer. Equivalent to viewport.

  1. There are other modes beyond insert and normal mode (see modes), but they are infrequently used. 

  2. Using MacVim via the terminal mvim command requires adding the executable mvim script to one’s path. Two options: (1) Add the MacVim binary directory to one’s $PATH (located at /Applications/MacVim.app/Contents/bin); or (2) Copy the MacVim executable script to another binary directory of choice (e.g. /usr/local/bin

  3. A Vim dictionary is just a collection of words that are considered to by correctly spelled. It is not a dictionary in the traditional sense, i.e. a word with associated definitions. 

  4. File which tells Vim which keywords to mark in what color.