1use std::iter::once;
2
3use crate::Status;
4use itertools::chain;
5use ratatui::{
6    crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers},
7    prelude::*,
8    widgets::StatefulWidget,
9};
10
11pub trait Prompt: StatefulWidget {
13    fn draw(self, frame: &mut Frame, area: Rect, state: &mut Self::State);
21}
22
23#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
25pub enum FocusState {
26    #[default]
27    Unfocused,
28    Focused,
29}
30
31pub trait State {
45    fn status(&self) -> Status;
47
48    fn status_mut(&mut self) -> &mut Status;
50
51    fn focus_state_mut(&mut self) -> &mut FocusState;
53
54    fn focus_state(&self) -> FocusState;
56
57    fn focus(&mut self) {
59        *self.focus_state_mut() = FocusState::Focused;
60    }
61
62    fn blur(&mut self) {
64        *self.focus_state_mut() = FocusState::Unfocused;
65    }
66
67    fn is_focused(&self) -> bool {
69        self.focus_state() == FocusState::Focused
70    }
71
72    fn position(&self) -> usize;
74
75    fn position_mut(&mut self) -> &mut usize;
77
78    fn cursor(&self) -> (u16, u16);
80
81    fn cursor_mut(&mut self) -> &mut (u16, u16);
83
84    fn value(&self) -> &str;
86
87    fn value_mut(&mut self) -> &mut String;
89
90    fn len(&self) -> usize {
91        self.value().chars().count()
92    }
93
94    fn is_empty(&self) -> bool {
95        self.value().len() == 0
96    }
97
98    fn handle_key_event(&mut self, key_event: KeyEvent) {
99        if key_event.kind == KeyEventKind::Release {
100            return;
101        }
102
103        match (key_event.code, key_event.modifiers) {
104            (KeyCode::Enter, _) => self.complete(),
105            (KeyCode::Esc, _) | (KeyCode::Char('c'), KeyModifiers::CONTROL) => self.abort(),
106            (KeyCode::Left, _) | (KeyCode::Char('b'), KeyModifiers::CONTROL) => self.move_left(),
107            (KeyCode::Right, _) | (KeyCode::Char('f'), KeyModifiers::CONTROL) => self.move_right(),
108            (KeyCode::Home, _) | (KeyCode::Char('a'), KeyModifiers::CONTROL) => self.move_start(),
109            (KeyCode::End, _) | (KeyCode::Char('e'), KeyModifiers::CONTROL) => self.move_end(),
110            (KeyCode::Backspace, _) | (KeyCode::Char('h'), KeyModifiers::CONTROL) => {
111                self.backspace();
112            }
113            (KeyCode::Delete, _) | (KeyCode::Char('d'), KeyModifiers::CONTROL) => self.delete(),
114            (KeyCode::Char('k'), KeyModifiers::CONTROL) => self.kill(),
115            (KeyCode::Char('u'), KeyModifiers::CONTROL) => self.truncate(),
116            (KeyCode::Char(c), KeyModifiers::NONE | KeyModifiers::SHIFT) => self.push(c),
117            _ => {}
118        }
119    }
120
121    fn complete(&mut self) {
122        *self.status_mut() = Status::Done;
123    }
124
125    fn abort(&mut self) {
126        *self.status_mut() = Status::Aborted;
127    }
128
129    fn delete(&mut self) {
130        let position = self.position();
131        if position == self.len() {
132            return;
133        }
134        *self.value_mut() = chain!(
135            self.value().chars().take(position),
136            self.value().chars().skip(position + 1)
137        )
138        .collect();
139    }
140
141    fn backspace(&mut self) {
142        let position = self.position();
143        if position == 0 {
144            return;
145        }
146        *self.value_mut() = chain!(
147            self.value().chars().take(position.saturating_sub(1)),
148            self.value().chars().skip(position)
149        )
150        .collect();
151        *self.position_mut() = position.saturating_sub(1);
152    }
153
154    fn move_right(&mut self) {
155        if self.position() == self.len() {
156            return;
157        }
158        *self.position_mut() = self.position().saturating_add(1);
159    }
160
161    fn move_left(&mut self) {
162        *self.position_mut() = self.position().saturating_sub(1);
163    }
164
165    fn move_end(&mut self) {
166        *self.position_mut() = self.len();
167    }
168
169    fn move_start(&mut self) {
170        *self.position_mut() = 0;
171    }
172
173    fn kill(&mut self) {
174        let position = self.position();
175        self.value_mut().truncate(position);
176    }
177
178    fn truncate(&mut self) {
179        self.value_mut().clear();
180        *self.position_mut() = 0;
181    }
182
183    fn push(&mut self, c: char) {
184        if self.position() == self.len() {
185            self.value_mut().push(c);
186        } else {
187            *self.value_mut() = chain![
191                self.value().chars().take(self.position()),
192                once(c),
193                self.value().chars().skip(self.position())
194            ]
195            .collect();
196        }
197        *self.position_mut() = self.position().saturating_add(1);
198    }
199}
200
201#[cfg(test)]
202mod tests {
203    use super::*;
204
205    #[test]
206    fn status_symbols() {
207        assert_eq!(Status::Pending.symbol(), "?".cyan());
208        assert_eq!(Status::Aborted.symbol(), "✘".red());
209        assert_eq!(Status::Done.symbol(), "✔".green());
210    }
211}