Skip to content

Commit d4beb21

Browse files
committed
Support deleting/changing custom surrounds
Fixes #199, #210, #318, #346
1 parent bf3480d commit d4beb21

File tree

1 file changed

+70
-12
lines changed

1 file changed

+70
-12
lines changed

plugin/surround.vim

+70-12
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ endfunction
5757

5858
" }}}1
5959

60-
" Wrapping functions {{{1
60+
" Wrapping/unwrapping functions {{{1
6161

6262
function! s:extractbefore(str)
6363
if a:str =~ '\r'
@@ -75,6 +75,23 @@ function! s:extractafter(str)
7575
endif
7676
endfunction
7777

78+
if exists('*trim')
79+
function! s:trim(txt) abort
80+
return trim(a:txt)
81+
endfunction
82+
else
83+
function! s:trim(txt) abort
84+
return substitute(a:txt, '\%(^\s\+\|\s\+$\)', '', 'g')
85+
endfunction
86+
endif
87+
88+
function! s:customsurroundings(char, b, trim) abort
89+
let all = s:process(get(a:b ? b: : g:, 'surround_'.char2nr(a:char)))
90+
let before = s:extractbefore(all)
91+
let after = s:extractafter(all)
92+
return a:trim ? [s:trim(before), s:trim(after)] : [before, after]
93+
endfunction
94+
7895
function! s:fixindent(str,spc)
7996
let str = substitute(a:str,'\t',repeat(' ',&sw),'g')
8097
let spc = substitute(a:spc,'\t',repeat(' ',&sw),'g')
@@ -148,13 +165,9 @@ function! s:wrap(string,char,type,removed,special)
148165
let before = ''
149166
let after = ''
150167
elseif exists("b:surround_".char2nr(newchar))
151-
let all = s:process(b:surround_{char2nr(newchar)})
152-
let before = s:extractbefore(all)
153-
let after = s:extractafter(all)
168+
let [before, after] = s:customsurroundings(newchar, 1, 0)
154169
elseif exists("g:surround_".char2nr(newchar))
155-
let all = s:process(g:surround_{char2nr(newchar)})
156-
let before = s:extractbefore(all)
157-
let after = s:extractafter(all)
170+
let [before, after] = s:customsurroundings(newchar, 0, 0)
158171
elseif newchar ==# "p"
159172
let before = "\n"
160173
let after = "\n\n"
@@ -306,6 +319,43 @@ function! s:wrapreg(reg,char,removed,special)
306319
let new = s:wrap(orig,a:char,type,a:removed,a:special)
307320
call setreg(a:reg,new,type)
308321
endfunction
322+
323+
function! s:escape(str) abort
324+
return escape(a:str, '!#$%&()*+,-./:;<=>?@[\]^{|}~')
325+
endfunction
326+
327+
function! s:deletecustom(char, b, count) abort
328+
let [before, after] = s:customsurroundings(a:char, a:b, 1)
329+
let [before_pat, after_pat] = ['\v\C'.s:escape(before), '\v\C'.s:escape(after)]
330+
let found = searchpair(before_pat, '', after_pat, 'bcW')
331+
if found <= 0
332+
return ['','']
333+
endif
334+
" Handle count/nesting only for asymmetric surroundings
335+
if before !=# after
336+
for _ in range(a:count - 1)
337+
let found = searchpair(before_pat, '', after_pat, 'bW')
338+
if found <= 0
339+
return ['','']
340+
endif
341+
endfor
342+
endif
343+
norm! v
344+
if before ==# after
345+
call search(before_pat, 'ceW')
346+
let found = search(after_pat, 'eW')
347+
else
348+
let found = searchpair(before_pat, '', after_pat, 'W')
349+
call search(after_pat, 'ceW')
350+
endif
351+
if found <= 0
352+
exe "norm! \<Esc>"
353+
return ['','']
354+
endif
355+
norm! d
356+
return [before, after]
357+
endfunction
358+
309359
" }}}1
310360

311361
function! s:insert(...) " {{{1
@@ -380,11 +430,12 @@ function! s:dosurround(...) " {{{1
380430
let char = strpart(char,1)
381431
let spc = 1
382432
endif
383-
if char == 'a'
384-
let char = '>'
385-
endif
386-
if char == 'r'
387-
let char = ']'
433+
if !exists("b:surround_".char2nr(char)) && !exists("g:surround_".char2nr(char))
434+
if char == 'a'
435+
let char = '>'
436+
elseif char == 'r'
437+
let char = ']'
438+
endif
388439
endif
389440
let newchar = ""
390441
if a:0 > 1
@@ -405,6 +456,10 @@ function! s:dosurround(...) " {{{1
405456
let strcount = (scount == 1 ? "" : scount)
406457
if char == '/'
407458
exe 'norm! '.strcount.'[/d'.strcount.']/'
459+
elseif exists("b:surround_".char2nr(char))
460+
let [before, after] = s:deletecustom(char, 1, scount)
461+
elseif exists("g:surround_".char2nr(char))
462+
let [before, after] = s:deletecustom(char, 0, scount)
408463
elseif char =~# '[[:punct:][:space:]]' && char !~# '[][(){}<>"''`]'
409464
exe 'norm! T'.char
410465
if getline('.')[col('.')-1] == char
@@ -438,6 +493,9 @@ function! s:dosurround(...) " {{{1
438493
norm! "_x
439494
call setreg('"','/**/',"c")
440495
let keeper = substitute(substitute(keeper,'^/\*\s\=','',''),'\s\=\*$','','')
496+
elseif exists("b:surround_".char2nr(char)) || exists("g:surround_".char2nr(char))
497+
call setreg('"', before.after, "c")
498+
let keeper = substitute(substitute(keeper,'\v\C^'.s:escape(before).'\s=','',''), '\v\C\s='.s:escape(after).'$', '','')
441499
elseif char =~# '[[:punct:][:space:]]' && char !~# '[][(){}<>]'
442500
exe 'norm! F'.char
443501
exe 'norm! df'.char

0 commit comments

Comments
 (0)