Skip to content
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

Feature request: unmatched sequence "pass-through" behaviour #248

Closed
partiallyordered opened this issue Jan 16, 2023 · 8 comments
Closed
Labels
enhancement New feature or request

Comments

@partiallyordered
Copy link

partiallyordered commented Jan 16, 2023

Is your feature request related to a problem? Please describe.
When a sequence is not "matched", i.e. sequence-timeout expires, or a non-sequence key is pressed, Kanata swallows the typed keys.

Describe the solution you'd like
I would like Kanata to (optionally, perhaps) emit non-matched or timed-out sequence key presses.

The implementation notes on sequences (#97) describe them as being vim-like, but make an explicit carve-out for non-leaf sequence. I use the sequence "fd" to exit insert mode in vim, and I'm trying to map it to esc globally in Kanata. In Vim, when the sequence is not "matched", either timeoutlen (in Kanata, sequence-timeout) expires, or a non-sequence key is pressed, the unmapped part of the sequence is emitted.

Describe alternatives you've considered
It's possible to mostly achieve this behaviour by mapping all possible subsequent keys into the sequence, see e.g.: https://github.com/partiallyordered/dotfiles/blob/d0082ced7d5b2efc9ceab7cacfd7954b924d5e1e/xps.kanata.s#L44-L162 . For my purposes, this has the shortcoming that when I want to type just f (which is a frequent occurrence because of vim keybindings elsewhere!), I must hold f, instead of waiting for sequence-timeout.

It's also possible to mostly achieve this by defining a "sequence" layer, in this example called f-layer: https://github.com/partiallyordered/dotfiles/blob/679c733d007f3cd52f916003307f516ac83c1b1f/xps.kanata.s#L16 . Then defining each key in that layer to execute a macro, with the exception of the "sequence": https://github.com/partiallyordered/dotfiles/blob/679c733d007f3cd52f916003307f516ac83c1b1f/xps.kanata.s#L74 . This has the shortcoming that in order to emit an f character, one must type f-something, e.g. fa, then backspace over the second emitted character.

Additional context
None

@partiallyordered partiallyordered added the enhancement New feature or request label Jan 16, 2023
@jtroo jtroo added the selected label Jan 16, 2023
@jtroo
Copy link
Owner

jtroo commented Jan 16, 2023

Thanks for filing the issue! I've thought about this in the past but never got around to it, so this gave me a reason to look at it again.

You can test this out in #249, can read the documentation here.

@partiallyordered
Copy link
Author

partiallyordered commented Jan 16, 2023

Cool! I tried out visible-backspaced. A little feedback:

  • Personally, as I'm using a printing character (f) as a sequence leader, I'd hoped the leader key itself, as well as the "unmatched" sequence would be emitted when the sequence terminated unsuccessfully
  • I think repeated presses of the sequence leader restart the sequence, meaning that my simple sequence defined as follows:
    (defalias eff (tap-hold-release 200 200 sldr f))
    (defseq fd-escape (d))
    (deffakekeys fd-escape (macro esc))
    
    requires me to hold the f key to emit an f. I'd hoped that pressing f and waiting the sequence timeout would emit an f.

I want to respect your maintainership so I'd like to explicitly state that I have no expectations of a specific outcome from this ticket, I'm only stating my hopes and dreams! I respect whatever implementation you decide is best. Thank you for sharing your efforts.

Full config, in case it's useful:

(defcfg
  sequence-timeout 150
  sequence-input-mode visible-backspaced

  linux-dev /dev/input/by-path/platform-i8042-serio-0-event-kbd)

(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]
  caps a    s    d    f    g    h    j    k    l    ;    \    ret
  lsft 102d z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc                 ralt rctl
)

(defalias eff (tap-hold-release 200 200 sldr f))

(deflayer qwerty
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]
  caps a    s    d    @eff g    h    j    k    l    ;    \    ret
  lsft 102d z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc                 ralt rctl
)

(defseq fd-escape (d))
(deffakekeys fd-escape (macro esc))

@jtroo
Copy link
Owner

jtroo commented Jan 16, 2023

Maybe this config change could work for you, with no change to the kanata code:

(defalias eff (tap-hold-release 200 200 (macro sldr f) f))
(defseq fd-escape (f d))

Let me know how that goes.

@jtroo
Copy link
Owner

jtroo commented Jan 16, 2023

I could also easily make the change so that sending sequence leader again when sequence mode is already active will not reset the sequence.

Edit: I've pushed this change

@partiallyordered
Copy link
Author

partiallyordered commented Jan 16, 2023

The suggestion you made:

(defalias eff (tap-hold-release 200 200 (macro sldr f) f))
(defseq fd-escape (f d))

had some slightly funky behaviour- I think pressing fd within the tap timeout (i.e. within 200ms) would cause df to be emitted. I suspect because the sequence terminated unsuccessfully and then the final argument to tap-hold-release was evaluated. However, the following works really nicely, thanks for the inspiration:

(defalias eff (macro sldr f))
(defseq fd-escape (f d))

There's only one little thing that doesn't behave basically exactly as I'd want: once I enter the sequence, if I hold a "modifier key" (e.g. lalt) then the sequence exits but the modifier key isn't held. So a little more concretely, if I do this:

  1. depress f
  2. release f
  3. depress lalt
  4. depress tab
  5. release tab
  6. release lalt

I would expect the sequence to be exited and f lalt+tab to be emitted, but f lalt tab is emitted. The held modifier key is not emitted with the tab key, but before it. I could definitely live with this little wrinkle.

Thanks for working closely with me here, it's been great.

@jtroo
Copy link
Owner

jtroo commented Jan 17, 2023

I would expect the sequence to be exited and f lalt+tab to be emitted, but f lalt tab is emitted. The held modifier key is not emitted with the tab key, but before it. I could definitely live with this little wrinkle.

This was not too hard to fix, just required me to remove a line of code haha. I think the latest push should do the trick, let me know if it does when you can.

@partiallyordered
Copy link
Author

Perfect. Don't know what to say. Really cool, thank you! Let me know if there's some way I can buy you a coffee or a beer or something!

@jtroo
Copy link
Owner

jtroo commented Jan 17, 2023

I appreciate the thought! I'm intentionally not accepting any form of funding for kanata right now, so all good on that front.

@jtroo jtroo closed this as completed Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants