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

Support "Key Chords" in keybindings #1334

Open
4 tasks
zadjii-msft opened this issue Jun 19, 2019 · 14 comments
Open
4 tasks

Support "Key Chords" in keybindings #1334

zadjii-msft opened this issue Jun 19, 2019 · 14 comments
Labels
Area-Settings Issues related to settings and customizability, for console or terminal Help Wanted We encourage anyone to jump in on these. Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal.
Milestone

Comments

@zadjii-msft
Copy link
Member

Currently, we only support pressing a single key+modifiers to activate a keybinding action.

However, many text editors support "key chords" where the chord is a combination of multiple keys pressed in sequence. For example, in Visual Studio, the default keybinding for "Comment Code" is the chord [ctrl+c, ctrl+k].

We've already prepared for serializing these chords in the array of keybindings, but we don't support more than one key at a time. We'd have somehow check if a key is the start of a chord, and only dispatch the action when all keys for the chord have been pressed.

Lots of questions:

  • What happens if an action is bound to [ctrl+c, ctrl+k] and another is bound to [ctrl+c]?
  • If the first key of a chord is pressed, but the second key isn't bound to an action, should we write both keys to the input?
  • If the first key of a chord is pressed, but then nothing is pressed for a long time, should we time out?
  • What's the best way of finding the right keybinding for a chord?
    • Iterating over all of them when a key is pressed, until the chord is dispatched seems awful (but trivial to do).
    • Maybe we could build a tree of keychords, or a list of trees?
    • My CS542 senses are tingling and suggesting that this might be the case to use a state machine.
      • Is a state machine really different than a tree in this case?
@zadjii-msft zadjii-msft added Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Area-Settings Issues related to settings and customizability, for console or terminal Product-Terminal The new Windows Terminal. labels Jun 19, 2019
@zadjii-msft zadjii-msft added this to the Backlog milestone Jun 19, 2019
@ghost ghost added the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Jun 19, 2019
@carlos-zamora
Copy link
Member

Here’s a thought. What if we execute the keybinding when “CTRL” is released? So “CTRL-K, CTRL-D” is really just you hold CTRL, then press K, then press D. And it executes when you release CTRL.

We could use a Trie data structure. Traverse the Trie as you press more keys. If you end on a leaf, execute the code. If an internal node has a command linked to it, execute ONLY when the first key pressed (in this case, CTRL) is released.

@DHowett-MSFT DHowett-MSFT removed the Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting label Jun 20, 2019
@dnagl
Copy link
Contributor

dnagl commented Jul 1, 2019

Do you have already some idea how this could be structured in the profiles.json file?

@zadjii-msft
Copy link
Member Author

@dnagl Yep 😄

I actually made the "keys" property an array when I first implemented keybindings, despite there only ever being one key combo, because I knew that this is something we'd want eventually.

@dnagl
Copy link
Contributor

dnagl commented Jul 3, 2019

@zadjii-msft Seems obvious. The property contains an array. 😄

@0xabu
Copy link

0xabu commented Sep 19, 2019

IMHO: chorded key binding shortcuts are generally useful when there are many possible actions/bindings, so you need a bigger space of possible inputs. A text editor / IDE is obviously one such scenario. It seems unlikely that a terminal would ever have so many shortcuts... does anyone know of another non-IDE terminal that implemented this?

Per #2388 (comment) the array of "keys" might be a logical syntax to repurpose for multiple bindings to the same action.

@DHowett-MSFT
Copy link
Contributor

tmux and screen are both terminal emulators that have implemented chorded keys. 😄

@0xabu
Copy link

0xabu commented Sep 19, 2019

tmux and screen are both terminal emulators that have implemented chorded keys. 😄

Clearly I've massively underestimated your ambitions for this app!

@DHowett-MSFT
Copy link
Contributor

If you consider that iTerm2 can act as a tmux controller and turn tmux panes into physical terminal panes, the lines between the multiplexer and terminal emulator are already a bit blurry. We support panes, and we probably eventually want some higher-level concepts like pane selection, grouping, and movement that I don't think we should bind over the fairly limited set of level-1 keyboard characters.

