miv_editor/app/command_line/
mod.rs

1use crate::commands::Command;
2
3#[derive(Debug)]
4pub struct CommandLine {
5    pub value: String,
6    pub cursor_position: usize,
7}
8
9impl Default for CommandLine {
10    fn default() -> Self {
11        Self::new()
12    }
13}
14
15impl CommandLine {
16    pub fn new() -> Self {
17        Self {
18            value: Default::default(),
19            cursor_position: Default::default(),
20        }
21    }
22
23    pub fn deactivate(&mut self) {
24        self.value = "".into();
25        self.cursor_position = 0;
26    }
27
28    pub fn move_cursor_left(&mut self) {
29        let cursor_moved_left = self.cursor_position.saturating_sub(1);
30        self.cursor_position = self.clamp_cursor(cursor_moved_left);
31    }
32
33    pub fn move_cursor_right(&mut self) {
34        let cursor_moved_right = self.cursor_position.saturating_add(1);
35        self.cursor_position = self.clamp_cursor(cursor_moved_right);
36    }
37
38    pub fn enter_char(&mut self, new_char: char) {
39        self.value.insert(self.cursor_position, new_char);
40        self.move_cursor_right();
41    }
42
43    pub fn delete_char(&mut self) {
44        let is_not_cursor_leftmost = self.cursor_position != 0;
45        if is_not_cursor_leftmost {
46            // Method "remove" is not used on the saved text for deleting the selected char.
47            // Reason: Using remove on String works on bytes instead of the chars.
48            // Using remove would require special care because of char boundaries.
49
50            let current_index = self.cursor_position;
51            let from_left_to_current_index = current_index - 1;
52
53            // Getting all characters before the selected character.
54            let before_char_to_delete = self.value.chars().take(from_left_to_current_index);
55            // Getting all characters after selected character.
56            let after_char_to_delete = self.value.chars().skip(current_index);
57
58            // Put all characters together except the selected one.
59            // By leaving the selected one out, it is forgotten and therefore deleted.
60            self.value = before_char_to_delete.chain(after_char_to_delete).collect();
61            self.move_cursor_left();
62        }
63    }
64
65    pub fn clamp_cursor(&self, new_cursor_pos: usize) -> usize {
66        new_cursor_pos.clamp(0, self.value.len())
67    }
68
69    pub fn get_commands(&self) -> Vec<Command> {
70        match self.value.as_str() {
71            "q" => vec![Command::Quit],
72            "w" => vec![Command::EditorSave],
73            "wq" => vec![Command::EditorSave, Command::Quit],
74            _ => todo!(),
75        }
76    }
77}