1use crate::widgets::Editor;
9
10#[derive(Debug)]
13pub struct ConfigSetModal {
14 pub name: Editor,
15 pub value: Editor,
16 pub focus: ConfigSetField,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ConfigSetField {
21 Name,
22 Value,
23}
24
25#[derive(Debug)]
29pub enum Modal {
30 ConfigSet(ConfigSetModal),
31 Help,
32}
33
34#[derive(Debug, Default)]
36pub struct Stack {
37 modals: Vec<Modal>,
38}
39
40impl Stack {
41 #[must_use]
42 pub const fn new() -> Self {
43 Self { modals: Vec::new() }
44 }
45
46 pub fn push(&mut self, modal: Modal) {
47 self.modals.push(modal);
48 }
49
50 pub fn pop(&mut self) -> Option<Modal> {
51 self.modals.pop()
52 }
53
54 #[must_use]
55 pub fn top(&self) -> Option<&Modal> {
56 self.modals.last()
57 }
58
59 #[must_use]
60 pub fn top_mut(&mut self) -> Option<&mut Modal> {
61 self.modals.last_mut()
62 }
63
64 #[must_use]
65 pub fn is_empty(&self) -> bool {
66 self.modals.is_empty()
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use crate::widgets::EditMode;
74
75 fn a_config_set_modal() -> Modal {
76 Modal::ConfigSet(ConfigSetModal {
77 name: Editor::new(EditMode::Emacs),
78 value: Editor::new(EditMode::Emacs),
79 focus: ConfigSetField::Name,
80 })
81 }
82
83 #[test]
84 fn empty_stack_has_no_top() {
85 let stack = Stack::new();
86 assert!(stack.is_empty());
87 assert!(stack.top().is_none());
88 }
89
90 #[test]
91 fn push_then_pop_yields_last_in_first_out() {
92 let mut stack = Stack::new();
93 stack.push(Modal::Help);
94 stack.push(a_config_set_modal());
95 let popped = stack.pop().expect("expected a modal");
96 assert!(matches!(popped, Modal::ConfigSet(_)));
97 assert!(matches!(stack.top(), Some(Modal::Help)));
98 assert!(!stack.is_empty());
99 }
100
101 #[test]
102 fn pop_on_empty_returns_none() {
103 let mut stack = Stack::new();
104 assert!(stack.pop().is_none());
105 }
106
107 #[test]
108 fn top_mut_allows_mutating_focus_field() {
109 let mut stack = Stack::new();
110 stack.push(a_config_set_modal());
111 if let Some(Modal::ConfigSet(m)) = stack.top_mut() {
112 m.focus = ConfigSetField::Value;
113 }
114 match stack.top() {
115 Some(Modal::ConfigSet(m)) => assert_eq!(m.focus, ConfigSetField::Value),
116 _ => panic!("expected ConfigSet modal"),
117 }
118 }
119}