Skip to content

Instantly share code, notes, and snippets.

@haya14busa
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haya14busa/25af8128aa1f9a5ec536 to your computer and use it in GitHub Desktop.
Save haya14busa/25af8128aa1f9a5ec536 to your computer and use it in GitHub Desktop.
let s:TRUE = !0
let s:FALSE = 0
let s:escaped_backslash = '\m\%(^\|[^\\]\)\%(\\\\\)*\zs'
function! s:regexp_join(ps) abort
let rs = map(filter(copy(a:ps), 's:_is_valid_regexp(v:val)'), 's:escape_unbalanced_left_r(v:val)')
return printf('\m\%%(%s\m\)', join(rs, '\m\|'))
endfunction
function! s:_is_valid_regexp(pattern) abort
try
if '' =~# a:pattern
endif
return s:TRUE
catch
return s:FALSE
endtry
endfunction
" \m,\v: [ -> \[
" \M,\V: \[ -> [
function! s:escape_unbalanced_left_r(pattern) abort
let rs = []
let cs = split(a:pattern, '\zs')
" escape backslash (\, \\\, \\\\\, ...)
let escape_bs = s:FALSE
let flag = &magic ? 'm' : 'M'
let i = 0
while i < len(cs)
let c = cs[i]
" characters to add to rs
let addcs = [c]
if escape_bs && s:_is_flag(c)
let flag = c
elseif c is# '[' && s:_may_replace_left_r_cond(escape_bs, flag)
let idx = s:_find_right_r(cs, i)
if idx is# -1
if s:_is_flag(flag, 'MV')
" Remove `\` before unbalanced `[`
let rs = rs[:-2]
else
" Escape unbalanced `[`
let addcs = ['\' . c]
endif
else
let addcs = cs[(i):(i+idx)]
let i += idx
endif
endif
let escape_bs = (escape_bs || c isnot# '\') ? s:FALSE : s:TRUE
let rs += addcs
let i += 1
endwhile
return join(rs, '')
endfunction
" @ return boolean
function! s:_is_flag(flag, ...) abort
let chars = get(a:, 1, 'mMvV')
return a:flag =~# printf('\m[%s]', chars)
endfunction
" @ return boolean
function! s:_may_replace_left_r_cond(escape_bs, flag) abort
return (a:escape_bs && s:_is_flag(a:flag, 'MV')) || (!a:escape_bs && s:_is_flag(a:flag, 'mv'))
endfunction
" @return index
function! s:_find_right_r(cs, i) abort
return match(join(a:cs[(a:i+1):], ''), s:escaped_backslash . ']')
endfunction
echo '###### s:regexp_join()'
echo '===1'
let r = s:regexp_join(['[a', '[bcd]'])
echo r ==# '\m\%(\[a\m\|[bcd]\)'
echo '[a' =~# r
echo '[' !~# r
echo '\' !~# r
echo '###### s:escape_unbalanced_left_r()'
echo '===1'
echo s:escape_unbalanced_left_r('[') == '\['
echo s:escape_unbalanced_left_r('\[') == '\['
echo s:escape_unbalanced_left_r('\\[') == '\\\['
echo s:escape_unbalanced_left_r('\\\[') == '\\\['
echo '===2'
echo s:escape_unbalanced_left_r('[]') == '[]'
echo s:escape_unbalanced_left_r('\[]') == '\[]'
echo s:escape_unbalanced_left_r('\\[]') == '\\[]'
echo s:escape_unbalanced_left_r('\\\[]') == '\\\[]'
echo '===3'
echo s:escape_unbalanced_left_r('[][') == '[]\['
echo s:escape_unbalanced_left_r('\[][') == '\[]\['
echo s:escape_unbalanced_left_r('\\[][') == '\\[]\['
echo s:escape_unbalanced_left_r('\\\[][') == '\\\[]\['
echo '===4'
echo s:escape_unbalanced_left_r('[]...[') == '[]...\['
echo s:escape_unbalanced_left_r('\[]...[') == '\[]...\['
echo s:escape_unbalanced_left_r('\\[]...[') == '\\[]...\['
echo s:escape_unbalanced_left_r('\\\[]...[') == '\\\[]...\['
echo '===5'
echo s:escape_unbalanced_left_r('\m[') == '\m\['
echo s:escape_unbalanced_left_r('\m\[') == '\m\['
echo s:escape_unbalanced_left_r('\m\\[') == '\m\\\['
echo s:escape_unbalanced_left_r('\m\\\[') == '\m\\\['
echo s:escape_unbalanced_left_r('\v[') == '\v\['
echo s:escape_unbalanced_left_r('\v\[') == '\v\['
echo s:escape_unbalanced_left_r('\v\\[') == '\v\\\['
echo s:escape_unbalanced_left_r('\v\\\[') == '\v\\\['
echo '===6'
echo s:escape_unbalanced_left_r('\M[') == '\M['
echo s:escape_unbalanced_left_r('\M\[') == '\M['
echo s:escape_unbalanced_left_r('\M\\[') == '\M\\['
echo s:escape_unbalanced_left_r('\M\\\[') == '\M\\['
echo s:escape_unbalanced_left_r('\V[') == '\V['
echo s:escape_unbalanced_left_r('\V\[') == '\V['
echo s:escape_unbalanced_left_r('\V\\[') == '\V\\['
echo s:escape_unbalanced_left_r('\V\\\[') == '\V\\['
echo '===7'
echo s:escape_unbalanced_left_r('[\M\[\v[') == '\[\M[\v\['
echo s:escape_unbalanced_left_r('[\M\[\v[]') == '[\M\[\v[]'
echo s:escape_unbalanced_left_r('[[]') == '[[]'
echo s:escape_unbalanced_left_r('[\[]') == '[\[]'
echo s:escape_unbalanced_left_r('\M\[[]') == '\M\[[]'
echo '===8'
let p = '[' . repeat('[', 10000) . ']'
echo s:escape_unbalanced_left_r(p) == p
let p = '[' . repeat('\[', 10000) . ']'
echo s:escape_unbalanced_left_r(p) == p
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment