@@ -57,7 +57,7 @@ endfunction
5757
5858" }}}1
5959
60- " Wrapping functions {{{1
60+ " Wrapping/unwrapping functions {{{1
6161
6262function ! s: extractbefore (str)
6363 if a: str = ~ ' \r'
@@ -75,6 +75,23 @@ function! s:extractafter(str)
7575 endif
7676endfunction
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+
7895function ! 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,45 @@ 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 )
308321endfunction
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+ " searchpair()'s 'c' flag matches both start and end.
331+ " Append '\zs' to the closer pattern so that it doesn't match the closer on the cursor.
332+ let found = searchpair (before_pat, ' ' , after_pat.' \zs' , ' bcW' )
333+ if found <= 0
334+ return [' ' ,' ' ]
335+ endif
336+ " Handle count/nesting only for asymmetric surroundings
337+ if before !=# after
338+ for _ in range (a: count - 1 )
339+ let found = searchpair (before_pat, ' ' , after_pat, ' bW' )
340+ if found <= 0
341+ return [' ' ,' ' ]
342+ endif
343+ endfor
344+ endif
345+ norm! v
346+ if before == # after
347+ call search (before_pat, ' ceW' )
348+ let found = search (after_pat, ' eW' )
349+ else
350+ let found = searchpair (before_pat, ' ' , after_pat, ' W' )
351+ call search (after_pat, ' ceW' )
352+ endif
353+ if found <= 0
354+ exe " norm! \<Esc> "
355+ return [' ' ,' ' ]
356+ endif
357+ norm! d
358+ return [before, after]
359+ endfunction
360+
309361" }}}1
310362
311363function ! s: insert (... ) " {{{1
@@ -380,11 +432,12 @@ function! s:dosurround(...) " {{{1
380432 let char = strpart (char,1 )
381433 let spc = 1
382434 endif
383- if char == ' a'
384- let char = ' >'
385- endif
386- if char == ' r'
387- let char = ' ]'
435+ if ! exists (" b:surround_" .char2nr (char)) && ! exists (" g:surround_" .char2nr (char))
436+ if char == ' a'
437+ let char = ' >'
438+ elseif char == ' r'
439+ let char = ' ]'
440+ endif
388441 endif
389442 let newchar = " "
390443 if a: 0 > 1
@@ -405,6 +458,10 @@ function! s:dosurround(...) " {{{1
405458 let strcount = (scount == 1 ? " " : scount)
406459 if char == ' /'
407460 exe ' norm! ' .strcount.' [/d' .strcount.' ]/'
461+ elseif exists (" b:surround_" .char2nr (char))
462+ let [before, after] = s: deletecustom (char, 1 , scount)
463+ elseif exists (" g:surround_" .char2nr (char))
464+ let [before, after] = s: deletecustom (char, 0 , scount)
408465 elseif char = ~# ' [[:punct:][:space:]]' && char !~# ' [][(){}<>"'' `]'
409466 exe ' norm! T' .char
410467 if getline (' .' )[col (' .' )-1 ] == char
@@ -426,7 +483,10 @@ function! s:dosurround(...) " {{{1
426483 endif
427484 let oldline = getline (' .' )
428485 let oldlnum = line (' .' )
429- if char == # " p"
486+ if exists (" b:surround_" .char2nr (char)) || exists (" g:surround_" .char2nr (char))
487+ call setreg (' "' , before.after, " c" )
488+ let keeper = substitute (substitute (keeper,' \v\C^' .s: escape (before).' \s=' ,' ' ,' ' ), ' \v\C\s=' .s: escape (after).' $' , ' ' ,' ' )
489+ elseif char == # " p"
430490 call setreg (' "' ,' ' ,' V' )
431491 elseif char == # " s" || char == # " w" || char == # " W"
432492 " Do nothing
0 commit comments