aboutsummaryrefslogtreecommitdiff
path: root/src/command.rs
blob: 3beb700772a2543ebac49e89981f0e1fdff8256b (plain)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#[derive(Debug)]
pub struct CommandBox {
    pub enabled: bool,
    pub history: Vec<String>,
    pub text: String,
    pub cursor: usize,
}

// cursor value of 0 is behind all text
// cursor value of n is after n characters (insert after index n - 1)
// cursor value of text.len() is after all text

impl CommandBox {
    pub fn new() -> Self {
        CommandBox {
            enabled: false,
            history: vec![],
            text: String::new(),
            cursor: 0,
        }
    }

    pub fn forward(&mut self) {
        if self.cursor < self.text.len() {
            self.cursor += 1;
        }
    }

    pub fn backward(&mut self) {
        self.cursor = self.cursor.saturating_sub(1);
    }

    pub fn backspace(&mut self) {
        if self.cursor != 0 {
            self.text.remove(self.cursor - 1);
            self.backward();
        }
    }

    pub fn delete(&mut self) {
        if self.cursor < self.text.len() {
            self.text.remove(self.cursor);
        }
    }

    pub fn push_str(&mut self, v: &str) {
        self.text.push_str(v);
        self.cursor += v.len();
    }

    pub fn is_empty(&self) -> bool {
        self.text.is_empty()
    }

    pub fn clear(&mut self) {
        self.text.clear();
        self.cursor = 0;
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    fn setup_with(text: &str) -> CommandBox {
        let mut cmd = CommandBox::new();
        cmd.push_str(text);
        cmd
    }

    #[test]
    fn entering_text() {
        let cmd = setup_with("save as file.png");
        assert_eq!(&cmd.text, "save as file.png");
        assert_eq!(cmd.cursor, 16)
    }

    #[test]
    fn backspacing_from_end() {
        let mut cmd = setup_with("save");
        cmd.backspace();
        assert_eq!(&cmd.text, "sav");
        assert_eq!(cmd.cursor, 3);
    }

    #[test]
    fn backspacing_from_middle() {
        let mut cmd = setup_with("save");
        cmd.backward();
        cmd.backspace();
        assert_eq!(&cmd.text, "sae");
        assert_eq!(cmd.cursor, 2);
    }

    #[test]
    fn delete() {
        let mut cmd = setup_with("save");
        cmd.backward();
        cmd.delete();
        assert_eq!(&cmd.text, "sav");
        assert_eq!(cmd.cursor, 3);
    }

    #[test]
    fn delete_end() {
        let mut cmd = setup_with("save");
        cmd.delete();
        assert_eq!(&cmd.text, "save");
    }

    #[test]
    fn delete_all() {
        let mut cmd = setup_with("save");
        for _ in 0..4 {
            cmd.backward();
        }
        for _ in 0..4 {
            cmd.delete();
        }
        assert_eq!(&cmd.text, "");
        assert_eq!(cmd.cursor, 0);
    }

    #[test]
    fn seeking() {
        let mut cmd = setup_with("save");
        for _ in 0..4 {
            cmd.backward();
        }
        assert_eq!(cmd.cursor, 0);
        cmd.forward();
        assert_eq!(cmd.cursor, 1);
    }
}