MOVING AROUND
Learning Vim
Chapter 3 — Moving Around
Why Movement Matters
In most editors, moving around the file is an afterthought — you use the mouse, or hold arrow keys until you get where you want to go. In Vim, movement is a first-class skill. Because all editing happens in Normal mode using keyboard commands, the speed at which you can navigate directly determines the speed at which you can edit.
Vim's movement commands are also the foundation of its operator + motion grammar. Commands like "delete the next three words" or "copy from here to the end of the paragraph" are built by combining an editing operator with a movement command. Learning to move precisely and quickly therefore unlocks not just navigation but the entire editing system.
Everything in this chapter is a NORMAL mode command unless stated otherwise.
The HJKL Keys — Character Movement
Vim uses h, j, k, and l as arrow keys. This is not an arbitrary choice — it has its roots in the original ADM-3A terminal from the 1970s, on which the arrow symbols were actually printed on those keys. The layout has a practical advantage: these four keys sit on the home row of the keyboard, right where your fingers already rest. You never need to move your hand to the arrow cluster.
| Key | Direction | Memory aid |
|---|---|---|
h | Left (← ) | Leftmost of the four keys |
j | Down (↓ ) | The letter j has a tail that points down |
k | Up (↑ ) | k is above j on the keyboard |
l | Right (→ ) | Rightmost of the four keys |
Multiplying movement with counts
Any movement command can be prefixed with a number to repeat it that many times. This is one of the most efficient features of Vim navigation — instead of holding a key down and watching the cursor drift, you specify exactly how far you want to go.
5j # move 5 lines down 10l # move 10 characters to the right 3k # move 3 lines up 8h # move 8 characters to the left
Counts work with almost every movement command in this chapter — not just HJKL. When you see a new command, assume a count prefix will work unless stated otherwise.
:set relativenumber is enabled (introduced in Chapter 1), the number shown next to each line is its distance from the cursor. This makes count-based jumps trivial — you glance at the line you want, read off its number, and type that number followed by j or k.
Word-Level Movement
Moving character by character is slow even with counts. For navigating within a line or across a paragraph, word-level movements are far more efficient.
| Key | Movement |
|---|---|
w | Forward to the start of the next word |
W | Forward to the start of the next WORD (whitespace-delimited — ignores punctuation) |
e | Forward to the end of the current (or next) word |
E | Forward to the end of the current WORD |
b | Backward to the start of the current (or previous) word |
B | Backward to the start of the current WORD |
ge | Backward to the end of the previous word |
file-name.txt, w sees three words (file, -, name.txt approximately), whereas W sees one WORD. Use lowercase for precision within punctuation-heavy text; use uppercase for coarser, faster jumps.
Example — word movement on a line
Starting with cursor on "T" in "The":
| Command | Cursor lands on |
|---|---|
w | q (start of "quick") |
3w | f (start of "fox") |
e | e (end of "The") |
2e | k (end of "quick"… wait, end of "brown") |
b | T (back to start of "The") |
4w | j (start of "jumps") |
Line Movement
Moving within a line precisely is something you do constantly. These commands get you to the right position instantly:
| Key | Movement |
|---|---|
0 | Jump to the very beginning of the line (column 1) |
^ | Jump to the first non-whitespace character of the line |
$ | Jump to the end of the line |
g_ | Jump to the last non-whitespace character of the line |
f{char} | Find — jump forward to the next occurrence of char on the line |
F{char} | Find — jump backward to the previous occurrence of char on the line |
t{char} | Till — jump forward to just before char on the line |
T{char} | Till — jump backward to just after char on the line |
; | Repeat the last f, F, t, or T in the same direction |
, | Repeat the last f, F, t, or T in the opposite direction |
Example — f and t in action
Starting with cursor at the beginning of the line:
f(— jumps to the(before255t,— jumps to just before the first,(cursor sits on5);— repeats: jumps to just before the next,f;— jumps to the;at the end of the line
This is much faster than pressing l repeatedly or using the arrow keys to navigate within a long line.
0 and ^: 0 always goes to column 1, even if the line is indented. ^ goes to the first actual character, skipping any leading whitespace. In code, you almost always want ^ — it puts you at the start of the statement, not at the indentation.
Sentence and Paragraph Movement
When working with prose or structured documents, jumping sentence-by-sentence or paragraph-by-paragraph is faster than any word-level navigation.
| Key | Movement |
|---|---|
) | Forward to the beginning of the next sentence |
( | Backward to the beginning of the current (or previous) sentence |
} | Forward to the beginning of the next paragraph (next blank line) |
{ | Backward to the beginning of the previous paragraph |
., !, or ? followed by either end-of-line or at least two spaces. A paragraph is defined as a block of non-empty lines — it ends and begins at a blank line. In code, } and { are most useful for jumping between functions or blocks separated by blank lines.
As with all movement commands, counts work here too:
3} # jump 3 paragraphs forward 2{ # jump 2 paragraphs backward 5) # jump 5 sentences forward
File-Level Navigation
For large files you need to jump across long distances — to the top, the bottom, a specific line, or a screenful at a time.
Top and bottom
| Key | Movement |
|---|---|
gg | Jump to the first line of the file |
G | Jump to the last line of the file |
{n}G | Jump to line n (e.g. 42G jumps to line 42) |
:{n} | Jump to line n via the command line (e.g. :302) |
{n}% | Jump to n% through the file (e.g. 50% jumps to the midpoint) |
{n}G vs :{n}: Both jump to line n. {n}G is faster to type in Normal mode (just the number then G). :{n} is useful when you know the number from an error message — you can type it quickly after pressing :. Both are worth knowing.
Page scrolling
| Key | Movement |
|---|---|
Ctrl+F | Scroll forward one full page (keeps a couple of lines for context) |
Ctrl+B | Scroll backward one full page |
Ctrl+D | Scroll down half a page |
Ctrl+U | Scroll up half a page |
Ctrl+E | Scroll the screen down one line without moving the cursor |
Ctrl+Y | Scroll the screen up one line without moving the cursor |
Cursor positioning on screen
These three commands reposition the view around your cursor, not the cursor itself — useful for reading context around your current position:
| Key | Action |
|---|---|
zz | Scroll so the current line is in the centre of the screen |
zt | Scroll so the current line is at the top of the screen |
zb | Scroll so the current line is at the bottom of the screen |
zz is one of the most underrated commands in Vim. When you have just jumped to a line and want to read the surrounding context, zz centres it on screen instantly. It is also useful while reading — if the line you care about has drifted to the top or bottom of the screen, zz brings it back to eye level.
Searching
Search is arguably the fastest navigation tool in Vim for reaching a specific location. Instead of scrolling to where you think the text is, you tell Vim exactly what you are looking for and it takes you there instantly.
Forward and backward search
/pattern # search forward for pattern — press Enter to jump ?pattern # search backward for pattern — press Enter to jump
After pressing Enter, the cursor jumps to the first match. The matched text is highlighted across the entire file (if :set hlsearch is enabled). To navigate between matches:
| Key | Action |
|---|---|
n | Jump to the next match (in the direction of the original search) |
N | Jump to the previous match (opposite direction) |
The search wraps around — when you reach the end of the file Vim loops back to the beginning (you will see a message: search hit BOTTOM, continuing at TOP).
:nohlsearch (or its abbreviation :noh). Many users map this to a key in their config — for example :nnoremap <Esc><Esc> :nohlsearch<CR>.
Searching for the word under the cursor
Often the word you want to search for is already under your cursor. Rather than typing it out, use:
| Key | Action |
|---|---|
* | Search forward for the exact word under the cursor (whole-word match) |
# | Search backward for the exact word under the cursor |
g* | Search forward for the word under the cursor (partial match — finds it inside longer words too) |
g# | Search backward (partial match) |
* is particularly useful when reading code — place your cursor on a variable name and press * to jump through all its usages in the file.
Regular expressions in search
Vim's search supports regular expressions, making it enormously powerful for finding patterns rather than literal strings:
/ch.mb # . matches any single character: finds "chamber", "chimb", "chombs"... /^function # ^ = start of line: finds lines beginning with "function" /error$ # $ = end of line: finds lines ending with "error" /\d\+ # \d = digit, \+ = one or more: finds any number /colou\?r # \? = zero or one: finds both "color" and "colour" /\<word\> # \< and \> = word boundaries: whole-word match (like * does automatically)
:set ignorecase. A smarter option is :set smartcase — when enabled, searches are case-insensitive unless your pattern contains an uppercase letter, in which case they become case-sensitive. This is the behaviour most users prefer.
Search settings worth knowing
:set hlsearch # highlight all matches in the file :set incsearch # move cursor as you type the pattern (incremental search) :set ignorecase # case-insensitive search :set smartcase # case-sensitive only when pattern has uppercase :noh # clear current search highlights
Putting It All Together — Practical Examples
Navigation commands become powerful when combined. Here are the worked examples from the course, showing how you think through a multi-step navigation problem.
Navigate to the 4th word of the 2nd-to-last sentence of the 3rd paragraph
3} # jump 3 paragraphs forward (land at the start of paragraph 3) 2{ # oops — went too far? Step back 2 paragraphs # (adjust the count based on where you land) ( # move back one sentence to the 2nd-to-last 3w # move forward 3 words — now on the 4th word
The key insight is that you do not need to be perfect on the first jump. Vim navigation is iterative — overshoot, correct, refine.
Find the word immediately before "England"
/England # jump to "England" b # move back one word — the word before "England"
Find the last word on line 302
:302 # jump to line 302 $ # jump to the end of the line — cursor is now on the last character b # (optional) back to the start of that last word
Find the word after the 2nd occurrence of the first word on line 14
:14 # jump to line 14 ^ # go to the first non-whitespace character (start of first word) * # search forward for this word (1st occurrence — which might be itself) n # next occurrence (2nd) w # move one word forward — now on the word after the 2nd occurrence
Commands Introduced in This Chapter
Chapter 3 — Command Reference
5j)42G):302)