diff --git a/src/find/matchers/exec.rs b/src/find/matchers/exec.rs index 23055e06..29a64960 100644 --- a/src/find/matchers/exec.rs +++ b/src/find/matchers/exec.rs @@ -6,7 +6,7 @@ use std::error::Error; use std::ffi::OsString; -use std::io::{stderr, Write}; +use std::io::{stderr, stdin, stdout, Write}; use std::path::Path; use std::process::Command; @@ -21,6 +21,7 @@ pub struct SingleExecMatcher { executable: String, args: Vec, exec_in_parent_dir: bool, + interactive: bool, } impl SingleExecMatcher { @@ -28,6 +29,7 @@ impl SingleExecMatcher { executable: &str, args: &[&str], exec_in_parent_dir: bool, + interactive: bool, ) -> Result> { let transformed_args = args .iter() @@ -46,6 +48,7 @@ impl SingleExecMatcher { executable: executable.to_string(), args: transformed_args, exec_in_parent_dir, + interactive, }) } } @@ -83,6 +86,25 @@ impl Matcher for SingleExecMatcher { } } } + + // support interactive exec + if self.interactive { + let tips = format!( + "{} ... {} > ? [y/n]: ", + self.executable, + path_to_file.to_string_lossy() + ); + #[allow(clippy::explicit_write)] + write!(stdout(), "{}", tips).unwrap(); + stdout().flush().unwrap(); + + let mut input = String::new(); + let _result = stdin().read_line(&mut input).unwrap(); + if !input.trim().contains('y') { + return false; + } + } + match command.status() { Ok(status) => status.success(), Err(e) => { diff --git a/src/find/matchers/mod.rs b/src/find/matchers/mod.rs index dfe21fbf..07ecaf13 100644 --- a/src/find/matchers/mod.rs +++ b/src/find/matchers/mod.rs @@ -596,7 +596,7 @@ fn build_matcher_tree( Some(SizeMatcher::new(size, &unit)?.into_box()) } "-empty" => Some(EmptyMatcher::new().into_box()), - "-exec" | "-execdir" => { + "-exec" | "-execdir" | "-ok" | "-okdir" => { let mut arg_index = i + 1; while arg_index < args.len() && args[arg_index] != ";" { if args[arg_index - 1] == "{}" && args[arg_index] == "+" { @@ -616,10 +616,16 @@ fn build_matcher_tree( let expression = args[i]; let executable = args[i + 1]; let exec_args = &args[i + 2..arg_index]; + let interactive = expression == "-ok" || expression == "-okdir"; i = arg_index; Some( - SingleExecMatcher::new(executable, exec_args, expression == "-execdir")? - .into_box(), + SingleExecMatcher::new( + executable, + exec_args, + expression == "-execdir", + interactive, + )? + .into_box(), ) } #[cfg(unix)] diff --git a/tests/exec_unit_tests.rs b/tests/exec_unit_tests.rs index 7f1502c4..c2ad0dec 100644 --- a/tests/exec_unit_tests.rs +++ b/tests/exec_unit_tests.rs @@ -34,6 +34,7 @@ fn matching_executes_code() { &path_to_testing_commandline(), &[temp_dir_path.as_ref(), "abc", "{}", "xyz"], false, + false, ) .expect("Failed to create matcher"); let deps = FakeDependencies::new(); @@ -65,6 +66,7 @@ fn matching_executes_code_in_files_directory() { &path_to_testing_commandline(), &[temp_dir_path.as_ref(), "abc", "{}", "xyz"], true, + false, ) .expect("Failed to create matcher"); let deps = FakeDependencies::new(); @@ -96,6 +98,7 @@ fn matching_embedded_filename() { &path_to_testing_commandline(), &[temp_dir_path.as_ref(), "abc{}x{}yz"], false, + false, ) .expect("Failed to create matcher"); let deps = FakeDependencies::new(); @@ -129,6 +132,7 @@ fn execdir_in_current_directory() { &path_to_testing_commandline(), &[temp_dir_path.as_ref(), "abc", "{}", "xyz"], true, + false, ) .expect("Failed to create matcher"); let deps = FakeDependencies::new(); @@ -167,6 +171,7 @@ fn execdir_in_root_directory() { &path_to_testing_commandline(), &[temp_dir_path.as_ref(), "abc", "{}", "xyz"], true, + false, ) .expect("Failed to create matcher"); let deps = FakeDependencies::new(); @@ -205,6 +210,7 @@ fn matching_fails_if_executable_fails() { "xyz", ], true, + false, ) .expect("Failed to create matcher"); let deps = FakeDependencies::new();