Published on

Learning VIM

  • avatar
    Chris Postma

I'm finally fully committing to learning VIM. It's been a learning goal for the past year that I keep avoiding as other topics have taken priority. Recently, however, a close friend started teaching himself VIM and the excitement caught on. I could no longer resist.

I think it's also beneficial to learn as soon as possible because once you commit the basics to memory, you can continue to train it passively as you work. It's a skill that grows with you everyday while you work. Therefore, I plan to get myself to the same speed as my previous configuration with VIM as soon as possible so that I can begin training it passively while I take on new topics.

VIM stands for Vi IMproved, a vi-derivative text editor based on the original Vi editor that was released in 1976. VIM was written by Bram Moolenaar and released in 1991. VIM comes with Linux, BSD, and macOS. It's a small and fast program that can be run in a terminal.

Some of the main benefits of VIM are as follows:

  1. It is omnipresent -- available on most machines and bindings exist for most editors
  2. It has a low memory footprint and is fast
  3. Highly configurable via simple text files
  4. It uses commands that can be composed together to accomplish complex text-based tasks

VIM is also a modal editor as opposed to a modeless editor. Modal editors offer multiple types of interaction modes which are each optimized for specific tasks. The original intent of modal editors was to allow users to perform complex operations without the use of a mouse, which may not have been available at the time. This is still a primary benefit today, the ability to quickly move through and edit files without a mouse.

A few of the modes available are as follows:

  • Normal mode - movement (default)
  • Insert mode - editing
  • Visual mode - selecting
  • Visual line mode - selecting multiple lines
  • Command mode - do things like write buffer, quit, etc.
  • Replace mode - replace text at position

As part of my learning, I am following this video series by The Primeagen wherein he provides chunks of commands to get started so as to not be overwhelmed. Below are some notes from each video that I am taking to aid my learning.

Vim Learning Path (1 week practice minimum per chunk)

First Chunk

h/j/k/lleft/down/up/right directions
w/bforward/backward by word
emove to the end of the next word
iinsert mode
ainsert mode after cursor
Ainsert mode at end of line
giinsert mode at same position where insert mode was last used
escexit insert/visual mode
ctrl + cexit insert mode
crl + [exit insert mode
yyyanks a line
ppaste line one line below
dddelete line current line
uundo last command
xdelete under cursor, single char
shift-v (V)highlights a line
j or kto select lines up or down
yyank and save to register
ddeletes and saves to register
p/Pto paste register below/above cursor
vhighlights current letter (use movement to continue selecting)
:wsave your file (if in vim proper)
:qquit after saving
:q!quit without saving
.repeat last command

Second Chunk

o/Oinsert new line and enter insert mode below/above
shift-p (P)paste above
i/ainsert mode left of cursor, right of cursor
I/Ainsert mode beginning/end of current line
$/0go to end/beginning of current line, movement only
/search for ie: /word
*next occurrence of whatever is under your cursor
n/Ngo to next/previous occurrence once set with * or /<search term>

Third Chunk (Horizontal Speed)

fx/Fxsearch forward/backward for x, land on result
tx/Txsearch forward/backward for x, land one space before result
;after search, use to move forward to next instance
,after search, use to move backward to previous instance
:/,move forward/backward through search result from f/t
xdelete single character
sdelete single character + enter insert mode
cjust like delete (d) but goes into insert mode as well
shift-d (D)delete full line from current position
shift-c (C)delete full line and enter insert mode from current position
shift-s (S)delete full line and enter insert mode

Some examples:

dt)delete everything up until ) but not ) itself
yt)delete everything up until ) but not ) itself
df)delete everything up to and including the )
dT(delete everything back to, but not including the (
dF(delete everything back to and including the (
vf)select everything up to )
ct)delete everything up until ) and enter insert mode
cf)delete everything up to and including the ) and enter insert mode

Fourth Chunk (Vertical Speed)

