Cursor Movement in Vim

Before we discuss some of the more common, and useful, ones, remember that movement commands become even more valuable when combined with Vim’s verbs.

In addition to verbs like Delete, you can combine most of the movement commands with numbers. For example, To jump 30 characters to the right you could say 30→ That’s a silly use-case, but moving down 2 paragraphs? That’s useful.

This gets even more useful when we start using visual mode to select sections of text.

Movement by character

h,j,k,l: the most famous of Vim’s movement commands. Vim’s most ardent zealots will tell you you should never use the mouse, or arrow keys. They’ll tell you that h,j,k,l is the one true path to eternal salvation1. What they won’t tell you is that using h,j,k,l forces you to leave “start position” which screws up touch typists2. They won’t tell you that those keys are in completely different places that make their use difficult in keyboard layouts like Dvorak. They also won’t tell you, that h,j,k,l are the arrow keys on the keyboard Vi was initially created on3. Even if you don’t choose to use them, they’re important to know, because many of the combo commands you will encounter involve them.

h,j,k,l will move your cursor left, down, up, and right respectively.

,,, will also move your cursor left, down, up, and right respectively.

Use whatever keys you like.

The end of line gotcha

In every other editor I’ve encountered, when you hit the end of a line, and then move your cursor one more character to the right it will wrap around to the start of the next line. When you move it to the start and then go back one more character it will wrap around to the end of the previous line.

Vim does not do this, by default. Let’s fix that. Add the following line to your .vimrc

	set whichwrap=<,>,h,l

What exactly does that do? Well, whichwrap is a way to tell Vim which keys wrap. < and > (in this context) mean the left and right arrow keys. h, and l are our left and right character motion commands. So, this command tells vim that <,>,h,l are the keys which will wrap. The order isn’t important, and the reference docs don’t recommend including h and l but I don’t like inconsistent behavior, so I include them.

Movement by word (or WORD)

Quick Answer: The easiest way to move between words is to hold the shift key and use the left and right arrows. That will jump you to the beginning of the next or previous word.

Vim has a concept of “words” and “WORDS”. The difference is simple. “WORDS” are what normal English speakers think of as “words”: things separated by white-space. “words” are separated by things like hyphens and periods (and white-space).

“foo-bar” and “” are both one “WORD” and two “words”. If you want to move by “word” then use b for the beginning and e for the end. If you want to move by “WORD”, B goes back to the previous Beginning of a WORD and E goes to the next End of a WORD.

Here’s an easy way to remember it. A little letter “word” has smaller pieces than big letters “WORD”. Little letters b and e move by little letter “words” and big letters B and E move by big letter “WORDS”

Where this becomes more valuable is when you’re dealing with things like chained method calls in source code:

If you had your cursor in the middle of that you might want to move forward to the next section, or maybe to the end of it. Knowing about “words” and “WORDS” makes this easy.

Movement by sentence

( moves to the previous beginning of a sentence. ) moves to the next end.

Want to Delete everything to the end of the sentence? Combine d with the end of sentence movement d) Want to delete the rest of this sentence and the next one? That’s 2 sentences, so preface it with a 2: 2d)

See help sentence for the definition of a “sentence” in Vim.

Movement by paragraph

{ moves to line above the paragraph, and } to the bottom.

This can be combined with verbs and numbers just like sentence movement.

See help paragraph for the definition of “paragraph” in Vim.

Search can be used in place of any of these movement commands even when combined with other verbs. See Cut, Copy, Paste for an example of this. You can also use it with intra-line modifications like Change, Substitute, and Replace.

Even search can be combined with verbs and numbers. Want to delete to everything up to the 2nd “and”? 2 + delete + search for “and”: 2d/and. Personally I find it easier to not think about the counting and just add more to the search like d/and then. It’s the same result with less counting.

Intra-Line Movement

In addition to those language style movement commands Vim has some commands that are for moving within the current line only. If you want to move “‘til” (t) the next “v” you’d say tv (move ‘til v). If you want to include the v you’d use f instead of t Sadly, that f doesn’t correspond to any useful word.

By themselves, I don’t find t and f very useful, but combining them with Change is awesome.

Start and End of line jumps

Vim takes its commands to jump to the start and end of line from regular expressions. 0 (zero) for start of line and $ for the end.

You can also jump to the start or end of the line and switch into Insert mode. You know that i inserts where the cursor currently is, well I jumps to the start of the line and puts you in Insert mode, and A jumps you to the end of the line and puts you in Insert mode.

Similarly _ or ^ or I will jump you to the first non-whitespace character in the line. g_ (that’s g followed by _ underscore) will jump you to the last non-whitespace character.

Example: “ This is a sentence with a space before and after it. “

  ^          " Moves the cursor to the T.
  g^         " Moves the cursor to the T.
  _          " (underscore) Moves cursor to the T.
  I          " Moves the cursor to the T.
  0          " Moves the cursor to the space before the T.
  |          " Moves the cursor to the space before the T.
               " See the section below about jumping to a specific column.
  g_         " Moves the cursor to the period.
  $          " Moves the cursor to the space after the period.

Jump to the end of the file

G takes you to the last line. Combine that with A or $ to get to the last character of the last line, in insert mode or normal mode respectively. You already know A and $.

Note: G is a junk drawer with a ton of things tied to it. No single mnemonic will work for it. Sorry.

Jump to a specific column

This functionality isn’t used on a daily basis, at least I don’t use it very often but it becomes more useful as you become a more advanced Vimmer.

If you’ve got the Airline or Powerline plugins running then you’ve got a constant indicator of what column you’re on in the bottom right of your screen. If you don’t you can hit <CTRL>g to see an indication of where you are in the file along with what column you’re at.

The pipe character | is what you use to make the jump. Type the number of the column you want to jump to followed by the pipe and your cursor will jump there. If you enter a number that’s longer than the line Vim will place your cursor on the last character of the line.

Ok, so how is this remotely useful? Well, one use is padding. Maybe I want to make a nice comment heading in my code like this:

## WARNING =====================================================================

I wrap my code at 80 characters, so I want my comment line to stop at the 80th column, but I hate counting. I haven’t memorized how many letters are in “WARNING” and don’t feel like counting them, then counting how many characters came before it, and the number of spaces I want after, and adding the numbers together. Arg! The math! It hurts us!

Type out ## WARNING hit escape then 80A=<ESC>d80|

Yeah, I know that probably looks like some weird file encoding. Let’s break it down:

  • 80 (80 times)
  • A (append some text)
  • = (the text I want it to append 80 times)
  • <ESC> (I’m done telling you what to append Vim.)
  • d (I want you to delete…)
  • 80| (from the cursor position (end of the line) to the 80th character)

Note that the d80| actually deletes backwards. The command is essentially “Delete everything from the cursor position to the Nth column.”, but it doesn’t care if that means it needs to move forwards or backwards. In our case we’re past the 80th column by 11 characters (the length of ## WARNING).

  1. That may be an exaggeration.
  2. Yes, moving to the arrow keys means a touch-typist is leaving “start position”, but at least it’s a completely different position, not “start position but not quite”.
  3. Vi (Vim’s predecessor) was created on an ADM-3A computer terminal.