From eee2c994f9bfba05c2504a5fa9e64c44ad7248fd Mon Sep 17 00:00:00 2001 From: Ulyssa Date: Sun, 6 Sep 2026 21:33:18 -0400 Subject: [PATCH] Allow fetching the `ModalMachine` contained by `InputIterator` --- crates/keybindings/src/lib.rs | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/crates/keybindings/src/lib.rs b/crates/keybindings/src/lib.rs index f007d74..7a5b3fb 100644 --- a/crates/keybindings/src/lib.rs +++ b/crates/keybindings/src/lib.rs @@ -713,6 +713,22 @@ pub struct InputIterator<'a, Key: InputKey, S: Step> { keys: std::vec::IntoIter, } +impl InputIterator<'_, K, S> +where + K: InputKey, + S: Step, +{ + /// Return a reference to the inner [ModalMachine]. + pub fn inner(&self) -> &ModalMachine { + self.bindings + } + + /// Return a mutable reference to the inner [ModalMachine]. + pub fn inner_mut(&mut self) -> &mut ModalMachine { + self.bindings + } +} + impl Iterator for InputIterator<'_, K, S> where K: InputKey, @@ -1723,6 +1739,13 @@ mod tests { } } + impl TestContext { + fn operation(mut self, op: TestOperation) -> Self { + self.temp.operation = Some(op); + self + } + } + impl InputState for TestContext { type Output = Self; type CursorHint = Option; @@ -3145,4 +3168,46 @@ mod tests { assert_eq!(tm.mode(), TestMode::Insert); assert_eq!(tm.get_cursor_hint(), None); } + + #[test] + fn test_execute() { + let mut tm = TestMachine::default(); + let mut acts = vec![]; + + let mut iter = tm.execute(vec![ + key!('c'), + key!('b'), + ctl!('o'), + key!('d'), + key!('d'), + ctl!('l'), + key!('d'), + key!('d'), + key!('n'), + ]); + + while let Some((a, c)) = iter.next() { + let mode = iter.inner().mode(); + acts.push((a, c, mode)); + } + + // Verify that `InputIterator` gradually feeds keys, which means that we can see the mode + // after each input_key(), and not just the mode after they've all been done. + assert_eq!(acts, vec![ + (TestAction::Type('c'), TestContext::default(), TestMode::Insert), + (TestAction::Type('b'), TestContext::default(), TestMode::Insert), + ( + TestAction::EditLine, + TestContext::default().operation(TestOperation::Delete), + TestMode::Insert + ), + (TestAction::NoOp, TestContext::default(), TestMode::Normal), + ( + TestAction::EditLine, + TestContext::default().operation(TestOperation::Delete), + TestMode::Normal + ), + (TestAction::NoOp, TestContext::default(), TestMode::Normal), + ]); + } }