smart_read/
input_validation.rs

1use crate::*;
2
3
4
5/// Keeps taking using input until a programmed condition is met
6pub struct SimpleValidate<F: Fn(&str) -> Result<(), String>>(pub F);
7
8impl<F: Fn(&str) -> Result<(), String>> TryRead for SimpleValidate<F> {
9	type Output = String;
10	type Default = String;
11	fn try_read_line(self, prompt: Option<String>, default: Option<Self::Default>) -> BoxResult<Self::Output> {
12		let mut prompt = prompt.unwrap_or_default();
13		if let Some(default) = default.as_ref() {
14			prompt += &format!("(default: {default}) ");
15		}
16		loop {
17			
18			print!("{prompt}");
19			let input = read_stdin()?;
20			if input.is_empty() && let Some(default) = default {
21				return Ok(default.to_string());
22			}
23			match (self.0)(&input) {
24				Ok(_) => return Ok(input),
25				Err(error_message) => {
26					println!();
27					println!("{error_message}")
28				}
29			}
30			
31		}
32	}
33}
34
35
36
37/// Keeps taking using input until a programmed condition and transformation is met
38pub struct TransformValidate<F: Fn(String) -> Result<O, String>, O: Display>(pub F);
39
40impl<F: Fn(String) -> Result<O, String>, O: Display> TryRead for TransformValidate<F, O> {
41	type Output = O;
42	type Default = O;
43	fn try_read_line(self, prompt: Option<String>, default: Option<Self::Default>) -> BoxResult<Self::Output> {
44		let mut prompt = prompt.unwrap_or_default();
45		if let Some(default) = default.as_ref() {
46			prompt += &format!("(default: {default}) ");
47		}
48		loop {
49			
50			print!("{prompt}");
51			let input = read_stdin()?;
52			if input.is_empty() && let Some(default) = default {
53				return Ok(default);
54			}
55			match (self.0)(input) {
56				Ok(output) => return Ok(output),
57				Err(error_message) => {
58					println!();
59					println!("{error_message}")
60				}
61			}
62			
63		}
64	}
65}