1use std::{
2 io::{self, Stdin, Write},
3 str::FromStr,
4};
5
6use crate::Ignore;
7
8pub use ux::{input, input_string, prompt};
9
10pub mod ux;
11
12#[derive(Debug)]
13pub struct Prompt<'msg> {
14 message: Option<&'msg str>,
15 buf: String,
16 std_in: Stdin,
17}
18
19impl<'msg> Prompt<'msg> {
20 pub fn msg(mut self, msg: &'msg str) -> Self {
21 self.message = Some(msg);
22 self
23 }
24}
25
26impl Default for Prompt<'_> {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl Prompt<'_> {
33 pub fn new() -> Self {
34 Self {
35 message: None,
36 buf: String::new(),
37 std_in: io::stdin(),
38 }
39 }
40
41 fn run(&mut self) {
42 self.buf.clear();
43 if let Some(message) = self.message {
44 print!("{}", message);
45 io::stdout().flush().ignore();
46 }
47
48 self.std_in.read_line(&mut self.buf).ignore();
49 }
50
51 pub fn get<T: FromStr>(&mut self) -> Result<T, T::Err> {
52 self.get_str().parse()
53 }
54
55 pub fn get_str(&mut self) -> &str {
56 self.run();
57 self.buf.trim()
58 }
59
60 pub fn get_string(mut self) -> String {
61 self.run();
62 self.buf
63 }
64
65 pub fn get_until_ok<A, Ef>(&mut self, mut handle_error: Ef) -> A
66 where
67 A: FromStr,
68 Ef: FnMut(A::Err),
69 {
70 self.get().unwrap_or_else(|err| {
71 handle_error(err);
72 self.get_until_ok(handle_error)
73 })
74 }
75
76 pub fn get_until_ok_with<T, E, F, Ef>(&mut self, mut action: F, mut handle_error: Ef) -> T
77 where
78 F: FnMut(&str) -> Result<T, E>,
79 Ef: FnMut(E),
80 {
81 action(self.get_str()).unwrap_or_else(|err| {
82 handle_error(err);
83 self.get_until_ok_with(action, handle_error)
84 })
85 }
86}