diff --git a/crates/nu-cli/src/commands/commandline/edit.rs b/crates/nu-cli/src/commands/commandline/edit.rs index 7b51ba0002..2a01321ae5 100644 --- a/crates/nu-cli/src/commands/commandline/edit.rs +++ b/crates/nu-cli/src/commands/commandline/edit.rs @@ -26,6 +26,11 @@ impl Command for CommandlineEdit { "replaces the current contents of the buffer (default)", Some('r'), ) + .switch( + "accept", + "immediately executes the result after edit", + Some('A'), + ) .required( "str", SyntaxShape::String, @@ -61,6 +66,9 @@ impl Command for CommandlineEdit { repl.buffer = str; repl.cursor_pos = repl.buffer.len(); } + + repl.accept = call.has_flag(engine_state, stack, "accept")?; + Ok(Value::nothing(call.head).into_pipeline_data()) } } diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 7ec0b725c9..be66618537 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -491,7 +491,9 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) { // CLEAR STACK-REFERENCE 1 .with_highlighter(Box::::default()) // CLEAR STACK-REFERENCE 2 - .with_completer(Box::::default()); + .with_completer(Box::::default()) + // Ensure immediately accept is always cleared + .with_immediately_accept(false); // Let's grab the shell_integration configs let shell_integration_osc2 = config.shell_integration.osc2; @@ -671,7 +673,7 @@ fn loop_iteration(ctx: LoopContext) -> (bool, Stack, Reedline) { run_shell_integration_reset_application_mode(); } - flush_engine_state_repl_buffer(engine_state, &mut line_editor); + line_editor = flush_engine_state_repl_buffer(engine_state, line_editor); } Ok(Signal::CtrlC) => { // `Reedline` clears the line content. New prompt is shown @@ -1126,7 +1128,10 @@ fn run_shell_integration_reset_application_mode() { /// /// Clear the screen and output anything remaining in the EngineState buffer. /// -fn flush_engine_state_repl_buffer(engine_state: &mut EngineState, line_editor: &mut Reedline) { +fn flush_engine_state_repl_buffer( + engine_state: &mut EngineState, + mut line_editor: Reedline, +) -> Reedline { let mut repl = engine_state.repl_state.lock().expect("repl state mutex"); line_editor.run_edit_commands(&[ EditCommand::Clear, @@ -1136,8 +1141,13 @@ fn flush_engine_state_repl_buffer(engine_state: &mut EngineState, line_editor: & select: false, }, ]); + if repl.accept { + line_editor = line_editor.with_immediately_accept(true) + } + repl.accept = false; repl.buffer = "".to_string(); repl.cursor_pos = 0; + line_editor } /// diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 11335cfe06..45e7d13ef9 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -46,6 +46,8 @@ pub struct ReplState { pub buffer: String, // A byte position, as `EditCommand::MoveToPosition` is also a byte position pub cursor_pos: usize, + /// Immediately accept the buffer on the next loop. + pub accept: bool, } pub struct IsDebugging(AtomicBool); @@ -185,6 +187,7 @@ impl EngineState { repl_state: Arc::new(Mutex::new(ReplState { buffer: "".to_string(), cursor_pos: 0, + accept: false, })), table_decl_id: None, #[cfg(feature = "plugin")] @@ -1078,6 +1081,7 @@ impl EngineState { self.repl_state = Arc::new(Mutex::new(ReplState { buffer: "".to_string(), cursor_pos: 0, + accept: false, })); } if Mutex::is_poisoned(&self.jobs) { diff --git a/tests/repl/test_commandline.rs b/tests/repl/test_commandline.rs index 1b52797fc4..c40923cddb 100644 --- a/tests/repl/test_commandline.rs +++ b/tests/repl/test_commandline.rs @@ -140,3 +140,11 @@ fn commandline_test_cursor_end() -> TestResult { fn commandline_test_cursor_type() -> TestResult { run_test("commandline get-cursor | describe", "int") } + +#[test] +fn commandline_test_accepted_command() -> TestResult { + run_test( + "commandline edit --accept \"print accepted\"\n | commandline", + "print accepted", + ) +}