Skip to content

Commit 777dfb7

Browse files
committed
Merge branch 'support-move-x-function'
Close gh-23.
2 parents 2045cc1 + e93fa80 commit 777dfb7

File tree

2 files changed

+156
-7
lines changed

2 files changed

+156
-7
lines changed

autoload/textobj/user.vim

+39-7
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,22 @@ endfunction
394394

395395

396396
function! s:plugin.define_interface_key_mappings() "{{{3
397-
let RHS_PATTERN = ':<C-u>call g:__textobj_' . self.name . '.%s'
398-
\ . '("%s", "%s", "<mode>")<Return>'
399-
let RHS_FUNCTION = ':<C-u>call <SID>select_function_wrapper('
400-
\ . 'g:__textobj_' . self.name . '.obj_specs["%s"]["%s"],'
401-
\ . '"<mode>"'
402-
\ . ')<Return>'
397+
let RHS_PATTERN =
398+
\ ':<C-u>call g:__textobj_' . self.name . '.%s('
399+
\ . '"%s",'
400+
\ . '"%s",'
401+
\ . '"<mode>"'
402+
\ . ')<Return>'
403+
let RHS_SELECT_FUNCTION =
404+
\ ':<C-u>call <SID>select_function_wrapper('
405+
\ . 'g:__textobj_' . self.name . '.obj_specs["%s"]["%s"],'
406+
\ . '"<mode>"'
407+
\ . ')<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>'
403413

404414
for [obj_name, specs] in items(self.obj_specs)
405415
for spec_name in filter(keys(specs), 's:is_ui_property_name(v:val)')
@@ -409,7 +419,11 @@ function! s:plugin.define_interface_key_mappings() "{{{3
409419
" rhs
410420
let _ = spec_name . '-function'
411421
if has_key(specs, _)
412-
let rhs = printf(RHS_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
413427
elseif has_key(specs, 'pattern')
414428
if spec_name =~# '^move-[npNP]$'
415429
let flags = ''
@@ -524,6 +538,24 @@ endfunction
524538

525539

526540

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+
527559
" Etc "{{{2
528560

529561
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)