Closed flamingjupiter closed 1 year ago
Also, this isn't the best place to notify it but I don't know where I should do it or if I should just open a new issue, but there's an issue on the macro-release-cancel example of the documentation:
"E.g. in the example below, when holding the key, first 1 is typed, then replaced by ! after 500ms, and finally that is replaced by @ after another 500ms. However, if the key is released, the last character typed will remain and the rest of the macro does not run."
(defalias
;; macro-release-cancel to output different characters with visual feedback
;; after holding for different amounts of time.
1!@ (macro-release-cancel 1 500 bspc S-1 500 bspc S-2)
)
The number 1 needs to be aliased (and therefore declared above/before the action alias) cause if not it will be treated as a delay instead of a character to be typed.
@flamingjupiter for the doc issue, you could also open a PR directly by changing the documentation from either of the 2 web editors.
For the design, I wonder if it might be sufficient for there to be a version of tap-dance
where the action sequence always activates but changes on sequential taps. It sounds like the rest of it could be supported by existing functionality using the more complex actions such as:
The thought I have is that multi would use both:
tap-hold
within the new version of tap-dance
above for simulating hold actions@flamingjupiter if you are able, please try out #243 and see if it works for the use case you're describing when combined with other existing functionality.
One of the best features of kanata is that the timings for doing "home row shift" really work out of the box. but still I like all improvments regarding timings.
I am using tap=q hold=! double-tap=@ long-hold=@
q!@ (tap-hold 1 100 (tap-dance 150 (q @@ )) (multi @! (tap-hold 200 600 XX (macro bspc @@ ))) )
or without long hold
q!@ (tap-hold 1 100 (tap-dance 150 (q @@ )) @! )
For everyday use I can't feel the delay, but on keybr.com I could not pass the tests for letter q,
keen to test if tap-dance-eager will fix this.
@flamingjupiter if you are able, please try out #243 and see if it works for the use case you're describing when combined with other existing functionality.
Hi, sorry for the late response. I'm not a developer, but I read an article or two and downloaded the source code (with tap dance eager) and used cargo build and I guess I correctly built normal, no cmd enabled, no wintercept kanata (?).
Then I tested tap-dance-eager action and although it is outputting instantly, it is not resetting with timeout expiring (at least not the timeout configured on the kanata.kbd file, it does expire, but takes A LOT of time and it doesn't change no matter what you put as timeout for the tap-dance-eager action).
For the design, I wonder if it might be sufficient for there to be a version of
tap-dance
where the action sequence always activates but changes on sequential taps. It sounds like the rest of it could be supported by existing functionality using the more complex actions such as:
- multi
- fake keys
The thought I have is that multi would use both:
tap-hold
within the new version oftap-dance
above for simulating hold actions- fake key functionality which would allow one to activate actions when a key gets released
The timeout not expiring aside, if we put tap-hold action inside tap-dance-eager without removing the delay tap-hold action currently has, it will still have the delay coming from the tap-hold action, won't it?
@flamingjupiter for the doc issue, you could also open a PR directly by changing the documentation from either of the 2 web editors.
I thought opening PRs was reserved for "something big" such as implementing a new feature or something like that. Also I tried to but didn't understand how to indicate a change in the doc file (I really have no coding knowledge). Thanks for lmk.
it is not resetting with timeout expiring
I'll look into this
I thought opening PRs was reserved for "something big" such as implementing a new feature or something like that. Also I tried to but didn't understand how to indicate a change in the doc file (I really have no coding knowledge). Thanks for lmk.
A PR is for changes of any size 🙂.
if we put tap-hold action inside tap-dance-eager without removing the delay tap-hold action currently has, it will still have the delay coming from the tap-hold action, won't it
If you want instant activation on a tap-hold you could try do something like:
(multi (macro a) (tap-hold 100 100 xx b))
I'll look into this
I built kanata cmd enabled, wintercept using the main branch as source code (a few hours ago, with "cargo build --features cmd,interception_driver")
And I'm not having the problem of fixed timeout anymore. I really don't know why I was having it (well, I previously tested with the #243 branch, not the main branch as of january 19, 2023, ~18:45 UTC, but it could be a problem on my side nevertheless).
I did find something that idk if it's intentional or an unnoticed undesired behavior: on both tap-dance and tap-dance-eager, if I put a tap-dance action on a layer I access by pressing another key (layer-while-held action) and do this:
press the key mapped to the layer-while-held action, entering that layer;
press and release the key mapped to the tap-dance action on the layer I entered;
release the key mapped to the layer-while-held action, exiting that layer;
press (or press and release, it doesn't matter) the key that is mapped to the tap-dance action on the layer I exited but is mapped to something else on the layer I entered
If this sequence happens within the configured timeout, kanata will interpret as another press/tap of the key and the action will keep going on and the timeout will be reset to wait for another press of the key. Basically, tap-dance doesn't respect layer switching, it'll keep behaving as if the key that is now (on the current layer) mapped to something else still is the key that was (on the previous layer) mapped to the tap-dance action. I believe an option to choose whether it'll have this behavior or not would be useful. Maybe it's not that big of a deal when using the normal tap-dance action, because it's slower. But with tap-dance-eager it is possible to type very fast, and then you could end up switching to another layer yet the tap-dance action is still running and waiting for input. Sorry for the (possibly) bad explanation.
If you want instant activation on a tap-hold you could try do something like:
(multi (macro a) (tap-hold 100 100 xx b))
Damn, didn't think of that, thanks. I'm now testing tap-dance-eager with multi, tap-hold and fake-key actions in order to implement the features I mentioned, but found two things:
(defalias
fk1 (on-release-fakekey d tap)
a1 (macro a)
a2 (macro bspc b)
a3 (macro bspc c)
b1 (macro bspc m)
b2 (macro bspc n)
b3 (macro bspc o)
c1 (tap-hold 150 150 XX @b1)
c2 (tap-hold 150 150 XX @b2)
c3 (tap-hold 150 150 XX @b3)
d1 (multi @a1 @c1)
d2 (multi @a2 @c2)
d3 (multi @a3 @c3)
test2 (tap-dance-eager 200 (@d1 @d2 @d3))
test3 (multi @test2 @fk1)
)
I can load kanata with the configuration above, but it crashes if I try to activate "test3" (until "test2" it works normally). Tested with normal tap-dance action and it crashes as well, but I was able to extract this text that appeared on kanata window before crashing:
"thread 'RUST_BACKTRACE=1
environment variable to display a backtrace"
On the first press it works reliably. I press, it outputs "a". I keep holding it and then it backspaces "a" and types "m". On the second and subsequent presses, if I press the key very fast the hold action won't activate even if I keep holding the key e.g. I press the key for the first time, it outputs "a". I press the key again very fast, it backspaces "a" and types "b". I keep holding the key for any amount of time, but it doesn't backspaces "b" and types "n".
Thanks for testing! Some notes:
And I'm not having the problem of fixed timeout anymore. I really don't know why I was having it (well, I previously tested with the https://github.com/jtroo/kanata/pull/243 branch, not the main branch as of january 19, 2023, ~18:45 UTC, but it could be a problem on my side nevertheless).
Yea there were probably some extra fixes in the main branch that were added after the PR was merged. I'm too lazy to look though haha 😅. The git log would probably say.
I did find something that idk if it's intentional or an unnoticed undesired behavior: on both tap-dance and tap-dance-eager, if I put a tap-dance action on a layer I access by pressing another key (layer-while-held action) and do this:
This is currently intentional by the code design, but I can see how this can negatively affect the use case you're describing. Perhaps you can work around it in the config by adding an on-release fake key tap of a non-action modifier key like rsft
? If that's not workable then I can look into adding an option to change that behaviour. You may run into the crash you've found for now though, so testing might have to wait until that's fixed.
With the same configuration above, the hold action on tap hold won't activate if I press the key again very fast:
Try changing the first number to 0 in tap-hold
. You can read up about what that does in the docs 🙂.
"thread '' panicked at 'assertion failed: self.waiting.is_none()', C:\Users\XXXXX.cargo\registry\src\github.com-1ecc6299db9ec823\kanata-keyberon-0.6.1\src\layout.rs:809:9" "note: run with RUST_BACKTRACE=1 environment variable to display a backtrace"
Thanks for reporting the bug! I'll look into it. It's unclear if you're already doing this, but just in case, for the sake of learning, you can also open up a cmd
or powershell
instance and run kanata from there, instead of clicking the executable, and the window will not close if kanata crashes.
@flamingjupiter I've fixed the issues I've been able to find from your provided test configuration in #257. Let me know how it goes when you've had a chance to try it out.
I believe an option to choose whether it'll have this behavior or not would be useful. Maybe it's not that big of a deal when using the normal tap-dance action, because it's slower. But with tap-dance-eager it is possible to type very fast, and then you could end up switching to another layer yet the tap-dance action is still running and waiting for input. Sorry for the (possibly) bad explanation.
I just want to advocate for the one-shot-layer + tap-dance use case, where the tap-dance should survive the layer-switchback.
I realized this doesn't work with one of the changes made in the latest PR
Perhaps you can work around it in the config by adding an on-release fake key tap of a non-action modifier key like rsft?
Since fake keys are now ignored for the purposes of interrupting tap-dance-eager. Perhaps instead I can instead add a custom action to cancel tap-dance-eager, which can then be activated via an on-release fake key activation. The new action could be added to any places where it might be desired from a toggle standpoint.
Try changing the first number to 0 in
tap-hold
. You can read up about what that does in the docs 🙂.The tap timeout is the number of milliseconds within which a rapid press+release+press of a key will result in the tap action being held instead of the hold action activating.
Damn, sorry for the blunder. I come from AHK where the function I used for tap-dance functionality did not possess a mechanism that allowed tap action repeat. I'm also not used to thinking on how to do things in kanata taking the multi and fakekeys action in consideration. I changed tap timeout to 0 and now it's working flawlessly, thanks!
Thanks for reporting the bug! I'll look into it. It's unclear if you're already doing this, but just in case, for the sake of learning, you can also open up a
cmd
orpowershell
instance and run kanata from there, instead of clicking the executable, and the window will not close if kanata crashes.
I didn't know that 😯, thanks for lmk!!
I realized this doesn't work with one of the changes made in the latest PR
Perhaps you can work around it in the config by adding an on-release fake key tap of a non-action modifier key like rsft?
Since fake keys are now ignored for the purposes of interrupting tap-dance-eager. Perhaps instead I can instead add a custom action to cancel tap-dance-eager, which can then be activated via an on-release fake key activation. The new action could be added to any places where it might be desired from a toggle standpoint.
I was gonna try it and I think it'd do the job? I'm really not used to the fakekeys action. But since fake keys don't interrupt tap-dance actions anymore ig a cancel-tap-dance-eager action would be the way to do it.
@flamingjupiter I've fixed the issues I've been able to find from your provided test configuration in #257. Let me know how it goes when you've had a chance to try it out.
Just tested and it's not crashing anymore. Fakekeys is also terminating tap-dance-eager, while normal tap-dance action isn't affected.
Though you said fakekeys won't terminate tap-dance actions anymore because of changes you've made, and even if they did it won't have the desired effect because well, if it terminates tap-dance-eager whenever it is used, you won't be able to reach taps above the first you put the fakekey action.
So, with the config on my previous comment, I can't ever get past the first action on the tap dance (type a) because as soon as I release the key the fakekey action occurs (types d) and terminates tap-dance-eager. I believe a custom action to cancel tap-dance-eager would be best. That way, it'll be possible to use fakekey action to do something on the release of the key as well.
@flamingjupiter
The keyberon code worked differently from what I remember, and I was testing with a slightly modified config. Turns out the custom action is actually not necessary, since the use cases listed already work:
rsft
workaround does interrupt tap dance stateWhen a macro
action is used on a fake key, it does not interrupt the tap dance state. But if the fake key has a normal key action (among other types of actions), it does interrupt the tap dance state. A bit complicated and accidental complexity - I don't remember if it's intentional or not - and it's not documented right now. But it's useful behaviour since it supports the use case properly, so I'll leave it in and add documentation for it.
@flamingjupiter
The keyberon code worked differently from what I remember, and I was testing with a slightly modified config. Turns out the custom action is actually not necessary, since the use cases listed already work:
- the
rsft
workaround does interrupt tap dance state- fake keys can do some actions without interrupting tap dance state
When a
macro
action is used on a fake key, it does not interrupt the tap dance state. But if the fake key has a normal key action (among other types of actions), it does interrupt the tap dance state. A bit complicated and accidental complexity - I don't remember if it's intentional or not - and it's not documented right now. But it's useful behaviour since it supports the use case properly, so I'll leave it in and add documentation for it.Test config: click me
Just tested and you're right, it works nicely, tysm! I believe all features and use cases requested here are now covered?
What I want is
the ability to use tap-hold and tap-dance actions to immediately send the key/action of the taps, instead of having a small delay on the tap-hold action and sending on timeout expiring/pressing another key/reaching tap limit on the tap-dance action.
mix taps and holds (hold at the end of the sequence): instead of having an action with 2 options, 1 tap or hold (tap-hold action) or an action with arbitrary number of taps (tap-dance action), allow for combinations of taps and the hold at the end. So, 1 tap could give letter a, 1 tap + hold (the "hold" on tap-hold, I'm counting the hold as a tap as well, but how you define them doesn't matter, it won't change the functionality) could give letter b, 2 taps = letter c, 2 taps + hold = letter d, et cetera.
If you use macros on the taps and holds of actions with the two possibilities/features above you could have blazing fast, no delay variable characters, just like you have on the macro-release-cancel action, but instead of continuously holding the key and waiting for the delays you configured on the macro, you'd control that with number of taps + hold.
Example of an use case: 1 tap = "S-9"; 2 taps = "bspc S-["; 1 tap + hold (one single tap that you don't release i.e. you keep it pressed, it becomes a hold) = "bspc ["; 2 taps + hold (tap once, hold on the second tap) = "(macro-release-cancel bspc S-' 200 bspc ')".
If you tap it once, you send (. Tap twice, erases the ( and sends {. Hold your first tap/long press, erases the { and sends [. Tap once and hold your second tap/long press, erases the [ and sends ", then, if you keep pressed until the delay on the macro-release-cancel action is over, it erases the " and sends '. With only two keys you could type very fast the () [] {} "" '' keys (in this specific example there'd even be space for other two characters on a possible macro-release-cancel of the second key).
Tap-hold possess a small delay on tap that messes with fast typing. Tap-dance activates only upon timeout expiring, pressing another key or reaching the tap limit. Even though it activates upon pressing another key so it won't interfere with fast typing, the option to choose between the current tap-dance implementation and the one I'm proposing would be nice, also it'd be faster when you're not continuously fast typing something (you'd have (fast) visual feedback, just like macro-release-cancel, but by tapping instead of holding until you get the desired character). Allowing immediate sending of the key would solve both problems.
As things are right now, it's not possible to mix tap-hold and normal keys on alphanumeric keys when fast typing because of that delay. Making all character keys + space + backspace a tap-hold action where the tap sends it's own original key and the hold does whatever is a possible solution, because now all typing keys have that delay, but that is really difficult to get used to. That delay makes what you see on the screen not match what you're doing with your fingers, leading to a lot of repetitions because you think you haven't pressed the key, at least on my experience.
That's what I want and "really need". But tap-hold, tap-dance and macro-release-cancel could be further improved. Example of other features/further improvement:
Send on key press/down, send on key release/up, send on both: what I'm asking for is the ability to immediately send keys upon key press on tap-hold and tap-dance actions. But that could be further improved and allow for a combination of sending on key press, key release, or both (besides what we currently have i.e. sending with a small delay on tap-hold and sending upon timeout expiring/pressing another key/tap limit on tap-dance). E.g.:
1 tap down = a ; 1 tap up = 1 ; 1 tap + 1 hold = alpha ; 2 taps down = b ; 2 taps up = 2 2 taps + 1 hold = beta .
Output if you tap once: "a1"; output if you tap once and hold: "aalpha" ; output if you tap twice and hold: "a1b2beta". These are all possible outcomes. Then one would choose (by any means, like specifying a variant action) the combination they'd prefer for their use case and set up the taps and holds accordingly i.e. instead of configuring like on my example it'd probably be more useful to put a macro with backspaces (and delays, if possible) to erase what you previously typed on the taps before your last one. There could be options for sending keys on the release of the hold and the release of the macro-release-cancel, though those would probably have very few use cases. Allow for arbitrarily having a hold on a "tap-dance sequence" would also be an improvement but I guess that would be pretty difficult to implement.
I was gonna say that the hold could be further improved by giving it functionality like the macro-release-cancel, but you can do that already, you just need to put a macro-release-cancel on the hold. Still, making the macro action be able to do more than keys, delays, chords would be a great improvement.