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