modcli/output/input/
text.rs

1use crate::output::print;
2use std::io::{stdin, stdout, Write};
3
4/// Prompts for free-form text and returns the trimmed input.
5///
6/// Behavior:
7/// - On I/O failure, logs an error via `output::print` and retries.
8/// - If a validator is provided (see `prompt_text_with_validation`), it will retry on validation errors.
9pub fn prompt_text(message: &str) -> String {
10    prompt_text_with_validation(message, |_| Ok(()))
11}
12
13/// Prompts for text input with a validator.
14///
15/// Behavior:
16/// - On I/O failure, logs an error via `output::print` and retries.
17/// - On validation failure, shows a status message and retries.
18pub fn prompt_text_with_validation<F>(message: &str, validator: F) -> String
19where
20    F: Fn(&str) -> Result<(), &str>,
21{
22    let mut input = String::new();
23    loop {
24        print!("{message}: ");
25        if let Err(e) = stdout().flush() {
26            print::warn(&format!("flush failed: {e}"));
27        }
28        input.clear();
29        if let Err(e) = stdin().read_line(&mut input) {
30            print::error(&format!("Error reading input: {e}. Try again."));
31            continue;
32        }
33        let trimmed = input.trim();
34
35        match validator(trimmed) {
36            Ok(_) => return trimmed.to_string(),
37            Err(err) => print::status(&format!("Invalid input: {err}")),
38        }
39    }
40}