Improve delim skip, make minor changes to readme

This commit is contained in:
Andy K. Massimino
2017-10-27 11:56:22 -04:00
parent 5e940b4e5d
commit 9a33c91522
6 changed files with 104 additions and 45 deletions

View File

@@ -3,11 +3,14 @@
:warning: warning :warning: this plugin is unfinished and under heavy
active development. It is not ready for use yet!
match-up is a replacement for the venerable vim plugin
[matchit.vim](http://ftp.vim.org/pub/vim/runtime/macros/matchit.txt).
match-up is a replacement for the venerable vim plugin [matchit.vim]
match-up aims to replicate all of matchit's features, fix a number of its
deficiencies and bugs, and add a few totally new features. It also
replaces the plugin matchparen, allowing matchit words to be highlighted.
replaces the standard plugin [matchparen], allowing all of matchit's words
to be highlighted along with the `matchpairs` (`(){}[]`).
[matchit.vim]: http://ftp.vim.org/pub/vim/runtime/macros/matchit.txt
[matchparen]: http://ftp.vim.org/pub/vim/runtime/doc/pi_paren.txt
<img src='https://github.com/andymass/matchup.vim/wiki/images/teaser.jpg' width='300px' alt='and in this corner...'>
@@ -19,6 +22,8 @@ Contributions are welcome!
* [Overview](#overview)
* [Installation](#installation)
* [Features](#features)
* [FAQ](#faq)
* [Interoperability](#interoperability)
* [Development](#development)
## Overview
@@ -49,20 +54,20 @@ Or use some other plugin manager:
## Features
| feature | __match-up__ | matchit | matchparen |
| -------------------------------------- | ------------- | ------------- | ------------- |
| (a.1) jump between matching constructs | :thumbsup: | :thumbsup: | :x: |
| (a.2) jump to open, close | :thumbsup: | :question: | :x: |
| (a.3) jump inside | :thumbsup: | :question: | :x: |
| (b.1) full set of text objects | :thumbsup: | :x: | :x: |
| (c.1) auto-insert open, close, and mid | :thumbsup: | :x: | :x: |
| (c.2) auto-completion | :thumbsup: | :x: | :x: |
| (c.3) parallel transmutations :star2: | :thumbsup: | :x: | :x: |
| (c.4) split and join | :thumbsup: | :x: | :x: |
| (d.1) highlight ()[]{} | :thumbsup: | :x: | :thumbsup: |
| (d.2) highlight _all_ matches | :thumbsup: | :x: | :x: |
| (e.1) modern, modular coding style | :thumbsup: | :x: | :x: |
| (e.2) actively developed | :thumbsup: | :x: | :x: |
| | feature | __match-up__ | matchit | matchparen |
| ----- | -------------------------------- | ------------- | ------------- | ------------- |
| (a.1) | jump between matching constructs | :thumbsup: | :thumbsup: | :x: |
| (a.2) | jump to open, close | :thumbsup: | :question: | :x: |
| (a.3) | jump inside | :thumbsup: | :question: | :x: |
| (b.1) | full set of text objects | :thumbsup: | :x: | :x: |
| (c.1) | auto-insert open, close, and mid | :thumbsup: | :x: | :x: |
| (c.2) | auto-completion | :thumbsup: | :x: | :x: |
| (c.3) | parallel transmutations :star2: | :thumbsup: | :x: | :x: |
| (c.4) | split and join | :thumbsup: | :x: | :x: |
| (d.1) | highlight ()[]{} | :thumbsup: | :x: | :thumbsup: |
| (d.2) | highlight _all_ matches | :thumbsup: | :x: | :x: |
| (e.1) | modern, modular coding style | :thumbsup: | :x: | :x: |
| (e.2) | actively developed | :thumbsup: | :x: | :x: |
Legend: :thumbsup: supported. :construction: TODO, planned, or in progress.
:question: poorly implemented, broken, or uncertain. :x: not possible.
@@ -87,20 +92,20 @@ constructs are `else` and `elseif`. The `if`/`endif` pair is called an
"open-to-close" block and the `if`/`else`, `else`/`elsif`, and
`elseif`/`endif` are called "any" blocks.
- (a.1) jump between matching constructs
#### (a.1) jump between matching constructs
- `%` go forwards matching construct `[count]` times
- `{count}%` forwards `{count}` times. Requires
`let g:matchup_override_Npercent = 1`
- `g%` go backwards matching construct `[count]` times
- (a.2) jump to open and close
#### (a.2) jump to open and close
- `[%` go to `[count]` previous unmatched open construct
- `]%` go to `[count]` next unmatched close construct
- (a.3) jump inside
#### (a.3) jump inside
- `z%` go to inside nearest `[count]`th inner contained block.
- (b.1) full set of text objects
#### (b.1) full set of text objects
- `i%` the inside of an open to close block
- `1i%` the inside of an any block
- `{count}i%` If count is not 1, the inside open-to-close block
@@ -203,9 +208,11 @@ as possible when submitting issues and pull requests.
## Interoperability
- Conflicts with end-wise
- match-up is not compatible with [vimtex](https://github.com/lervag/vimtex)
and will be disabled automatically when vimtex is detected.
- the end-completion maps conflict with [vim-endwise](https://github.com/tpope/vim-endwise).
- matchit.vim should not be loaded. If it is loaded, it must be loaded
before match-up.
before match-up (in this case, matchit is disabled).
- match-up loads matchparen if it is not already loaded.
## Acknowledgments

View File

@@ -20,7 +20,7 @@ function! s:init_options()
" see *cpo-M*
call s:init_option('matchup_motion_enabled', 1)
call s:init_option('matchup_motion_cursor_end', 1) " xxx to implement
call s:init_option('matchup_motion_cursor_end', 1)
call s:init_option('matchup_motion_override_Npercent', 0)
call s:init_option('matchup_text_obj_enabled', 1)
@@ -29,6 +29,9 @@ function! s:init_options()
call s:init_option('matchup_transmute_enabled', 1)
call s:init_option('matchup_imap_enabled', 1)
call s:init_option('matchup_complete_enabled', 1)
endfunction
function! s:init_option(option, default)

View File

@@ -286,9 +286,11 @@ function! s:get_delim(opts) " {{{1
let a:opts.cursorpos = l:cursorpos
" TODO XXX does this make any sense?
if a:opts.direction !=# 'prev'
let l:re .= '\%>'.(l:cursorpos).'c'
" TODO XXX does this even make any sense?
"
" for current, we want to find matches that end after the cursor
if a:opts.direction ==# 'current'
let l:re .= '\%>'.(l:cursorpos).'c'
endif
" let l:re .= '\%>'.(col('.')).'c'
@@ -311,19 +313,25 @@ function! s:get_delim(opts) " {{{1
\ : searchpos(l:re, 'bcnW', line('.'))
if l:lnum == 0 | break | endif
" echo l:re l:lnum l:cnum | sleep 1
" echo l:lnum l:cnum line('.')-s:stopline a:opts.direction | sleep 1
"echo l:lnum l:re a:opts.direction ==# 'prev' | sleep 1
" echo l:lnum l:cnum | sleep 1
" if invalid match, move cursor and keep looking
" TODO this function should never be called
" in 'current' mode, but we should be more explicit
" if matchup#util#in_comment(l:lnum, l:cnum)
" \ || matchup#util#in_string(l:lnum, l:cnum)
" XXX get rid of this..
call matchup#pos#set_cursor([l:lnum, l:cnum])
" note: this function should never be called
" in 'current' mode, but be explicit
if a:opts.direction !=# 'current'
\ && matchup#delim#skip(l:lnum, l:cnum)
" echo 'rejct'
" if invalid match, move cursor and keep looking
call matchup#pos#set_cursor(a:opts.direction ==# 'next'
\ ? matchup#pos#next(l:lnum, l:cnum)
\ : matchup#pos#prev(l:lnum, l:cnum))
@@ -728,7 +736,7 @@ function! s:get_matching_delims(down) dict " {{{1
let l:open = self.augment.str
endif
" echo 'op' l:open 'cl' l:close 're' l:re '|' self.groups 'a' self.augment
echo '% op' l:open 'cl' l:close 're' l:re '|' self.groups 'a' self.augment
" turn \(\) into \%(\) for searchpairpos
let l:open = s:remove_capture_groups(l:open)
@@ -970,7 +978,7 @@ function! s:init_delim_lists() " {{{1
" so we just disallow it.. (ref-2)
" get the groups like \(foo\) in the 'open' pattern
let l:cg = s:get_delim_capture_groups(l:words[0])
let l:cg = matchup#delim#get_capture_groups(l:words[0])
" if any of these contain \d raise a warning
" and substitute it out (ref-2)
@@ -1045,13 +1053,14 @@ function! s:init_delim_lists() " {{{1
" turn things like \1 into \(...\)
" replacement is guaranteed to exist and not contain \d
let l:words_backref[l:i] = substitute(l:words_backref[l:i],
\ s:notslash.'\\'.l:bref,
\ g:matchup#re#backref,
\ '\='''.l:cg[l:bref].str."'", '') " not global!!
" \ s:notslash.'\\'.l:bref,
" echo '#'.l:i '%' '\'.l:bref l:words_backref[l:i] l:cg[l:bref]
let l:prev_max = max(keys(l:cg2))
let l:cg2 = s:get_delim_capture_groups(l:words_backref[l:i])
let l:cg2 = matchup#delim#get_capture_groups(l:words_backref[l:i])
" echo l:i '%' l:bref l:words_backref[l:i] l:cg2
@@ -1366,8 +1375,11 @@ function! s:init_delim_regexes_generator(list_name) " {{{1
endfunction
" }}}1
function! s:get_delim_capture_groups(str) " {{{1
let l:pat = s:notslash.'\zs\(\\(\|\\)\)'
function! matchup#delim#get_capture_groups(str, ...) " {{{1
let l:allow_percent = a:0 ? a:1 : 0
let l:pat = g:matchup#re#not_bslash . '\zs\('
\ . (l:allow_percent ? '\\%(\|' : '') . '\\(\|\\)\)'
let l:start = 0
@@ -1379,7 +1391,7 @@ function! s:get_delim_capture_groups(str) " {{{1
if l:match[1] < 0 | break | endif
let l:start = l:match[2]
if l:match[0] ==# '\('
if l:match[0] ==# '\(' || l:match[0] ==# '\%('
let l:counter += 1
call add(l:stack, l:counter)
let l:brefs[l:counter] = {
@@ -1412,12 +1424,12 @@ function! s:init_delim_skip() "{{{1
" S:foo becomes (current syntax item) !~ foo
" r:foo becomes (line before cursor) =~ foo
" R:foo becomes (line before cursor) !~ foo
let l:cursyn = "synIDattr(synID(line('.'),col('.'),1),'name')"
let l:preline = "strpart(getline('.'),0,col('.'))"
let l:cursyn = "synIDattr(synID(s:effline('.'),s:effcol('.'),1),'name')"
let l:preline = "strpart(s:geteffline('.'),0,s:effcol('.'))"
if l:skip =~# '^[sSrR]:'
let l:syn = strpart(l:skip, 2)
let l:skip = {
\ 's': l:cursyn."=~?'".l:syn."'",
\ 'S': l:cursyn."!~?'".l:syn."'",
@@ -1426,8 +1438,13 @@ function! s:init_delim_skip() "{{{1
\}[l:skip[0]]
endif
let l:skip = substitute(l:skip, '\<col\ze(',
\ 's:effcol', 'g')
for [l:pat, l:str] in [
\ [ '\<col\ze(', 's:effcol' ],
\ [ '\<line\ze(', 's:effline' ],
\ [ '\<getline\ze(', 's:geteffline' ],
\]
let l:skip = substitute(l:skip, l:pat, l:str, 'g')
endfor
return l:skip
endfunction
@@ -1445,13 +1462,27 @@ function! matchup#delim#skip(...) " {{{1
\ || matchup#util#in_string(l:lnum, l:cnum)
endif
" call s:set_effective_curpos(l:lnum, l:cnum)
" call matchup#pos#set_cursor([l:lnum, l:cnum])
execute 'return (' b:matchup_delim_skip ')'
endfunction
function! s:set_effective_curpos(lnum, cnum)
endfunction
function! s:effcol(expr)
return col(a:expr)
endfunction
function! s:effline(expr)
return line(a:expr)
endfunction
function! s:geteffline(expr)
return getline(a:expr)
endfunction
" }}}1
function! s:remove_capture_groups(re) "{{{1
@@ -1482,6 +1513,9 @@ let s:not_bslash = '\v%(\\@<!%(\\\\)*)@<=\m'
" xxx need to use this through code
let s:backref = s:notslash.'\\'.'\(\d\)'
" whether we're behaving like in insert mode
let s:insertmode = 0
let s:sidedict = {
\ 'open' : ['open'],
\ 'mid' : ['mid'],
@@ -1505,3 +1539,4 @@ let s:types = {
let &cpo = s:save_cpo
" vim: fdm=marker sw=2

View File

@@ -110,7 +110,7 @@ function! s:matchparen.highlight() abort dict " {{{1
if empty(l:corrlist) | return | endif
" echo l:corrlist
echo map(copy(l:corrlist), 'v:val.rematch')
"echo map(copy(l:corrlist), 'v:val.rematch')
" echo map(copy(l:corrlist), 'v:val.lnum.",".v:val.cnum')
" echo l:corrlist[0].class l:corrlist[1].class
" \ l:corrlist[0].side l:corrlist[1].side

View File

@@ -17,10 +17,11 @@ function! matchup#motion#init_module() " {{{1
" <silent> XXX
" todo make % vi compatible wrt yank (:h quote_number)
" the basic motions % and g%
nnoremap <silent> <plug>(matchup-%)
\ :<c-u>call matchup#motion#find_matching_pair(0, 1)<cr>
\ :<c-u>call matchup#motion#find_matching_pair(0, 1)<cr>
nnoremap <silent> <plug>(matchup-g%)
\ :<c-u>call matchup#motion#find_matching_pair(0, 0)<cr>
\ :<c-u>call matchup#motion#find_matching_pair(0, 0)<cr>
xnoremap <sid>(matchup-%)
\ :<c-u>call matchup#motion#find_matching_pair(1, 1)<cr>

13
autoload/matchup/re.vim Normal file
View File

@@ -0,0 +1,13 @@
" vim match-up - matchit replacement and more
"
" Maintainer: Andy Massimino
" Email: a@normed.space
"
let g:matchup#re#not_bslash = '\v%(\\@<!%(\\\\)*)@<=\m'
" 1 \1 \\1 \\\1 \\\\1 \\\\\1
let g:matchup#re#backref = g:matchup#re#not_bslash.'\\'.'\(\d\)'
" vim: fdm=marker sw=2