mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-04 05:00:03 +08:00
147 lines
3.6 KiB
VimL
147 lines
3.6 KiB
VimL
|
" vim match-up - even better matching
|
||
|
"
|
||
|
" Maintainer: Andy Massimino
|
||
|
" Email: a@normed.space
|
||
|
"
|
||
|
|
||
|
let s:save_cpo = &cpo
|
||
|
set cpo&vim
|
||
|
|
||
|
function! matchup#transmute#init_module() " {{{1
|
||
|
if !g:matchup_transmute_enabled | return | endif
|
||
|
|
||
|
call matchup#transmute#enable()
|
||
|
endfunction
|
||
|
|
||
|
" }}}1
|
||
|
|
||
|
function! matchup#transmute#enable() " {{{1
|
||
|
" TODO: add insert mode map
|
||
|
" TODO: add g:matchup_transmute_auto
|
||
|
endfunction
|
||
|
|
||
|
" }}}1
|
||
|
function! matchup#transmute#disable() " {{{1
|
||
|
|
||
|
endfunction
|
||
|
|
||
|
" }}}1
|
||
|
|
||
|
function! matchup#transmute#tick(insertmode) " {{{1
|
||
|
if !g:matchup_transmute_enabled | return 0 | endif
|
||
|
|
||
|
if a:insertmode
|
||
|
return 0
|
||
|
endif
|
||
|
|
||
|
if changenr() > get(w:, 'matchup_transmute_last_changenr', -1)
|
||
|
\ && !empty('w:matchup_matchparen_context.prior')
|
||
|
let w:matchup_transmute_last_changenr = changenr()
|
||
|
|
||
|
return matchup#transmute#dochange(
|
||
|
\ w:matchup_matchparen_context.prior.corrlist,
|
||
|
\ w:matchup_matchparen_context.prior.current,
|
||
|
\ w:matchup_matchparen_context.normal.current)
|
||
|
endif
|
||
|
|
||
|
return 0
|
||
|
endfunction
|
||
|
|
||
|
" }}}1
|
||
|
function! matchup#transmute#reset() " {{{1
|
||
|
if !g:matchup_transmute_enabled | return 0 | endif
|
||
|
let w:matchup_transmute_last_changenr = changenr()
|
||
|
endfunction
|
||
|
|
||
|
" }}}1
|
||
|
function! matchup#transmute#dochange(list, pri, cur) " {{{1
|
||
|
if empty(a:list) || empty(a:pri) || empty(a:cur) | return 0 | endif
|
||
|
|
||
|
let l:cur = a:cur
|
||
|
|
||
|
" check back one
|
||
|
if a:pri.class[0] != l:cur.class[0]
|
||
|
let l:cur = matchup#delim#get_current('all', a:pri.side,
|
||
|
\ {'insertmode': 1})
|
||
|
if empty(l:cur) | return 0 | endif
|
||
|
endif
|
||
|
|
||
|
" right now, only same-class changes are supported
|
||
|
if a:pri.class[0] != l:cur.class[0]
|
||
|
return 0
|
||
|
endif
|
||
|
if a:pri.side =~# '^open\|close$' && a:pri.side isnot l:cur.side
|
||
|
return 0
|
||
|
endif
|
||
|
if !matchup#pos#equal(a:pri, l:cur)
|
||
|
return 0
|
||
|
endif
|
||
|
|
||
|
let l:num_changes = 0
|
||
|
|
||
|
let l:delta = strdisplaywidth(l:cur.match)
|
||
|
\ - strdisplaywidth(a:pri.match)
|
||
|
|
||
|
for l:i in range(len(a:list))
|
||
|
if l:i == a:pri.match_index | continue | endif
|
||
|
|
||
|
let l:corr = a:list[l:i]
|
||
|
let l:line = getline(l:corr.lnum)
|
||
|
|
||
|
let l:column = l:corr.cnum
|
||
|
if l:corr.lnum == l:cur.lnum && l:i > a:pri.match_index
|
||
|
let l:column += l:delta
|
||
|
endif
|
||
|
|
||
|
let l:re_anchored = '\%'.(l:column).'c'
|
||
|
\ . '\%('.(l:corr.regexone[l:corr.side]).'\)'
|
||
|
|
||
|
let l:groups = copy(l:corr.groups)
|
||
|
for l:grp in keys(l:groups)
|
||
|
let l:count = len(split(l:re_anchored,
|
||
|
\ g:matchup#re#not_bslash.'\\'.l:grp))-1
|
||
|
if l:count == 0 | continue | endif
|
||
|
|
||
|
if l:cur.groups[l:grp] ==# l:groups[l:grp]
|
||
|
continue
|
||
|
endif
|
||
|
|
||
|
for l:dummy in range(len(l:count))
|
||
|
" create a pattern which isolates the old group text
|
||
|
let l:prevtext = s:qescape(l:groups[l:grp])
|
||
|
let l:pattern = substitute(l:re_anchored,
|
||
|
\ g:matchup#re#not_bslash.'\\'.l:grp,
|
||
|
\ '\=''\zs\V'.l:prevtext.'\m\ze''', '')
|
||
|
let l:pattern = matchup#delim#fill_backrefs(l:pattern,
|
||
|
\ l:groups, 0)
|
||
|
let l:string = l:cur.groups[l:grp]
|
||
|
let l:line = substitute(l:line, l:pattern,
|
||
|
\ '\='''.s:qescape(l:string)."'", '')
|
||
|
endfor
|
||
|
|
||
|
let l:groups[l:grp] = l:cur.groups[l:grp]
|
||
|
endfor
|
||
|
|
||
|
if getline(l:corr.lnum) !=# l:line
|
||
|
if g:matchup_transmute_breakundo && l:num_changes == 0
|
||
|
execute "normal! a\<c-g>u"
|
||
|
endif
|
||
|
call setline(l:corr.lnum, l:line)
|
||
|
let l:num_changes += 1
|
||
|
endif
|
||
|
endfor
|
||
|
|
||
|
return l:num_changes
|
||
|
endfunction
|
||
|
|
||
|
function s:qescape(str)
|
||
|
return escape(substitute(a:str, "'", "''", 'g'), '\')
|
||
|
endfunction
|
||
|
|
||
|
" }}}1
|
||
|
|
||
|
let &cpo = s:save_cpo
|
||
|
|
||
|
" vim: fdm=marker sw=2
|
||
|
|