Modes, Navigation & Basic Editing

"Vim is like a language: once you learn the grammar, you can express anything."

If you have ever watched an experienced Vim user edit code, you may have noticed something almost musical about the way they work. Their fingers barely leave the home row, yet text seems to rearrange itself at the speed of thought. There is no frantic mouse-grabbing, no holding down arrow keys. Just short, deliberate keystrokes that compose into powerful editing actions. The secret behind that fluency is what this chapter teaches you: modes, navigation, and basic editing commands. These are the building blocks of everything you will do in Vim and Neovim. Master them, and the editor stops being a tool you fight against — it becomes an extension of how you think.

What you'll learn in this chapter:

  • Understand Vim's modal editing paradigm and switch between Normal, Insert, Visual, and Command modes

  • Navigate efficiently within lines, across words, and through files using motions and the jumplist

  • Use the dot command and the cgn workflow to repeat changes with minimal keystrokes

  • Leverage the z commands, page navigation, and g-prefixed commands for advanced movement

  • Save, quit, and manage files from Command mode

Understanding Vim Modes

Vim is a modal editor — it has different modes for different tasks. This is what makes Vim unique and powerful.

Most editors you have used before are modeless: every key you press inserts a character, and you need modifier keys or menus to do anything else. Vim turns this idea on its head. In Vim, your keyboard has different "personalities" depending on which mode you are in. In Normal mode, every key is a command — d deletes, w moves forward a word, p pastes. In Insert mode, keys type text just like any other editor. This separation is the core insight of modal editing: since you spend far more time navigating and manipulating text than actually typing new characters, it makes sense to give those actions first-class keybindings instead of burying them behind Ctrl and Alt combinations. Once this clicks, you will wonder how you ever edited text any other way.

Mode
What it does
How to get there

Normal

Move around and change text

Esc

Insert

Type text

a, A, i, I, o, O

Command

Run commands

Esc:

Visual

Select text

Esc v V or Ctrl + v

Terminal

Interact with terminal (Neovim)

:terminal

Entering Insert Mode

You will frequently move between Normal and Insert mode, so Vim gives you many ways to enter Insert mode — each one placing your cursor exactly where you need it. Choosing the right entry point saves you from repositioning after the fact.

Shortcut
What it does

a

Start Insert Mode after current character

A

Start Insert Mode at the end of current line

i

Start Insert Mode before current character

I

Start Insert Mode at start of the line

o

Start Insert Mode one line below

O

Start Insert Mode one line above

cc

Delete current line and start Insert Mode

S

Delete current line and start Insert Mode

gi

Restart Insert Mode from the last insert point

Neovim: Neovim adds Terminal mode accessed via :terminal. Press Ctrl+\ Ctrl+n to return to Normal mode from Terminal mode.

The $MYVIMRC Environment Variable

Before we dive deeper into navigation, let's take a quick detour into configuration. As you learn new commands in this chapter, you will want a place to save your settings and customizations. That place is your configuration file, and Vim makes it easy to find through a single environment variable.

The environment variable $MYVIMRC is the main config file of Vim/Neovim. It changes accordingly with your system:

Editor
OS
Config Path

Vim

Linux/macOS

~/.vimrc

Vim

Windows

$HOME/vimfiles/vimrc

Neovim

Linux/macOS

~/.config/nvim/init.vim or ~/.config/nvim/init.lua

Neovim

Windows

~/AppData/Local/nvim/init.vim or init.lua

Tip: Using $MYVIMRC in your mappings and commands is more portable than hardcoding the path.

How to Get Help

Every great craftsperson knows how to consult the manual, and Vim's built-in help system is one of the best you will ever encounter. Before you reach for a web search, try :help first — the answer is almost always there, and often more precise than what you will find online.

Command
What it does

:help gR

Help for gR in normal mode

:help v_r

Help for r in visual mode

:help i_CTRL-W

Help for Ctrl+w in insert mode

:help :quit

Help for :quit in command mode

:help c_CTRL-R

Help for Ctrl+r in command line editing

:help togg<TAB>

Help for all topics containing 'togg'

Tip: You can abbreviate the word help: :h :help — in the vim help you see h[elp], the part between brackets is optional.

Tip: After opening the vim help you will see some "links" in different colors. When you are over any of these links you can type Ctrl+] to jump to a topic, and Ctrl+o or Ctrl+t to get back.

Now we arrive at the heart of this chapter: movement. In Vim, navigation is not just a way to get somewhere — it is half of the editing language itself. When you combine a motion like $ (end of line) with an operator like d (delete), you get d$ — "delete to end of line." Learning motions well is therefore learning to edit well.

Let's start with moving within a single line. Vim has four native keybindings to jump to specific positions in the line:

Shortcut
What it does

0

Go to the first column of the line

^

Go to the first non-blank character

$

Go to the end of the line

g_

Go to the last non-blank character

Moving on the line

Tip: You can be at the middle of the line and want to delete until the first non-blank character — just type: d^

Word Motions

Jumping to the beginning or end of a line is useful, but most of the time you want to move in smaller, more precise increments. Word motions let you hop forward and backward through text one word at a time — and they are the motions you will use most often in everyday editing.

Command
What it does

w

Move to the beginning of the next word

W

Move to the beginning of the next WORD

b

Move to the beginning of the previous word

B

Move to the beginning of the previous WORD

e

Move to the end of the current/next word

E

Move to the end of the current/next WORD

Note: word vs WORD — A word is a sequence of letters, digits, and underscores (or a sequence of other non-blank characters). A WORD is any sequence of non-blank characters separated by whitespace. For example, my-variable is three words but one WORD. See :help word.

These motions combine with operators: dw deletes to the next word, cW changes to the end of the current WORD, d2w deletes the next two words (see Text Objects & Motions for a complete guide to combining operators with text objects).

F{chars}: Jumping to Characters

Now that you know how to move by words, let's learn how to jump to specific characters. Imagine your cursor is at the beginning of a long line and you need to get to a comma halfway through it. You could press w several times, but there is a faster way.

The f{char} motions are one of those Normal Mode commands that make people fall in love with Vim. They let you jump directly to any character on the current line.

Shortcut
Example
What it does

f{char}

f,

Jump to the next comma

F{char}

F,

Jump to the previous comma

t{char}

t)

Jump until before close parenthesis

T{char}

T)

Jump back until after open parenthesis

df{char}

df.

Delete until dot (included)

vt{char}

vt"

Select until before quotes

Tip: The uppercase versions F and T jump in the opposite direction. Use ; to repeat the last f/t motion forward, and , to repeat it backward.

Neovim: Plugins like flash.nvimarrow-up-right, leap.nvimarrow-up-right, or vim-sneakarrow-up-right extend this concept to jump anywhere on the screen with just 2-3 keystrokes. vim-sneak works in both Vim and Neovim, while flash.nvim and leap.nvim are Neovim-only.

The "z" Commands: Page View

So far, all our motions have moved the cursor. But sometimes the cursor is exactly where you want it — the problem is that the surrounding context has scrolled off screen. The z commands solve this by repositioning the viewport around your cursor without moving the cursor itself.

Command
What it does

zt

Move current line to the top of the window

zz

Move current line to the middle of the window

zb

Move current line to the bottom of the window

Tip: Set scrolloff to keep some lines visible above/below the cursor: :set scrolloff=8

Moving Around: Jumplist & Changelist

When you work on real code, you rarely stay in one place. You jump to a function definition, check a variable somewhere else, then need to get back to where you started. Vim quietly tracks all of these movements for you in two lists — the jumplist and the changelist — so you can always retrace your steps.

The Jumplist

Vim maintains a list of all your jumps. This is incredibly useful for navigating back and forth:

Command
What it does

Ctrl+o

Jump to older position in jumplist

Ctrl+i

Jump to newer position in jumplist

:jumps

Show the jumplist

''

Toggle between last two positions

Note: '' vs Ctrl+o — These two are often confused. '' toggles between exactly two positions — pressing it twice returns you to the same place. Ctrl+o walks backward through the entire jumplist (which can contain many positions across files). Use '' for quick back-and-forth between two spots, and Ctrl+o when you need to retrace your steps through multiple jumps.

The Changelist

Similar to the jumplist, Vim tracks where you made changes:

Command
What it does

g;

Go to older position in changelist

g,

Go to newer position in changelist

'.

Jump to last modification

:changes

Show the changelist

Beyond the jumplist and changelist, you will often need to scroll through a file quickly. These commands move you by pages or half-pages, and let you jump to any line by number.

Command
What it does

Ctrl+f

Page forward

Ctrl+b

Page backward

Ctrl+d

Half page down

Ctrl+u

Half page up

gg

Go to first line

G

Go to last line

{count}G

Go to line {count}

Neovim: Plugins like vim-smoothiearrow-up-right (Vim/Neovim) or Neovim's built-in vim.opt.smoothscroll = true (Neovim 0.10+) add animated scrolling to Ctrl+d/u/f/b, making it easier to maintain context when jumping.

The Dot Command

If you take away only one thing from this chapter, let it be the dot command. Ask any long-time Vim user what their favorite feature is, and many will answer . without hesitation. The reason is simple: the dot command repeats your last change. That single key turns any edit — no matter how complex — into a repeatable action. Delete a word? Press . to delete the next one. Change a function argument? Press . to make the same change somewhere else. The dot command rewards you for thinking in composable edits: the better you structure your initial action, the more mileage you get from repeating it.

In Normal mode, the dot command . repeats your last action. This is one of the most powerful concepts in Vim.

Example: Adding --> between the last two words on multiple lines:

Literal Inserting

When using the dot command with paste operations, you need to paste literally to ensure the dot command replays the correct content.

If you use ciw to change a word, type replacement text, and then try to repeat with . on another word — it works. But if you paste from a register during the change, the dot command will paste the same text again.

