Vim’s built-in text objects let you operate on words, sentences, paragraphs, and quoted or bracketed regions using commands like ciw, da", or yap. Plugin options extend this with custom objects for functions, arguments, indentation levels, and more, giving you precise, repeatable editing without moving the cursor manually.
What Are Text Objects, Really?
A text object is a Vim motion that defines a region of text as a single unit, independent of where your cursor sits. You combine it with an operator (d delete, c change, y yank, v visual select) and a modifier: i for inner (inside the delimiters, excluding them) or a for around (including the delimiters and often surrounding whitespace). For example, with your cursor anywhere inside a double-quoted string, ci" deletes the string’s content and puts you in insert mode, while da" deletes the quotes as well.
The power is that you don’t need to count characters or move to the start of the region first. The same command works whether the object is on one line or spans twenty. This is a core reason Vim users report faster editing: the motion itself encodes the structure of the text.
Built-in Text Objects: The Complete List
Vim ships with a fixed set of text objects that cover common code and prose structures. Here they are, grouped by what they select:
- Word and WORD:
iw/awselect a word (letters, digits, underscores);iW/aWselect a WORD (any non-whitespace run).aincludes trailing whitespace. - Sentence and paragraph:
is/as(sentence, defined by punctuation and whitespace);ip/ap(paragraph, defined by blank lines). - Quotes:
i",a",i',a',i`,a`. Theaversion includes the quote marks. - Brackets and parentheses:
i(/a(,i[/a[,i{/a{, and the angle bracketi</a<. Also available with the matching closing character (e.g.,i)works identically). - Tags:
itselects the content inside an HTML/XML tag;atincludes the tag itself. This is invaluable for web development.
These are hardcoded into Vim’s source. You cannot redefine them, but you can create new ones that layer on top. Note that as and ap include the trailing whitespace that separates the object from the next one, which is usually what you want when deleting or changing.
How the i and a Modifiers Differ in Practice
The distinction between inner and around is subtle but critical. i selects the content strictly inside the delimiters. a selects the content plus the delimiters, and for word/paragraph/sentence objects, it also includes one trailing space or newline. Consider this line:
foo(bar, baz)
With the cursor on r in bar:
ci(leaves you withfoo()and cursor inside the parens.ca(leaves you withfoo(the parens and content are gone).ciwchangesbarto nothing, leavingfoo(, baz).cawdeletesbarand the following comma-space, givingfoo(baz).
The trailing whitespace behavior of a is what prevents double spaces when you delete a word mid-sentence. For brackets, a does not add whitespace—it only includes the delimiters themselves.
Plugin Options: Extending Beyond the Built-ins
Plugins add new text objects by mapping operator-pending keys. The most popular and mature options include:
- vim-textobj-user (by Kana Natsuno): A framework that makes writing custom text objects trivial. Most other text-object plugins depend on it. You define a key and a function that returns start and end positions.
- vim-textobj-function (also by Kana): Adds
if/afto select a function body (or including the signature), respecting language-specific syntax via Vim’s syntax highlighting. - vim-textobj-argument: Selects function arguments:
iaselects one argument,aaincludes the trailing comma. Cycles through arguments with repeated presses. - vim-textobj-indent: Selects a block of text at the same indentation level:
ii/ai. Great for Python or YAML. - vim-textobj-comment: Selects comments:
ic/ac. Works across line comments and block comments. - targets.vim: A more powerful replacement for the built-in bracket objects. It adds
i(variants that can select nested levels, and lets you used2i(to delete the second pair outward.
Most of these are installable via plugin managers like vim-plug, packer.nvim, or lazy.nvim. They don’t conflict with built-ins because they use distinct keys (e.g., i followed by f is not a built-in combination). The key is to install vim-textobj-user first if a plugin requires it.
How to Choose and Set Up Plugins
Start with the built-ins—they cover 80% of needs. Once you find yourself doing manual motions like f( then d% or counting lines to delete a function, look for a plugin. Here’s a practical selection process:
- Identify the repetitive structure you edit most: function bodies, arguments, indented blocks, or comments.
- Install
vim-textobj-userif the plugin you want depends on it (most do). - Add the specific plugin. For example, for Python development,
vim-textobj-indentis more useful thanvim-textobj-functionbecause Python functions are indent-based. - Test with
vi+ the new key in visual mode to see what gets selected before you use destructive operators. - Map a few keys if the defaults are awkward. For instance, some users remap
iatoiifor arguments to avoid conflict with the built-inion a word.
Remember that you can also define your own text objects without a plugin by writing a small function in your vimrc, but vim-textobj-user handles the boilerplate for you.
Common Mistakes and Misconceptions
One frequent error is assuming a always includes whitespace. For quotes and brackets, it only includes the delimiters. Another is using iw when you want iW—if your code has underscores, iw treats my_var as one word, which is often what you want, but iW would treat it as three. Also, text objects work in operator-pending mode, so you can’t use them directly in normal mode without an operator—viw is the visual form.
A common misconception is that plugins are required for advanced editing. In reality, the built-in i( and it handle most bracket and tag needs. Plugins shine for language-specific structures like functions or arguments, but they add complexity. Start minimal.
Another pitfall: a" includes the quotes, but if there is whitespace before the opening quote, it does not include that. So da" leaves a leading space. This is by design, but it surprises many users.
Comparing Built-ins vs. Plugins: Which Should You Use?
Built-ins are always available, fast, and well-documented. They handle generic text structures: words, sentences, paragraphs, quotes, brackets, and tags. Plugins add context-aware objects that understand your code’s syntax. For example, vim-textobj-function knows where a function starts and ends based on the language, which the built-ins cannot do generically.
In practice, a hybrid approach works best. Use built-ins for everyday edits—changing a word, deleting a quoted string, replacing a bracket’s content. Use plugins for larger structural edits: deleting an entire function, swapping two arguments, or selecting a YAML block. The learning curve for plugins is low once you’re comfortable with the i/a concept.
Performance is a non-issue; both are instant. The real cost is configuration and remembering the keys. If you install too many plugins, you’ll forget which key does what. Start with one or two that match your primary language.
Frequently Asked Questions
Q: What is the difference between iw and aw?
A: iw selects the word under the cursor without any surrounding whitespace. aw selects the word plus one trailing space (or newline if at end of line). So daw deletes the word and the space after it, preventing double spaces. diw leaves the space, so you might get two spaces if you delete mid-sentence.
Q: Can I create my own text objects without a plugin?
A: Yes, but it’s involved. You’d write a function that returns the start and end positions of the object, then map it to a key in operator-pending mode using :omap. The vim-textobj-user plugin simplifies this significantly, so most users go that route. A basic custom object for a comma-separated list item is about 20 lines of Vimscript.
Q: Do text objects work in visual mode?
A: Yes. Press v (or V for linewise, Ctrl-V for blockwise) to enter visual mode, then type the text object command. For example, vi( selects the content inside parentheses. This is useful for checking what you’re about to change before you delete or yank.
Q: Why doesn’t a( include the surrounding whitespace?
A: Unlike aw or ap, the bracket and quote objects only include the delimiters themselves. This is intentional: if a( also grabbed a leading space, then da( would sometimes leave an extra space before the preceding word. The behavior is consistent across all paired delimiters.
Q: What’s the best plugin for editing function arguments?
A: vim-textobj-argument is the most popular. It maps ia to select one argument (without the comma) and aa to include the trailing comma. Pressing ia repeatedly cycles through arguments. It requires vim-textobj-user. Some users prefer targets.vim because it also improves bracket handling, but it has a steeper learning curve.
Q: Are text objects available in Neovim?
A: Yes, Neovim includes all of Vim’s built-in text objects, and the same plugins work unchanged. Neovim also has built-in support for language server protocol (LSP), and some LSP plugins expose text objects for symbols, but the classic text-object plugins remain the standard approach.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Philips DST7060/20 7000 Series Iron: Specs & Fit
- Coal Fueled Jet Aircraft: Could It Work?675 L
- Remote Desktop on Raspberry Pi: How to Enable It
- Word Select Last Line in Paragraph?
- Google Assistant IFTTT Recipes: 7 Useful Automations
- OLED TVs in Dark Rooms: Why They Look Better and When They Don’t