diff options
Diffstat (limited to 'src/commands/custom_search.rs')
-rw-r--r-- | src/commands/custom_search.rs | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/commands/custom_search.rs b/src/commands/custom_search.rs new file mode 100644 index 0000000..422143e --- /dev/null +++ b/src/commands/custom_search.rs @@ -0,0 +1,110 @@ +use super::change_directory::change_directory; +use super::sub_process::current_filenames; +use crate::commands::cursor_move; +use crate::context::AppContext; +use crate::error::{AppError, AppErrorKind, AppResult}; +use crate::ui::AppBackend; +use shell_words::split; +use std::process::{Command, Stdio}; + +pub fn custom_search( + context: &mut AppContext, + backend: &mut AppBackend, + words: &[String], + interactive: bool, +) -> AppResult { + let custom_command = context + .config_ref() + .custom_commands + .as_slice() + .iter() + .find(|x| x.name == words[0]) + .ok_or(AppError::new( + AppErrorKind::InvalidParameters, + "No custom command with given name".into(), + ))? + .command + .clone(); + + let current_filenames = current_filenames(context); + + let text = custom_command.replace("%s", ¤t_filenames.join(" ")); + let text = text.replace( + "%text", + &words + .iter() + .skip(1) + .cloned() + .collect::<Vec<String>>() + .join(" "), + ); + let mut command_with_args: Vec<String> = split(&text).map_err(|_| { + AppError::new( + AppErrorKind::InvalidParameters, + "Command cannot be splitted".into(), + ) + })?; + + let mut cmd = Command::new(command_with_args.remove(0)); + command_with_args.into_iter().for_each(|x| { + cmd.arg(x); + }); + + let cmd_result = if interactive { + backend.terminal_drop(); + let cmd_result = cmd + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()? + .wait_with_output()?; + backend.terminal_restore()?; + cmd_result + } else { + cmd.output()? + }; + + if cmd_result.status.success() { + let returned_text = std::str::from_utf8(&cmd_result.stdout) + .map_err(|_| { + AppError::new( + AppErrorKind::ParseError, + "Could not get command result as utf8".into(), + ) + })? + .trim_end(); + + let path = std::path::Path::new(returned_text); + change_directory( + context, + path.parent().ok_or(AppError::new( + AppErrorKind::ParseError, + "Could not get parent directory".into(), + ))?, + )?; + + if let Some(current_dir_items) = context.tab_context_ref().curr_tab_ref().curr_list_ref() { + let position = current_dir_items + .iter() + .enumerate() + .find(|x| x.1.file_name() == path.file_name().unwrap_or_default()) + .map(|x| x.0) + .unwrap_or_default(); + + cursor_move::cursor_move(context, position); + } + + Ok(()) + } else { + let returned_text = std::str::from_utf8(&cmd_result.stderr).map_err(|_| { + AppError::new( + AppErrorKind::ParseError, + "Could not get command result as utf8".into(), + ) + })?; + + Err(AppError::new( + AppErrorKind::ParseError, + format!("Command failed: {}", returned_text), + )) + } +} |