Context and mappings

Hello,

I’m struggling a bit on making contextual (depending on filetype) mapping works.

Repro. code:

# foo.kak
hook -group ft-foo global WinSetOption filetype=foo %{

map -docstring "Print the call stack."     window callstack b           ":foo-stack "
map -docstring "Go back to sup-mode."      window callstack <backspace> ":enter-user-mode debugs <ret>"

map -docstring "Set a foo debugger variable." window debugs S ":foo-set "
map -docstring "Enter callstack sub-mode." window debugs c ":enter-user-mode callstack "

map window normal D ":enter-user-mode debugs"
}
# bar.kak
hook -group ft-bar global WinSetOption filetype=bar %{

map window normal <F4> ":repl-send-text next <ret>"

map -docstring "Print the call stack." window callstack p ":debug-print "

map -docstring "Set a bar debugger variable." window debugs S ":bar-set "
map -docstring "Enter callstack sub-mode." window debugs c ":enter-user-mode callstack "

map window normal D ":enter-user-mode debugs"
}
# kakrc
source "%val{config}/foo.kak"
source "%val{config}/bar.kak"

declare-user-mode debugs
declare-user-mode callstack

If I open either a .foo or a .bar file, mappings work as intended, and I can even back and forth with kakrc, and retrieve correct mappings.
However if I open, say the .foo then switch to the .bar, mappings wont work in the second file.

I don’t quite understand why Kakoune does not overwrite mapping despite giving it orders to.

NOTE: I tested with hook -group ft-bar global WinDisplay .*\.bar %{ as the opening condition, does not fix it…
I had a look at InsertChar for a specific filetype - #2 by alexherbo2 but unmap hook does not fix it either.

Any help would be welcome, thanks.

A small and reproducible example would be useful here but one thing that strikes me is that most of your mappings are missing <ret>, for example:

map window normal D ":enter-user-mode debugs"

try:

map window normal D ":enter-user-mode debugs<ret>"

Also declare your user modes before sourcing files that depend on them. Here it probably will work since you refer to them in the hook, but still:

declare-user-mode debugs
declare-user-mode callstack

source "%val{config}/foo.kak"
source "%val{config}/bar.kak"
1 Like

Well sorry for the half-way example, I could have simplified it and indeed terminate the mappings with <ret>.
Nevertheless you are right that on this provided example, putting the declare-user-mode before fix it. Thank you very much !

I said half-way because this comes from a real-world example where it is still not working, I will further investigate, especially import orders with all other external files and plugins.

It may not be strictly relevant to your original question, but just in case you were unaware, source %val{config}/foo.kak is pretty unusual. The usual approach is to put external .kak files into the %val{config}/autoload/ directory — Kakoune loads every .kak in that directory (recursively) before it loads your kakrc.

If you have .kak files that depend on each other (for example, in the way that both your examples depend on user modes being defined), you can use the provide-module and require-module commands to express those dependencies. For example:

# modes.kak

# Defines a module that will be evaluated when required
provide-module debug-user-modes %{
    declare-user-mode debugs
    declare-user-mode callstack
}
# foo.kak
hook global winSetOption filetype=foo %{
    # Ensure this module is evaluated before we go further
    require-module debug-user-modes
    map window callstack b ":foo-stack "
    # etc.
}

Assuming these files are in the autoload directory, Kakoune will read them both at startup, registering the hook and the module. When a .foo file is opened, the hook ensures the module is loaded before trying to use the user-modes it declares.

1 Like

Thank you for the message.

I was indeed aware of autoload but went directly for a simplified repro example.

As I said in my previous message I need to investigate my real-world case and how Kakoune operate more. Some things are not quite clear in my mind.
For example, testing with autoload my provided example (commenting out the source … and putting foo.kak and bar.kak in autoload) works.
But as you said and I was thinking too, autoload seems to be loading before any command from kakrc, while as @danr suggested and I verified, putting declare … in kakrc before source… fix my provided example.
This is a bit at odd as I should conclude that declare… should be parsed by Kakoune before any mapping using it (and thus autoload action), shouldn’t I ?

I will probably try to play with wrapping these in a module too, thanks for the suggestion.

I usually reach for the debug option when trying to figure out what kak does and in which order. You can set it from the command prompt just like a normal option but in this case since you’re trying to figure out what happens at startup you can start kak as

kak -E 'set global debug commands|shell'
1 Like