Markdown text objects allow you to operate on document structures using standard Vim operators like d (delete), c (change), y (yank), and v (visual select). These objects are aware of Markdown syntax, enabling precise editing of formatted text, links, and structural blocks.
When the Neovim RPC backend is connected, emphasis, inline code, math, strikethrough, links and wikilinks, code fences, blockquotes, callouts, tags, table rows, and table cells execute inside Neovim through buffer-local mappings. The companion uses Neovim’s bundled Markdown treesitter parsers for structural ranges and native it/at for tags, then applies operators to an explicit bounded character range. i= / a= highlight objects are unavailable in RPC mode because the bundled grammar does not expose ==...== as a node; delimiter scanning is intentionally not substituted for a treesitter range.
Markdown text objects
Operate on Markdown structures with standard Vim operators (
d,c,y,v).The Neovim RPC backend supports the tree-backed objects below in operator-pending and visual modes.
i=/a=remains fork-only because Neovim’s bundled Markdown grammar has no highlight node.Link to original
Keybinding Description i*/a*Inside/around bold ( **...**) or italic (*...*)i_/a_Inside/around italic ( _..._)i`/a`Inside/around inline codei$/a$Inside/around math ( $...$or$$...$$), with smart disambiguationi~/a~Inside/around strikethrough(~~...~~)i=/a=Inside/around highlight ( ==...==)il/alInside/around links ( [[wikilink]]or[text](url))iC/aCInside/around fenced code blocks iB/aBInside/around blockquotes ( >)io/aoInside/around callouts ( > [!type])it/atInside/around HTML/XML tags ir/arInside/around table row (raw markdown only) i|/a|Inside/around table cell (between |pipes)iS/aSSubword in/anNumber iq/aqAny quote iD/aDDouble brackets gLURL i,/a,Argument ii/aiIndentation
Delimiter text objects
The following text objects operate on inline Markdown delimiters:
i*/a*: Bold (**...**) or italic (*...*)i_/a_: Underscore italic (_..._)i`/a`: Inline code (`...`)i$/a$: Math ($...$or$$...$$)i~/a~: Strikethrough (~~...~~)i=/a=: Highlight (==...==)
These objects support multi-line scanning, allowing you to select content that spans across line breaks. To maintain performance, the scanner skips lines within fenced code blocks.
Inner objects require the cursor to be inside the content, not on the opening or closing delimiter. Around objects also work with the cursor on a delimiter. Tree-backed matching checks the actual delimiter character and width, so $...$ is not mistaken for $$...$$, and ~~...~~ includes both tildes on each side.
Bracket objects search forward
The bracket objects
i(/i{/i[/i<(andib/iB) find the next pair ahead of the cursor when the cursor is not already inside one, matching Neovim. The search is not limited to the current line, and it never looks backwards — past the last pair in the document, the operator is a no-op.
Smart asterisk disambiguation
i*tries to match**bold**first, then falls back to*italic*. In cases of nested formatting like***bold italic***, the**pair is matched first. Usei_for underscore italic to select the italic portion specifically.
Smart dollar disambiguation
i$/a$tries to match$$(block math) first, then falls back to$(inline math). For nested math like$$ $inner$ $$, the$$pair is matched first.
Configurable scan range
The multi-line scanner searches a set number of lines in each direction (default: 20). You can adjust this in Settings → Vim Motions → Advanced → Multi-line text object scan range (5–200 lines).
Link text objects
Link text objects (il / al) support both wikilinks and standard Markdown links:
- Wikilinks:
[[Link]]or[[Link|Alias]] - Markdown links:
[Text](URL)
il selects the content inside the brackets or parentheses, while al selects the entire link structure.
Block text objects
Block text objects operate on structural Markdown elements:
- Code blocks (
iC/aC): Fenced code blocks starting and ending with```. - Blockquotes (
iB/aB): Lines prefixed with>. - Callouts (
io/ao): Obsidian callouts (> [!type]).
Blockquotes select contiguous lines at the cursor line’s nesting depth or deeper, supporting both >> and > > prefixes. Unmarked continuation lines and shallower outer quote lines are excluded, even when the Markdown parser includes them in the same paragraph. Inner selections preserve the full opening quote prefix; around selections remove nested quote lines without leaving an extra empty line between adjacent quote lines.
The scanner for these blocks skips lines within fenced code blocks to avoid false positives. Note that fenced code blocks inside blockquotes (> ```) are currently not detected as separate blocks.
Tag text objects
Tag text objects (it / at) allow you to operate on HTML or XML tags within your Markdown files. These are implemented via raw text scanning rather than a full HTML parser to ensure compatibility with Markdown-mixed content.
General-purpose text objects
These text objects provide standard Vim-like behavior for common programming and writing patterns:
iS/aS— Subword: camelCase, snake_case, or kebab-case segments. Around includes the trailing separator.in/an— Number: Full numeric literals, including signs and decimals. Around includes surrounding whitespace.iq/aq— Any quote: The nearest quote pair (",', or`) on the current line.iD/aD— Double brackets: Wikilink-style[[...]]content. Supports nested brackets.gL— URL: Forward-seeking URL selection. Jumps to the next URL on the line and selects it.i,/a,— Argument: Comma-separated arguments in lists or function calls. Supports nesting (e.g.,func(a, [b, c], d)).ii/ai— Indentation: Contiguous lines with same-or-greater indentation. Around includes parent line above and trailing blank lines.
Custom text objects via Lua
You can define your own text objects using the Lua API. This is useful for custom delimiters or specific document structures.
Defining pairs
The vim.gen_spec.pair() function creates a text object specification for delimiter pairs:
-- Inner angle bracket
vim.textobject.add('i<', vim.gen_spec.pair('<', '>'))
-- Around angle bracket
vim.textobject.add('a<', vim.gen_spec.pair('<', '>'))API Reference
vim.textobject.add(keys, spec): Registers a new text object.keysmust start withiora.vim.gen_spec.pair(open, close, opts?): Generates a pair specification.multiline(boolean, defaulttrue): Whether to search across multiple lines.
See lua-config > vim.textobject for more examples and details.
Table cell text objects
Table cell text objects (i| / a|) operate on individual cells within Markdown tables:
i|: Selects the content inside the cell (between the|pipes).a|: Selects the content plus the trailing pipe.
These objects are particularly useful for quickly changing or deleting cell data without affecting the table structure.
See known-limitations > Text objects for detailed technical limitations.