commit c020d53e238ccb28b6cbf7ee9345a87244d05155
parent cb029377146f9cce87f0532ab55b4855c2f10738
Author: Benno Schulenberg <bensberg@telfort.nl>
Date: Sat, 27 Apr 2024 16:29:04 +0200
input: snip the `recordmacro` and `runmacro` keystrokes in a better way
When recording a macro over a laggy connection or on a slow, overloaded
computer, several keystrokes could be recorded in one burst, and if any
but the last of those keystrokes was the shortcut for `runmacro`, then
running the macro would lead to an infinite loop and nano would hang.
This new implementation of snipping the "last keystroke" will, however,
snip *too many* keystrokes when several of them were recorded at once
and `runmacro` or `recordmacro` was among them, resulting in a cropped
and thus misrecorded macro. But... that's better than hanging.
In general, though, the user should be slow and deliberate when
recording a macro: waiting for nano to have processed the last
keystroke before typing the next.
This fixes https://savannah.gnu.org/bugs/?65649.
The issue was reported by `correctmost`.
Problem existed since version 2.9.0, since macros were introduced.
Diffstat:
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/src/winio.c b/src/winio.c
@@ -79,6 +79,8 @@ static int *macro_buffer = NULL;
/* A buffer where the recorded key codes are stored. */
static size_t macro_length = 0;
/* The current length of the macro. */
+static size_t milestone = 0;
+ /* Where the last burst of recorded keystrokes started. */
/* Add the given code to the macro buffer. */
void add_to_macrobuffer(int code)
@@ -88,15 +90,6 @@ void add_to_macrobuffer(int code)
macro_buffer[macro_length - 1] = code;
}
-/* Remove the last key code plus any leading Esc codes from macro buffer. */
-void snip_last_keystroke(void)
-{
- if (macro_length > 0)
- macro_length--;
- while (macro_length > 0 && macro_buffer[macro_length - 1] == '\x1b')
- macro_length--;
-}
-
/* Start or stop the recording of keystrokes. */
void record_macro(void)
{
@@ -106,7 +99,8 @@ void record_macro(void)
macro_length = 0;
statusline(REMARK, _("Recording a macro..."));
} else {
- snip_last_keystroke();
+ /* Snip the keystroke that invoked this function. */
+ macro_length = milestone;
statusline(REMARK, _("Stopped recording"));
}
@@ -120,7 +114,7 @@ void run_macro(void)
{
if (recording) {
statusline(AHEM, _("Cannot run macro while recording"));
- snip_last_keystroke();
+ macro_length = milestone;
return;
}
@@ -280,6 +274,9 @@ void read_keys_from(WINDOW *frame)
/* If we got a SIGWINCH, get out as the frame argument is no longer valid. */
if (input == KEY_WINCH)
return;
+
+ /* Remember where the recording of this keystroke (or burst of them) started. */
+ milestone = macro_length;
#endif
/* Read in any remaining key codes using non-blocking input. */