Refactor pairs handling

This commit is contained in:
Israel Chauca Fuentes
2017-04-01 12:00:36 -04:00
parent 9ec998e87a
commit c4d51a21b3
2 changed files with 93 additions and 48 deletions

View File

@@ -110,10 +110,12 @@ endfunction
function! s:balance_pairs(pair, info, opts) "{{{1
let left = strcharpart(a:pair, 0, 1)
let right = strcharpart(a:pair, 1, 1)
let behind = matchstr(a:info.cur.behind, '['.escape(left, '\^[]').'].*')
let ahead = matchstr(a:info.cur.ahead, '^.*['.escape(right, '\^[]').']')
let pat = '[^' . escape(a:pair, '\^[]') . ']'
let behind = substitute(a:info.cur.behind, '\\.', '', 'g')
let behind = matchstr(behind, '['.escape(left, '\^[]').'].*')
let behind = substitute(behind, pat, '', 'g')
let ahead = substitute(a:info.cur.ahead, '\\.', '', 'g')
let ahead = matchstr(ahead, '^.*['.escape(right, '\^[]').']')
let ahead = substitute(ahead, pat, '', 'g')
let lefts = 0
let rights = 0
@@ -185,14 +187,32 @@ function! s:any_is_true(expressions, info, options) "{{{1
return !empty(exprs)
endfunction
function! s:rights2jump(char, pair, info, opts) "{{{1
function! s:rights2jump_pair(char, pair, info, opts, go_next) "{{{1
" TODO consider escaped characters
let go_next = a:go_next
\ && empty(a:info.cur.ahead)
\ && a:info.cur.next_line =~# '^\s*['.escape(a:char, '[]^-\').']'
let line = a:info.cur.ahead
3DMDebug 'ahead: ' . line
let pair_pat = '[' . escape(a:pair, '[]^\-') . ']'
let char_pat = '[' . escape(a:char, '[]^\-') . ']'
let idx = match(line, pair_pat)
let balance = 0
while idx >= 0 && balance >= 0 && line[idx : ] !~# char_pat
while go_next || idx >= 0 && balance >= 0 && line[idx : ] !~# char_pat
if idx == -1
let idx = strchars(matchstr(a:info.cur.next_line, '^\s*\S'))
break
endif
if line[idx : ] =~# char_pat
let balance -= 1
else
let balance += 1
endif
let idx = match(line, pair_pat, idx + 1)
endwhile
3DMDebug 'idx: ' . idx
return idx + 1
endfunction
if line[idx : ] =~# char_pat
let balance -= 1
else
@@ -223,6 +243,14 @@ function! s:keys4space(info, opts) "{{{1
endfunction
function! s:keys4left(char, pair, info, opts) "{{{1
"| cases | criteria | action options | action
"| | balance | auto balance back smart | close back
"|--------|----------|-----------------------------|------------
"| any | any | 0 0 1 1 | 0 0
"| any | any | 0 0 1 0 | 0 0
"| (|)) | -1 | 1 1 1 0 | 0 0
"| (|) | 0 | 1 1 1 0 | 1 1
"| ((|) | 1 | 1 1 1 0 | 1 0
if !a:opts.autoclose
2DMDebug "No autoclose"
return ''
@@ -240,44 +268,53 @@ function! s:keys4left(char, pair, info, opts) "{{{1
\&& empty(a:info.cur.ahead) ? a:opts.eol_marker
\ . "\<C-G>U\<Left>" : ''
2DMDebug "add right delimiter"
return "\<C-V>" . strcharpart(a:pair, 1, 1) . eol_marker . "\<C-G>U\<Left>"
let jump_back = a:opts.jump_back ? "\<C-G>U\<Left>" : ''
return "\<C-V>" . strcharpart(a:pair, 1, 1) . eol_marker . jump_back
endfunction
function! s:keys4right(char, pair, info, opts) "{{{1
" cases | variables | jump options
" | next prev bal space close | next exp long to back
"------------------------------------------------------------
"1 x(|)x | 1 1 0 0 1 | 1 1 1 1 0
"2 (|)) | 1 1 -1 0 1 | 1 1 1 1 0
"3 ((|) | 1 1 1 0 1 | 1 1 1 1 0
"4 x|) | 1 0 -1 0 1 | 1 1 1 1 0
"5 (| | 0 1 1 0 0 | 0 0 0 0 1
"6 |x) | 0 0 -1 0 1 | 0 1 1 1 0
"7 ( | ) | 0 0 0 1 1 | 0 1 1 1 0
"8 (x|x) | 0 0 0 0 1 | 0 0 1 1 0
"9 x| | 0 0 0 0 0 | 0 0 0 0 0
"10 (x| | 0 0 1 0 0 | 0 0 0 0 0
"| cases | criteria | action options | action
"| | next prev close bal | next long bal | jump back
"|--------|---------------------|----------------|-----------
"| (|)) | 1 1 1 -1 | 1 1 0 | 1 0
"| (|) | 1 1 1 0 | 1 1 0 | 1 0
"| ((|) | 1 1 1 1 | 1 1 0 | 1 0
"| x|) | 1 0 1 -1 | 1 1 0 | 1 0
"| (x|) | 1 0 1 0 | 1 1 0 | 1 0
"| ((x|) | 1 0 1 1 | 1 1 1 | 1 0
"| (| | 0 1 0 1 | 0 0 1 | 0 1
"| |x) | 0 0 1 -1 | 0 1 0 | 1 0
"| (x|x)) | 0 0 1 -1 | 0 1 0 | 1 0
"| (x|x) | 0 0 1 0 | 0 1 0 | 1 0
"| ((x|x) | 0 0 1 1 | 0 0 1 | 0 1
"| x| | 0 0 0 0 | 0 0 0 | 0 0
"| (x| | 0 0 0 1 | 0 0 0 | 0 0
let previous = strcharpart(a:pair, 0, 1) ==# a:info.cur.prev_char
let next = a:char ==# a:info.cur.next_char
let is_cr_exp = a:opts.expand_cr
\ && empty(a:info.cur.ahead)
\ && matchstr(a:info.cur.next_line, '^\s*\zs\S') ==# a:char
let is_space_exp = a:opts.expand_space
\ && matchstr(a:info.cur.ahead, '^\s\zs\S') ==# a:char
let next = a:char ==# a:info.cur.next_char || is_cr_exp || is_space_exp
let balance = s:balance_pairs(a:pair, a:info, a:opts)
let has_space = a:info.cur.next_char == ' '
let has_closing = s:rights2jump(a:char, a:pair, a:info, a:opts)
let jump_opts = a:opts.jump_next + (a:opts.jump_expansion * 2)
\ + (a:opts.jump_long * 4)
2DMDebug 'previous: ' . previous
\ - is_cr_exp
let next_line = a:opts.jump_expansion && a:opts.expand_cr
let closing = s:rights2jump_pair(a:char, a:pair, a:info, a:opts, next_line)
let jump_opts = a:opts.jump_next + (a:opts.jump_long * 2)
2DMDebug 'is_cr_exp: ' . is_cr_exp
2DMDebug 'is_space_exp: ' . is_space_exp
2DMDebug 'next: ' . next
2DMDebug 'previous: ' . previous
2DMDebug 'closing: ' . closing
2DMDebug 'balance: ' . balance
2DMDebug 'has_space: ' . has_space
2DMDebug 'has_closing: ' . has_closing
2DMDebug 'next_line: ' . next_line
2DMDebug 'jump_opts: ' . jump_opts
if next
2DMDebug "next"
if previous && !has_space && has_closing && jump_opts
2DMDebug "cases 1, 2, 3"
return "\<BS>" . repeat("\<C-G>U\<Right>", has_closing)
elseif !previous && balance < 0 && !has_space && has_closing && jump_opts
2DMDebug "case 4"
return "\<BS>" . repeat("\<C-G>U\<Right>", has_closing)
if closing && jump_opts && (!a:opts.balance_pairs || balance <= 0)
2DMDebug "cases: '(|)', '(|))' or '((|)'"
2DMDebug "cases: 'x|)', '(x|)' or '((x|)'"
return "\<BS>" . repeat("\<C-G>U\<Right>", closing)
endif
2DMDebug "Nothing to do"
return ''
@@ -285,26 +322,25 @@ function! s:keys4right(char, pair, info, opts) "{{{1
" !next
if previous
2DMDebug "!next && previous"
if balance > 0 && a:opts.jump_back
2DMDebug "case 5"
if (!a:opts.balance_pairs || balance > 0) && a:opts.jump_back
2DMDebug "case: '(|'"
return "\<C-G>U\<Left>"
endif
2DMDebug "Nothing to do"
return ''
endif
" !next && !previous
if balance < 0 && !has_space && has_closing && jump_opts >= 2
2DMDebug "case 6"
return "\<BS>" . repeat("\<C-G>U\<Right>", has_closing)
elseif balance == 0
2DMDebug "!next && !previous && balance == 0"
if has_space && has_closing && jump_opts >= 2
2DMDebug "case 7"
return "\<BS>" . repeat("\<C-G>U\<Right>", has_closing)
elseif !has_space && has_closing && jump_opts >= 4
2DMDebug "case 8"
return "\<BS>" . repeat("\<C-G>U\<Right>", has_closing)
if closing
2DMDebug "!next && !previous && closing"
if (!a:opts.balance_pairs || balance <= 0) && jump_opts >= 2
2DMDebug "case: '(x|x))' or '(x|x)'"
return "\<BS>" . repeat("\<C-G>U\<Right>", closing)
elseif (!a:opts.balance_pairs || balance > 0) && a:opts.jump_back
2DMDebug "case: '((x|x)'"
return "\<C-G>U\<Left>"
endif
2DMDebug "Nothing to do"
return ''
endif
2DMDebug "Nothing to do"
return ''

View File

@@ -12,7 +12,7 @@
call vimtest#StartTap()
call vimtap#Plan(217)
call vimtap#Plan(239)
let g:delimitMate_matchpairs = '(:),{:},[:],<:>,¿:?,¡:!,,::'
@@ -90,10 +90,15 @@ call DMTest_single('()', 'a\<magic>x', '()x', 0, 1)
call DMTest_single('{()}', 'la\<magic>x', '{()}x', 0, 1)
let g:delimitMate_balance_pairs = 0
call DMTest_pairs('ab cd)', "la(x", 'ab(x) cd)')
" Issue #229
call DMTest_pairs('((ab cd)', "$i)x", '((ab cd)x')
let g:delimitMate_balance_pairs = 1
call DMTest_pairs('ab cd)', "la(x", 'ab(x cd)')
" Issue #229
call DMTest_pairs('((ab cd)', "A)", '((ab cd))')
call DMTest_pairs('((ab cd)', "$i)x", '((ab cd)x)')
unlet g:delimitMate_balance_pairs
" Issue #220
@@ -111,9 +116,13 @@ unlet g:delimitMate_jump_long
" Issues #207 and #223
let g:delimitMate_jump_all = 1
call DMTest_single('{[(foobar)]}', 'fbi)x', '{[(foobar)]}x', 0, 1)
call DMTest_single('{[(foobar)]}', 'fbi<magic>x', '{[(foobar)]}x', 0, 1)
unlet g:delimitMate_jump_all
let g:delimitMate_jump_back = 1
call DMTest_pairs('', 'i()x', '()x')
unlet g:delimitMate_jump_back
" Disable on syntax groups
new
syntax on