Vim’s text objects are a hidden superpower that can make you a ridiculously fast editor, but most people only ever use iw (inner word) and aw (a word).

Let’s see them in action. Imagine you’re editing this line:

This is a sentence with "quoted text" and (parenthesized text).

You want to change the text inside the double quotes. Instead of iwwi"e"ce", you can just type ci" (change inner double quote). Boom. The text inside is gone, and you’re in insert mode.

What if you want to change the text including the quotes? Type ca" (change a double quote). Same result, but the quotes are also deleted.

This works for parentheses too. Put your cursor anywhere on parenthesized text and type ci( (change inner parenthesis).

Here’s the magic: i means "inner" and a means "a" (or "around"). The second character specifies the delimiter.

  • w: word (inner word, a word)
  • W: WORD (whitespace-delimited block; inner WORD, a WORD)
  • s: sentence (inner sentence, a sentence)
  • p: paragraph (inner paragraph, a paragraph)
  • ( or b: block (parentheses; inner block, a block)
  • { or B: block (curly braces; inner block, a block)
  • [: block (square brackets; inner block, a block)
  • <: block (angle brackets; inner block, a block)
  • ": double quote (inner double quote, a double quote)
  • ': single quote (inner single quote, a single quote)
  • ``` `: backtick (inner backtick, a backtick)

So, cit would change the inner text of a tag (like <tag>content</tag>). cat would change the inner text and the tags.

The core problem text objects solve is reducing repetitive cursor movements and selections. Without them, changing the text inside quotes might look like this:

  1. f" (find the opening quote)
  2. l (move one character right)
  3. v (start visual mode)
  4. f" (find the closing quote)
  5. d (delete the selection)
  6. i (enter insert mode)

That’s six keystrokes. With ci", it’s two.

The a variants are slightly different from the i variants. aw deletes "a word" and the space after it. iw deletes "inner word" and leaves the space. If you’re on the word "sentence" in This is a sentence, aw will delete "sentence " (including the space). iw will delete just "sentence".

Consider a paragraph. If your cursor is anywhere within the paragraph, cip will delete all the text of the paragraph, leaving the blank lines above and below intact. ap will delete the text and one of the surrounding blank lines. This is subtle but powerful for manipulating blocks of text.

The real power comes from combining these with Vim’s other motions and operators. d (delete), c (change), y (yank), v (visual select), gU (uppercase), gu (lowercase) — they all work with text objects.

So, di" deletes the inner text of double quotes. yi( yanks the inner content of parentheses. gUa" uppercases the text and the surrounding double quotes. vat visually selects the text within angle brackets.

Most people think of "word" as just letters. But Vim’s w and W are smarter. iw on hello-world will select hello-world. iW on hello-world will select hello and then world separately, because - is punctuation, not whitespace. This distinction is crucial for code editing where variable names often contain hyphens.

The most surprising thing about text objects is how they handle nested delimiters. If you have ((nested_call(argument))) and you’re on argument, ci( will delete argument. If you then type ci( again, it will delete nested_call(argument). If you type it a third time, it will delete ((nested_call(argument))). Vim keeps track of the innermost matching delimiter.

The next concept you’ll want to explore is Vim’s ability to define your own text objects.

Want structured learning?

Take the full Vim course →