Colors

Vim Text Objects: The Definitive Guide

Jared Carroll ·

To edit efficiently in Vim, you have to edit beyond individual characters. Instead, edit by word, sentence, and paragraph. In Vim, these higher-level contexts are called text objects. Vim provides text objects for both plaintext and common programming language constructs. You can also define new text objects using Vim script. Learning these text objects can take your Vim editing to a whole new level of precision and speed.

Structure of an Editing Command

In Vim, editing commands have the following structure:

  <number><command><text object or motion>

The number is used to perform the command over multiple text objects or motions, e.g., backward three words, forward two paragraphs. The number is optional and can appear either before or after the command. The command is an operation, e.g., change, delete (cut), or yank (copy). The command is also optional; but without it, you only have a motion command, not an edit command The text object or motion can either be a text construct, e.g., a word, a sentence, a paragraph, or a motion, e.g., forward a line, back one page, end of the line. An editing command is a command plus a text object or motion, e.g., delete this word, change the next sentence, copy this paragraph.

Plaintext Text Objects

Vim provides text objects for the three building blocks of plaintext: words, sentences and paragraphs.

Words

  • aw – a word (includes surrounding white space)
  • iw – inner word (does not include surrounding white space)
Lorem ipsum dolor sit amet...

daw

Lorem dolor sit amet...

Text objects beginning with a include the surrounding white space in the text object, those starting with i do not. This convention is followed by all text objects. The motion w may seem similar to the text object aw. The difference is in the allowed cursor position. For example, to delete a word using dw the cursor must be at the start of the word, any other position would delete only part of the word; however, daw allows the cursor to be at any position in the word.

Sentences

  • as – a sentence
  • is – inner sentence
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

cis

 Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.

Notice how the “inner” text object does not include the trailing white space. Like aw, as offers the same cursor position advantage over its motion counterparts ( ), forward and backward a sentence. To operate on the entire previous sentence ( requires the cursor to be at the end of the sentence; to operate on the entire next sentence ) requires your cursor to be at the start of the sentence.

Paragraphs

  • ap – a paragraph
  • ip – inner paragraph
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis 
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.

dap

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.

Again, ap and ip provide the same cursor position advantage that Vim’s sentence and word text objects provide: your cursor can be anywhere within the paragraph in order to operate on it.

Motion Commands vs. Text Objects Commands

A command using a motion, e.g., cw, operates from the current cursor position. A command using a text-object, e.g., ciw operates on the whole object regardless of the cursor position. We saw this behavior in each of the various plaintext text objects. Although this requires one more character, it saves you the time and effort of moving the cursor into the “right” position.

Programming Language Text Objects

Vim provides several text objects based on common programming language constructs.

Strings

  • a” – a double quoted string
  • i” – inner double quoted string
  • a’ – a single quoted string
  • i’ – inner single quoted string
  • a` – a back quoted string
  • i` – inner back quoted string
puts 'Hello "world"'

ci"

puts 'Hello ""'

Notice that the cursor was not even within the double-quoted phrase (“world”); the command defaulted to changing the first double-quoted phrase in the line.

puts 'Hello "world"'

ci'

puts ''

Current line searches offer an alternative way to delete a quoted phrase. Continuing with the previous example, placing the cursor on the first ' and executing ct' would delete the contents of the single quoted string and place us in insert mode. However, this is less flexible than using a text object because it requires the cursor to be on the opening '. A search pattern /' could also be used, but it too requires the cursor to be on the opening '. It also deletes the closing '. It’s best to use search commands for searching and not editing.

Parentheses

  • a) – a parenthesized block
  • i) – inner parenthesized block
Project.all(:conditions => { :published => true })

da)

Project.all

Both of these text objects are also available as ab and ib, however I find these less intuitive than using the version that includes a parenthesis character. The % motion is another way to match a pair of parentheses. Entering % on an opening parenthesis will move the cursor to the closing parenthesis. Combined with a command, this can provide the same
functionality as a), e.g., c% is equivalent to ca). However, the disadvantage to using % is that the cursor must be on the opening or closing parenthesis; with a) the cursor can be anywhere on or the parenthesized phrase. There is also no way to replicate i) using %.

Brackets

  • a] – a bracketed block
  • i] – inner bracketed block
(defn sum [x y]
  (+ x y))

di]

(defn sum []
  (+ x y))

The % movement can also be with []. However, it has the same limited flexibility when using it with ().

Braces

  • a} – a brace block
  • i} – inner brace block
puts "Name: #{user.name}"

ci}

puts "Name: #{}"

Both of these text objects are also available as aB and iB, however, I find these less intuitive than using the version that includes a brace character. Again, the % movement can also be with {}. However, it has the same limited flexibility when using it with () or [].

Markup Language Tags

  • at – a tag block
  • it – inner tag block
<h2>Sample Title</h2>

cit

<h2></h2>

Notice that the cursor was not even within the <h2>. This is a very efficient way to quickly replace tag content.

  • a> – a single tag
  • i> – inner single tag
<div id="content"></div>

di>

<></div>

This text object can be used to quickly operate on a single tag and its attributes.

Vim Scripts Providing Additional Text Objects

Using Vim script, it’s possible to create new text objects. Here’s a few of my favorite scripts that introduce new programming language text objects.

CamelCaseMotion

CamelCaseMotion provides a text object to move by words within a camel or snake-cased word.

  • i,w – inner camel or snake-cased word
BeanFactoryTransactionAttributeSourceAdvisor

ci,w

FactoryTransactionAttributeSourceAdvisor

VimTextObj

VimTextObj provides a text object for function arguments.

  • aa – an argument
  • ia – inner argument
foo(42, bar(5), 'hello');

cia

foo(42, , 'hello');

Indent Object

Indent Object provides a text object based on indentation level. This script is aimed at programming languages that use significant whitespace to delimit code blocks, e.g., Python, CoffeeScript, because its text object does not include the line after the last line of the indentation level.

  • ai – the current indentation level and the line above
  • ii – the current indentation level excluding the line above
def foo():
  if 3 > 5:
    return True
  return "foo"

dai

def foo():
  return "foo"

Ruby Block

Ruby Block provides a text object based on a Ruby block, i.e., any expression that is closed with the end keyword.

  • ar – a Ruby block
  • ir – inner Ruby block
hash.each do |key, value|
  puts key
  puts value
end

cir

hash.each do |key, value|
   
end

Vi Command Line Editing

If you use Vi command line editing in your shell, enabled with set -o vi in bash and bindkey -v in zsh, Vim’s text objects are not available. Text objects were introduced by Vim but shell command line editing is based on Vi.

Precision Editing

Vim’s text objects provide an incredible level of precision. The key is to try to always edit by text objects. Editing by motions e.g., by part of a line, to the next occurrence of a character, is tedious, clumsy, and slow. Instead of correcting a misspelling character by character, change the entire word and re-type it. Don’t be discouraged by the large number of text objects, their conventions make them intuitive and easy to learn. After some practice, like every other Vim command, they’ll quickly become just another muscle memory.


Now hiring developers, designers and product managers.
Apply now: www.carbonfive.com/careers