Skip to content

Commit e93fa80

Browse files
committed
Support move-x-function
1 parent 1d0e253 commit e93fa80

File tree

2 files changed

+145
-1
lines changed

2 files changed

+145
-1
lines changed

autoload/textobj/user.vim

+28-1
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,11 @@ function! s:plugin.define_interface_key_mappings() "{{{3
405405
\ . 'g:__textobj_' . self.name . '.obj_specs["%s"]["%s"],'
406406
\ . '"<mode>"'
407407
\ . ')<Return>'
408+
let RHS_MOVE_FUNCTION =
409+
\ ':<C-u>call <SID>move_function_wrapper('
410+
\ . 'g:__textobj_' . self.name . '.obj_specs["%s"]["%s"],'
411+
\ . '"%s"'
412+
\ . ')<Return>'
408413

409414
for [obj_name, specs] in items(self.obj_specs)
410415
for spec_name in filter(keys(specs), 's:is_ui_property_name(v:val)')
@@ -414,7 +419,11 @@ function! s:plugin.define_interface_key_mappings() "{{{3
414419
" rhs
415420
let _ = spec_name . '-function'
416421
if has_key(specs, _)
417-
let rhs = printf(RHS_SELECT_FUNCTION, obj_name, _)
422+
if spec_name =~# '^select'
423+
let rhs = printf(RHS_SELECT_FUNCTION, obj_name, _)
424+
else
425+
let rhs = printf(RHS_MOVE_FUNCTION, obj_name, _, spec_name)
426+
endif
418427
elseif has_key(specs, 'pattern')
419428
if spec_name =~# '^move-[npNP]$'
420429
let flags = ''
@@ -529,6 +538,24 @@ endfunction
529538

530539

531540

541+
" "move-function" wrapper "{{{3
542+
function! s:move_function_wrapper(function_name, spec_name)
543+
let ORIG_POS = s:gpos_to_spos(getpos('.'))
544+
545+
let _ = function(a:function_name)()
546+
if _ is 0
547+
call cursor(ORIG_POS)
548+
else
549+
" FIXME: Support motion_type. But unlike selecting a text object, the
550+
" motion_type must be known before calling a user-given function.
551+
let [motion_type, start_position, end_position] = _
552+
call setpos('.', a:spec_name =~# '[np]$' ? start_position : end_position)
553+
endif
554+
endfunction
555+
556+
557+
558+
532559
" Etc "{{{2
533560

534561
function! textobj#user#_sid()

t/move-x-function.vim

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
describe 'move-x-function'
2+
before
3+
new
4+
5+
" Anchored-word is <a> <word> <like> <this>.
6+
" But <> is not valid, because it doesn't contain a word.
7+
8+
function! b:move_next()
9+
while !0
10+
let [bl, bc] = searchpos('<', 'W')
11+
let [el, ec] = searchpos('>', 'W')
12+
if bl == 0 || el == 0
13+
return 0
14+
else
15+
if bl == el && bc + 1 < ec
16+
return ['v', [0, bl, bc, 0], [0, el, ec, 0]]
17+
else
18+
continue
19+
endif
20+
endif
21+
endwhile
22+
endfunction
23+
24+
function! b:move_previous()
25+
while !0
26+
let [el, ec] = searchpos('>', 'bW')
27+
let [bl, bc] = searchpos('<', 'bW')
28+
if bl == 0 || el == 0
29+
return 0
30+
else
31+
if bl == el && bc + 1 < ec
32+
return ['v', [0, bl, bc, 0], [0, el, ec, 0]]
33+
else
34+
continue
35+
endif
36+
endif
37+
endwhile
38+
endfunction
39+
40+
call textobj#user#plugin('anchoredword', {
41+
\ '-': {
42+
\ 'move-n': '<buffer> [n]',
43+
\ 'move-n-function': 'b:move_next',
44+
\ 'move-N': '<buffer> [N]',
45+
\ 'move-N-function': 'b:move_next',
46+
\ 'move-p': '<buffer> [p]',
47+
\ 'move-p-function': 'b:move_previous',
48+
\ 'move-P': '<buffer> [P]',
49+
\ 'move-P-function': 'b:move_previous',
50+
\ }
51+
\ })
52+
end
53+
54+
after
55+
close!
56+
end
57+
58+
it 'is used to move the cursor to a text object'
59+
put ='The <quick> brown fox jumps <over> the lazy <dog'
60+
put ='The> quick <brown> fox <jumps over the> lazy dog'
61+
1 delete _
62+
63+
let cases = [
64+
\ [1, 4, 'n', 1, 5],
65+
\ [1, 5, 'n', 1, 29],
66+
\ [1, 6, 'n', 1, 29],
67+
\ [1, 11, 'n', 1, 29],
68+
\ [1, 12, 'n', 1, 29],
69+
\ [1, 28, 'n', 1, 29],
70+
\ [1, 29, 'n', 2, 12],
71+
\ [2, 21, 'n', 2, 24],
72+
\ [2, 23, 'n', 2, 24],
73+
\ [2, 24, 'n', 2, 24],
74+
\ [2, 26, 'n', 2, 26],
75+
\ [1, 4, 'N', 1, 11],
76+
\ [1, 5, 'N', 1, 34],
77+
\ [1, 6, 'N', 1, 34],
78+
\ [1, 11, 'N', 1, 34],
79+
\ [1, 12, 'N', 1, 34],
80+
\ [1, 28, 'N', 1, 34],
81+
\ [1, 29, 'N', 2, 18],
82+
\ [2, 21, 'N', 2, 39],
83+
\ [2, 23, 'N', 2, 39],
84+
\ [2, 24, 'N', 2, 24],
85+
\ [2, 26, 'N', 2, 26],
86+
\ [1, 4, 'p', 1, 4],
87+
\ [1, 5, 'p', 1, 5],
88+
\ [1, 6, 'p', 1, 6],
89+
\ [1, 11, 'p', 1, 11],
90+
\ [1, 12, 'p', 1, 5],
91+
\ [1, 28, 'p', 1, 5],
92+
\ [1, 29, 'p', 1, 5],
93+
\ [2, 21, 'p', 2, 12],
94+
\ [2, 23, 'p', 2, 12],
95+
\ [2, 24, 'p', 2, 12],
96+
\ [2, 26, 'p', 2, 12],
97+
\ [1, 4, 'P', 1, 4],
98+
\ [1, 5, 'P', 1, 5],
99+
\ [1, 6, 'P', 1, 6],
100+
\ [1, 11, 'P', 1, 11],
101+
\ [1, 12, 'P', 1, 11],
102+
\ [1, 28, 'P', 1, 11],
103+
\ [1, 29, 'P', 1, 11],
104+
\ [2, 21, 'P', 2, 18],
105+
\ [2, 23, 'P', 2, 18],
106+
\ [2, 24, 'P', 2, 18],
107+
\ [2, 26, 'P', 2, 18],
108+
\ ]
109+
for [il, ic, d, el, ec] in cases
110+
call cursor(il, ic)
111+
Expect [il, ic] == getpos('.')[1:2]
112+
execute 'silent! normal' printf('[%s]', d)
113+
let [_, al, ac, _] = getpos('.')
114+
Expect [il, ic, d, al, ac] == [il, ic, d, el, ec]
115+
endfor
116+
end
117+
end

0 commit comments

Comments
 (0)