Vim - a Fancy Text Editor

Motion

Below are some advanced motion tips beyond basic hjkl, ^$ and wWeE motion

  • 0: move to the very beginning of the line
  • ^: move to the first non-blank character of the line
  • I: move to the first non-blank character of the line and enter insert mode
  • A: move to the last character of the line and enter insert mode
  • %: jump to the corresponding pair (e.g., matching parentheses, brackets, braces, or quotes)
  • Ctrl+d: move half page down
  • Ctrl+u: move half page up
  • f<char>: move forward to the next occurrence of <char>
  • F<char>: move backward to the previous occurrence of <char>
  • t<char>: move forward until before the next occurrence of <char>
  • T<char>: move backward until after the previous occurrence of <char>
  • *: move forward to the next occurrence of the current word
  • #: move backward to the previous occurrence of the current word
  • g*: move forward to the next occurrence of the current word, including partial matches
  • g#: move backward to the previous occurrence of the current word, including partial matches

After using any of *#g*g#, n repeats the search in the same direction.

EasyMotion

EasyMotion is a plugin of Vim. It’s highly recommended to move cursor with it.

Installation

To install EasyMotion, we utilize a plugin manager called Vim-Plug. Install the plugin manager first:

curl --proxy http://127.0.0.1:10809 -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

Update your ~/.vimrc file:

call plug#begin()
Plug 'easymotion/vim-easymotion'
call plug#end()

Note: If you’re behind a proxy, you may need to configure it:

# Configure git proxy (if needed)
git config --global http.https://github.com.proxy http://127.0.0.1:10809

# Configure curl proxy (if needed)
export http_proxy=http://127.0.0.1:10809
export https_proxy=http://127.0.0.1:10809

Start Vim and in command mode issue :PlugInstall to install the plugins according to your ~/.vimrc file. Once done, start Vim and try <leader><leader>w to verify if EasyMotion works. The default leader key is <leader> (typically \ or ,).

Usage

Some commonly used keystrokes:

  • <leader><leader>w - Jump to start of words forward
  • <leader><leader>b - Jump to start of words backward
  • <leader><leader>j - Jump to lines below
  • <leader><leader>k - Jump to lines above

Configuration for Bidirectional Motion

EasyMotion provides bidirectional motion. Configure key bindings in ~/.vimrc:

" Other configuration in ~/.vimrc

" Bidirectional word motion
nmap <Leader><Leader>w <Plug>(easymotion-bd-w)
nmap gw <Plug>(easymotion-bd-w)

" Bidirectional word-end motion
nmap <Leader><Leader>e <Plug>(easymotion-bd-e)
nmap ge <Plug>(easymotion-bd-e)

Grammar

Vim supports <num> <operation> syntax. For example, 5yy copies the current line and the following 4 lines.

Vim also supports <operation> <motion> syntax. For example, c$ changes from the current position to the end of the line.

Text Objects

Vim supports text objects to further improve productivity. Text objects allow you to operate on linguistic units (words, sentences, paragraphs) rather than character positions.

Common text objects:

Text Object Description
iw / aw inner/around word
is / as inner/around sentence
ip / ap inner/around paragraph
it / at inner/around tag
i<delimiters> / a<delimiters> inner/around delimiters (quotes, brackets, etc.)