To fix this, paste your register literally with Ctrl+r Ctrl+o" instead of Ctrl+r". Now the dot command will paste the current content of the register.

The site vimgolf.comarrow-up-right has Vim challenges where the goal is to solve editing problems with the fewest keystrokes possible. Many of these challenges require understanding literal inserting to use the dot command effectively with cgn-style workflows.

VimGolf challenge

Normal Commands That Stand Out

Vim has a collection of commands prefixed with g that don't fit neatly into the categories above but are too useful to overlook. Think of them as Vim's utility belt — once you discover them, you will reach for them constantly.

Shortcut
What it does

gd

Go to local definition

gD

Go to global definition

gf

Go to the file under the cursor

gi

Enter insert mode at last insertion point

gv

Repeat last visual selection

gx

Open URL under cursor in browser

ga

Show ASCII/Unicode value for character under cursor

gJ

Join lines with no space in between

gu{motion}

Make text lowercase

gU{motion}

Make text UPPERCASE

gn

Search forward and select the match (useful with cgn)

gR

Start virtual replace mode

The cgn Workflow

Here is a scenario every programmer knows: you have renamed a variable in your head, and now you need to update it in fifteen places across a file. You could use :%s/old/new/g, but what if some of those instances should stay the same? Maybe user appears as a variable name in some lines but as part of a comment or string in others, and you only want to change certain occurrences. This is the exact problem cgn solves. It combines searching, changing, and the dot command into a workflow that lets you step through matches one by one, applying or skipping each change with a single keystroke.

The gn command is a game-changer for search-and-replace workflows:

  1. Search for a word: /pattern

  2. Press cgn to change the match

  3. Type your replacement

  4. Press Esc

  5. Press . to repeat on the next match, or n to skip

This is often faster and more flexible than :%s/old/new/g because you can selectively apply changes. See the excellent Vimcasts episode on gnarrow-up-right for a visual walkthrough.

Tip: gf only works properly if you enable: :set hidden and :set path+=**

The Ex put Command

Stepping briefly into Command mode, the :put command is a handy way to insert text without entering Insert mode at all. It is especially powerful when combined with expressions, letting you generate content programmatically right inside your editor.

The :put command inserts text from a register or expression after a given line:

This puts the string after line zero (before the first line). You can combine put with Vim's scripting to generate content programmatically:

Note: We use | to separate commands on the same line.

To add a blank line at the end of your document: :$put _ — the $ represents the last line and _ is the black hole register.

Leaving the File

Every editing session has to end at some point. Vim offers several ways to save your work and exit — and yes, knowing how to quit Vim is a rite of passage. Here are the commands you need.

Shortcut
What it does

:q

Quit (fails if unsaved changes)

:q!

Quit without saving

:w

Save (write)

:wq or ZZ

Save and quit

:x

Save only if changed, then quit

ZQ

Quit without saving (same as :q!)

:qa

Quit all windows

:wa

Save all windows

Tip: For custom keybindings to streamline saving, quitting, and other frequent operations, see Mappings.

Summary

This chapter covered the core mechanics of working in Vim: its modal editing paradigm, the full spectrum of navigation commands from single-character jumps to page-level scrolling, and essential editing workflows like the dot command and the cgn pattern. Together, these building blocks form the foundation for everything that follows in this book.

Key takeaways:

  • Vim's modal design separates navigation from text entry, giving every key a command in Normal mode and freeing you from modifier-key gymnastics

  • Line motions (0, ^, $, g_), word motions (w, b, e), and character jumps (f, t) compose with operators (d, c, y) to form a powerful editing language

  • The jumplist (Ctrl+o / Ctrl+i) and changelist (g; / g,) let you retrace your steps across files and edits

  • The dot command (.) repeats your last change, and the cgn workflow combines search, change, and repeat into a selective find-and-replace

  • The g-prefixed commands (gd, gf, gv, gn, gU, gu) provide advanced navigation and text manipulation

Exercises

  1. Mode switching drill — Open a file and practice entering Insert mode with each of the entry commands: i, I, a, A, o, O, cc, and gi. After each insertion, return to Normal mode with Esc. Pay attention to where the cursor lands for each command.

  2. Navigate with word and character motions — Given the line const user = getUser(id, { includeProfile: true });, start at the beginning and reach the word true using only w, W, f, and t motions. Try multiple approaches and count keystrokes.

  3. Jumplist navigation — Open three different files (or use :help to jump around). Navigate between them using Ctrl+o and Ctrl+i. Then use :jumps to view your jumplist.

  4. The cgn workflow — Create a buffer with this content: foo bar foo baz foo qux. Use the cgn workflow to replace only the first and third occurrences of foo with hello, skipping the second.

  5. Combine motions with operators — On a line like delete [everything] inside these {curly braces} please, delete the content inside the square brackets and then inside the curly braces using the fewest keystrokes.

Last updated

Was this helpful?