Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: add support for custom keybindings and editor actions in the REPL #2739

Merged
merged 20 commits into from
Nov 23, 2024

Conversation

Snehil-Shah
Copy link
Member

@Snehil-Shah Snehil-Shah commented Aug 3, 2024

Towards #2647.

Description

What is the purpose of this pull request?

This pull request:

  • adds editor actions
  • adds support for custom keybindings
  • make existing actions configurable
  • adds settings, APIs and update docs

Related Issues

Does this pull request have any related issues?

This pull request:

Questions

Any questions for reviewers of this pull request?

For the sake of user experience, I decided the key object can have 4 properties: name, ctrl, shift, and meta. In actuality, a readline key object also has properties like sequence and code, which mainly contain the escape sequence of the keypress.

In most keypresses, the name, ctrl, shift, and meta properties are correctly emitted and are enough to determine the action we have to trigger. But in some cases, for instance, CTRL+/, instead of emitting an event with { 'name': '/', 'ctrl': true }, it emits a sequence { 'sequence': '\x1f' }. So if a user has keybindings with CTRL+/ as the key, it won't work, as such a keypress is never emitted.

Now such cases might be limited, as readline only uses the sequence prop to identify two keypress actions, namely undo and redo.
Maybe we can handle these two special cases manually in code? Not sure if a robust solution exists.

Ofcourse, we can also punt the entire responsibility of giving the readline-ready key object, onto the user, but that's not user friendly IMO.

Other

Any other information relevant to this pull request? This may include screenshots, references, and/or implementation notes.

No.

Checklist

Please ensure the following tasks are completed before submitting this pull request.


@stdlib-js/reviewers

@Snehil-Shah
Copy link
Member Author

Another solution to the problem in OP is, we can expect the user to give us the ASCII sequence of the keypress instead.

image

Every keypress will always have a sequence prop unlike name, ctrl, shift and meta.

Now this is not user-friendly as the user is expected to know the control sequence of the keypress they are wanting to assign.

So, another approach would be to maintain a table mapping all possible keybindings to their corresponding emitted control sequences. Something like:

const CONTROL_SEQUENCES = {
    '\x01': 'Ctrl+A',
    '\x02': 'Ctrl+B',
    '\x03': 'Ctrl+C',
    '\x04': 'Ctrl+D',
    '\x05': 'Ctrl+E',
    '\x06': 'Ctrl+F',
    '\x07': 'Ctrl+G',
    '\x08': 'Ctrl+H',
    '\x09': 'Ctrl+I',
    '\x0A': 'Ctrl+J',
    '\x0B': 'Ctrl+K',
    '\x0C': 'Ctrl+L',
    '\x0D': 'Ctrl+M',
    '\x0E': 'Ctrl+N',
    '\x0F': 'Ctrl+O',
    '\x10': 'Ctrl+P',
    '\x11': 'Ctrl+Q',
    '\x12': 'Ctrl+R',
    '\x13': 'Ctrl+S',
    '\x14': 'Ctrl+T',
    '\x15': 'Ctrl+U',
    '\x16': 'Ctrl+V',
    '\x17': 'Ctrl+W',
    '\x18': 'Ctrl+X',
    '\x19': 'Ctrl+Y',
    '\x1A': 'Ctrl+Z'
};

But not sure if control sequences and their corresponding keys are standardized across emulators..?
How should we proceed?

@Snehil-Shah
Copy link
Member Author

https://github.com/nodejs/node/blob/main/lib/internal/readline/utils.js#L59

readline parses some keys based on xterm and gnome emulator behaviors (I guess). Maybe we can enforce xterm standards to parse keys? I suppose most combinations might emit standardized sequences..(?)

@Planeshifter
Copy link
Member

@Snehil-Shah Not requiring providing a sequence was the right call, I think, given that asking users to know or look up the control sequences for keybindings they want is undesirable. The current approach of a key object with Boolean modifier properties seems good; we could consider renaming meta to alt, as that the latter be understood by more people maybe?

Enforcing xterm standards for key parsing could be feasible. xterm is widely used and AFAIK many terminal emulators aim for compatibility with xterm, so this sounds worth investigating.

I also do think that it would be a pragmatic choice to handle the undo and redo special cases separately.

@Snehil-Shah
Copy link
Member Author

Now if we decide to go ahead and enforce xterm control sequences, we also have the flexibility to change the input format the user can give. So we can have something like the string "CTRL-E" as input, and map this to the corresponding xterm control sequence..

Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@Snehil-Shah
Copy link
Member Author

Went ahead and added parsing of unrecognized keypresses. Fortunately, there were not many cases to cover, the above problems were mainly around keys involving symbols.

@Planeshifter I think it would be better to stick to meta as the internal readline key object, also uses it. This makes it easier to map keybindings. And julia also uses meta instead of alt in their naming so we're not alone.

@Snehil-Shah Snehil-Shah marked this pull request as ready for review August 11, 2024 13:52
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Copy link
Member

@Planeshifter Planeshifter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

One small comment: I believe we can safely assume that _rli.line is a string, correct? Hence, we could use the base package equivalents, so e.g. @stdlib/string/base/uppercase instead of @stdlib/string/uppercase, to bypass runtime argument validation of these functions.

@Planeshifter Planeshifter added the Ready To Merge A pull request which is ready to be merged. label Aug 14, 2024
@Snehil-Shah
Copy link
Member Author

@Planeshifter Makes sense..

@kgryte kgryte removed the Ready To Merge A pull request which is ready to be merged. label Aug 15, 2024
@kgryte
Copy link
Member

kgryte commented Aug 15, 2024

we could use the base package equivalents

We should go ahead and make those changes. Too easy to forget to do them later.

Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
For instance, the right arrow key should also complete the completion.
It would be a better idea to clean up this logic in the PR where we add support for configuring keybindings for existing actions.

Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@kgryte kgryte added Feature Issue or pull request for adding a new feature. Needs Review A pull request which needs code review. REPL Issue or pull request specific to the project REPL. Needs Changes Pull request which needs changes before being merged. labels Aug 22, 2024
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@kgryte
Copy link
Member

kgryte commented Sep 20, 2024

Maybe we can handle these two special cases manually in code? Not sure if a robust solution exists

@Snehil-Shah I'll defer to your judgement on that.

Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@Snehil-Shah Snehil-Shah requested a review from kgryte September 20, 2024 16:47
@kgryte
Copy link
Member

kgryte commented Nov 19, 2024

@Snehil-Shah Gentle ping regarding resolving the above comments.

@stdlib-bot
Copy link
Contributor

stdlib-bot commented Nov 21, 2024

Coverage Report

Package Statements Branches Functions Lines
repl $\color{red}11592/14373$
$\color{green}+80.65\%$
$\color{red}663/895$
$\color{green}+74.08\%$
$\color{red}153/266$
$\color{green}+57.52\%$
$\color{red}11592/14373$
$\color{green}+80.65\%$

The above coverage report was generated for the changes in this PR.

Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@Snehil-Shah
Copy link
Member Author

@kgryte cleaned up some stuff. Regarding keybindings overlapping with system preferences, I don't see a way out.

@kgryte kgryte removed the Needs Changes Pull request which needs changes before being merged. label Nov 22, 2024
@kgryte
Copy link
Member

kgryte commented Nov 22, 2024

I don't see a way out

@Snehil-Shah Maybe the way out is just clearly documenting that overlap may happen and that there is likely also going to be some platform variability, so MMV.

@Snehil-Shah
Copy link
Member Author

@kgryte should I update the docs in this PR itself? I'll raise another PR to add keybindings to existing actions..

@kgryte
Copy link
Member

kgryte commented Nov 22, 2024

@Snehil-Shah Let's punt updating the docs, and let the keybindings fly under the radar for the time being while we test out, and then we can add to docs in a follow-up PR.

Signed-off-by: Athan <kgryte@gmail.com>
Copy link
Member

@kgryte kgryte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from one small comment, this PR LGTM. Once resolved, this PR should be ready for merge. Thanks, @Snehil-Shah!

@kgryte kgryte added Needs Changes Pull request which needs changes before being merged. and removed Needs Review A pull request which needs code review. labels Nov 22, 2024
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
@Snehil-Shah Snehil-Shah requested a review from kgryte November 23, 2024 11:41
Copy link
Member

@Planeshifter Planeshifter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @Snehil-Shah! Great to have this finally land. 🚀

@Planeshifter Planeshifter added Ready To Merge A pull request which is ready to be merged. and removed Needs Changes Pull request which needs changes before being merged. labels Nov 23, 2024
@stdlib-bot

This comment was marked as outdated.

@Planeshifter Planeshifter merged commit 917119f into stdlib-js:develop Nov 23, 2024
17 checks passed
pranav-1720 pushed a commit to pranav-1720/stdlib that referenced this pull request Nov 25, 2024
PR-URL: stdlib-js#2739
Ref: stdlib-js#2647

Co-authored-by: Athan Reines <kgryte@gmail.com>
Reviewed-by: Athan Reines <kgryte@gmail.com>
Reviewed-by: Philipp Burckhardt <pburckhardt@outlook.com>
Signed-off-by: Athan Reines <kgryte@gmail.com>
Signed-off-by: Snehil Shah <snehilshah.989@gmail.com>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Feature Issue or pull request for adding a new feature. Ready To Merge A pull request which is ready to be merged. REPL Issue or pull request specific to the project REPL.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants