Merge branch 'feature-midmap'

This commit is contained in:
Andy K. Massimino
2019-08-02 19:07:33 -04:00
5 changed files with 102 additions and 4 deletions

View File

@@ -0,0 +1,17 @@
if !exists('b:did_ftplugin')
finish
endif
let s:save_cpo = &cpo
set cpo&vim
call matchup#util#patch_match_words('retry', 'retry\|return')
let b:match_midmap = [
\ ['rubyRepeat', 'next'],
\ ['rubyDefine', 'return'],
\]
let b:undo_ftplugin .= '| unlet! b:match_midmap'
let &cpo = s:save_cpo

View File

@@ -34,6 +34,7 @@ function! matchup#delim#get_current(type, side, ...) " {{{1
endfunction
" }}}1
function! matchup#delim#get_matching(delim, ...) " {{{1
if empty(a:delim) || !has_key(a:delim, 'lnum') | return {} | endif
@@ -112,7 +113,7 @@ function! matchup#delim#get_matching(delim, ...) " {{{1
return l:matching_list
else
" old syntax: open->close, close->open
if !len(l:matching_list) | return {} | endif
if len(l:matching_list) < 2 | return {} | endif
return a:delim.side ==# 'open' ? l:matching_list[-1]
\ : l:matching_list[0]
endif
@@ -120,6 +121,7 @@ function! matchup#delim#get_matching(delim, ...) " {{{1
endfunction
" }}}1
function! matchup#delim#get_surrounding(type, ...) " {{{1
call matchup#perf#tic('delim#get_surrounding')
@@ -615,6 +617,7 @@ function! s:parser_delim_new(lnum, cnum, opts) " {{{1
\ 'get_matching' : s:basetypes['delim_tex'].get_matching,
\ 'regexone' : l:thisre,
\ 'regextwo' : l:thisrebr,
\ 'midmap' : get(l:list, 'midmap', {}),
\ 'rematch' : l:re,
\ 'highlighting' : get(a:opts, 'highlighting', 0),
\}
@@ -667,6 +670,27 @@ function! s:get_matching_delims(down, stopline) dict " {{{1
let l:skip = 'matchup#delim#skip0()'
endif
" disambiguate matches for languages like julia, matlab, ruby, etc
if !empty(self.midmap)
let l:midmap = self.midmap.elements
if self.side ==# 'mid'
let l:idx = filter(range(len(l:midmap)),
\ 'self.match =~# l:midmap[v:val][1]')
else
let l:syn = synIDattr(synID(self.lnum, self.cnum, 0), 'name')
let l:idx = filter(range(len(l:midmap)),
\ 'l:syn =~# l:midmap[v:val][0]')
endif
if len(l:idx)
let l:valid = l:midmap[l:idx[0]]
let l:skip = printf("matchup#delim#skip1(%s, %s)",
\ string(l:midmap[l:idx[0]]), string(l:skip))
else
let l:skip = printf("matchup#delim#skip2(%s, %s)",
\ string(self.midmap.strike), string(l:skip))
endif
endif
if matchup#perf#timeout_check() | return [['', 0, 0]] | endif
" improves perceptual performance in insert mode
@@ -746,7 +770,7 @@ function! s:get_matching_delims(down, stopline) dict " {{{1
if matchup#perf#timeout_check() | break | endif
let [l:lnum, l:cnum] = searchpairpos(l:open, l:mids, l:close,
\ l:flags, l:skip, l:lnum_corr, matchup#perf#timeout())
\ l:flags, l:skip, l:lnum_corr, matchup#perf#timeout())
if l:lnum <= 0 | break | endif
if a:down
@@ -759,6 +783,10 @@ function! s:get_matching_delims(down, stopline) dict " {{{1
let l:re_anchored = s:anchor_regex(l:re, l:cnum, l:has_zs)
let l:matches = matchlist(getline(l:lnum), l:re_anchored)
if empty(l:matches)
" this should never happen
continue
endif
let l:match = l:matches[0]
call add(l:list, [l:match, l:lnum, l:cnum])
@@ -802,6 +830,26 @@ function! matchup#delim#skip0()
execute 'return' (s:invert_skip ? '!(' : '(') b:matchup_delim_skip ')'
endfunction
""
" advanced mid/syntax skip when found in midmap
" {val} is a 2 element array of allowed [syntax, words]
" {def} is the fallback skip expression
function! matchup#delim#skip1(val, def)
if getline('.')[col('.')-1:] =~# '^'.a:val[1]
return eval(a:def)
endif
let l:s = synIDattr(synID(line('.'),col('.'), 0), 'name')
return l:s !~# a:val[0] || eval(a:def)
endfunction
""
" advanced mid/syntax skip when word is not in midmap
" {strike} pattern of disallowed mid words
" {def} is the fallback skip expression
function! matchup#delim#skip2(strike, def)
return getline('.')[col('.')-1:] =~# '^'.a:strike || eval(a:def)
endfunction
let s:invert_skip = 0
let s:eff_curpos = [1, 1]

View File

@@ -84,7 +84,8 @@ let s:match_word_cache = {}
" }}}1
function! s:init_delim_lists(...) abort " {{{1
let l:lists = { 'delim_tex': { 'regex': [], 'regex_backref': [] } }
let l:lists = { 'delim_tex': { 'regex': [], 'regex_backref': [],
\ 'midmap': {} } }
" very tricky examples:
" good: let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
@@ -434,10 +435,19 @@ function! s:init_delim_lists(...) abort " {{{1
\})
endfor
if exists('b:match_midmap') && type(b:match_midmap) == type([])
let l:elems = deepcopy(b:match_midmap)
let l:lists.delim_tex.midmap = {
\ 'elements': l:elems,
\ 'strike': join(map(range(len(l:elems)),
\ '"\\(".l:elems[v:val][1]."\\)"'), '\|')
\}
endif
" generate combined lists
let l:lists.delim_all = {}
let l:lists.all = {}
for l:k in ['regex', 'regex_backref']
for l:k in ['regex', 'regex_backref', 'midmap']
let l:lists.delim_all[l:k] = l:lists.delim_tex[l:k]
let l:lists.all[l:k] = l:lists.delim_all[l:k]
endfor

8
test/lang/ruby/next.rb Normal file
View File

@@ -0,0 +1,8 @@
for i in 0..5
if i < 2 then
next
else
end
puts "Value of local variable is #{i}"
end

15
test/vader/ruby.vader Normal file
View File

@@ -0,0 +1,15 @@
Given ruby (Ruby for if):
for i in 0..5
if i < 2 then
next
end
puts "Value of local variable is #{i}"
end
Do (Motion %):
go
%
Then (Verify):
AssertEqual 'next', expand('<cword>')