Skip to main content

How to Edit Inside Quotes, Brackets, and Tags in Vim

·1020 words·5 mins
Linux Learning Lab
Author
Linux Learning Lab
Writing about code, tools, and workflows.

The Problem
#

You’re editing code and your cursor is somewhere inside a string:

message = "The quick brown fox jumps over the lazy dog"
                        ^  cursor here

You want to replace the entire string content without disturbing the quotes. Moving to the first quote, deleting to the second quote, then repositioning — that’s slow. Vim’s text objects let you do it in three keystrokes.

Inner vs Around
#

Every delimiter-based text object has two variants:

PrefixMeaningIncludes delimiters?
iInnerNo — just the content between
aAroundYes — content plus the delimiters themselves
"hello world"
 ^^^^^^^^^^^   ← ci" changes this (inner)
^^^^^^^^^^^^^  ← ca" changes this (around)

Quotes
#

Double quotes
#

ci"     " Change inside double quotes
di"     " Delete inside double quotes
yi"     " Yank inside double quotes
vi"     " Visually select inside double quotes

ca"     " Change around double quotes (removes the quotes too)
da"     " Delete around double quotes

Example:

name = "John Smith"

With cursor anywhere between the quotes:

  • ci" → deletes John Smith, leaves you in insert mode between empty quotes: name = ""
  • di" → deletes John Smith, stays in normal mode: name = ""
  • da" → deletes "John Smith" entirely: name =

Single quotes
#

ci'     " Change inside single quotes
di'     " Delete inside single quotes
yi'     " Yank inside single quotes
const greeting = 'hello world'
// ci' → 'hello world' becomes ''

Backticks
#

ci`     " Change inside backticks
di`     " Delete inside backticks
Use the `find` command to search.
// ci` → `find` becomes ``

Parentheses
#

ci(     " Change inside parentheses
ci)     " Same thing
cib     " Also the same (b = block/brackets)

di(     " Delete inside parentheses
yi(     " Yank inside parentheses
vi(     " Select inside parentheses

Example:

int result = calculate(x + y, z * 2);

Cursor anywhere inside the parens:

  • ci( → deletes x + y, z * 2, leaves you typing inside empty parens: calculate()
  • da( → deletes (x + y, z * 2) including the parens

Nested parentheses
#

Vim finds the innermost pair containing your cursor:

printf("Result: %d\n", compute(a + b));
                              ^  cursor
  • ci( → changes a + b (innermost)
  • Move cursor outside compute(...) and ci( changes "Result: %d\n", compute(a + b) (outer pair)

Curly Braces
#

ci{     " Change inside curly braces
ci}     " Same thing
ciB     " Also the same (B = Block)

di{     " Delete inside braces
yi{     " Yank inside braces

Example — empty a function body:

function processData(input) {
    const cleaned = sanitize(input);
    const result = transform(cleaned);
    return result;
}

Cursor anywhere inside the braces:

  • ci{ → deletes the entire body, puts you in insert mode between the braces
  • di{ → deletes the body, stays in normal mode

This works across multiple lines — Vim finds the matching { and }.

Square Brackets
#

ci[     " Change inside square brackets
ci]     " Same thing

di[     " Delete inside brackets
yi[     " Yank inside brackets

Example:

colors = ["red", "green", "blue"]
  • ci[ → deletes "red", "green", "blue", leaves colors = []
  • yi[ → yanks the array contents

Angle Brackets
#

ci<     " Change inside angle brackets
ci>     " Same thing

di<     " Delete inside angle brackets

Example:

<div class="container">
  • ci< → changes div class="container" inside the angle brackets

HTML/XML Tags
#

cit     " Change inside tag (content between opening and closing tag)
dit     " Delete inside tag
yit     " Yank inside tag
vit     " Select inside tag

cat     " Change around tag (includes the tags themselves)
dat     " Delete around tag

Example:

<p>This is a paragraph with <strong>bold text</strong> in it.</p>

Cursor on “bold text”:

  • cit → deletes bold text, leaves <strong></strong>
  • dat → deletes <strong>bold text</strong> entirely

Cursor on “This is a paragraph…”:

  • cit → deletes everything between <p> and </p>
  • dat → deletes the entire <p>...</p> element

Nested tags
#

<div>
    <ul>
        <li>Item one</li>
    </ul>
</div>

Cursor on “Item one”:

  • cit → changes content of <li> (innermost)
  • Move up, cit on the <ul> line → changes content of <ul>

Combining with the Dot Command
#

The real power shows when you repeat these edits:

Replace multiple strings
#

config = {
    "host": "old-server.example.com",
    "port": "8080",
    "path": "/api/v1"
}
  1. Cursor on first value → ci"new-value Esc
  2. Move to next string → . (repeats ci" with “new-value”)

Or more selectively:

  1. /"old to search
  2. ci"replacement Esc
  3. n to next match, . to repeat

Empty all function arguments
#

doSomething(complex, args, here);
doAnother(more, stuff);
doThird(yet, more, things);
  1. On first line: ci(Esc`
  2. Move to next line: j
  3. . → repeats the “change inside parens” edit

Working with Nested Delimiters
#

When delimiters are nested, Vim uses the innermost pair containing your cursor:

console.log("Value: " + calculate(x, y));
Cursor positionci( changes
On xx, y
On "Value"Value: " + calculate(x, y)

If you need the outer pair when cursor is deep inside, use visual mode to expand:

  • vi( selects inner pair
  • Repeat i( to expand to the next outer pair (in some Vim versions)
  • Or manually position with F( then ci(

Quick Reference
#

Text ObjectInner (i)Around (a)
Double quotesci" di" yi"ca" da" ya"
Single quotesci' di' yi'ca' da' ya'
Backticksci` di`ca` da`
Parenthesesci( di( yi(ca( da( ya(
Curly bracesci{ di{ yi{ca{ da{ ya{
Square bracketsci[ di[ yi[ca[ da[ ya[
Angle bracketsci< di< yi<ca< da< ya<
HTML tagscit dit yitcat dat yat

Best Practices
#

  • Use ci (change inner) when you want to replace content — it deletes and drops you into insert mode in one motion
  • Use di when you want to empty something without typing new content
  • Use yi to grab content without modifying anything — paste it elsewhere with p
  • Use a (around) when you want to remove the delimiters too — da" removes the quotes, da( removes the parens
  • Your cursor can be anywhere inside the delimiters — you don’t need to be at the start
  • Combine with the dot command for repetitive edits across similar structures
  • For deeply nested structures, use vi( first to visually confirm what’s selected, then operate on it