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

lib/mp-readline/readline.c: Added backward/forward/kill-word support. #5024

Conversation

derekenos
Copy link
Sponsor

This PR adds forward-word (Alt-f), backward-word (Alt-b), kill-word (Alt-d), and backward-kill-word (Alt-Backspace) support to readline.

@stinos
Copy link
Contributor

stinos commented Aug 20, 2019

This is a good addition in general I think as it makes the REPL more useful, problem for me personally is that I don't use standard readline shortcuts for this but the 'gui text editor-style' ones (Ctrl+Left Arrow, Ctrl+Del etc), which as far as I know this is not that uncommon (CPython's REPL also has a subset of it for instance). Now the core logic is the same, so if you refactor what is now in the switch statement into functions or macros it would be fairly easy to provide both sets of shortcuts. possibly configurable?

@derekenos
Copy link
Sponsor Author

I'll be happy to add hooks for Ctrl-Left and Ctrl-Right which I see are implemented in the CPython REPL, though it'll take more work than I initially thought because these escape sequences comprise more characters than the current logic supports.

Ctrl-Del, however, doesn't appear to be supported in the CPython REPL; when I type this, I just see:5~

I'm also getting some ctypes-related build errors for various ports that I don't really understand and need to investigate.

Copy link
Member

@dpgeorge dpgeorge left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution. Please note that MicroPython needs to maintain a relatively small footprint, so adding functionality like this is not always the right way to go. Nevertheless, if it's a small impact in code size for a large impact in usability then it'd be considered for inclusion.

It might be good to conditionally include the new features here with the existing MICROPY_REPL_EMACS_KEYS option.

lib/mp-readline/readline.c Outdated Show resolved Hide resolved
lib/mp-readline/readline.c Outdated Show resolved Hide resolved
lib/mp-readline/readline.c Outdated Show resolved Hide resolved
lib/mp-readline/readline.c Outdated Show resolved Hide resolved
lib/mp-readline/readline.c Outdated Show resolved Hide resolved
@stinos
Copy link
Contributor

stinos commented Aug 22, 2019

Ctrl-Del, however, doesn't appear to be supported in the CPython REPL; when I type this, I just see:5~

Yes I know, quite an oversight imo. Which is likely why it gets usually reimplemented in the IDEs using it. Anyway I can understand if this is considered too non-standard for a REPL but I can always implement it in a fork.

@derekenos
Copy link
Sponsor Author

Thank you, @dpgeorge, for this project! I've done a lot of microcontroller firmware development, some in C but mostly Assembly, and the ability to use Python on these platforms is really amazing.

I understand that MicroPython needs to stay small, but these key bindings will make the REPL more functional for me, and hopefully others.

I apologize in advance if my code is doing anything that's obviously ridiculous. I'll look into making this feature condition with that MICROPY_REPL_EMACS_KEYS

#define FORWARD true
#define BACKWARD false

size_t get_word_cursor_pos(bool direction) {
Copy link
Member

Choose a reason for hiding this comment

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

This can be made a STATIC function, since it's local to this file.

Also direction can be an int taking value 1 or -1, then there's no need to convert it to cursor_pos_step, nor have FORWARD and BACKWARD constants.

char buf_idx_offset = direction == FORWARD ? 0 : -1;
size_t cursor_pos = rl.cursor_pos;
bool in_leading_nonalphanum = true;
char c;
Copy link
Member

Choose a reason for hiding this comment

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

char c should go below in the while loop.

if (!in_leading_nonalphanum) {
break;
}
} else if (in_leading_nonalphanum) {
Copy link
Member

Choose a reason for hiding this comment

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

This check is not needed, can just be an else (saves code size).

} else if (in_leading_nonalphanum) {
in_leading_nonalphanum = false;
}
if (direction == FORWARD) {
Copy link
Member

Choose a reason for hiding this comment

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

No need for this check, just unconditionally test if cursor_pos >= rl.line->len

}
cursor_pos += cursor_pos_step;
}
return cursor_pos;
Copy link
Member

Choose a reason for hiding this comment

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

Can probably return cursor_pos - rl.cursor_pos here, since all callers just want the number of chars skipped.

@dpgeorge
Copy link
Member

Eventually this would also need tests, see eg tests/cmdline/repl_emacs_keys.py

@jimmo
Copy link
Member

jimmo commented Aug 25, 2019

I know M-del is the Emacs shortcut for backward-kill-word, but GNU readline also supports C-w which is a far easier option to type. So if you're adding the implementation anyway, would you be prepared to spend a few extra bytes on making C-w also trigger backward-kill-word ?

@stinos
Copy link
Contributor

stinos commented Aug 25, 2019

That makes already for 3 different shortcuts people want for this. So whether or not they all get implemented in the main port, I really think it's for the best if all functionality is in seperate functions and/or macros so people who want a shortcut not available in the main port can easily add it in their fork by referring to said functions/macros simply by adding switch cases and populating them with clls like word_backward kill_word_forward etc.

@dpgeorge
Copy link
Member

Since alt- shortcuts are not currently used anywhere in this readline implementation it would be important to check -- for multiple terminal programs -- that this PR uses the correct escape sequences for it. For me (Linux + urxvt) it works correctly.

That makes already for 3 different shortcuts people want for this.

The simplest option is not to add any :)

Adding a way to customise the shortcuts via a config file would add more code than just supporting all the different keys by default.

So I would suggest that by default there just be one shortcut and it be consistent with some existing application, eg emacs.

@stinos
Copy link
Contributor

stinos commented Aug 27, 2019

Doesn't work on windows port but that's because the mapping in windows_mphal.c doesn't implement Alt so that's a different issue. Works in e.g. xfce4-terminal and Terminator but not in xterm here.

Per: micropython#5024 (comment)

Made the function STATIC, changed direction to an int, moved 'char c' into the
while loop, removed unnecessary check, renamed function to
get_next_word_cursor_offset() and made it return the signed cursor position offset
to the next word in the specified direction.

Also changed the shortcut comments to reflect the Emacs key notation.
@Jongy
Copy link
Contributor

Jongy commented Dec 14, 2019

@derekenos do you plan on finishing this? I wrote a quick forward-word and backward-word now and I thought to check in the existing PRs only after I was done... ;(

I can pick it up / continue with my impl. I've also made it work for "Ctrl+Right" / "Ctrl+Left" since I usually use them.

@derekenos
Copy link
Sponsor Author

@Jongy please feel free to pick up this up or continue with your own. I was at the point of adding tests but became busy with other things. I considered closing this PR but hoped to come back to it, and didn't want the feature-relevant conversation contained herein to disappear from sight.

@Jongy Jongy mentioned this pull request Dec 15, 2019
@Jongy
Copy link
Contributor

Jongy commented Jan 12, 2020

#5420 was merged.

@dpgeorge dpgeorge closed this Jan 12, 2020
tannewt pushed a commit to tannewt/circuitpython that referenced this pull request Jul 21, 2021
Don't blink blue on non-BLE workflow boards
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants