1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum PendingState {
6 Replace {
7 count: usize,
8 },
9 Find {
13 count: usize,
14 forward: bool,
15 till: bool,
16 },
17 AfterG {
22 count: usize,
23 },
24 AfterZ {
29 count: usize,
30 },
31 }
33
34#[derive(Debug, Clone, PartialEq, Eq)]
36pub enum Outcome {
37 Wait(PendingState),
39 Commit(crate::cmd::EngineCmd),
41 Cancel,
43 Forward,
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum Key {
52 Char(char),
53 Esc,
54 Enter,
55 Backspace,
56 Tab,
57 }
59
60pub fn step(state: PendingState, key: Key) -> Outcome {
61 match state {
62 PendingState::Replace { count } => match key {
63 Key::Esc => Outcome::Cancel,
64 Key::Char(ch) => Outcome::Commit(crate::cmd::EngineCmd::ReplaceChar { ch, count }),
65 Key::Enter => Outcome::Commit(crate::cmd::EngineCmd::ReplaceChar { ch: '\n', count }),
66 _ => Outcome::Cancel,
67 },
68 PendingState::Find {
69 count,
70 forward,
71 till,
72 } => match key {
73 Key::Esc => Outcome::Cancel,
74 Key::Char(ch) => Outcome::Commit(crate::cmd::EngineCmd::FindChar {
75 ch,
76 forward,
77 till,
78 count,
79 }),
80 _ => Outcome::Cancel,
82 },
83 PendingState::AfterG { count } => match key {
84 Key::Esc => Outcome::Cancel,
85 Key::Char(ch) => Outcome::Commit(crate::cmd::EngineCmd::AfterGChord { ch, count }),
86 _ => Outcome::Cancel,
88 },
89 PendingState::AfterZ { count } => match key {
90 Key::Esc => Outcome::Cancel,
91 Key::Char(ch) => Outcome::Commit(crate::cmd::EngineCmd::AfterZChord { ch, count }),
92 _ => Outcome::Cancel,
94 },
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use crate::cmd::EngineCmd;
102
103 #[test]
106 fn after_g_gg_commits() {
107 let state = PendingState::AfterG { count: 1 };
108 assert_eq!(
109 step(state, Key::Char('g')),
110 Outcome::Commit(EngineCmd::AfterGChord { ch: 'g', count: 1 })
111 );
112 }
113
114 #[test]
115 fn after_g_gv_commits() {
116 let state = PendingState::AfterG { count: 1 };
117 assert_eq!(
118 step(state, Key::Char('v')),
119 Outcome::Commit(EngineCmd::AfterGChord { ch: 'v', count: 1 })
120 );
121 }
122
123 #[test]
124 fn after_g_gu_operator_commits() {
125 let state = PendingState::AfterG { count: 1 };
127 assert_eq!(
128 step(state, Key::Char('U')),
129 Outcome::Commit(EngineCmd::AfterGChord { ch: 'U', count: 1 })
130 );
131 }
132
133 #[test]
134 fn after_g_gi_commits() {
135 let state = PendingState::AfterG { count: 1 };
136 assert_eq!(
137 step(state, Key::Char('i')),
138 Outcome::Commit(EngineCmd::AfterGChord { ch: 'i', count: 1 })
139 );
140 }
141
142 #[test]
143 fn after_g_esc_cancels() {
144 let state = PendingState::AfterG { count: 1 };
145 assert_eq!(step(state, Key::Esc), Outcome::Cancel);
146 }
147
148 #[test]
149 fn after_g_count_carry_through() {
150 let state = PendingState::AfterG { count: 5 };
152 assert_eq!(
153 step(state, Key::Char('g')),
154 Outcome::Commit(EngineCmd::AfterGChord { ch: 'g', count: 5 })
155 );
156 }
157
158 #[test]
159 fn after_g_non_char_cancels() {
160 let state = PendingState::AfterG { count: 1 };
162 assert_eq!(step(state, Key::Enter), Outcome::Cancel);
163 }
164
165 #[test]
168 fn after_z_zz_commits() {
169 let state = PendingState::AfterZ { count: 1 };
170 assert_eq!(
171 step(state, Key::Char('z')),
172 Outcome::Commit(EngineCmd::AfterZChord { ch: 'z', count: 1 })
173 );
174 }
175
176 #[test]
177 fn after_z_zf_commits() {
178 let state = PendingState::AfterZ { count: 1 };
179 assert_eq!(
180 step(state, Key::Char('f')),
181 Outcome::Commit(EngineCmd::AfterZChord { ch: 'f', count: 1 })
182 );
183 }
184
185 #[test]
186 fn after_z_esc_cancels() {
187 let state = PendingState::AfterZ { count: 1 };
188 assert_eq!(step(state, Key::Esc), Outcome::Cancel);
189 }
190
191 #[test]
192 fn after_z_count_carry_through() {
193 let state = PendingState::AfterZ { count: 3 };
195 assert_eq!(
196 step(state, Key::Char('z')),
197 Outcome::Commit(EngineCmd::AfterZChord { ch: 'z', count: 3 })
198 );
199 }
200
201 #[test]
202 fn after_z_non_char_cancels() {
203 let state = PendingState::AfterZ { count: 1 };
205 assert_eq!(step(state, Key::Enter), Outcome::Cancel);
206 }
207}