More to the point, though, I personally hold all the things that could be serialized in VT as sacred and "under the purview of the receiving application", so chording gives us an escape hatch to add a terminal control plane keyset. Ya know?

ghost pushed a commit that referenced this issue Mar 5, 2020
## Summary of the Pull Request

Adds warning messages for a pair of keybindings-related scenarios. This covers the following two bugs:
* #4239 - If the user has supplied more than one key chord in their `"keys"` array.
* #3522 - If a keybinding has a _required_ argument, then we'll display a message to the user
  - currently, the only required parameter is the `direction` parameter for both `resizePane` and `moveFocus`

## References

When we get to #1334, we'll want to remove the `TooManyKeysForChord` warning.

## PR Checklist
* [x] Closes #4239
* [x] Closes #3522
* [x] I work here
* [x] Tests added/passed
* [n/a] Requires documentation to be updated

![image](https://user-images.githubusercontent.com/18356694/75593132-f18ec700-5a49-11ea-9d26-6acd0d28b0b7.png)


## Validation Steps Performed
Tested manually, added tests.
@jonschlinkert
Copy link

does anyone know of another non-IDE terminal that implemented this?

FWIW, we're also implementing chords in enquirer, a prompt system, and this has turned out to be useful for not just traditional chords, but also multi-digit numbers. In general, one of the things that makes this challenging in the terminal (or at least limited in node.js) is there is no way to get key up/down events, so we can't determine when someone is holding down the ctrl key, etc.

If the first key of a chord is pressed, but the second key isn't bound to an action, should we write both keys to the input?

This is effectively what we're doing, and it seems to work well. Basically we store the first key if there is a non-chord key binding that should be used if the second key in the chord isn't pressed. If the second key is either a) not pressed before the timeout expires, or b) another key that does not match the second key in the chord is pressed, then we re-dispatch the stored key as a non-chord, then we dispatch the new (second) key.

@NotWearingPants
Copy link
Contributor

IMHO: chorded key binding shortcuts are generally useful when there are many possible actions/bindings, so you need a bigger space of possible inputs. A text editor / IDE is obviously one such scenario. It seems unlikely that a terminal would ever have so many shortcuts...

A terminal runs another application inside it, which also has keybindings of it's own. For example, this is why Ctrl+Shift+W closes tabs instead of Ctrl+W, since Ctrl+W is used in most shells to delete a word. Since the terminal can even run editors such as emacs/vim inside it, the need for more obscure keybindings arises very quickly.

@zadjii-msft zadjii-msft modified the milestones: Terminal Backlog, Backlog Jan 4, 2022
@jcrben
Copy link

jcrben commented Jun 12, 2022

@0xabu terminal apps which support this feature already are https://github.com/Eugeny/tabby (formerly terminus)
image

and https://github.com/vercel/hyper/ as well

I'm not able to use these at work so looking forward to support with this terminal

@coffeebe4code
Copy link

What is needed here to get this going/finished?

@zadjii-msft
Copy link
Member Author

Someone would need to figure out how to mechanically get a chorded keybinding to work with our TermControl right now. I left notes in the OP for things I would look into. I'd think the trick would be finding the way for KeyBindings to "stash" a key if it was the start of a chord, but the next key wasn't, then also sending the original stashed key if the second key doesn't match.

Alas, I don't think this is something I'll have time to get to anytime soon, but if someone else would like to take a look I'd be happy to help in whatever way I can ☺️

@zadjii-msft
Copy link
Member Author

Dropping a note in here:

Lib/_pyrepl/windows_eventqueue.py

that's pretty clever, the key parsing is a tree of maps like, map<char, char|map> and then each keystroke takes you deeper into the tree, till you find a leaf or nothing. gotta keep that in mind for key chords in the future

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Settings Issues related to settings and customizability, for console or terminal Help Wanted We encourage anyone to jump in on these. Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal.
Projects
None yet
Development

No branches or pull requests

9 participants