helix: Exit insert mode on key hold

Given the high frequency of exiting various modes it makes sense to find the easiest keybind way possible to switch back Helix has a helpful suggestion:

[keys.insert]
"A-x" = "normal_mode" # Maps Alt-X to enter normal mode
j = { k = "normal_mode" } # Maps `jk` to exit insert mode

However, the first requires a modifier and the second introduces a typing delay (j isn’t shown after <kbd>j</kbd> is pressed until the next key is pressed) (likewise, binding <kbd>Esc</kbd> to <kbd>Caps</kbd> is a pinky move, so not that great either)

I think an even better alternative would be to get rid of a useless letter repetition (if only for a single letter) to have an “on hold” normal_mode command so that you could hold an extremely convenient home row key, e.g., <kbd>a</kbd> for 0.5 seconds and that would switch back to normal mode (and, importantly, not execute any normal mode commands bound to <kbd>a</kbd> until it’s released) instead of typing aaa

(you might also need to delay the first a character before exiting after an “on hold” event to avoid typing delays and also avoid extraneous a)

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 16 (8 by maintainers)

Most upvoted comments

@eugenesvk let it go. This is approaching harassment. Unless you are going to be the person doing the work to implement this feature, and then maintaining its functionality for the foreseeable future, you really don’t get an opinion on whether it’s worth it or not.

One issue I see is we probably don’t want user to add 3 config to get this working.

Why not? The timing challenges are real, they are user hardware/software/preference specific, so user is the only person able to provide such information

archseer suggested https://docs.qmk.fm/#/tap_hold, maybe you can look into that.

As I mentioned above, firmware lacks the software knowledge to implement this

I myself won’t find this useful, but if you are interested to work on it (since I doubt others find this useful), feel free to give this a try and submit a pull request, then I can help you look into it.

Yeah, that might be a challenge, I don’t know any Rust and only implemented such a solution in AutoHokey, and your E-Hard label doesn’t give be a boost of confidence either 😃

Meanwhile, could you please reopen the issue as it’s not really GUI-dependent? Also might help someone else see it and appreciate the beauty of this mode-switching-without-leaving-home-row solution enough to help with the implementation 😃

I think this type of stuff is best addressed in keyboard firmware where you can have full control over the keys (i.e. https://docs.qmk.fm/#/tap_hold).

But the firmware doesn’t know what mode Helix is in! Firmware might not even know what application is running (also, way too many keyboards don’t have it, so it’d a very limited solution)

the input now has to be delayed until a timeout is reached

nope, you just pass the input through and then clean it up

I similar software-based text input functions like showing a symbol selection picker when you hold a button in a text editor and I don’t introduce input delay, the first key press always types a letter right away!, but rather add a simple cleaning-an-extra-symbol routine (it’s just one symbol since I can block further repeats), it’s just fine (granted, Helix can’t block further repeats, but it can still easily clean everything up — it knows how many as it has received and can delete all of them after an “on repeat” condition is met). However, the challenge is the same as with firmware based solutions — it has no knowledge of such intricacies like Helix modality (though software can be made aware of what application is running, not 100% sure, but likely with extra challenges even of a terminal-based app)

That’s why Helix is unforunately the only place to add such a bomb of a feature (mode switching is frequent enough to need the easy way to do it), and it would work just fine even in a terminal without a GUI

This is also why we don’t support vim’s feature where both g and ge can be mapped to a command, and g will execute after a timeout. There’s all sorts of questions out there “why is my command slow” and suggestions to set timeoutlen to 0

That strikes me more like just bad defaults, the users wishing to have such compex conflicting keybinds should suffer and tweak the delays to whatever suits them, not everyone! But again, there is no input delay in the suggested solution and it won’t affect anyone by default, a special command chain syntax (or something) would be needed to start timers on a key press, so Helix wouldn’t have these issues either

don’t get an opinion on whether it’s worth it or not

please quote me where I’ve expressed one

limitation of the terminal, I don’t think this is even possible

Sure thing, maybe this could only work in a proper GUI whenever Helix gets one, though why not? Helix is able to see char a being sent to it 5 times in a row in 0.5 seconds, that’s not something that would ever happen “organically”, or would it?