Skip to content

Expose more matching logic without triggering side effects #10

Description

@savetheclocktower

Have you checked for existing feature requests?

  • Completed

Summary

Keyboard input handling in the terminal package is fraught. Many bindings theoretically can produce control characters in terminals, and that means many bindings can end up being swallowed by the terminal even when the user intends them to trigger ordinary actions in Pulsar.

Ctrl+F is a good example. It's the default keybinding on Windows and Linux for opening up the terminal's “find” palette. But it has an obscure potential function in a terminal, too, since it matches an emacs-style binding for moving the cursor forward one character.

XTerm.js allows us to be consulted on all keypresses, and to inspect the keyboard event and decide whether we should handle the event instead of XTerm.js. But that's not an easy question to answer in the hypothetical! The most reliable way to answer that question for sure is to call atom.keymaps.handleKeyboardEvent — but that actually handles the event! We're not trying to replace or preempt Pulsar's keyboard handling; we're just trying to tell XTerm.js whether to swallow the event or let it propagate to us, at which point keyboard handling will proceed. If we actually call handleKeyboardEvent for an event that would trigger a Pulsar command, it'll end up getting triggered twice.

(You might think: “Just handle it manually, then tell XTerm.js to swallow it!” Yet that will still result in two triggers for those bindings that don't match any XTerm.js control sequences. We get a bite at the apple before we know if the event represents a key binding with special meaning in a terminal — so if it tries to handle it and strikes out, the event propagates to us anyway, and Pulsar will respond once again to an event that we impatiently handled before its time.)

The best way to fix this would be to have a “dry run” mode for handleKeyboardEvent, or else to split the logic in handleKeyboardEvent into two methods — one for identifying the match or matches for a given keyboard event, and another to actually invoke them.

What benefits does this feature provide?

Introspection is good! It gives us the flexibility we need for the terminal scenario described above.

Any alternatives?

The alternative is to reimplement a lot of atom-keymap's logic in pieces. For instance, I can use the keyboard event to get a list of matching keybindings, but I must then do some of the work that handleKeyboardEvent would do: crawling up the DOM tree to winnow the matches based on their CSS selectors. This is duplication of effort and will only diverge from the true implementation in atom-keymap over time if we need to tweak it.

Other examples:

I'm sure VS Code has a similar problem to our terminal dilemma, since it uses both node-pty and XTerm.js. But I haven't researched how they handle it. That research might give us some insight into heuristics for deciding whether a user meant to invoke a terminal binding or a Pulsar binding, but it seems unlikely that it would help with this specific problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions