How do I create custom text objects for my own operator-pending motions?
Answer
onoremap ih :<C-u>execute "normal! ?^==\+$\r:noh\rkvg_"<CR>
Explanation
Vim lets you define custom text objects using operator-pending mode mappings (onoremap) and visual mode mappings (vnoremap). These mappings work with any operator like d, c, y, or gq.
How it works
An operator-pending mapping defines what text an operator should act on. When you type d followed by your custom motion, Vim uses your mapping to select the target text.
Example: "inside heading" text object
" Select the content under a Markdown heading
onoremap ih :<C-u>execute "normal! ?^#\\+\\s\r:noh\rjV/^#\\+\\s\\\|\\%$\r:noh\rk"<CR>
vnoremap ih :<C-u>execute "normal! ?^#\\+\\s\r:noh\rjV/^#\\+\\s\\\|\\%$\r:noh\rk"<CR>
Simpler examples
" 'in line' — select from first to last non-blank character
onoremap il :<C-u>normal! ^vg_<CR>
vnoremap il :<C-u>normal! ^vg_<CR>
" 'around line' — select entire line content
onoremap al :<C-u>normal! 0v$<CR>
vnoremap al :<C-u>normal! 0v$<CR>
" 'in number' — select a number under cursor
onoremap in :<C-u>execute "normal! /\\d\+\r:noh\rvgn"<CR>
" 'entire buffer' text object
onoremap ae :<C-u>normal! ggVG<CR>
vnoremap ae :<C-u>normal! ggVG<CR>
Usage after defining
dil " Delete 'in line'
yae " Yank entire buffer
cal " Change around line
=ae " Reindent entire buffer
Tips
onoremapdefines the text object for operator-pending modevnoremapdefines it for visual mode (sovilworks too)- The
<C-u>clears any count from the command line - For complex text objects, consider the
vim-textobj-userplugin which provides a framework - Custom text objects compose naturally with all operators — that's the power of Vim's grammar