Binding complex command

So I roughly understands how kakoune’s parsing works and I can get buy raw dogging a command in the kakoune’s command line. Right now, I’m trying to bind this:

:try %{exec "%%s(/\*.*\*/\n){11}<ret>”}

this selects C-multiline comment that is 11 lines long.
but when putting this into kakrc

map global user b ':try %{exec "%%s(/\*.*\*/\n){11}<lt>ret<gt>”}<ret>'

it says parsing error 1:7 unterminated string %{…}
but this works

define-command 11-comment %{
    try %{exec "%%s(/\*.*\*/\n){11}<ret>”}
}

can someone please explain why the mapping doesn’t work
Thank you!

If I launch Kakoune 2025.06.03-20-gba41928a with:

kak -n -e 'map global user b %{:try %{exec "%%s(/\*.*\*/\n){11}<lt>ret<gt>”}<ret>}'

…I do not get any errors, either at startup, or when executing the mapping.

Are you sure it’s this command that is causing the error in your kakrc?

P.S. you might want to change your regex to (/\*[^\n]*\*/\n){11} or Kakoune will match all consecutive winged comments as a single match, so there won’t be 11 of them.

My bad. I didn’t write the edited part.
So this throws an error when executing the mapping

map global user b %{:try %{exec "%%s(/\*.*\*/\n){11}<ret>”}<ret>}’

which I now know that I didn’t escape the ‘<‘ ‘>’ inside the exec block
but with that fixed it doesn’t do any thing

also thanks for the regex tip, my use case is a bit weird because every multiline comment I want to match is a single liner now I’ve changed the regex to

\A(^/\*.*\*/\n){11}?

so it matches 11 lines of this at the start of a file

/* blah blah blah…. */\n

and it does what I want when I use it in select
but this :

map global user b %{:try %{exec "%%s\A(^/\*.*\*/\n){11}?<lt>ret<gt>”}<ret>}’

sadly doesn’t do anything right now.

Ah, right. The right-hand-side of a mapping is already a list of keys to press, so sticking a execute-keys inside a mapping requires double-escaping key-names.

There are various reasons why your mapping might be broken, but the try statement is hiding the error message. What happens if you take the try out of the mapping?

1 Like

As @Screwtapello mentioned, the RHS of a mapping expects a list of keys to press, which complicates things when you’re trying to do a “nested exec”. Let’s refer to the second one as the “inner exec”. When you say the name of a key (like a key name surrounded by <>), you’re telling the outer exec to literally press that key. So this can complicate things like needing to turn <ret> into <lt>ret<gt>, because you don’t want to literally press enter before you’re done typing.

This complication can cause a lot of issues or behavior you don’t expect. That’s the reason why in your OP, the command works, but the mapping doesn’t. I highly, highly recommend always defining a command for anything complex like this. It can help avoid a lot of headaches!

1 Like

Yes, it is indeed much easier to just bind to a command. I went with this. For anyone wandering around, just make a new command it’s far more simpler.

my bad again, it works now, just a typo :slight_smile:

1 Like