Making sense of debug messages

Is anyone else a little confused by Kakoune’s debug messages?
The seem to model after a stack trace, which is good, but the numbers don’t make any sense.

For example: add asdf at the end of kakrc (line 156).
Debug:

/home/user/.config/kak/kakrc:no such command: 'asdf'
/usr/share/kak/kakrc:5:853: 'evaluate-commands' 103:18933: 'source' no such command: 'asdf'
error while parsing kakrc:
    1:1: 'source' 5:853: 'evaluate-commands' 103:18933: 'source' no such command: 'asdf'

So, I’m wondering if someone could explain what the numbers mean, and why 156 isn’t among them.

So far as I understand it, the numbers are “line” and “column”, as per convention. However, Kakoune’s scripting language is based on a somewhat unusual “nested string” syntax: the %{} thing you see all through Kakoune’s scripts isn’t blocks like in C or C++, it’s just another way of writing strings like "" or ''. Commands that take a block of commands (like :hook or :try, etc.) really just take a string, and then Kakoune interprets it later.

By the time Kakoune gets around to interpreting the string, the original context is lost - or it might never have even existed (consider the idiom of evaluate-commands %sh{} where a shell script dynamically generates commands). So when it comes time to report a line and column, Kakoune reports the line and column within the string it’s executing, and when interpreting nested strings, you get the line and column at each level of nesting. For example, put the following into a file named explode.kak:

eval %{
    eval %{
        eval %{
            asdf
        }
    }
}

When I :source explode.kak, I get the following error:

1:1: 'source' 1:1: 'eval' 2:6: 'eval' 2:10: 'eval' no such command: 'asdf'

The error occurs at:

  • line 1, column 1 of the string I typed at the : prompt, in the source command
  • line 1, column 1 of the string interpreted by the source command, in theeval` command
  • line 2, column 6 of the string interpreted by the eval command, in the eval command
  • line 2, column 10 of the string interpreted by the eval command, in the eval command

…and the actual error is “no such command: ‘asdf’”.

Now that I actually try it, though, it seems a bit weird to me. As I understand it, the second eval is at line two, column four of the string, so why does Kakoune report column six?

OK, I spent some time playing around, and I think I understand what the numbers mean now:

The first coordinate is the the number of lines from the beginning of the block to the command that had the error, minus any lines that occurred inside blocks. So:

eval %{
    asdf
}

…reports the error on line 1, while:

nop
eval %{
    asdf
}

…reports the error on line 2, but:

nop %{
}
eval %{
    asdf
}

…also reports the error on line 2, because the extra line-break occurs within %{}.

The second column is the number of bytes from the beginning of the block to the command that had the error, plus 1. So:

eval %{
    asdf
}

…reports the error at byte 1, while:

nop a
eval %{
    asdf
}

…reports the error at byte 7 (nop a\n is six bytes), but:

nop 🐄
eval %{
    asdf
}

…reports the error at byte 10, because :cow2: is four UTF-8 bytes.

I filed #2895.

1 Like