handy text object motions
at main 4.1 kB view raw
1" Credits: romainl and habamax 2 3" 24 simple text objects 4" ---------------------- 5" i_ i. i: i, i; i| i/ i\ i* i+ i- i# 6" a_ a. a: a, a; a| a/ a\ a* a+ a- a# 7for char in [ '_', '.', ':', ',', ';', '<bar>', '/', '<bslash>', '*', '+', '-', '#' ] 8 execute 'xnoremap i' . char . ' :<C-u>normal! T' . char . 'vt' . char . '<CR>' 9 execute 'onoremap i' . char . ' :normal vi' . char . '<CR>' 10 execute 'xnoremap a' . char . ' :<C-u>normal! F' . char . 'vf' . char . '<CR>' 11 execute 'onoremap a' . char . ' :normal va' . char . '<CR>' 12endfor 13 14" line text objects 15" ----------------- 16" il al 17xnoremap il g_o^ 18onoremap il :<C-u>normal vil<CR> 19xnoremap al $o0 20onoremap al :<C-u>normal val<CR> 21 22" backquote text objects 23" ----------------- 24" ix ax 25xnoremap ix :<C-u>normal vi`<CR> 26onoremap ix :<C-u>normal vi`<CR> 27xnoremap ax :<C-u>normal va`<CR> 28onoremap ax :<C-u>normal va`<CR> 29 30" number text object (integer and float) 31" -------------------------------------- 32" in 33function! VisualNumber() 34 call search('\d\([^0-9\.]\|$\)', 'cW') 35 normal v 36 call search('\(^\|[^0-9\.]\d\)', 'becW') 37endfunction 38xnoremap in :<C-u>call VisualNumber()<CR> 39onoremap in :<C-u>normal vin<CR> 40 41" buffer text objects 42" ------------------- 43" i% a% 44xnoremap i% :<C-u>let z = @/\|1;/^./kz<CR>G??<CR>:let @/ = z<CR>V'z 45onoremap i% :<C-u>normal vi%<CR> 46xnoremap a% GoggV 47onoremap a% :<C-u>normal va%<CR> 48 49" square brackets text objects 50" ---------------------------- 51" ir ar 52xnoremap ir i[ 53xnoremap ar a[ 54onoremap ir :normal vi[<CR> 55onoremap ar :normal va[<CR> 56 57" C++ style block comment text objects 58" ------------------------------------ 59" i? a? 60xnoremap a? [*o]* 61onoremap a? :<C-u>normal va?V<CR> 62xnoremap i? [*jo]*k 63onoremap i? :<C-u>normal vi?V<CR> 64 65" last change text object 66" ----------------------- 67" ik ak 68xnoremap ik `]o`[ 69onoremap ik :<C-u>normal vik<CR> 70onoremap ak :<C-u>normal vikV<CR> 71 72 73" Indent text object 74" ------------------ 75" ii ai 76func! s:indent_textobj(inner) 77 if getline('.') =~ '^\s*$' 78 let ln_start = s:detect_nearest_line() 79 let ln_end = ln_start 80 else 81 let ln_start = line('.') 82 let ln_end = ln_start 83 endif 84 85 let indent = indent(ln_start) 86 if indent > 0 87 while indent(ln_start) >= indent && ln_start > 0 88 let ln_start = prevnonblank(ln_start-1) 89 endwhile 90 91 while indent(ln_end) >= indent && ln_end <= line('$') 92 let ln_end = s:nextnonblank(ln_end+1) 93 endwhile 94 else 95 while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$' 96 let ln_start -= 1 97 endwhile 98 while indent(ln_start) > 0 && ln_start > 0 99 let ln_start = prevnonblank(ln_start-1) 100 endwhile 101 while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$' 102 let ln_start -= 1 103 endwhile 104 105 while indent(ln_end) == 0 && ln_end <= line('$') && getline(ln_end) !~ '^\s*$' 106 let ln_end += 1 107 endwhile 108 while indent(ln_end) > 0 && ln_end <= line('$') 109 let ln_end = s:nextnonblank(ln_end+1) 110 endwhile 111 endif 112 113 if a:inner || indent == 0 114 let ln_start = s:nextnonblank(ln_start+1) 115 endif 116 117 if a:inner 118 let ln_end = prevnonblank(ln_end-1) 119 else 120 let ln_end = ln_end-1 121 endif 122 123 if ln_end < ln_start 124 let ln_end = ln_start 125 endif 126 127 exe ln_end 128 normal! V 129 exe ln_start 130endfunc 131 132 133func! s:nextnonblank(lnum) abort 134 let res = nextnonblank(a:lnum) 135 if res == 0 136 let res = line('$')+1 137 endif 138 return res 139endfunc 140 141 142func! s:detect_nearest_line() abort 143 let lnum = line('.') 144 let nline = s:nextnonblank(lnum) 145 let pline = prevnonblank(lnum) 146 if abs(nline - lnum) > abs(pline - lnum) || getline(nline) =~ '^\s*$' 147 return pline 148 else 149 return nline 150 endif 151endfunc 152 153onoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR> 154onoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR> 155xnoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR> 156xnoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>