Add support for custom match functions#54
Conversation
If b:match_function is defined, matchit will first call this function to perform matching. This is useful for languages with an indentation-based block structure (such as Python) or other complex matching requirements that cannot be expressed with regular expression patterns. If b:match_function doesn't return a result, we fall through to regular matching (b:match_words, matchpairs, etc.). Errors thrown by the b:match_function are fatal and won't continue. The exception is printed when b:match_debug is enabled.
|
I also have a nice Python matchit function that integrates well with this (more complete than the example in the docs). |
Due to Python's indentation-based block structure, it's not possible to implement Python language support directly in matchit.vim. To address this (and similar challenges with other languages), I proposed custom function support in chrisbra/matchit#54. This change implements a local b:match_function function for Python. It's possible this might make a good vim runtime contribution in time, but I'm going to let it bake here while the above matchit.vim pull request is considered.
Unfortunately, in its current form, matchit is not able to support Python's `if` syntax. It expects there to be a reliable "end" pattern, whereas Python allows either `elif` and `else` to be the final keyword (which zero or more `elif`s in between). Given that, remove this partial support until its possible to implement a more complete solution.
|
@chrisbra curious what you think about this extension mechanism. |
|
I think this makes sense. Let me merge it. Thanks! |
dkearns
left a comment
There was a problem hiding this comment.
I'm not sure this offers much in functionality beyond using `b:match_words = 'Foo()' but the interface is nicer so it seems like a good idea. Maybe something should be added to the docs where the old expression based example is described.
Because One downside to Here's my more complete Python matchit implementation for reference: jparise/dotfiles@3ef0e10 |
| If the function throws an error, matchit gives up and doesn't continue. | ||
| Enable |b:match_debug| to see error messages from custom match functions. | ||
|
|
||
| Python example (simplified): > |
There was a problem hiding this comment.
Sorry if this is somehow duplicated but I don't think it was sent with my previous comment as I expected.
This example doesn't work for g%. It needs separate patterns when working in that direction.
Perhaps it could be simplified to just work i the forward direction with a note, "backwards jumping is left as an exercise for the reader". Otherwise it should probably be improved so it can at least be dropped in as a working example.
There was a problem hiding this comment.
Thanks, that's a good idea. I've done that in #55.
There was a problem hiding this comment.
It's a good documentation improvement, but it doesn't change any functionality. Do you agree @dkearns?
There was a problem hiding this comment.
Yes, I think it would be a good idea to include it.
There was a problem hiding this comment.
alright, will merge it then in both projects
|
|
||
| let flags = a:forward ? 'nW' : 'nbW' | ||
| let [lnum, col] = searchpos('^\s*\%(' . pattern . '\)\>', flags, 0, 0, | ||
| \ 'indent(".") != ' . indent('.')) |
There was a problem hiding this comment.
This skip pattern needs to test the indent at the jump point with that at the destination.
There was a problem hiding this comment.
Scrap that, sorry, I misread it .
You're probably aware of: tpict/vim-ftplugin-python#15 |
Yes, I looked at that previously before exploring this new approach. It also identifies the limitations of |
|
Sorry for being a bit terse, it's been a long day. I was just suggesting you might wish to submit your solution to close out that PR, if you were unaware of it. Thanks for improving matchit! |
If b:match_function is defined, matchit will first call this function to perform matching. This is useful for languages with an indentation-based block structure (such as Python) or other complex matching requirements that cannot be expressed with regular expression patterns.
If b:match_function doesn't return a result, we fall through to regular matching (b:match_words, matchpairs, etc.).
Errors thrown by the b:match_function are fatal and won't continue. The exception is printed when b:match_debug is enabled.