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.

49 Responses to Vim Text Objects: The Definitive Guide

  1. Anonymous says:

    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…

  2. Aaron says:

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

  3. 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 says:

      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%’.

  4. Rob Pak says:

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

  5. Johan Hilding says:

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

  6. Rudy Jahchan says:

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

  7. Omar Gomez says:

    Terrific post. Thanks for making this look so simple.

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

  9. Validid says:

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

  10. Vimmer says:

    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).

  11. Alan MacDougall says:

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

  12. Pingback: A Look at Vim Text Objects |

  13. PeterAzP says:

    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!

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

  15. Microbe says:

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

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

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

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

  19. Pingback: Weekly links for 11/10/30 | xQuant

  20. Paul Grayson says:

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

  21. Pingback: Frattanto nella blogosfera #50 « Ok, panico

  22. John F. Mercer says:

    Great article. Many thanks.

  23. Pingback: Vim Text Objects - Control+R

  24. Pingback: Yet another Vim post « justaguyinphilly

  25. Zhopon says:

    best VIM tutorial that I ever read
    THANKS!

  26. Anonymous says:

    Thanks for such a simple and clear writing.

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

  28. Arhuman says:

    Great article !

  29. David Kinzer says:

    Thanks! Great Article.

  30. Sergio Luiz Araújo Silva says:

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

  31. dimko_desu says:

    Thanks you for this very usefull post.

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

  33. Marin Usalj says:

    Very nice! thanks

  34. dmmmdfll says:

    Thanks for writing this.

  35. Pingback: Computer Tips | Annotary

  36. Pingback: Vim Text Objects: The Definitive Guide | Enjoying The Moment

  37. Pingback: Vim Text Objects: The Definitive Guide | Rocketboom

  38. Pingback: Lebanon web design company

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

  40. Pingback: Why Vim? | Blog 1

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

  42. Pingback: 一些 Vim 文本对象的插件 – 马开东博客

  43. Pingback: [Vim] Objetos de texto | Geek's Story

  44. Vincent Murphy says:
  45. Wow, NOW I get it, thanks!

  46. Pingback: How to replace text between quotes in vi? | Nikola Brežnjak's blog

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>