More flexible m

In Vim I was using this plugin, as it adds lots of matching keywords to already smart % (Kakoune equivalent m) vim feature. In stock Vim there’s is an embedded plugin matchit, that does pretty same thing as current implementation of m, but in addition to various parens, it can match keywords, like pressing % on #ifdef will bring you to matching #else and later to #endif in C filetype. Matchup extends this idea with more languages, and some other things, as highlighting matching pairs. It brings more control to how we navigate in code, since not all languages have parens that we can jump (and (some (languages (have (too (many)))))).

I kinda miss this feature, It helped me a lot in ifndef mess, and some shellscripting where if you have case your paren mathcing is dead.

Well – now you ruined m for me and I want to do this!

2 Likes

cool, I’d love to have such plugin in my configuration!

Wouldn’t it be a lot of work to write such a plugin. There are a lot languages with very different “brackets” from XML’s <tag> to </tag> to LATEX’s \begin{} to \end{} to everything in between. Someone who knows how to code in Kak should write a plugin and everybody can pull request their favorite language’s “brackets”.

this should be extendable, ofcourse

I think this should be implementable using the existing text objects. Basically the logic we need is:

  • Find first instance of possible starting “words”, which is just a regex search #ifdef|#endif|#else|begin|end|...
  • Find matching opener/closer. This can be implemented by mapping the selected word to its matching word, and the direction to search for. Then its just a matter of using [ or ] depending on that direction with a custom object description (for example, if I found “begin”, ]c\bbegin\b,\bend\b<ret>, if I found “#endif[c#if(def)|#else,#endif

Maybe you have something in mind that wasn’t mentioned by you, but wouldn’t this method fail on this example?

#ifndef TIMEOUT /* cursor is on this ifdef macro */
#ifdef RTL
#define TIMEOUT 0x1000
#else
#define TIMEOUT 0x10000
#endif
#endif

With simple regexp search I see that we will find #else even if first #ifndef doesn’t have any #else. When we jump to the matching paren, we don’t end up on first closing one, since we’re keeping track of how many nested opened parens is inside. I think that the same logic should be applied here.

@mawww described using the ]c and [c commands, which accept a start and an end regex, but properly handle nesting.

1 Like

omg, I didn’t knew that it handles nesting. Thats super cool

Oh my god, this is life changer!! @mawww once again you’ve and all the Kakoune devs blew my mind! I’ve did a ton of work to create this kind of functionality inside Vim for my snippet plugin, to make possible nested placeholdes, and it was so damn hard to create with pure VimScript, so I’ve actually dropped the whole idea (there were more problems, but that was one of them), and it’s works inside Kakoune like no problem. Genius!

one more thing that I somewhat dislike about m key is that it doesn’t work completely if there’s no pair before the cursor. To be exact, here’s an example:

[fn vaiv()] -> u32 {
     5
 }

I’ve selected from beginning of the line to the closing paren with M, and now I want to continue it, I move forward with L extending selection and hit M again, but getting the error complaining that there’s bo matching < found.

I think this relates to this GH issue by @alexherbo2 https://github.com/mawww/kakoune/issues/1149