aboutsummaryrefslogtreecommitdiff
path: root/plugin/better-text-objs.vim
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/better-text-objs.vim')
-rw-r--r--plugin/better-text-objs.vim148
1 files changed, 148 insertions, 0 deletions
diff --git a/plugin/better-text-objs.vim b/plugin/better-text-objs.vim
new file mode 100644
index 0000000..e959e6e
--- /dev/null
+++ b/plugin/better-text-objs.vim
@@ -0,0 +1,148 @@
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" number text object (integer and float)
23" --------------------------------------
24" in
25function! VisualNumber()
26 call search('\d\([^0-9\.]\|$\)', 'cW')
27 normal v
28 call search('\(^\|[^0-9\.]\d\)', 'becW')
29endfunction
30xnoremap in :<C-u>call VisualNumber()<CR>
31onoremap in :<C-u>normal vin<CR>
32
33" buffer text objects
34" -------------------
35" i% a%
36xnoremap i% :<C-u>let z = @/\|1;/^./kz<CR>G??<CR>:let @/ = z<CR>V'z
37onoremap i% :<C-u>normal vi%<CR>
38xnoremap a% GoggV
39onoremap a% :<C-u>normal va%<CR>
40
41" square brackets text objects
42" ----------------------------
43" ir ar
44xnoremap ir i[
45xnoremap ar a[
46onoremap ir :normal vi[<CR>
47onoremap ar :normal va[<CR>
48
49" C++ style block comment text objects
50" ------------------------------------
51" i? a?
52xnoremap a? [*o]*
53onoremap a? :<C-u>normal va?V<CR>
54xnoremap i? [*jo]*k
55onoremap i? :<C-u>normal vi?V<CR>
56
57" last change text object
58" -----------------------
59" ik ak
60xnoremap ik `]o`[
61onoremap ik :<C-u>normal vik<CR>
62onoremap ak :<C-u>normal vikV<CR>
63
64
65" Indent text object
66" ------------------
67" ii ai
68func! s:indent_textobj(inner)
69 if getline('.') =~ '^\s*$'
70 let ln_start = s:detect_nearest_line()
71 let ln_end = ln_start
72 else
73 let ln_start = line('.')
74 let ln_end = ln_start
75 endif
76
77 let indent = indent(ln_start)
78 if indent > 0
79 while indent(ln_start) >= indent && ln_start > 0
80 let ln_start = prevnonblank(ln_start-1)
81 endwhile
82
83 while indent(ln_end) >= indent && ln_end <= line('$')
84 let ln_end = s:nextnonblank(ln_end+1)
85 endwhile
86 else
87 while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$'
88 let ln_start -= 1
89 endwhile
90 while indent(ln_start) > 0 && ln_start > 0
91 let ln_start = prevnonblank(ln_start-1)
92 endwhile
93 while indent(ln_start) == 0 && ln_start > 0 && getline(ln_start) !~ '^\s*$'
94 let ln_start -= 1
95 endwhile
96
97 while indent(ln_end) == 0 && ln_end <= line('$') && getline(ln_end) !~ '^\s*$'
98 let ln_end += 1
99 endwhile
100 while indent(ln_end) > 0 && ln_end <= line('$')
101 let ln_end = s:nextnonblank(ln_end+1)
102 endwhile
103 endif
104
105 if a:inner || indent == 0
106 let ln_start = s:nextnonblank(ln_start+1)
107 endif
108
109 if a:inner
110 let ln_end = prevnonblank(ln_end-1)
111 else
112 let ln_end = ln_end-1
113 endif
114
115 if ln_end < ln_start
116 let ln_end = ln_start
117 endif
118
119 exe ln_end
120 normal! V
121 exe ln_start
122endfunc
123
124
125func! s:nextnonblank(lnum) abort
126 let res = nextnonblank(a:lnum)
127 if res == 0
128 let res = line('$')+1
129 endif
130 return res
131endfunc
132
133
134func! s:detect_nearest_line() abort
135 let lnum = line('.')
136 let nline = s:nextnonblank(lnum)
137 let pline = prevnonblank(lnum)
138 if abs(nline - lnum) > abs(pline - lnum) || getline(nline) =~ '^\s*$'
139 return pline
140 else
141 return nline
142 endif
143endfunc
144
145onoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR>
146onoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>
147xnoremap <silent>ii :<C-u>call <sid>indent_textobj(v:true)<CR>
148xnoremap <silent>ai :<C-u>call <sid>indent_textobj(v:false)<CR>