Files
chg-shell/main.rs
2025-04-04 15:37:24 -04:00

112 lines
4.2 KiB
Rust

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<String> {
// 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)
}
}
}
}