Vim Text Objects: The Definitive Guide

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.

About Jared Carroll

After a short stint in the fashion industry Jared found his true calling at Carbon Five. Yes... he looks like a serial killer in this photo. But really he is as gentle as a flower.
This entry was posted in Process and tagged . Bookmark the permalink.
  • Anonymous

    This stuff looks pretty powerful. I really like how the commands are mostly acronyms for what you want to do:

    daw = Delete A Word
    cip = Change Inner Paragraph
    da,w = Delete A Comma (Camel) Word

    I need to get better at vim…

  • Aaron

    “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.”

    However, if you’re editing a command (in set -o vi mode), you can ESC and then press the ‘v’ key, which will open a full vim session initialized with your command line. Edit the command, then “:wq” which will exit vim and execute the command.

    Works in bash, probably similar or the same in other modern shells.

    • Jared Carroll

      Good tip Aaron. ‘v’ from the command line is a sweet way to get access to Vim’s text objects.

  • http://joshtriplett.org/ Josh Triplett

    You don’t have to have the cursor on a (, [, or { to use %. % will actually find the next bracketing character on the line, and then go to the matching character. So, if you have “foo(bar);” , with the cursor on the first ‘o’, and press d%, you’ll end up with just “f”.

    • Jared Carroll

      You’re right Josh. What I meant to say about ‘%’ was that when trying to replicate a command on a parenthesized block such as ‘ca)’ you have to have the cursor on one of the parentheses when executing ‘c%’.

  • Rob Pak

    Thanks for the post. This will be helpful to all vimmers.

  • Johan Hilding

    So *b is the suffix for both ( and {, or did you just have the same sentence copied twice?

    • Jared Carroll

      Good catch. It’s ‘b’ for ‘(‘ and ‘B’ for ‘{‘. I’ll update the post.

  • http://rudyjahchan.com Rudy Jahchan

    Love these tips actually; will make writing in Vim in general (with the word, sentence, and paragraph objects) a joy.

  • http://twitter.com/omargomez Omar Gomez

    Terrific post. Thanks for making this look so simple.

  • http://twitter.com/umamipanda Niklas Schmücker

    How could I have missed half of this for my whole life?? +1

  • Validid

    This VIM text objects are simple, intuitive and powerful. Thanks for sharing.

  • Vimmer

    like “c” for change — “v” is another handy command for it will visualize or highlight the area in question. For example, “vas” is useful for sentences which contain odd punctuations within; it can double-check the area before a delete or change (given by d or c respectively *after* the visualize operation).

  • Alan MacDougall

    Tim Pope’s remarkable surround.vim makes use of text objects, and is very handy: https://github.com/tpope/vim-surround

  • Pingback: A Look at Vim Text Objects |

  • http://twitter.com/PeterAzP PeterAzP

    This is friggin insanely good. I came to this post thinking “Hell, I’m pretty good at the whole sentence/paragraph/block-editing but obviously I knew nothing! Just like Jon Snow.

    I will immediately start using text-objects, this was awesome! So much easier to remember das or di” than its movement counterparts as well!

  • Pingback: Four short links: 19 October 2011 | National Cyber Security

  • Microbe

    Wow, great. I recently learned gqip. It is very useful but I couldn’t quite decompose the command. Now I know what it means.

  • Pingback: Links 20/10/2011: Linux 3.1 RC 10, Gnome Pie 0.2 | Techrights

  • Pingback: Guides, Papers and APIs – Part 1 | The Naked Technologist

  • Pingback: A Look at Vim Text Objects « GhazaliRidzwan.com

  • Pingback: Weekly links for 11/10/30 | xQuant

  • Paul Grayson

    Jared, this is great! Thanks very much for writing this.

  • Pingback: Frattanto nella blogosfera #50 « Ok, panico

  • John F. Mercer

    Great article. Many thanks.

  • Pingback: Vim Text Objects - Control+R

  • Pingback: Yet another Vim post « justaguyinphilly

  • Zhopon

    best VIM tutorial that I ever read
    THANKS!

  • Anonymous

    Thanks for such a simple and clear writing.

  • Pingback: VIM – Compensating no Visual Studio (part 1) « Binarycreatures's Blog

  • Arhuman

    Great article !

  • David Kinzer

    Thanks! Great Article.

  • Sergio Luiz Araújo Silva

    Creating new text objects by wikia: http://vim.wikia.com/wiki/Creating_new_text_objects

  • dimko_desu

    Thanks you for this very usefull post.

  • Pingback: Links of the Day (Vim Edition) – 11/27/2012 | Buzu’s Oficial Blog

  • http://mneorr.com/ Marin Usalj

    Very nice! thanks

  • dmmmdfll

    Thanks for writing this.

  • Pingback: Computer Tips | Annotary

  • Pingback: Vim Text Objects: The Definitive Guide | Enjoying The Moment

  • Pingback: Vim Text Objects: The Definitive Guide | Rocketboom

  • Pingback: Lebanon web design company

  • http://jeditux.wordpress.com/ Fernando Basso

    Nice guide. Thanks. We should add it to vimgor bot in #vim.

  • Pingback: Why Vim? | Blog 1

  • Pingback: Simple Vim commands I discovered, that I wish I new about earlier. | Development blog of @martynthewolf

  • Vincent Murphy
  • http://momentary.eu/ Joseph Harriott

    Wow, NOW I get it, thanks!