Navigation: Moving Without Touching the Arrow Keys
hjkl
The four motion keys that define Vim:
h left
j down
k up
l right
They sit under your right hand on a QWERTY keyboard. Your fingers never leave home row. That is the whole point.
Yes, the arrow keys also work. Use them if you want. You will slowly drift toward hjkl anyway because the other commands in this chapter compose with hjkl in ways they don't compose with arrows.
j and k are the confusing pair. Mnemonic: j looks like a hook going down. Or just accept it and move on.
Counts
Prefix any motion with a number to repeat:
5j move down 5 lines
10l move right 10 characters
3k move up 3 lines
You won't use small counts often. 5j is faster than jjjjj. 50j is faster than counting. For anything bigger, use the motions below.
Word Motions
Words are where Vim starts to feel efficient:
w move to the start of the next word
b move to the start of the previous word (back)
e move to the end of the current (or next) word
ge move to the end of the previous word
A "word" is a run of letters, digits, and underscores. Punctuation breaks a word.
Capital variants use a looser definition, where "word" means "anything non-whitespace":
W next WORD (space-delimited)
B previous WORD
E end of WORD
gE end of previous WORD
The difference matters for code:
user.name = "Alice"
Pressing w on user moves you through user, ., name, =, ", Alice. Six steps. Pressing W skips to =, then "Alice". Two steps.
Use lowercase when you need precision. Uppercase when you need speed.
Line Motions
Within a line:
0 first character of the line (column zero)
^ first non-blank character of the line
$ end of the line
g_ last non-blank character of the line
| first column (same as 0)
5| column 5
^ is the one you want most of the time. 0 jumps past leading indentation, which you usually don't want.
Character-by-Character Jumps
Jump to a specific character on the current line:
f{char} jump to the next occurrence of {char}
F{char} jump to the previous occurrence
t{char} jump to just before the next {char} ("till")
T{char} jump to just after the previous {char}
; repeat the last f/F/t/T
, repeat in the opposite direction
Example. Your cursor is at the start of this line:
const user = { name: "Alice", age: 30 };
Press f" to jump to the first quote. Press ; to jump to the next quote. Press f, to jump to the comma. Press t; to jump to just before the semicolon.
This is one of the fastest ways to position the cursor inside a line. Learn it. Use it.
Screen Motions
Move around what you can see without scrolling:
H top of the screen (High)
M middle of the screen
L bottom of the screen (Low)
And scroll the viewport:
<C-d> scroll down half a page
<C-u> scroll up half a page
<C-f> scroll down a full page (Forward)
<C-b> scroll up a full page (Back)
<C-e> scroll down one line without moving cursor
<C-y> scroll up one line without moving cursor
And centre the current line:
zz put the current line in the middle of the screen
zt put the current line at the top
zb put the current line at the bottom
zz is the one you'll use most. Press it after any jump to get your bearings.
File Motions
Whole-file navigation:
gg go to the first line
G go to the last line
{n}G go to line n (e.g. 42G goes to line 42)
:{n} same (:42<Enter> goes to line 42)
gg and G are two of the most-used commands in Vim. Memorise both.
Paragraphs and Sections
{ previous blank line (paragraph start)
} next blank line (paragraph end)
( previous sentence
) next sentence
[[ previous section (e.g. previous function in C)
]] next section
Paragraphs and sentences are defined in :help paragraph and :help sentence. For most code, { and } jump between blocks of code separated by blank lines, which is what you usually want.
Matching Pairs
% jump to the matching bracket, brace, or parenthesis
On (, % jumps to the matching ) and vice versa. Same for [] and {}. In supported languages, % also jumps between if/else/endif and similar pairs, if the matchit plugin is loaded (it usually is).
The Jump List
Vim remembers where you've been. Every significant jump (a search, gg, G, %, a line-number jump) goes into the jump list.
<C-o> jump back (older position)
<C-i> jump forward (newer position)
:jumps show the jump list
This is the browser back/forward button for your cursor. If you're reading code and follow a function definition, <C-o> takes you back to where you were.
Small motions (hjkl, word motions) do not go into the jump list. Only bigger jumps do. That is usually what you want.
The Change List
Vim also remembers where you've edited:
g; jump to the previous edit
g, jump to the next edit
Useful when you make a change, scroll around, and want to get back to what you were working on.
Marks (Preview)
Marks let you bookmark a position. More in chapter 11, but a taste:
ma set mark 'a' at the current position
'a jump to the start of the line containing mark 'a'
`a jump to the exact column of mark 'a'
Marks a to z are local to a file. A to Z are global (they work across files).
Composing Motions with Operators
The payoff for learning motions comes when you combine them with operators:
d + motion delete through the motion
c + motion change through the motion
y + motion yank through the motion
dw delete a word
d$ delete to end of line
y) yank to end of sentence
cf" change up to and including the next quote
d5j delete 5 lines down
gUw uppercase a word
Every motion you learn works with every operator. That is how Vim gets expressive with so few keys.
Common Pitfalls
"I held down j and the cursor crawled." Don't hold keys. Use counts (20j), or <C-d> to scroll, or /text<Enter> to jump to what you're looking for.
"I lost my place after a big jump." Use <C-o> to come back. Or press zz to recentre the screen on the current line.
"w and b don't work the way I expect in code." Lowercase treats punctuation as a boundary. Use W and B if you want to skip whole tokens.
"I want to jump to the last place I was." <C-o> goes back through the jump list. '' (two backticks or two single quotes) jumps to the position before the last jump.
"I can never remember f vs t." f finds and lands on the character. t goes til just before it. Use t when you want to change up to but not including a delimiter: ct; changes up to the next semicolon, leaving the semicolon alone.
Next Steps
Continue to 04-editing.md to turn all these motions into edits.