neophyte_ui/
cmdline.rs

1use neophyte_ui_event::{CmdlineShow, CmdlineSpecialChar, Content};
2
3#[derive(Debug, Clone, Default)]
4pub struct Cmdline {
5    pub mode: Option<Mode>,
6}
7
8impl Cmdline {
9    pub fn show(&mut self, event: CmdlineShow) {
10        let i = event.level as usize;
11        let level = event.into();
12        match &mut self.mode {
13            Some(Mode::Normal { levels }) => {
14                if i > levels.len() {
15                    levels.push(level);
16                } else {
17                    levels[i - 1] = level;
18                }
19            }
20            Some(Mode::Block {
21                previous_lines: _,
22                current_line,
23            }) => {
24                *current_line = level;
25            }
26            None => {
27                self.mode = Some(Mode::Normal {
28                    levels: vec![level],
29                })
30            }
31        }
32    }
33
34    pub fn hide(&mut self) {
35        if let Some(Mode::Normal { levels }) = &mut self.mode {
36            match levels.len() {
37                0 | 1 => {
38                    self.mode = None;
39                }
40                _ => {
41                    levels.pop();
42                }
43            }
44        }
45    }
46
47    pub fn hide_block(&mut self) {
48        self.mode = None;
49    }
50
51    pub fn show_block(&mut self, lines: Vec<Content>) {
52        self.mode = Some(Mode::Block {
53            previous_lines: lines,
54            // Will be filled in by a cmdline_show event before next flush
55            current_line: Default::default(),
56        });
57    }
58
59    pub fn append_block(&mut self, line: Content) {
60        if let Some(Mode::Block {
61            previous_lines,
62            current_line,
63        }) = &mut self.mode
64        {
65            previous_lines.push(line);
66            // Will be filled in by a cmdline_show event before next flush
67            *current_line = Default::default();
68        }
69    }
70
71    pub fn set_cursor_pos(&mut self, pos: u32) {
72        match &mut self.mode {
73            Some(Mode::Normal { levels }) => {
74                if let Some(level) = levels.last_mut() {
75                    level.cursor_pos = pos;
76                }
77            }
78            Some(Mode::Block {
79                previous_lines: _,
80                current_line,
81            }) => {
82                current_line.cursor_pos = pos;
83            }
84            None => {}
85        }
86    }
87
88    pub fn special(&mut self, event: CmdlineSpecialChar) {
89        let special = Some(Special::new(event.c, event.shift));
90        match &mut self.mode {
91            Some(Mode::Normal { levels }) => {
92                if let Some(level) = levels.last_mut() {
93                    level.special = special;
94                }
95            }
96            Some(Mode::Block {
97                previous_lines: _,
98                current_line,
99            }) => {
100                current_line.special = special;
101            }
102            None => {}
103        }
104    }
105}
106
107#[derive(Debug, Clone)]
108pub enum Mode {
109    Normal {
110        levels: Vec<Prompt>,
111    },
112    Block {
113        previous_lines: Vec<Content>,
114        current_line: Prompt,
115    },
116}
117
118#[derive(Debug, Clone, Default)]
119pub struct Prompt {
120    pub content_lines: Vec<Content>,
121    pub cursor_pos: u32,
122    pub first_char: Option<char>,
123    pub prompt: String,
124    pub special: Option<Special>,
125    #[allow(unused)]
126    pub indent: u32,
127}
128
129impl From<CmdlineShow> for Prompt {
130    fn from(value: CmdlineShow) -> Self {
131        Self {
132            content_lines: vec![value.content],
133            cursor_pos: value.pos,
134            first_char: value.firstc.chars().next(),
135            prompt: value.prompt,
136            special: None,
137            indent: value.indent,
138        }
139    }
140}
141
142#[derive(Debug, Clone)]
143pub struct Special {
144    #[allow(unused)]
145    pub c: char,
146    #[allow(unused)]
147    pub shift: bool,
148}
149
150impl Special {
151    pub fn new(c: char, shift: bool) -> Self {
152        Self { c, shift }
153    }
154}