diff options
author | Tim Ruffing <crypto@timruffing.de> | 2023-12-27 14:32:09 +0100 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2024-03-10 10:40:13 -0400 |
commit | 6f46dd516b84ad7d59b49c2e9e3fc1a2d4ef4d1c (patch) | |
tree | 4075841773bcb6992af91b1ec81b21d6c0b96f9e /src/macros.c | |
parent | d6f326452ecc761498d627a365c8014a467812eb (diff) | |
download | emacs-6f46dd516b84ad7d59b49c2e9e3fc1a2d4ef4d1c.tar.gz |
Continue reading in 'read-event' etc. at the end of a keyboard macro
This fixes a bug that could make 'read-event', 'read-char', and
'read-char-exclusive' erroneously return -1, an internal magic return
value of 'read_char' leaked from C to lisp. Instead of returning -1, the
aforementioned lisp functions now transparently continue reading
available input (e.g., from the keyboard) when reaching the end of a
keyboard macro.
* src/keyboard.c (read_char, read_key_sequence): Move handling
of the end of a keyboard macro from 'read_char' to its caller
'read_key_sequence', which is the only caller that can
meaningfully deal with this case.
* src/macros.c (Fexecute_kbd_macro): Document how the end of keyboard
macro is processed.
* etc/NEWS: Announce this change.
Diffstat (limited to 'src/macros.c')
-rw-r--r-- | src/macros.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/macros.c b/src/macros.c index faec9dc646d..230195d9488 100644 --- a/src/macros.c +++ b/src/macros.c @@ -314,6 +314,48 @@ buffer before the macro is executed. */) Vreal_this_command)); record_unwind_protect (pop_kbd_macro, tem); + /* The following loop starts the execution of possibly multiple + iterations of the macro. + + The state variables that control the execution of a single + iteration are Vexecuting_kbd_macro and executing_kbd_macro_index, + which can be accessed from lisp. The purpose of the variables + executing_kbd_macro and executing_kbd_macro_iteration is to + remember the most recently started macro and its iteration count. + This makes it possible to produce a meaningful message in case of + errors during the execution of the macro. + + In a single iteration, individual characters from the macro are + read by read_char, which takes care of incrementing + executing_kbd_macro_index after each character. + + The end of a macro iteration is handled as follows: + - read_key_sequence asks at_end_of_macro_p whether the end of the + iteration has been reached. If so, it returns the magic value 0 + to command_loop_1. + - command_loop_1 returns Qnil to command_loop_2. + - command_loop_2 returns Qnil to this function + (but only the returning is relevant, not the actual value). + + Macro executions form a stack. After the last iteration of the + execution of one stack item, or in case of an error during one of + the iterations, pop_kbd_macro (invoked via unwind-protect) will + restore Vexecuting_kbd_macro and executing_kbd_macro_index, and + run 'kbd-macro-termination-hook'. + + If read_char happens to be called at the end of a macro interation, + but before read_key_sequence could handle the end (e.g., when lisp + code calls 'read-event', 'read-char', or 'read-char-exclusive'), + read_char will simply continue reading other available input + (Bug#68272). Vexecuting_kbd_macro and executing_kbd_macro remain + untouched until the end of the iteration is handled. + + This is similar (in observable behavior) to a posibly simpler + implementation of keyboard macros in which this function pushed all + characters of the macro into the incoming event queue and returned + immediately. Maybe this is the implementation that we ideally + would like to have, but switching to it will require a larger code + change. */ do { Vexecuting_kbd_macro = final; |