From 030de46e6b9568f27fd89b1543d978b21da7464e Mon Sep 17 00:00:00 2001 From: PabloMansanet Date: Tue, 28 Jun 2022 21:30:27 +0900 Subject: [PATCH] Fix recursive macro crash and empty macro lockout (#2902) --- helix-term/src/commands.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 0a28444bd..d1bec0cef 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -4655,8 +4655,6 @@ fn replay_macro(cx: &mut Context) { return; } - cx.editor.macro_replaying.push(reg); - let keys: Vec = if let Some([keys_str]) = cx.editor.registers.read(reg) { match helix_view::input::parse_macro(keys_str) { Ok(keys) => keys, @@ -4670,6 +4668,10 @@ fn replay_macro(cx: &mut Context) { return; }; + // Once the macro has been fully validated, it's marked as being under replay + // to ensure we don't fall into infinite recursion. + cx.editor.macro_replaying.push(reg); + let count = cx.count(); cx.callback = Some(Box::new(move |compositor, cx| { for _ in 0..count { @@ -4677,7 +4679,9 @@ fn replay_macro(cx: &mut Context) { compositor.handle_event(crossterm::event::Event::Key(key.into()), cx); } } + // The macro under replay is cleared at the end of the callback, not in the + // macro replay context, or it will not correctly protect the user from + // replaying recursively. + cx.editor.macro_replaying.pop(); })); - - cx.editor.macro_replaying.pop(); }