diff --git a/README.md b/README.md index 19f73be..868f780 100644 --- a/README.md +++ b/README.md @@ -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 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 diff --git a/autoload/matchup.vim b/autoload/matchup.vim index fb49949..fc6b985 100644 --- a/autoload/matchup.vim +++ b/autoload/matchup.vim @@ -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) diff --git a/autoload/matchup/delim.vim b/autoload/matchup/delim.vim index 3649b9c..a493b25 100644 --- a/autoload/matchup/delim.vim +++ b/autoload/matchup/delim.vim @@ -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, '\ XXX " todo make % vi compatible wrt yank (:h quote_number) + " the basic motions % and g% nnoremap (matchup-%) - \ :call matchup#motion#find_matching_pair(0, 1) + \ :call matchup#motion#find_matching_pair(0, 1) nnoremap (matchup-g%) - \ :call matchup#motion#find_matching_pair(0, 0) + \ :call matchup#motion#find_matching_pair(0, 0) xnoremap (matchup-%) \ :call matchup#motion#find_matching_pair(1, 1) diff --git a/autoload/matchup/re.vim b/autoload/matchup/re.vim new file mode 100644 index 0000000..5eeec0e --- /dev/null +++ b/autoload/matchup/re.vim @@ -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%(\\@