-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Higher powered modality with callbacks #102
Comments
For example I'm not sure input should be silently discarded... perhaps the default is for a miss is to send the input straight to output instead - unless a user decides to suppress it. This isn't backwards compatible but makes more sense to me. |
Are there other desirable behaviors one might want here that couldn't be modeled on the two hit/miss callbacks? |
You could possibly then have self-focusing modals: keymap("Grave"), {
C("Alt-Grave"): [UC(0x0060), C("Shift-Left"), go_modal],
C("A"): UC(0x00E0), # à Latin Small a with Grave
C("E"): UC(0x00E8), # è Latin Small e with Grave
C("I"): UC(0x00EC), # ì Latin Small i with Grave
C("O"): UC(0x00F2), # ò Latin Small o with Grave
C("U"): UC(0x00F9), # ù Latin Small u with Grave
"after:hit": [cancel_modal], # default
"after:miss": [UC(0x0060), cancel_modal, reinject_input]
}) No need to track the dead key character... the modality system would handle all that for you... locking you into the grave modal until you chose to exit. Though maybe that's half-baked since we can't have the whole keymap "out there" when it's not modal yet... and if we hide it in a special "modals" group then the go_modal keystroke would never be exposed... oh well... neat idea still. Might be other uses for such things. Just change it to a nested keymap though with keymap("dead keys"), {
C("Alt-Grave"): {
immediately: [UC(0x0060), C("Shift-Left") ],
C("A"): UC(0x00E0), # à Latin Small a with Grave
C("E"): UC(0x00E8), # è Latin Small e with Grave
C("I"): UC(0x00EC), # ì Latin Small i with Grave
C("O"): UC(0x00F2), # ò Latin Small o with Grave
C("U"): UC(0x00F9), # ù Latin Small u with Grave
"after:hit": [cancel_modal], # default
"after:miss": [UC(0x0060), cancel_modal, reinject_input]
}
}
) |
Due to the issue of many combos needing to be transformed, it doesn't make much sense to me to just pass combos to output by default. Like I brought up with the tab nav shortcuts, many combos that are just passed to output without being transformed will end up doing unexpected things.
Can't think of anything right now. The choices are pretty comprehensive.
I can't see how that would ever work. The trigger has to somehow be on the "outside" of the modality, like there has to be a combo that triggers a nested keymap, but it's not part of the "inner" nested keys. |
A benefit of the multi-keymap approach you helped me implement is that I'm able to cascade through the dead keys keymaps to the "escape keys" keymap and therefore didn't have to include any of those keys with unusual escape actions in any of the dead keys keymaps. The dead keys keymaps at this point are fairly small. They only need to have the "valid" keys that would normally combine with the diacritic to make an accented character. "after:hit": [cancel_modal], # default
"after:miss": [UC(0x0060), cancel_modal, reinject_input] If there was something like But that would not work if the keymap were modal like nested keys. I'm sure it could work with nested keys, but ideally I'd have to build a function that inserts those special escape keys and their non-default actions inside of 30 different nested keymaps. (That's including the future ABC Extended layout.) At the moment they are still listed explicitly in the Switch/Case statements in the AHK version. So I could do that too, it would just make the config another (approximately) 300 lines longer. If you think it's easier to implement the callbacks in nested keys for now, I could give it a test when it's available. |
I'm not sure I follow you at all. A nested keymap with There shouldn't need to be an "escape" keymap since you're handing escape in the So I wonder if I'm missing something or you are? |
Well, I kept thinking from remembering the AHK implementation that there would be several at the top that need to stay because they don't act exactly the same as other keys, but it looks like I was overestimating. If there were to be a true keymap("Escape actions for dead keys", {
# special case shortcuts that should cancel dead keys
C("Esc"): [getDK(),setDK(None)], # Leave accent char if dead keys Escaped
C("Space"): [getDK(),setDK(None)], # Leave accent char if user hits Space
C("Delete"): [getDK(),setDK(None)], # Leave accent char if user hits Delete
C("Backspace"): [getDK(),C("Backspace"),setDK(None)], # Delete character if user hits Backspace
C("Tab"): [getDK(),C("Tab"),setDK(None)], # Leave accent char, insert Tab
C("Enter"): [getDK(),C("Enter"),setDK(None)], # Leave accent char, Enter key
C("Up"): [getDK(),C("Up"),setDK(None)], # Leave accent char, up arrow
C("Down"): [getDK(),C("Down"),setDK(None)], # Leave accent char, down arrow
C("Left"): [getDK(),C("Left"),setDK(None)], # Leave accent char, left arrow
C("Right"): [getDK(),C("Right"),setDK(None)], # Leave accent char, right arrow
C("RC-Tab"): [getDK(),bind,C("Alt-Tab"),setDK(None)], # Leave accent char, task switch
C("Shift-RC-Tab"): [getDK(),bind,C("Shift-Alt-Tab"),setDK(None)], # Leave accent char, task switch (reverse)
C("RC-Grave"): [getDK(),bind,C("Alt-Grave"),setDK(None)], # Leave accent char, in-app window switch
C("Shift-RC-Tab"): [getDK(),bind,C("Shift-Alt-Grave"),setDK(None)], # Leave accent char, in-app window switch (reverse) So really that would just leave these two(?) lines that still need to be in every nested keymap. keymap("Escape actions for dead keys", {
# special case shortcuts that should cancel dead keys
# C("Esc"): [getDK(),setDK(None)], # Leave accent char if dead keys Escaped
C("Space"): [getDK(),setDK(None)], # Leave accent char if user hits Space
C("Delete"): [getDK(),setDK(None)], # Leave accent char if user hits Delete So the situation is not nearly as bad as I thought. Again, that's if the The special cases that will remain:
With a true default action and I'm here for it. Let's do this. Hrrrg! [insert Hulk Hogan tearing his shirt GIF] Now I remember why I had to put a lot of these in the AHK Switch/Case. The usual process that lets you grab and analyze input fails to catch a large selection of "special" keys, unless you put equally special traps and flags in place to notice them. Keyszer/evdev doesn't have that problem, so the default action should cover almost anything. Phew. 😅 |
I think that sounds right since you're wanting special behavior from those two keys and we don't yet have a way to sniff which key was pressed... |
I think I'm coming back around on modality as an explicit concept... so you could have a modal keymap with different exit behaviors rather than the current "one and done" or "throw away invalid input"... one easily images "allow repeat" (you can stay in the modal) or "don't consume exit" so that an unrecognized keystroke could cancel modality but also return to the entire world of keymaps allowing them to handle the keystroke.
Just trying to think of a simple way to manage all this.
Now let's imagine building callbacks instead of building these features:
after:hit
=>cancel_modal
)after:miss
=>cancel_modal
)after:miss
=>ignore_key; cancel_modal
)after:hit
=>[]
) (vs the default of cancel)after:miss
:cancel_modal; recycle_input
)So you might build your dead keys with:
Recycle input being something like what you've been looking for, but it would technically be running in a special modality pre-handler - so it's not really reinjecting the input, just allowing the modality to quickly change before the input is regularly processed.
Of course default behaviors for all these things would need to be considered, I'm not sure the current defaults are "appropriate".
Originally posted by @joshgoebel in #100 (comment)
The text was updated successfully, but these errors were encountered: