I'm trying to implement a custom regexp string to be used by matchit.vim for identifying matching keywords that can be jumped between with %
.
I found a utility from FileExchange (in the ftplugin folder when downloaded and unzipped), but it is not perfect in that
It detects
for
,if
, etc. in comment lines (the%
character in Matlab)It incorrectly tries to match
end
with something for certain formats of array indexing (e.g.MyArray(1,end,2)
usesend
to return a scalar slice, but since it is separated by commas the original tried to match it with something)It only matches starting/ending pairs (e.g. no
elseif
orelse
)
I've tried making a modified version that fixes these, but I'm getting errors. One is E51: Too many \(
, which means too many groups or something, right? Not sure how that's possible. Also when I include an escaped comma \,
in the \(\)\@!
and \(\)\@<!
blocks the error changes which suggests to me the string is not getting parsed properly between un-escaped commas (disparate keyword groups) and colons (keywords in each keyword group). But really not sure.
Anyway, was hoping for some ideas on what could be wrong here. The original and modified regexps are below. Thanks!
Edit: Here is the matchit documentation.
It appears that comma separation works (e.g. a simple if:end,for:end
) but when I try more than one line I get the errors:
E872: (NFA regexp) Too many '(' E51: Too many \(
This is in addition to the error when I include \,
in the []
.
Can either be circumvented somehow? It appears my problem has to do with limitations in terms of numbers of regular expressions, and also for some reason matchit tried to parse on the escaped comma.
Original b:match_words
let s:conditionalEnd = '\([-+{\*\:(\/]\s*\)\@<!\<end\>\(\s*[-+}\:\*\/)]\)\@!'
let b:match_words = '\<classdef\>\|\<methods\>\|\<events\>\|\<properties\>\|\<if\>\|\<while\>\|\<for\>\|\<switch\>\|\<try\>\|\<function\>:' . s:conditionalEnd
Modified b:match_words
let s:conditionalEnd = '\(%\+.*\|[\,-+{\*\:(\/]\s*\)'.'\@<!'.'\<end\>'.'\(\s*[\,-+}\:\*\/)]\)'.'\@!'
let s:noComment = '\(%\+.*\)\@<!'
let b:match_words = s:noComment.'\<if\>' .':'. s:noComment.'\<elseif\>' .':'. s:noComment.'\<else\>' .':'. s:conditionalEnd .','.
\ s:noComment.'\<switch\>' .':'. s:noComment.'\<case\>' .':'. s:noComment.'\<otherwise\>' .':'. s:conditionalEnd .','.
\ s:noComment.'\<classdef\>\|\<properties\>\|\<methods\>\|\<events\>\|\<enumeration\>' .':'. s:conditionalEnd .','.
\ s:noComment.'\<for\>\|\<parfor\>\|\<while\>' .':'. s:noComment.'\<continue\>' .':'. s:noComment.'\<break\>' .':'. s:conditionalEnd .','.
\ s:noComment.'\<function\>' .':'. s:noComment.'\<return\>' .':'. s:conditionalEnd
b:match_words
first. Try it withif...endif
first and get that right before worrying about everything else. You can also try making(:)
or(:\%(else\|elseif\):)
the first pair to make matchit prioritize that.E51: Too many \(
with the\,
in the[]
group, andE16: Invalid range
without. Turning off comment detection doesn't do anything either.