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
|
#[cfg(test)]
mod tests;
use std::collections::HashMap;
use lazy_static::lazy_static;
use crate::{
display::DisplayColor,
input::{Event, InputOptions, KeyCode},
util::handle_view_data_scroll,
view::{LineSegment, ViewData, ViewLine},
};
lazy_static! {
pub(crate) static ref INPUT_OPTIONS: InputOptions = InputOptions::RESIZE | InputOptions::MOVEMENT;
}
pub(crate) struct Choice<T> {
map: HashMap<char, T>,
view_data: ViewData,
options: Vec<(T, char, String)>,
invalid_selection: bool,
}
impl<T> Choice<T>
where T: Clone
{
#[allow(clippy::pattern_type_mismatch)]
pub(crate) fn new(options: Vec<(T, char, String)>) -> Self {
let map = options
.iter()
.map(|(v, k, _)| {
let c = *k;
let t = v.clone();
(c, t)
})
.collect::<HashMap<char, T>>();
Self {
map,
options,
view_data: ViewData::new(|updater| {
updater.set_show_title(true);
updater.set_retain_scroll_position(false);
}),
invalid_selection: false,
}
}
pub(crate) fn set_prompt(&mut self, prompt_lines: Vec<ViewLine>) {
self.view_data.update_view_data(|updater| {
updater.clear();
for line in prompt_lines {
updater.push_leading_line(line);
}
updater.push_leading_line(ViewLine::new_empty_line());
});
}
#[allow(clippy::pattern_type_mismatch)]
pub(crate) fn get_view_data(&mut self) -> &ViewData {
let options = &self.options;
let invalid_selection = self.invalid_selection;
self.view_data.update_view_data(|updater| {
updater.clear_body();
for (_, key, description) in options {
updater.push_line(ViewLine::from(format!("{key}) {description}")));
}
updater.push_line(ViewLine::new_empty_line());
if invalid_selection {
updater.push_line(ViewLine::from(LineSegment::new_with_color(
"Invalid option selected. Please choose an option.",
DisplayColor::IndicatorColor,
)));
}
else {
updater.push_line(ViewLine::from(LineSegment::new_with_color(
"Please choose an option.",
DisplayColor::IndicatorColor,
)));
}
});
&self.view_data
}
pub(crate) fn handle_event(&mut self, event: Event, view_state: &crate::view::State) -> Option<&T> {
if handle_view_data_scroll(event, view_state).is_none() {
if let Event::Key(key_event) = event {
if let KeyCode::Char(c) = key_event.code {
if let Some(v) = self.map.get(&c) {
self.invalid_selection = false;
return Some(v);
}
}
self.invalid_selection = true;
}
}
None
}
}
|