prompt_input/
primitive.rs

1use std::io::{self, Write};
2
3pub trait Promptable {
4    fn prompt(output: &str) -> Self;
5}
6
7pub trait PromptableWithOption
8where
9    Self: Sized,
10{
11    fn prompt(output: &str) -> Option<Self>;
12}
13
14pub trait PromptableWithAlternatives
15where
16    Self: Sized,
17{
18    fn prompt(output: &str, trues: Vec<&str>, falses: Vec<&str>) -> Option<Self>;
19}
20
21impl Promptable for String {
22    fn prompt(output: &str) -> Self {
23        print!("{}", output);
24        io::stdout().flush().unwrap();
25
26        let mut input = String::new();
27        io::stdin()
28            .read_line(&mut input)
29            .expect("Failed to read the prompt");
30
31        input.trim().to_string()
32    }
33}
34
35impl PromptableWithAlternatives for bool {
36    fn prompt(output: &str, trues: Vec<&str>, falses: Vec<&str>) -> Option<Self> {
37        let input = String::prompt(output).to_lowercase();
38
39        let mapped_trues: Vec<String> = trues.into_iter().map(|w| w.to_lowercase()).collect();
40        let mapped_falses: Vec<String> = falses.into_iter().map(|w| w.to_lowercase()).collect();
41
42        if mapped_trues.contains(&input) {
43            return Some(true);
44        }
45
46        if mapped_falses.contains(&input) {
47            return Some(false);
48        }
49
50        return None;
51    }
52}
53
54macro_rules! create_promptable_with_option {
55    ($($type:ty), *) => {
56        $(
57            impl PromptableWithOption for $type {
58                fn prompt(output: &str) -> Option<Self> {
59                    let input = String::prompt(output);
60
61                    input.parse().ok()
62                }
63            }
64        )*
65    };
66}
67
68create_promptable_with_option!(
69    i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, isize, usize, f32, f64, char
70);