How do I select or operate on a block of code based on its indentation level in Vim?
Answer
ii / ai
Explanation
The vim-indent-object plugin by Michael Smith adds text objects based on indentation level, giving you ii (inner indent) and ai (an indent) to select, delete, change, or yank blocks of code that share the same indentation. This is a game-changer for languages like Python, YAML, and CoffeeScript where indentation defines code structure, but it works brilliantly in any language.
How it works
The plugin provides four text objects:
ii " inner indent — select all lines at the same indent level
ai " an indent — select all lines at the same indent level PLUS one line above
aI " an Indent — select all lines at the same indent level PLUS one line above AND below
iI " inner Indent — same as ii (alias)
Example: Python function body
Given this Python code with the cursor anywhere inside the function body:
def calculate(x, y):
result = x + y
if result > 100:
result = 100
return result
def other():
pass
Pressing vii selects the four indented lines (the entire function body) without selecting the def line or the blank line after.
Pressing vai selects the same four lines plus the def calculate(x, y): line above — the complete function.
Common operations
dii " delete the indented block
cii " change the indented block (delete and enter insert mode)
yii " yank the indented block
>ii " indent the block one more level
<ii " unindent the block one level
gUii " uppercase the entire indented block
vii " visually select the indented block
Example: YAML structure
In a YAML file with the cursor on any line under database::
server:
port: 8080
host: localhost
database:
host: db.example.com
port: 5432
name: myapp
cache:
ttl: 300
Pressing dii deletes the three database configuration lines. Pressing dai deletes those three lines plus the database: header.
Why indentation beats braces
In brace-delimited languages, you have i} and a} to work with blocks. But in Python, YAML, Haml, Pug, CoffeeScript, and other indentation-sensitive languages, there are no braces to target. The indent text object fills this gap perfectly.
Even in languages with braces, ii is often faster because you do not need your cursor to be inside the braces — just anywhere on an indented line.
Tips
- Combine with vim-commentary:
gciicomments out an entire indented block in one keystroke - Works with counts:
v2iiselects the current indent block and the parent block above it - Pairs naturally with
>and<for adjusting indentation of logical code blocks - The
aiobject is perfect for selecting a complete Python function or class (body + header) for moving or deleting - Works in all visual modes: characterwise, linewise, and blockwise