gg/Ggo to top of document/bottom of document
:100go to line number
100Ggo to line 100
{ or }jump up/down to next empty line (paragraph)
%if on a bracket/brace, move to matching bracket/brace
di}delete inside }, such as if inside an if statement
ci}delete inside } and enter insert mode
yi}copy inside }
cipcut entire paragraph
vi[copy everything inside square brackets
va[copy everything inside square brackets and including brackets
da{delete everything inside curly brackets including the brackets
shift+i (I)enter insert mode before first non-blank character in same line

Some examples:

4jjump down four lines
12kjump backward by 12 line
4wjump forward four words
6bjump backwards four words
100Ggo to line 100
ctrl+d, ctrl+upage down, page up
diwdelete word, cursor can be anywhere in word
cipdelete paragraph and enter insert mode
yi)copy inside parenthesis
d2i{delete most immediate plus surrounding content inside {

Other commands

gqon a visual selection, reflow and wordwrap blocks of text
gbadd another cursor on the next word found that matches word under cursor
ghpreview type definition (similar to hovering over a word)
gdjump to local definition
gDjump to global definition
ctrl+emove screen down one line without moving cursor
ctrl+ymove screen up one line without moving cursor
:100go to line number
>>, <<indent line

Marking text (visual mode)

vstart visual mode, mark lines, then do a command (like y-yank)
Vstart linewise visual mode
ctrl+vstart visual block mode
O or omove to other corner of block
awmark a word
aba block with ()
aBa block with {}
ata block with <> tags
ibinner block with ()
iBinner block with {}
itinner block with <> tags
Escexit visual model

Helpful commands learned during week 3

g;return to last edit made
gvreturn to last selection
yibyank inside brackets
==auto indent
cs"'change surrounding double quotes to single quotes
cs]}change surrounding brackets to parens
vibS{select and replace surrounding motion with brackets
gUibchange casing within brackets to uppercase
:%s/foo/barreplace all instances of foo with bar in file
[{jump to above curly bracket (e.g. if inside function body)

Helpful commands/ideas learned during week 4

ctrl+fmove forward in the document
ctrl+bmove backward in the document
shift+hplace cursor at top of screen
shift+mplace cursor at middle of screen
shift+lplace cursor at bottom of screen
z entermove screen down and keep cursor at some position
10ggsame as :10
_move to first non-empty character in line
ctrl+imove cursor to previous position, newer
ctrl+omove cursor to previous position, older
shift+renter replace mode
rreplace a single character
ccchange an entire line
g~<motion>switch case inside motion
g~~switch case of entire line
guuchange line to lowercase
gUUchange line to uppercase
gU<motion>change motion to uppercase
gJappend below line to current line without space at end of first line
*forward search for word
#backward search for word

This week I started to take the Udemy course called Vim Masterclass by Jason Cannon. Much of the course is reiterating what I've already learned so far but in much more detail and with the ideas behind each command explained better than they were on YouTube.

One idea Jason shares is the correct words to refer to each optional and required part of VIM commands, such as [count]operation[count]{motion}. This is helpful in learning how to think in VIM.

The example he uses to teach this idea is delete a word:

  • dw delete word is an operation{motion}
  • dh delete one character to the left is the same as X
  • dl deleted one character to the right is the same as x
  • dk delete current line and one above it
  • d0 delete from cursor to start of line
  • d$ delete from cursor to end of line
  • D the same as above but an alterante
  • 3dd delete line three times
  • d3w delete 3 words
  • 2d3w delete three words two times

linewise command - a command that operates on an entire line

characterwise command - a command that operates on a character

  • ! forces a command in vim
  • ! can be used to execute external commands
  • :help opens vim help
  • :help <COMMAND>

A register is a place where cut and copy text is stored, similar to the system clipboard. The unamed register is commonly referred to as the default register.

There are many types of registers in VIM:

  • Unnamed
  • Numbered
  • Named

Registers are preceded by a ".

  • Unnamed register = ""
  • Numbered registers = "0, "1 ... "9

The unnamed register contains the last text from d, c, s, x, and y operations.

  • "0 holds the last text yanked (y)
  • "1 holds the last text deleted (d) or changed (c)
  • Numbered registers shift with each d or c

To view registers, issue the command :reg

  • "_ is known as the blackhole register. Nothing happens when sent to this register.
  • There are 26 named registers, from a to z.
  • The capital letter of the register name will append to the register.

We can type :reg <register> to view a specific registers content.

We can use registers with the following patterns, [count][register]operator or [register][count]operator.

You can repeat insert commands any number of times, such as insert 80 asterisks, which would be 80i* and then escape. Or create five new lines with a pound character, 5o# and then escape.

Week 5

:s/foo/bar/replace foo with bar, one instance only
:s/foo/bar/greplace foo with bar, multiple times same line
:1,5s/foo/bar/replace foo with bar, multiple lines as specified
:%s/foo/bar/replace foo with bar, entire document
at or itwhen editing html tags, use text objects
ditdelete inside tags
>i{indent all text between {

The pattern for search and replace is: :[range]s/old/new/[flags].

This week I am also focusing on macros.

VIM macros record keystrokes into a register. To begin recording a macro, press q<register>. Then type in the commands for the macro to record. It is generally a nice idea to make the final command a movement down to the next line to make repeating the command more convenient.

To stop record, press q.

To replay a macro, press @<register>. To replay the last played macro, press @@.

Best practices:

  • Normalize the cursor position, e.g. 0
  • Position cursor for next replay using j

I can replay a macro [count] times, e.g. 5@a. I can append to a register using the capital letter of the register. E.g. qa and then later qA.

I can hit ctrl+g to get the line count of the file. This can be useful when wanting to apply a macro to the entire file when it is not possible to see the last line without scrolling down. I can then issue a command such as :27,35normal @a or current line to end of file with :.,$ @a.

To edit a macro, I can just put the contents of the register, modify it, then yank it back into the register.

It is also possible to save macros to the .vimrc file.

Another focus is visual mode.

  • Use v to start characterwise visual mode.
  • Use V to start linewise visual mode.
  • Use ctrl+v to start blockwise visual mode.

I can use motions to expand the visual area. I can also use text objects to expand the visual area.

I can use most regular VIM commands in visual mode, such as ~, c, d, y, r, u, I, etc.

I can use gv to start visual mode with the same area selected as the last area selected the last time I used visual mode.

  • o allows me to switch from one side of a selection to the other, vetically.
  • O allows me to switch from one side to the other horizontally.

In blockwise visual mode, I can use $ to select to the end of all lines, even if they have varying lengths.

Update 2023-01-15

A few very useful discoveries:

  • ctrl + w + hjkl will move between buffers in VSCode's VIM plugin
  • gt and gT will cycle between buffers
  • ctrl + a is used for incrementing
  • ctrl + x is used for decrementing
  • g ctrl + a can be used to increment an entire paragraph if used after entering visual mode, e.g. vap
  • If at the beginning of a line that has something in quotation marks or backticks, you can change from there by using ci', for example, which will jump to that single quote in the line.