Shell quoting argument bug?

When I try to add quotes to an argument, the result seems mangled. Short example:

define-command -override -params 1 \
    quote-test %{ nop %sh{
        qtest="'$1'"
        printf %s\\n "evaluate-commands -client ${kak_client} echo -debug 'quote test x${qtest}x'" | kak -p ${kak_session}
    }}

:quote-test thisisatest
quote test x thisisatest'x'
:quote-test "another test with spaces"
quote test x another test with spaces'x'

Is this a bug or am I doing something wrong or maybe it’s something in my environment?

1 Like

This is equivalent to

:echo 'quote test x'thisisatest'x'

Which is calling echo with two strings. The first is
'quote test x'
which is single quote delimited and therefore echoes without quotes. The string is only quote delimited if it starts with a quote. After that is a second string thisisatest'x', since it doesn’t start with a quote they’re just interpreted as characters. If you want to echo x'thisisatest'x then you can either remove the quotes at the start and end or use two single quotes which is the escape sequence for quotes.

2 Likes

Hi Maxxus, I also find “‘quoting’” an obstacle to overcome in kakoune.

Take the below data structure when you break it apart you’ll find that the entire structure falls over on just omitting a \n character. It’s fragile as well as being complex.

A community member Guest0x0 github repository handles a wide range of “‘quoting’” in alternate ways. This helped me gain a deeper understanding on the topic and some new ideas on tackling future problems.

# BEFORE
# ref: https://github.com/mawww/config/blob/master/kakrc#L136
printf %s\\n "evaluate-commands -try-client '$kak_opt_toolsclient' %{
                edit! -fifo ${output} *fifo*
                hook -always -once buffer BufCloseFifo .* %{ nop %sh{ rm -r $(dirname ${output}) } }
            }"

# AFTER
# ref: https://github.com/Guest0x0/coqoune/blob/master/kak_util.sh#L47
# see the '\n' newline character here:
printf "evaluate-commands -try-client '$kak_opt_toolsclient' %%{"
printf " edit! -fifo ${output} '*fifo*'\n"
printf " hook -once -always buffer BufCloseFifo .* %%{"
printf " nop %%sh{"
printf " rm -r $(dirname ${output})"
printf " } } }\n"

Hope this helps, and welcome to the community. Bye :wave:

There’s a complete quoter for kakoune arguments written in shell here: Add a kakquote function to the prelude of shell blocks · Issue #3340 · mawww/kakoune · GitHub

@Maxxus: did you know that in this case you could just use eval %sh{..} instead of nop %sh{.. | kak -p $kak_session}? Then you don’t need to specify the client again. It would look like this:

define-command -override -params 1 \
    quote-test %{ eval %sh{
        qtest="'$1'"
        printf %s\\n "echo -debug 'quote test x${qtest}x'"
    }}

I see the mistake now, thank you. It’s when the string is passed back to kakoune for echo. It falls back to kakoune quoting rules. In kakoune echo, is a space automatically inserted between two strings that are butted together?

I’m actually modifying and existing kak script, so I don’t want to change the structure if I can help it. But I will keep in mind the eval vs nop difference in the future.

Kakoune’s quoting uses different rules than the shell. The biggest difference is that Kakoune escapes quote characters by doubling, rather than with backslashes, but also Kakoune only cares about quotes at the beginning of a space-delimited word, or after the end of another quoted string, not in the middle of a word.

Input Shell Kakoune Comment
“foo” foo foo Ordinary quoting
"foo"bar foobar foo bar The end of a quote is the end of the word
foo"bar" foobar foo"bar" Quotes only matter at the start of a word
“foo”“bar” foobar foo"bar Quote escaping
1 Like