git-send 0.1.6

Commit and push changes with a single command
//! Interactive prompts and user input handling

use anyhow::Result;
use std::io::{self, Write};

/// Prompts the user for input.
pub fn prompt(prompt_text: &str) -> Result<String> {
    print!("{prompt_text}");
    io::stdout().flush()?;
    let mut input = String::new();
    io::stdin().read_line(&mut input)?;
    Ok(input.trim().to_string())
}

/// Gets default text for confirmation prompt.
const fn get_default_text(default: bool) -> &'static str {
    if default { "Y/n" } else { "y/N" }
}

/// Checks if a string represents a truthy value.
pub fn is_truthy(value: &str) -> bool {
    let lower = value.to_lowercase();
    lower == "1" || lower == "true" || lower == "yes" || lower == "on"
}

/// Gets environment variable value.
pub fn get_env_var(key: &str) -> Option<String> {
    std::env::var(key).ok()
}

/// Gets boolean from environment variable.
pub fn get_env_bool(key: &str) -> bool {
    get_env_var(key).is_some_and(|v| is_truthy(&v))
}

/// Prompts for yes/no confirmation.
pub fn confirm(prompt_text: &str, default: bool, auto_yes: bool) -> Result<bool> {
    if auto_yes {
        return Ok(true);
    }

    let default_text = get_default_text(default);
    let response = prompt(&format!("{prompt_text} [{default_text}]: "))?;

    if response.is_empty() {
        return Ok(default);
    }

    let lower = response.to_lowercase();
    Ok(lower == "y" || lower == "yes")
}

/// Prompts with default text (optimized string building)
pub fn prompt_with_default(prompt_text: &str, default_text: &str) -> Result<String> {
    use std::fmt::Write;
    let mut prompt_str = String::with_capacity(prompt_text.len() + default_text.len() + 15);
    write!(
        &mut prompt_str,
        "{prompt_text} [default: '{default_text}']: "
    )
    .expect("String write failed");
    prompt(&prompt_str)
}