Common delimiter examples:

  • i" / a" - inside/around double quotes
  • i' / a' - inside/around single quotes
  • i( / a( - inside/around parentheses
  • i[ / a[ - inside/around brackets
  • i{ / a{ - inside/around braces

<operation> <text object> is supported in Vim. For example:

  • yiw - yank (copy) the current word
  • ci" - change the content inside the current quotes
  • daw - delete (remove) the current word including surrounding whitespace
  • ca" - change the content around the current quotes (including the quotes themselves)

Why use text objects?

  • More intuitive than character-based motions
  • Works with varying content sizes automatically
  • Less prone to errors from incorrect character counts
  • Consistent behavior regardless of content length

Unnecessary Motion

With some shortcuts and the Vim ‘grammar’ concept, many motions become unnecessary. Here are some examples:

Insert mode shortcuts:

  • A - move to end of line and enter insert mode (no need for $a)
  • I - move to first non-blank character and enter insert mode (no need for ^i)
  • o - open a new line below and enter insert mode
  • O - open a new line above and enter insert mode

Text object operations:

  • ci" - change inside quotes (works even if cursor is outside the quotes, searches forward)
  • da" - delete around quotes (removes quotes and their content)
  • ca" - change around quotes (replaces quotes and their content)

Why ci" works without being inside the quote: Vim’s text object operations perform a forward search to find the target. This means:

  • If you’re already inside the quote, it targets the current pair
  • If you’re outside the quote, it finds the next matching pair
  • It does not perform backward search

Comparison table:

Command Behavior Note
ci" Change inside quotes Searches forward, even from outside
ca" Change around quotes Includes the quotes themselves
da" Delete around quotes Removes quotes and content
di" Delete inside quotes Removes content only, keeps quotes
caw Change around word Includes surrounding whitespace
ciw Change inside word Only the word characters

Common pitfalls to avoid:

  • Using d$ when you could use D (delete to end of line)
  • Using ^i when you could use I (insert at start of line)
  • Using a" when you meant i" (includes extra quotes unexpectedly)

Command Mode

Command‑line mode (also called Ex mode) allows you to run colon commands beyond simple commands like :q, :w, etc. Many practical operations can be done with command mode. :help ex-cmd-index shows the list of EX commands

==============================================================================
6. EX commands                                  ex-cmd-index :index

This is a brief but complete listing of all the ":" commands, without
mentioning any arguments.  The optional part of the command name is inside [].
The commands are sorted on the non-optional part of their name.

tag             command         action
------------------------------------------------------------------------------
:               :               nothing
:range          :{range}        go to last line in {range}
:!              :!              filter lines or execute an external command
:!!             :!!             repeat last ":!" command
:#              :#              same as ":number"
:&              :&              repeat last ":substitute"
:star           :*              execute contents of a register
:<              :<              shift lines one 'shiftwidth' left
:=              :=              print the cursor line number
:>              :>              shift lines one 'shiftwidth' right
...

To view help for a specific command, use :help :<cmd>, e.g. :help :s. To get word completion in command mode, use Ctrl-d and TAB key**.

Range

A range defines the set of lines an Ex command operates on. The syntax is <start_position>,<end_position>, for example

  • 1, 5 - lines 1 through 5
  • 1,. - from the first line to the current line
  • .,$ - from the current line to the end of the buffer
  • .-1,.+1 - one line above to one line below the cursor

In Visual mode, when multiple lines are selected, pressing : will enter command mode with :'<,'> shown in the command mode prompt. '<,'> represents from the entire first line to the entire last line of the selected multiple lines.

Similary '[,'] represents from the entire first line to the entire last line of the most recently changed area.

Move Lines

To move the current line and the next 3 lines to the bottom of the file:

:.,.+3m$

To move lines 1–4 to the current cursor position:

:1,4m.

The m command places the moved lines after the destination line.

Copy Lines

To copy lines, use co command. For example, below command copies the current line with 1 line ‘context’ to the bottom of the buffer:

:.-1,.+1co$

Contents Substitution

To replace text in the entire buffer, use s command:

:%s#Hello#Hi#g

Some useful options

  • g — replace all matches on each line
  • i — ignore case
  • c — confirm each substitution

Global Command

Sometimes, instead of using range, we need to perform the operation on matching items. For example, to get a “clean” version of Nginx configuration, we need to delete all comment lines in the configuration file.

:g/^#/d

Explanation

  • g means to globally apply the command, so the entire buffer is impacted.
  • ^# is the regular expression to match the leading pond sign, aka the comment line.
  • d means to delete the matching lines.

To operate on non‑matching lines, use v. For example, to copy all non‑comment lines to the bottom:

:v/^#/co$

Shell Interaction

In Vim command-line mode, you can execute shell command directly using exclamation mark like :!<shell_cmd>

:!date

Read from Command Output

To read the output of a shell command into the current buffer, use :r with !:

:r !date

Beyond that, Vim can read the output of any program that writes to STDOUT:

:r !python my_script.py

Treat Contents as Command String to Execute

If a line contains a shell command such as ls ~/Videos, you can send it to shell as a command to execute using !!. Once entered, you will be navigated to the command mode with below command prompt

:.!

Appending a shell name (e.g., sh) runs the line through that shell:

:.!sh

This replaces the command string in the buffer with the output produced by the shell.

Marks

A mark labels a specific position in a file so you can quickly jump back to it or use it in Ex commands. Create a mark with m<letter>. Notes:

  • Lowercase marks (a–z) are local to the current file
  • Uppercase marks (A–Z) are global across files

To jump to a mark

  • 'a jump to the line of mark a
  • a jump to the exact position of mark a, considering the mark created on the position like the second character of the line

Use Marks with Commands

Marks can be used as line addresses in command mode. If mark a is set on a line:

  • :'am. - move the marked line to the current line
  • :'aco$ - copy the marked line to the end of the buffer
  • :'ad - delete the marked line

Register & Macro

Register Basics

Registers are containers that store text for later retrieval. View all registers with :registers or :reg:

:reg
Type Name Content
  c  ""   ?asdf ad
  c  "0   ??
  l  "1   asdfa1234asdf^J
  l  "2   1234asdf^J
  l  "3   9866756^J
  l  "4   asdfasd1234^J879-0iasdf^J
  l  "5   asdfasdfasdf^Jasdfasd1234^J
  l  "6   ^J
  l  "7   adsf 134 asdf^J

Notes:

  • c means characterwise
  • l means linewise

To use a register:

  • in normal mode: use "<reg_name>, such as "add to cut the current line into a register
  • in insert mode: use Ctrl-r<reg_name>, such as Ctrl-ra to paste the contents stored in a register

Register types:

  • unamed register
  • numbered registers
  • named registers

Unamed Register

The unnamed register ("") is used when no register is specified. For example, dd stores the deleted line in “”.

A practical use case - surrounding a word with quotes:

  1. ciw - ‘cut’ the word into unnamed register
  2. " - the opening quote
  3. Ctrl-r " - read the unnamed register
  4. " - the closing quote

Numbered Registers

Numbered registers "0"9 behave as follows:

  • "0 - contains the last yanked contents (y), including characterwise and linewise
  • "1 to "9 - deletion history (dd), linewise only, newest in "1

These registers can help recover mistakenly deleted lines.

Named Registers

Named registers "a"z and "A"Z provide 52 registers total. They can store characterwise or linewise text, and they can also store macros.

Use Macro to Repeat Operations

Macros are recorded in named registers as characterwise. To record a macro, in normal mode perform

  1. q<named register> - start recording
  2. perform desired operation
  3. q - stop recording
  4. @<named register> - replay the macro

To edit a macro stored in a register:

  1. :let @<named_register>='
  2. Ctrl-r <named_register> - insert the macro contents for modification
  3. edit as needed
  4. press ENTER to save

Replay the most recently executed macro with @@.

Undo, Redo & Repeat

Keystrokes:

  • Undo: u
  • Redo: Ctrl-r
  • Repeat: .

Notice the difference between redo and repeat

  • Redo - re-apply an undone change
  • Repeat - re-execute the last change command

Example: if a line is deleted with dd

  • u restores the deleted line
  • . deletes the current line again

Work with Multiple Files

Netrw is Vim’s built‑in file explorer. Open it with :Exp. To open and edit a file directly, use :e <file>.

To open a file in a split windows, use

  • :sp <file> - horizontal split
  • :vs <file> - vertical split

To move betwen windows, using Ctrl-w followed by

  • h - move the cursor to the left window
  • j - move the cursor to the bottom window
  • k - move the cursor to the top window
  • l - move the cursor to the right window

Buffer

File contents are loaded into buffers before being written to disk. View all buffers with :buffers.

:buffers
  2      "lab.scala"            line 2
  3 #a   "sample.scala"         line 1
  4 %a   "lab2.scala"           line 1

Explanation

  • To open a specific buffer in the current winwdow, use b <buffer_number>. For instance, b 2 to open “lab.scala” in the current window
  • a - the active buffer (visible in at least one window)
  • % - the current buffer (visible in the current window)
  • # - alternative buffer (last visited buffer)

To delete a buffer, use :bd <buffer_number>.

Options

Options can be configured in command‑line mode using :set <option>. Common useful options:

  • hls - highlight search matches
  • nu - show absolute line numbers
    • rnu - show relative line numbers
    • nu rnu - show relative line numbers with an absolute line number on the current line
  • ic - ignore case when searching

To toggle an option, use :set <option>!. For example :set hls! to disable search highlighting.

Use Vim Key Binding Elsewhere

Vim keybindings can be used in many other applications to improve productivity. Examples include:

  • Tmux — a terminal multiplexer with Vim‑style navigation
  • VS Code Vim — an extension that enables Vim keybindings in Visual Studio Code
  • Vifm — a file manager with native Vim‑like commands
  • Vimium — a browser extension that brings Vim navigation to Chrome and Firefox
Built with Hugo
Theme Stack designed by Jimmy