" Credits: romainl and habamax " 24 simple text objects " ---------------------- " i_ i. i: i, i; i| i/ i\ i* i+ i- i# " a_ a. a: a, a; a| a/ a\ a* a+ a- a# for char in [ '_', '.', ':', ',', ';', '', '/', '', '*', '+', '-', '#' ] execute 'xnoremap i' . char . ' :normal! T' . char . 'vt' . char . '' execute 'onoremap i' . char . ' :normal vi' . char . '' execute 'xnoremap a' . char . ' :normal! F' . char . 'vf' . char . '' execute 'onoremap a' . char . ' :normal va' . char . '' endfor " line text objects " ----------------- " il al xnoremap il g_o^ onoremap il :normal vil xnoremap al $o0 onoremap al :normal val " number text object (integer and float) " -------------------------------------- " in function! VisualNumber() call search('\d\([^0-9\.]\|$\)', 'cW') normal v call search('\(^\|[^0-9\.]\d\)', 'becW') endfunction xnoremap in :call VisualNumber() onoremap in :normal vin " buffer text objects " ------------------- " i% a% xnoremap i% :let z = @/\|1;/^./kzG??:let @/ = zV'z onoremap i% :normal vi% xnoremap a% GoggV onoremap a% :normal va% " square brackets text objects " ---------------------------- " ir ar xnoremap ir i[ xnoremap ar a[ onoremap ir :normal vi[ onoremap ar :normal va[ " C++ style block comment text objects " ------------------------------------ " i? a? xnoremap a? [*o]* onoremap a? :normal va?V xnoremap i? [*jo]*k onoremap i? :normal vi?V " last change text object " ----------------------- " ik ak xnoremap ik `]o`[ onoremap ik :normal vik onoremap ak :normal vikV " Indent text object " ------------------ " ii ai func! s:indent_textobj(inner) if getline('.') =~ '^\s*$' let ln_start = s:detect_nearest_line() let ln_end = ln_start else let ln_start = line('.') let ln_end = ln_start endif let indent = indent(ln_start) if indent > 0 while indent(ln_start) >= indent && ln_start > 0 let ln_start = prevnonblank(ln_start-1) endwhile while indent(ln_end) >= indent && ln_end <= line('$') let ln_end = s:nextnonblank(ln_end+1) endwhile else while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$' let ln_start -= 1 endwhile while indent(ln_start) > 0 && ln_start > 0 let ln_start = prevnonblank(ln_start-1) endwhile while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$' let ln_start -= 1 endwhile while indent(ln_end) == 0 && ln_end <= line('$') && getline(ln_end) !~ '^\s*$' let ln_end += 1 endwhile while indent(ln_end) > 0 && ln_end <= line('$') let ln_end = s:nextnonblank(ln_end+1) endwhile endif if a:inner || indent == 0 let ln_start = s:nextnonblank(ln_start+1) endif if a:inner let ln_end = prevnonblank(ln_end-1) else let ln_end = ln_end-1 endif if ln_end < ln_start let ln_end = ln_start endif exe ln_end normal! V exe ln_start endfunc func! s:nextnonblank(lnum) abort let res = nextnonblank(a:lnum) if res == 0 let res = line('$')+1 endif return res endfunc func! s:detect_nearest_line() abort let lnum = line('.') let nline = s:nextnonblank(lnum) let pline = prevnonblank(lnum) if abs(nline - lnum) > abs(pline - lnum) || getline(nline) =~ '^\s*$' return pline else return nline endif endfunc onoremap ii :call indent_textobj(v:true) onoremap ai :call indent_textobj(v:false) xnoremap ii :call indent_textobj(v:true) xnoremap ai :call indent_textobj(v:false)