mermaid_cli/utils/
confirm.rs1use std::io::{self, IsTerminal, Write};
8
9use anyhow::{Result, bail};
10
11pub fn is_affirmative(s: &str) -> bool {
14 s.eq_ignore_ascii_case("y") || s.eq_ignore_ascii_case("yes")
15}
16
17pub fn should_refuse_noninteractive(is_tty: bool, assume_yes: bool) -> bool {
21 !is_tty && !assume_yes
22}
23
24pub fn confirm_or_refuse(prompt: &str, assume_yes: bool) -> Result<bool> {
29 if assume_yes {
30 return Ok(true);
31 }
32 if should_refuse_noninteractive(io::stdin().is_terminal(), assume_yes) {
33 bail!(
34 "Refusing to proceed without confirmation in a non-interactive session. \
35 Re-run in an interactive terminal, or pass --force/--yes to allow it."
36 );
37 }
38 print!("{prompt} [y/N]: ");
39 io::stdout().flush()?;
40 let mut input = String::new();
41 io::stdin().read_line(&mut input)?;
42 Ok(is_affirmative(input.trim()))
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn affirmative_accepts_only_y_yes() {
51 assert!(is_affirmative("y"));
52 assert!(is_affirmative("Y"));
53 assert!(is_affirmative("yes"));
54 assert!(is_affirmative("YES"));
55 assert!(!is_affirmative("n"));
56 assert!(!is_affirmative(""));
57 assert!(!is_affirmative("sure"));
58 }
59
60 #[test]
61 fn refuses_noninteractive_without_optin() {
62 assert!(should_refuse_noninteractive(false, false));
64 assert!(!should_refuse_noninteractive(false, true));
66 assert!(!should_refuse_noninteractive(true, false));
68 }
69
70 #[test]
71 fn confirm_returns_true_immediately_when_assume_yes() {
72 assert!(confirm_or_refuse("do the thing?", true).expect("assume_yes is infallible"));
74 }
75}