diff --git a/crates/nu-command/src/filesystem/cp.rs b/crates/nu-command/src/filesystem/cp.rs index d9a6d1e2e4..b84d76a750 100644 --- a/crates/nu-command/src/filesystem/cp.rs +++ b/crates/nu-command/src/filesystem/cp.rs @@ -322,8 +322,10 @@ fn interactive_copy( span: Span, copy_impl: impl Fn(PathBuf, PathBuf, Span) -> Value, ) -> Value { - let (interaction, confirmed) = - try_interaction(interactive, "cp: overwrite", &dst.to_string_lossy()); + let (interaction, confirmed) = try_interaction( + interactive, + format!("cp: overwrite '{}'? ", dst.to_string_lossy()), + ); if let Err(e) = interaction { Value::Error { error: ShellError::GenericError( diff --git a/crates/nu-command/src/filesystem/mv.rs b/crates/nu-command/src/filesystem/mv.rs index 76df68bc5a..39770ba8df 100644 --- a/crates/nu-command/src/filesystem/mv.rs +++ b/crates/nu-command/src/filesystem/mv.rs @@ -283,8 +283,10 @@ fn move_file( } if interactive && to.exists() { - let (interaction, confirmed) = - try_interaction(interactive, "mv: overwrite", &to.to_string_lossy()); + let (interaction, confirmed) = try_interaction( + interactive, + format!("mv: overwrite '{}'? ", to.to_string_lossy()), + ); if let Err(e) = interaction { return Err(ShellError::GenericError( format!("Error during interaction: {:}", e), diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index 28e651c174..c3b336e709 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -65,6 +65,11 @@ impl Command for Rm { .switch("force", "suppress error when no file", Some('f')) .switch("verbose", "print names of deleted files", Some('v')) .switch("interactive", "ask user to confirm action", Some('i')) + .switch( + "interactive-once", + "ask user to confirm action only once", + Some('I'), + ) .rest( "rest", SyntaxShape::GlobPattern, @@ -138,6 +143,7 @@ fn rm( let force = call.has_flag("force"); let verbose = call.has_flag("verbose"); let interactive = call.has_flag("interactive"); + let interactive_once = call.has_flag("interactive-once") && !interactive; let ctrlc = engine_state.ctrlc.clone(); @@ -299,6 +305,24 @@ fn rm( )); } + if interactive_once { + let (interaction, confirmed) = try_interaction( + interactive_once, + format!("rm: remove {} files? ", all_targets.len()), + ); + if let Err(e) = interaction { + return Err(ShellError::GenericError( + format!("Error during interaction: {:}", e), + "could not move".into(), + None, + None, + Vec::new(), + )); + } else if !confirmed { + return Ok(PipelineData::Empty); + } + } + Ok(all_targets .into_keys() .map(move |f| { @@ -325,8 +349,10 @@ fn rm( || is_fifo || is_empty() { - let (interaction, confirmed) = - try_interaction(interactive, "rm: remove", &f.to_string_lossy()); + let (interaction, confirmed) = try_interaction( + interactive, + format!("rm: remove '{}'? ", f.to_string_lossy()), + ); let result; #[cfg(all( diff --git a/crates/nu-command/src/filesystem/util.rs b/crates/nu-command/src/filesystem/util.rs index db15c58d0a..1ef1523b24 100644 --- a/crates/nu-command/src/filesystem/util.rs +++ b/crates/nu-command/src/filesystem/util.rs @@ -90,11 +90,9 @@ impl Resource {} pub fn try_interaction( interactive: bool, - prompt_msg: &str, - file_name: &str, + prompt: String, ) -> (Result, Box>, bool) { let interaction = if interactive { - let prompt = format!("{} '{}'? ", prompt_msg, file_name); match get_interactive_confirmation(prompt) { Ok(i) => Ok(Some(i)), Err(e) => Err(e),