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

feat: commandline edit --accept to instantly execute command #13728

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

mrdgo
Copy link

@mrdgo mrdgo commented Aug 29, 2024

Example use case: atuin

I primarily wanted to see how difficult this feature is to implement. I would appreciate some feedback/review.

Description

This feature had to be split in two separate PRs because I had to also touch reedline.
The concept is fairly simple: I added a queue to which commands can write ReedlineEvents to.
Reedline however, was not developed with asynchronous events in mind.
So it waits for input with event::read() without checking for new events in its queue.
So I added a check whether the queue is empty before blocking and waiting for new input.
This way commandline edit simply accepts a new flag, namely --accept and whenever it detects this flag, it writes a ReedlineEvent::Enter to the queue.

To use:

  • clone my fork gh repo clone mrdgo/nushell
  • cd nushell; cargo run
  • now you run a shell with this feature. Test it: commandline edit --accept "print hello"

This is the reason, why I committed the versioning foo in all the *.toml files. These should of course not be merged to main.

User-Facing Changes

New feature: commandline edit now accepts a flag --accept/-A that immediately executes the resulting command. As an atuin user, I would greatly appreciate.

Tests Formatting

I added a simple test case and it only shows the absence of a regression because run_test only captures stdout from the command it runs. --accept runs a new command whose output will not be captured by run_test.
How relevant will a test be? Couldn't we also run a .nu script to test this? Or maybe I access the event queue in the test and assert presence of a ReedlineEvent::Enter?

After Submitting

@mrdgo mrdgo marked this pull request as draft August 29, 2024 14:59
@mrdgo mrdgo marked this pull request as ready for review August 29, 2024 16:26
@mrdgo
Copy link
Author

mrdgo commented Aug 29, 2024

CI can probably not build because of relative paths for reedline, right? We will have to wait until that one is merged until these jobs can succeed.

Copy link
Member

@sholderbach sholderbach 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 giving this a try, as I mentioned on nushell/reedline#822 (comment) the change on reedline appears a bit overgeneralized to me.

repl.buffer = str;
repl.cursor_pos = repl.buffer.len();
}
if call.has_flag(engine_state, stack, "accept")? {
if let Ok(mut queue) = engine_state.reedline_event_queue.lock() {
queue.push(ReedlineEvent::Enter);
Copy link
Member

Choose a reason for hiding this comment

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

ReedlineEvent::Enter is not solitary confined to running the command.

  • if a menu is active it will perform its accepting action instead
  • it triggers a run of the ! history expression expansions if necessary
  • it will run the syntax validation to decide if it should insert a newline due to open expressions
  • if not it will return the entered content

https://github.com/nushell/reedline/blob/020142f6ee857353c289119a04d8fc71c474ce59/src/engine.rs#L1085-L1120
so this implementation choice may have surprising behavior based on the state of the line editor (see nushell/reedline#821 for folks wanting to have an always open menu)

Copy link
Author

Choose a reason for hiding this comment

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

I see, what do you suggest? Submit?

Copy link
Author

@mrdgo mrdgo Sep 11, 2024

Choose a reason for hiding this comment

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

Ooh and where do I find the code that does the history expansion? I would also give it a shot to use this feature to instantly accept a !! expansion.

nvm, I found it in reedline.

@@ -137,7 137,7 @@ rand = "0.8"
rand_chacha = "0.3.1"
ratatui = "0.26"
rayon = "1.10"
reedline = "0.34.0"
Copy link
Member

Choose a reason for hiding this comment

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

If you use a git dependency pointing to your fork and branch, things can be tested both in CI and more easily by folks just fetching for a functional shakedown.

In general we tend to specify our non-crates-io dependencies only in the patch section at the bottom of the main Cargo.toml (to centralize those dependencies that we can't merge or publish like that, and as the workspace dependency only became a thing post 1.64)

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I wouldn't spend too much time on this and clean it up completely when/if reedline is merged. Then I would only need to bump its version.

fn commandline_test_accept() -> TestResult {
// Explanation: run_test captures a command's output.
// But `--accept` executes a new command that then outputs "accepted"
run_test("commandline edit --accept \"print accepted\"", "")
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't the expected value contain accepted?

Copy link
Author

Choose a reason for hiding this comment

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

As stated in the comment above the code: commandline edit runs successfully without any output. Instead, it creates a new command that runs print accepted. Therefore, the command's output is empty and the successor's output will be "accepted".

Copy link
Collaborator

Choose a reason for hiding this comment

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

I can understand this but when I saw it, it seemed a bit weird that my history would have "commandline edit --accept "print accepted"" and then another entry for "print accepted". I mean, I understand it, but it was unexpected.

@mrdgo
Copy link
Author

mrdgo commented Sep 2, 2024

Oh and I completely forgot: thanks for your review! ❤️

@mrdgo
Copy link
Author

mrdgo commented Sep 11, 2024

I refactored to use a channel and use ReedlineEvent::Submit instead of ReedlineEvent::Enter. I kindly request a review :)

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.

Implement equivalent to ZSH's zle accept-line for better integration with atuin
3 participants