Skip to content
This repository was archived by the owner on Feb 23, 2025. It is now read-only.

Commit fbd5ff8

Browse files
committed
Add iced#paredit#get_current_top_object
1 parent 1076f17 commit fbd5ff8

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed

autoload/iced/paredit.vim

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,68 @@ function! iced#paredit#move_to_parent_element() abort
9090
return col('.')
9191
endfunction
9292

93+
function! s:is_in_range(current_pos, start_pos, end_pos) abort
94+
return (a:current_pos[1] == a:start_pos[1] && a:start_pos[2] <= a:current_pos[2])
95+
\ || (a:current_pos[1] == a:end_pos[1] && a:current_pos[2] <= a:end_pos[2])
96+
\ || (a:start_pos[1] <= a:current_pos[1] && a:current_pos[1] <= a:end_pos[1])
97+
endfunction
98+
99+
function! iced#paredit#get_current_top_object_raw(...) abort
100+
let open_char = get(a:, 1, '(')
101+
let close_char = get(a:, 2, ')')
102+
let pos = getcurpos()
103+
let result = {}
104+
105+
try
106+
while v:true
107+
let line = getline('.')
108+
if empty(line) | break | endif
109+
110+
if substitute(line, '^#[^\(\[\{ ]\+ \?', '', '')[0] ==# open_char
111+
let start_pos = getcurpos()
112+
let start_pos[2] = stridx(line, open_char) + 1
113+
114+
call setpos('.', start_pos)
115+
" move to pair
116+
silent normal! %
117+
let end_pos = getcurpos()
118+
119+
if s:is_in_range(pos, start_pos, end_pos)
120+
call setpos('.', start_pos)
121+
" NOTE: `o0y` is to wrap top level tag literal
122+
silent exe printf('normal! va%so0y', open_char)
123+
124+
let result = {
125+
\ 'code': @@,
126+
\ 'pos': start_pos,
127+
\ }
128+
break
129+
endif
130+
endif
131+
132+
if line('.') == 1 | break | endif
133+
" Move cursor up
134+
silent normal! k
135+
endwhile
136+
finally
137+
silent exe "normal! \<Esc>"
138+
endtry
139+
140+
return result
141+
endfunction
142+
143+
function! iced#paredit#get_current_top_object(...) abort
144+
let view = winsaveview()
145+
let reg_save = @@
146+
147+
try
148+
return call('iced#paredit#get_current_top_object_raw', a:000)
149+
finally
150+
let @@ = reg_save
151+
call winrestview(view)
152+
endtry
153+
endfunction
154+
93155
function! iced#paredit#get_current_top_list_raw(...) abort
94156
let code = ''
95157
let pos = ''

test/paredit.vim

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,64 @@ function! s:suite.find_parent_form_raw_test() abort
169169

170170
call s:buf.stop_dummy()
171171
endfunction
172+
173+
function! s:suite.get_current_top_object_test() abort
174+
call s:buf.start_dummy([
175+
\ '(foo',
176+
\ ' (bar|))',
177+
\ ])
178+
let res = iced#paredit#get_current_top_object()
179+
call s:assert.equals(res['code'], "(foo\n (bar))")
180+
call s:buf.stop_dummy()
181+
182+
" with meta
183+
call s:buf.start_dummy([
184+
\ '#tag1/name (foo',
185+
\ ' (bar|))',
186+
\ ])
187+
let res = iced#paredit#get_current_top_object()
188+
call s:assert.equals(res['code'], "#tag1/name (foo\n (bar))")
189+
call s:buf.stop_dummy()
190+
endfunction
191+
192+
function! s:suite.get_current_top_object_vector_test() abort
193+
call s:buf.start_dummy([
194+
\ '[foo',
195+
\ ' [bar|]]',
196+
\ ])
197+
let res = iced#paredit#get_current_top_object()
198+
call s:assert.equals(res, {})
199+
let res = iced#paredit#get_current_top_object('[', ']')
200+
call s:assert.equals(res['code'], "[foo\n [bar]]")
201+
call s:buf.stop_dummy()
202+
203+
" with meta
204+
call s:buf.start_dummy([
205+
\ '#tag2/name [foo',
206+
\ ' [bar|]]',
207+
\ ])
208+
let res = iced#paredit#get_current_top_object('[', ']')
209+
call s:assert.equals(res['code'], "#tag2/name [foo\n [bar]]")
210+
call s:buf.stop_dummy()
211+
endfunction
212+
213+
function! s:suite.get_current_top_object_vector_test() abort
214+
call s:buf.start_dummy([
215+
\ '{:foo',
216+
\ ' {:bar 123|}}',
217+
\ ])
218+
let res = iced#paredit#get_current_top_object()
219+
call s:assert.equals(res, {})
220+
let res = iced#paredit#get_current_top_object('{', '}')
221+
call s:assert.equals(res['code'], "{:foo\n {:bar 123}}")
222+
call s:buf.stop_dummy()
223+
224+
" with meta
225+
call s:buf.start_dummy([
226+
\ '#tag3/name {:foo',
227+
\ ' {:bar 123|}}',
228+
\ ])
229+
let res = iced#paredit#get_current_top_object('{', '}')
230+
call s:assert.equals(res['code'], "#tag3/name {:foo\n {:bar 123}}")
231+
call s:buf.stop_dummy()
232+
endfunction

0 commit comments

Comments
 (0)