Initial commit: git-issue-commit CLI tool
This commit is contained in:
120
src/interactive/mod.rs
Normal file
120
src/interactive/mod.rs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
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())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user