use std::io::Write; use std::process::{Command, Output}; use std::io::Result as IoResult; use inquire::{Text, validator::Validation}; use inquire::Select; use inquire::ui::{RenderConfig, Styled}; use regex::Regex; fn execute_command(command: &str) -> IoResult { // Use Command to run the bash shell with the -c option to pass the command string let output: Output = Command::new("bash") .arg("-c") .arg(command) .output()?; if output.status.success() { // Convert the stdout of the command to a String Ok(String::from_utf8_lossy(&output.stdout).to_string()) } else { // Handle errors by converting stderr to a String and returning an Err variant let error_message = String::from_utf8_lossy(&output.stderr); Err(std::io::Error::new( std::io::ErrorKind::Other, format!("Command failed with error: {}", error_message), )) } } fn prompt(name:&str) -> String { let mut line = String::new(); print!("{}", name); std::io::stdout().flush().unwrap(); std::io::stdin().read_line(&mut line).expect("Error: Could not read a line"); return line.trim().to_string() } fn main() { let prompt_gen_command = "echo -n \"r-[${USER}@${HOSTNAME} ${PWD##*/}]$ \""; let mut empty_render_config: RenderConfig = RenderConfig::default(); empty_render_config = empty_render_config.with_prompt_prefix(Styled::new("")); empty_render_config = empty_render_config.with_answered_prompt_prefix(Styled::new("")); empty_render_config = empty_render_config.with_canceled_prompt_indicator(Styled::new("")); let re = Regex::new(r"CHG[0-9]{6}$").unwrap(); let options: Vec<&str> = vec!["File change", "Package Update", "Package Removal", "File Removal", "Misc. Command"]; let change_validator = move |input: &str| if input.chars().count() == 0 { Ok(Validation::Invalid("Change request cannot be empty".into())) } else if re.is_match(input) { Ok(Validation::Valid) } else { Ok(Validation::Invalid("Invalid change request (e.g: CHGXXXXXX)".into())) }; let mut bypass_change = false; loop { let prompt_command = match execute_command(&prompt_gen_command) { Ok(output) => { let prompt_output = prompt(&output); if prompt_output.chars().count() == 0 { continue; } else if prompt_output.starts_with("runme ") || prompt_output == "runme" { bypass_change = true; if prompt_output.len() > 6 { match execute_command(prompt_output.split_at(6).1) { Ok(output) => print!("{}", output), Err(e) => eprintln!("Command failed: {}", e), } } continue; } else { prompt_output } }, Err(_) => return }; if !bypass_change { let change_request = match Text::new("(e.g. CHGXXXXXX) Enter change request: ") .with_validator(change_validator.clone()) .prompt() { Ok(input) => input, Err(_) => return, }; println!("Change request validated: {}", change_request); let ans = Select::new("Change Type?", options.clone()) .with_render_config(empty_render_config.clone()) .prompt(); match ans { Ok(selected_option) => { println!("Selected option: {}", selected_option); match execute_command(&prompt_command) { Ok(output) => print!("{}", output), Err(e) => eprintln!("Command failed: {}", e), } } Err(_) => println!("not running command..."), } } else { match execute_command(&prompt_command) { Ok(output) => print!("{}", output), Err(e) => eprintln!("Command failed: {}", e) } } } }