[feature request] synthesizing multiple hotkeys per instance of skhd
It would be great for skhd to accept multiple -k or -t options to allow synthesizing keypresses many times per one execution of skhd.
Usecase: I'm attempting to make a vim-like mode using skhd and an external program. To run commands such as "20b", I'd need to synthesize "alt - left" 20 times in a row. Running something like for i in $(seq 1 20); skhd -k "alt - left" leads to considerable lag, as starting skhd 20 times incurs significant overhead.
Until this is implemented you might want to try cliclick: https://github.com/BlueM/cliclick
However, while it is probably less resource hungry (as it doesn't spawn new processes) the effective time might be even slower:
~ ❯ time cliclick kd:alt $(for i in $(seq 1 200); printf "kp:arrow-left ") ku:alt
0.08s user 0.03s system 0% cpu 26.077 total
~ ❯ time (for i in $(seq 1 200); skhd -k "alt - left")
3.09s user 2.52s system 54% cpu 10.312 total
I'm not sure if you can get much better than that without risking keys not to get registered. The reason 20b is fast in vim is as it controls the buffer and jumps instantly - if you just hold b down on your keyboard it will probably be as slow if not slower. The default (and minimum) delay between events in cliclick is 20ms.
BTW, I found this issue looking around if anyone have implemented vim emulation in skhd. I would appreciate if you can share your work.
I tried cliclick and indeed ran into the issues you mentioned - events seem to be throttled quite a bit.
My pull request #129 modifies the argument parser for skhd so that it accepts sequential -k <keycode> arguments, instead of exiting after the first -k detected. This allows the user to specify -k "alt - left" -k "alt - left", in which both will be executed immediately and sequentially. This seems to work with quite large arguments, like 100 shift - alt - rights followed by a cmd - x (generated by my vim emulation of v100wd), which in my experience deletes 100 words, no more, no less. Check this streamable to see it in action.
My vim emulation is broken and messy, but you can get a general gist for how it works here.
Even without the external tools, I am interested in your pull request. E.g. currently in my skhdrc I have things like:
mode_visual < shift - y : \
skhd -k 'i' && sleep 0.1 && \
skhd -k 'alt - down' && \
skhd -k 'alt + shift - up' && \
skhd -k 'cmd - c' && \
skhd -k 'escape'
It would be nice not to spawn several processes while doing so. BTW @patrickhpan is there significant performance improvement with your change ?
OK, I checked out @patrickhpan fork and measured the performance difference:
time ./bin/skhd -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a -k a
0.03s user 0.02s system 48% cpu 0.091 total
vs.
time (skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ; skhd -k a ;)
1.76s user 1.44s system 52% cpu 6.062 total
I think I will go with your fork until this is integrated here ;)
Having to launch a new process in the first place was a stupid decision that is the result of me previously not wanting to require the use of IPC mechanisms in the main daemon.
instead of exiting after the first
-kdetected
If this is indeed the current behaviour maybe the syntax for this suggestion could be skhd -k keysym [keysym ...]. It would make it even nicer to write and especially read.
Here's an example from my current config in the three variants:
skhd -k 'escape'; skhd -k 'ctrl - right'; skhd -k 'hyper - space'
skhd -k 'escape' -k 'ctrl - right' -k 'hyper - space'
skhd -k 'escape' 'ctrl - right' 'hyper - space'