121 lines
3.4 KiB
Rust
121 lines
3.4 KiB
Rust
use tokio::io::{self, AsyncWriteExt, BufReader};
|
|
use anyhow::Result;
|
|
use crate::generator::MessageGenerator;
|
|
|
|
pub async fn run_interactive_mode(mut generator: MessageGenerator) -> Result<MessageGenerator> {
|
|
let types = vec!["feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", "revert"];
|
|
|
|
generator.set_type(prompt_type(&types).await?);
|
|
generator.set_scope_opt(prompt_scope().await?);
|
|
generator.set_description(prompt_description().await?);
|
|
generator.set_body_opt(prompt_body().await?);
|
|
let is_breaking = prompt_breaking().await?;
|
|
generator.set_breaking(is_breaking);
|
|
if is_breaking {
|
|
generator.set_breaking_description(prompt_breaking_description().await?);
|
|
}
|
|
|
|
println!("\nGenerated commit message:");
|
|
println!("{}", generator.format_message());
|
|
|
|
Ok(generator)
|
|
}
|
|
|
|
async fn prompt_type(types: &[&str]) -> Result<String> {
|
|
let mut stdout = io::stdout();
|
|
|
|
println!("Select commit type:");
|
|
for (i, t) in types.iter().enumerate() {
|
|
println!(" {} - {}", i, t);
|
|
}
|
|
print!("Enter number (0-{}): ", types.len() - 1);
|
|
stdout.flush().await?;
|
|
|
|
let mut input = String::new();
|
|
let mut stdin = BufReader::new(io::stdin());
|
|
stdin.read_line(&mut input).await?;
|
|
|
|
let idx: Result<usize, _> = input.trim().parse();
|
|
match idx {
|
|
Ok(i) if i < types.len() => Ok(types[i].to_string()),
|
|
Ok(_) => {
|
|
eprintln!("Invalid selection, using default 'chore'");
|
|
Ok("chore".to_string())
|
|
}
|
|
Err(_) => {
|
|
eprintln!("Invalid input, using default 'chore'");
|
|
Ok("chore".to_string())
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn prompt_scope() -> Result<Option<String>> {
|
|
let mut stdout = io::stdout();
|
|
let mut stdin = BufReader::new(io::stdin());
|
|
|
|
print!("Scope (optional): ");
|
|
stdout.flush().await?;
|
|
|
|
let mut input = String::new();
|
|
stdin.read_line(&mut input).await?;
|
|
let trimmed = input.trim().to_string();
|
|
if trimmed.is_empty() {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some(trimmed))
|
|
}
|
|
}
|
|
|
|
async fn prompt_description() -> Result<String> {
|
|
let mut stdout = io::stdout();
|
|
let mut stdin = BufReader::new(io::stdin());
|
|
|
|
print!("Commit description: ");
|
|
stdout.flush().await?;
|
|
|
|
let mut input = String::new();
|
|
stdin.read_line(&mut input).await?;
|
|
Ok(input.trim().to_string())
|
|
}
|
|
|
|
async fn prompt_body() -> Result<Option<String>> {
|
|
let mut stdout = io::stdout();
|
|
let mut stdin = BufReader::new(io::stdin());
|
|
|
|
print!("Extended description (optional, leave empty to skip): ");
|
|
stdout.flush().await?;
|
|
|
|
let mut input = String::new();
|
|
stdin.read_line(&mut input).await?;
|
|
let trimmed = input.trim().to_string();
|
|
if trimmed.is_empty() {
|
|
Ok(None)
|
|
} else {
|
|
Ok(Some(trimmed))
|
|
}
|
|
}
|
|
|
|
async fn prompt_breaking() -> Result<bool> {
|
|
let mut stdout = io::stdout();
|
|
let mut stdin = BufReader::new(io::stdin());
|
|
|
|
print!("Is this a breaking change? [y/N]: ");
|
|
stdout.flush().await?;
|
|
|
|
let mut input = String::new();
|
|
stdin.read_line(&mut input).await?;
|
|
Ok(input.trim().eq_ignore_ascii_case("y"))
|
|
}
|
|
|
|
async fn prompt_breaking_description() -> Result<String> {
|
|
let mut stdout = io::stdout();
|
|
let mut stdin = BufReader::new(io::stdin());
|
|
|
|
print!("Describe the breaking change: ");
|
|
stdout.flush().await?;
|
|
|
|
let mut input = String::new();
|
|
stdin.read_line(&mut input).await?;
|
|
Ok(input.trim().to_string())
|
|
}
|