diff options
Diffstat (limited to 'src/command.rs')
-rw-r--r-- | src/command.rs | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/command.rs b/src/command.rs new file mode 100644 index 0000000..3beb700 --- /dev/null +++ b/src/command.rs | |||
@@ -0,0 +1,134 @@ | |||
1 | #[derive(Debug)] | ||
2 | pub struct CommandBox { | ||
3 | pub enabled: bool, | ||
4 | pub history: Vec<String>, | ||
5 | pub text: String, | ||
6 | pub cursor: usize, | ||
7 | } | ||
8 | |||
9 | // cursor value of 0 is behind all text | ||
10 | // cursor value of n is after n characters (insert after index n - 1) | ||
11 | // cursor value of text.len() is after all text | ||
12 | |||
13 | impl CommandBox { | ||
14 | pub fn new() -> Self { | ||
15 | CommandBox { | ||
16 | enabled: false, | ||
17 | history: vec![], | ||
18 | text: String::new(), | ||
19 | cursor: 0, | ||
20 | } | ||
21 | } | ||
22 | |||
23 | pub fn forward(&mut self) { | ||
24 | if self.cursor < self.text.len() { | ||
25 | self.cursor += 1; | ||
26 | } | ||
27 | } | ||
28 | |||
29 | pub fn backward(&mut self) { | ||
30 | self.cursor = self.cursor.saturating_sub(1); | ||
31 | } | ||
32 | |||
33 | pub fn backspace(&mut self) { | ||
34 | if self.cursor != 0 { | ||
35 | self.text.remove(self.cursor - 1); | ||
36 | self.backward(); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | pub fn delete(&mut self) { | ||
41 | if self.cursor < self.text.len() { | ||
42 | self.text.remove(self.cursor); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | pub fn push_str(&mut self, v: &str) { | ||
47 | self.text.push_str(v); | ||
48 | self.cursor += v.len(); | ||
49 | } | ||
50 | |||
51 | pub fn is_empty(&self) -> bool { | ||
52 | self.text.is_empty() | ||
53 | } | ||
54 | |||
55 | pub fn clear(&mut self) { | ||
56 | self.text.clear(); | ||
57 | self.cursor = 0; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | #[cfg(test)] | ||
62 | mod tests { | ||
63 | use super::*; | ||
64 | |||
65 | fn setup_with(text: &str) -> CommandBox { | ||
66 | let mut cmd = CommandBox::new(); | ||
67 | cmd.push_str(text); | ||
68 | cmd | ||
69 | } | ||
70 | |||
71 | #[test] | ||
72 | fn entering_text() { | ||
73 | let cmd = setup_with("save as file.png"); | ||
74 | assert_eq!(&cmd.text, "save as file.png"); | ||
75 | assert_eq!(cmd.cursor, 16) | ||
76 | } | ||
77 | |||
78 | #[test] | ||
79 | fn backspacing_from_end() { | ||
80 | let mut cmd = setup_with("save"); | ||
81 | cmd.backspace(); | ||
82 | assert_eq!(&cmd.text, "sav"); | ||
83 | assert_eq!(cmd.cursor, 3); | ||
84 | } | ||
85 | |||
86 | #[test] | ||
87 | fn backspacing_from_middle() { | ||
88 | let mut cmd = setup_with("save"); | ||
89 | cmd.backward(); | ||
90 | cmd.backspace(); | ||
91 | assert_eq!(&cmd.text, "sae"); | ||
92 | assert_eq!(cmd.cursor, 2); | ||
93 | } | ||
94 | |||
95 | #[test] | ||
96 | fn delete() { | ||
97 | let mut cmd = setup_with("save"); | ||
98 | cmd.backward(); | ||
99 | cmd.delete(); | ||
100 | assert_eq!(&cmd.text, "sav"); | ||
101 | assert_eq!(cmd.cursor, 3); | ||
102 | } | ||
103 | |||
104 | #[test] | ||
105 | fn delete_end() { | ||
106 | let mut cmd = setup_with("save"); | ||
107 | cmd.delete(); | ||
108 | assert_eq!(&cmd.text, "save"); | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn delete_all() { | ||
113 | let mut cmd = setup_with("save"); | ||
114 | for _ in 0..4 { | ||
115 | cmd.backward(); | ||
116 | } | ||
117 | for _ in 0..4 { | ||
118 | cmd.delete(); | ||
119 | } | ||
120 | assert_eq!(&cmd.text, ""); | ||
121 | assert_eq!(cmd.cursor, 0); | ||
122 | } | ||
123 | |||
124 | #[test] | ||
125 | fn seeking() { | ||
126 | let mut cmd = setup_with("save"); | ||
127 | for _ in 0..4 { | ||
128 | cmd.backward(); | ||
129 | } | ||
130 | assert_eq!(cmd.cursor, 0); | ||
131 | cmd.forward(); | ||
132 | assert_eq!(cmd.cursor, 1); | ||
133 | } | ||
134 | } | ||