1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::{read_string, BoxResult, ReadData, ReadLine};
use std::{collections::{LinkedList, VecDeque}, fmt::Display};





/// Internal utility function
pub fn read_input_option<T: Display + Clone>(choices: &[T], default: Option<usize>, mut read_data: ReadData<T>) -> BoxResult<T> {
	let prompt = read_data.prompt.unwrap_or(String::from("Enter one of the following:"));
	let choice_strings =
		choices.iter()
		.map(ToString::to_string)
		.collect::<Vec<_>>();
	loop {
		
		println!("{prompt}");
		for (i, choice) in choice_strings.iter().enumerate() {
			if let Some(default) = default {
				if i == default {
					println!("[{choice}]");
				} else {
					println!(" {choice}");
				}
			} else {
				println!("{choice}");
			}
		}
		
		let output = read_string(&mut read_data.input)?;
		if output.is_empty() && let Some(default) = default {
			return Ok(choices[default].clone());
		}
		
		for (i, choice) in choice_strings.iter().enumerate() {
			if choice.eq_ignore_ascii_case(&output) {
				return Ok(choices[i].clone());
			}
		}
		
		println!("Invalid option.");
	}
}





impl<'a, T: Display + Clone + PartialEq> ReadLine for &[T] {
	type Output = T;
	fn try_read_line(&self, read_data: ReadData<Self::Output>) -> BoxResult<Self::Output> {
		let default =
			self.iter().enumerate()
			.find(|v| Some(v.1) == read_data.default.as_ref())
			.map(|v| v.0);
		read_input_option(self, default, read_data)
	}
}

impl<'a, T: Display + Clone + PartialEq, const LEN: usize> ReadLine for &[T; LEN] {
	type Output = T;
	fn try_read_line(&self, read_data: ReadData<Self::Output>) -> BoxResult<Self::Output> {
		let default =
			self.iter().enumerate()
			.find(|v| Some(v.1) == read_data.default.as_ref())
			.map(|v| v.0);
		read_input_option(*self, default, read_data)
	}
}

impl<'a, T: Display + Clone + PartialEq> ReadLine for Vec<T> {
	type Output = T;
	fn try_read_line(&self, read_data: ReadData<Self::Output>) -> BoxResult<Self::Output> {
		let default =
			self.iter().enumerate()
			.find(|v| Some(v.1) == read_data.default.as_ref())
			.map(|v| v.0);
		read_input_option(self, default, read_data)
	}
}

impl<'a, T: Display + Clone + PartialEq> ReadLine for VecDeque<T> {
	type Output = T;
	fn try_read_line(&self, read_data: ReadData<Self::Output>) -> BoxResult<Self::Output> {
		let default =
			self.iter().enumerate()
			.find(|v| Some(v.1) == read_data.default.as_ref())
			.map(|v| v.0);
		read_input_option(&self.iter().cloned().collect::<Vec<_>>(), default, read_data)
	}
}

impl<'a, T: Display + Clone + PartialEq> ReadLine for LinkedList<T> {
	type Output = T;
	fn try_read_line(&self, read_data: ReadData<Self::Output>) -> BoxResult<Self::Output> {
		let default =
			self.iter().enumerate()
			.find(|v| Some(v.1) == read_data.default.as_ref())
			.map(|v| v.0);
		read_input_option(&self.iter().cloned().collect::<Vec<_>>(), default, read_data)
	}
}