Skip to content

Commit ff48eaa

Browse files
committed
Fix "Single-character CamelCase segments seem not to work" (#11)
The code isn't pretty but we wouldn't be using Vimscript if we had any beauty standards.
1 parent 51c323d commit ff48eaa

File tree

1 file changed

+79
-2
lines changed

1 file changed

+79
-2
lines changed

Diff for: autoload/textobj/variable_segment.vim

+79-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,85 @@
1+
" Given three positions, return the position closest to the first one.
2+
function! s:closest_position(main, a, b)
3+
let a_distance = mapnew(a:main, {k,v->abs(v-a:a[k])})
4+
let b_distance = mapnew(a:main, {k,v->abs(v-a:b[k])})
5+
if a_distance[1] < b_distance[1]
6+
return a:a
7+
endif
8+
if a_distance[1] > b_distance[1]
9+
return a:b
10+
endif
11+
if a_distance[2] < b_distance[2]
12+
return a:a
13+
endif
14+
if a_distance[2] > b_distance[2]
15+
return a:b
16+
endif
17+
" Distances are the same, return either one
18+
return a:a
19+
endfunction!
20+
121
function! s:select(object_type, right_boundary)
222
let left_boundaries = ['_\+\k', '\<', '\l\u', '\u\u\ze\l', '\a\d', '\d\a']
3-
call search(join(left_boundaries, '\|'), 'bce')
4-
let start_position = getpos('.')
523

24+
" Gather all possible matches
25+
let cursor_position = getpos('.')
26+
let all_positions = []
27+
for boundary in left_boundaries
28+
" search() moves the cursor, so we need to reset the cursor's position
29+
" before each search
30+
call setpos('.', cursor_position)
31+
if search(boundary, 'bce') > 0
32+
call add(all_positions, getpos('.'))
33+
endif
34+
endfor
35+
36+
" Try to find a good match on the same line and on the left of the cursor
37+
let start_position = v:null
38+
let potential_matches = filter(copy(all_positions),
39+
\ {v -> v[1] == cursor_position[1] && v[2] <= cursor_position[2]})
40+
if len(potential_matches) > 0
41+
let start_position = reduce(potential_matches,
42+
\ {a, b -> s:closest_position(cursor_position, a, b)})
43+
endif
44+
45+
if type(start_position) == type(v:null)
46+
" No match found yet, try on the same line but on the right of the
47+
" cursor
48+
let potential_matches = filter(copy(all_positions),
49+
\ {v -> v[1] == cursor_position[1] && v[2] > cursor_position[2]})
50+
if len(potential_matches) > 0
51+
let start_position = reduce(potential_matches,
52+
\ {a, b -> s:closest_position(cursor_position, a, b)})
53+
endif
54+
endif
55+
56+
if type(start_position) == type(v:null)
57+
" No match found yet, try to find one on lines above the cursor
58+
let potential_matches = filter(copy(all_positions),
59+
\ {v -> v[1] < cursor_position[1]})
60+
if len(potential_matches) > 0
61+
let start_position = reduce(potential_matches,
62+
\ {a, b -> s:closest_position(cursor_position, a, b)})
63+
endif
64+
endif
65+
66+
if type(start_position) == type(v:null)
67+
" No match found yet, try to find one on below after the cursor
68+
let potential_matches = filter(copy(all_positions),
69+
\ {v -> v[1] > cursor_position[1]})
70+
if len(potential_matches) > 0
71+
let start_position = reduce(potential_matches,
72+
\ {a, b -> s:closest_position(cursor_position, a, b)})
73+
endif
74+
endif
75+
76+
if type(start_position) == type(v:null)
77+
" The buffer must not contain any words - fall back to the cursor's
78+
" position
79+
let start_position = cursor_position
80+
endif
81+
82+
call setpos('.', start_position)
683
call search('\>', 'c')
784
let word_end = getpos('.')
885
call setpos('.', start_position)

0 commit comments

Comments
 (0)