mawww / kakoune

mawww's experiment for a better code editor
http://kakoune.org
The Unlicense
9.89k stars 712 forks source link

[BUG] unterminated string '%{...}' #4510

Closed sucrecacao closed 2 years ago

sucrecacao commented 2 years ago

Version of Kakoune

Kakoune v2020.09.01-806-ga70dbda5

Reproducer

In you autoload folder, paste the following code in a file called remember_filetype.kak

# remember the filetype of undefined file

define-command remeber-filetype %{
    edit "%val{config}/autoload/remember_filetype.kak"
    execute-keys gj
    execute-keys <a-o>j
    execute-keys <a-o>j
    # execute-keys 'idefine-command {{name}}  %{<esc>'    ( this is  line 8 )
    execute-keys 'ihook global BufCreate .*FILE_REGEX$ %{<esc>'
    execute-keys 'o set-option buffer filetype FILE_TYPE<esc>'
    execute-keys 'o}<esc>'
    execute-keys 'kk<a-h>'
    execute-keys '/FILE_<ret>'
}

######################
# ALL SAVED FILETYPE #
######################

hook global BufCreate .*lfrc$ %{
    set-option buffer filetype sh
}

( it's a macro to easily create filetype hook )

Save the file and open a new kak instance

Outcome

get the following error in my debug buffer:

/home/joe/.config/kak/autoload/remember_filetype.kak:parse error: 3:35: unterminated string '%{...}'
Autoload: could not load /home/joe/.config/kak/autoload/remember_filetype.kak

Expectations

kakoune loads remember_filetype.kak normally

Additional information

If I remove the comment on line 8 I don't get the error, so I guess the error comes from the extra { in line 8

mawww commented 2 years ago

This is the expected behaviour, see :doc command-parsing balanced-strings

sucrecacao commented 2 years ago

@mawww

Sorry for the previous verbose example, but to be sure do you mean that:

define-command test %{
    # {
    echo foo
}

raising an exception ( and not to being able to run :test<ret> ) is normal behavior?

occivink commented 2 years ago

This is expected yes. Balanced strings count occurrences of the delimiters, and the string ends on the first closing delimiter that does not have a matching opening.

If a balanced string must contain unbalanced occurrences of the delimiters, you have two options:

The advantage of doing this is that it is easy to nest such strings without resorting to multi-level escaping (sometimes known as backslash hell). Such nesting is very common when writing kakoune scripts, for example see here. Multiple %{..} strings are nested, and it just works thanks to the counting of braces. If '..' strings were used instead, the inner set-register call would have to use 4 consecutive '.

Balanced strings are not suited when their content is arbitrary input, normal '..' strings should be used in that case (and their content escaped if it may contain ').

alexherbo2 commented 2 years ago

To add up to @occivink’s explanation, Kakoune block strings should not be confused with blocks in programming languages: they are simply strings banged together, until they are being evaluated.

So for example, when you execute:

evaluate-commands %(echo %(foo))

the string passed to evaluate-commands is literally:

echo %(foo)

until the command evaluates it.