diff --git a/crates/modalkit/src/editing/action.rs b/crates/modalkit/src/editing/action.rs index ffe5fed..275e142 100644 --- a/crates/modalkit/src/editing/action.rs +++ b/crates/modalkit/src/editing/action.rs @@ -428,9 +428,14 @@ where #[non_exhaustive] pub enum MacroAction { /// Execute the contents of the contextually specified Register [*n* times](Count). + /// + /// If no register is specified, then this should default to [Register::UnnamedMacro]. Execute(Count), - /// Execute the contents of the previously specified macro [*n* times](Count). + /// Run the given macro string [*n* times](Count). + Run(String, Count), + + /// Execute the contents of the previously specified register [*n* times](Count). Repeat(Count), /// Start or stop recording a macro. diff --git a/crates/modalkit/src/editing/key.rs b/crates/modalkit/src/editing/key.rs index c3ea1ad..0d0b230 100644 --- a/crates/modalkit/src/editing/key.rs +++ b/crates/modalkit/src/editing/key.rs @@ -89,6 +89,7 @@ where (rope.to_string(), ctx.resolve(count)) }, + MacroAction::Run(s, count) => (s.clone(), ctx.resolve(count)), MacroAction::Repeat(count) => { let rope = store.registers.get_last_macro()?; @@ -284,7 +285,7 @@ mod tests { } } - #[derive(Clone, Debug)] + #[derive(Clone, Debug, Eq, PartialEq)] enum TestAction { Macro(MacroAction), SetFlag(bool), @@ -387,6 +388,34 @@ mod tests { } } + #[test] + fn test_macro_run() { + let (mut bindings, mut store) = setup_bindings(true); + let ctx = EditContext::default(); + + // Run a sequence of key presses twice. + let run = MacroAction::Run("fliffi".into(), 2.into()); + let _ = bindings.macro_command(&run, &ctx, &mut store).unwrap(); + + // Run the first time, starting in Normal mode. + assert_pop1!(bindings, TestAction::SetFlag(true), ctx); + assert_pop1!(bindings, TestAction::NoOp, ctx); + assert_pop1!(bindings, TestAction::NoOp, ctx); + assert_pop1!(bindings, TestAction::Type('f'), ctx); + assert_pop1!(bindings, TestAction::NoOp, ctx); + assert_pop1!(bindings, TestAction::SetFlag(true), ctx); + assert_pop1!(bindings, TestAction::NoOp, ctx); + + // Run the second time, but this time in Insert mode. + assert_pop1!(bindings, TestAction::Type('f'), ctx); + assert_pop1!(bindings, TestAction::Type('l'), ctx); + assert_pop1!(bindings, TestAction::Type('i'), ctx); + assert_pop1!(bindings, TestAction::Type('f'), ctx); + assert_pop1!(bindings, TestAction::NoOp, ctx); + assert_pop1!(bindings, TestAction::SetFlag(true), ctx); + assert_pop2!(bindings, TestAction::NoOp, ctx); + } + #[test] fn test_record_and_execute() { let (mut bindings, mut store) = setup_bindings(true);