joshgoebel / keyszer

a smart, flexible keymapper for X11 (a fork/reboot of xkeysnail )
Other
69 stars 15 forks source link

Merge keymaps' nested keys #142

Open Fom123 opened 1 year ago

Fom123 commented 1 year ago

Is your request related to a specific problem you're having? I would like nested keys to get merged, as it happens with usual keys in conditional keymaps.

For example

keymap("Brave", {
    C("C-j"): C("C-f6"),
    C("C-x"): {
        C("k"): C("C-w")
    }
}, when=wm_class_match(r"Brave-browser"))

keymap("Emacs-like keys", {
    C("C-b"): with_mark(C("left")),
    C("C-x"): {
        # C-x h (select all)
        C("h"): [C("C-home"), C("C-a"), set_mark(True)],
    }
}, when=lambda ctx: ctx.wm_class != "Emacs")

When we run this, we will get the following

Application Available Bindings
Brave C-b, C-j, C-x k
Anything else C-b, C-x h

The solution you'd prefer or feature you'd like to see added...

I would like to see the following

Application Available Bindings
Brave C-b, C-j, C-x k, C-x h
Anything else C-b, C-x h

Any alternative solutions you considered...

  1. Move combo's binding to separate variable

    emacs_bindings = {
     C("h"): [C("C-home"), C("C-a"), set_mark(True)],
    }
  2. Unpack it when it's needed.

    keymap("Brave", {
    C("C-j"): C("C-f6"),
    C("C-x"): dict({
        C("k"): C("C-w")
    }, **emacs_bindings)
    }, when=wm_class_match(r"Brave-browser"))

    But it's not that convinient.

joshgoebel commented 1 year ago

as it happens with usual keys in conditional keymaps.

Except it doesn't. The top-level keymaps are not merged... they are merely available at the top-level and then activated based on the conditional functions/criteria... but once a nested keymap is selected that is now the active keymap - and it handles keystrokes exclusively.

I do see how you might want your suggested behavior, in this example, but it doesn't seem clear to me at all that this would always (or even often) be desiredable behavior.

But it's not that convenient.

It's not that inconvenient. And it has the benefit of being explicit and unsurprising, which is good.


The config is also just Python. So you could write your own helper function that you called at the end of the configuration that did this merging for you (looping over all the keymaps, merging any nested maps, etc) - if that was truly the desired behavior.

In general I'm very slow to add new features when the feature could easily be accomplished with only Python and the existing API (or small hacks). If possible, someone should first write the feature as a plugin/helper and then let it prove it's general usefulness... perhaps then it could be added - and if not it can live on in the wiki as an extension.

In this case I don't even think you need any big hacks.