Use sigsetjmp/siglongjmp to catch SIGINT during readline/fgets input and jump back to the REPL loop with a fresh prompt. Running Lua code still gets interrupted via the existing laction/lstop mechanism. Fixes #11.
2.0 KiB
2.0 KiB
Issue #11 — Ctrl-C REPL behaviour
Status: resolved
Problem
The Lua REPL immediately exits on Ctrl-C. This is annoying — every other shell and REPL (bash, zsh, python, node) treats Ctrl-C as "cancel what I'm typing", not "quit".
Desired behaviour
Dirty line (cursor on a line with text already typed):
- Clear the current input line
- Print a fresh prompt on a new line
> local x = some_long_exp^C
>
Empty line (no text typed yet):
- Print
^Cand a fresh prompt (consistent with bash/zsh) - Optionally: two consecutive Ctrl-C on empty lines could exit (like Python's REPL), but this may be unnecessary if
Ctrl-D/exitworks
Current behaviour
The Lua REPL sets a debug hook via laction() on SIGINT that calls luaL_error(L, "interrupted!"). This aborts whatever Lua code is running and also kills the REPL input loop.
Implementation approach
The fix is in lua.c's REPL loop. The signal handler needs to behave differently depending on context:
During input (waiting for user to type a line):
- If using readline/libedit: readline already handles
SIGINT— it clears the line and returns. We just need to not treat this as a fatal error. - If using the
fgetsfallback: set a flag onSIGINT, check it afterfgetsreturns, clear the buffer and re-prompt.
During execution (running Lua code):
- Keep the existing behaviour: interrupt the running code with an error. This is correct —
SIGINTduring a long-running Lua computation should stop it.
Open questions
- Should readline's
rl_catch_signals/ signal handling be configured explicitly? - Does libedit (macOS default) handle
SIGINTthe same way as GNU readline? - Should Ctrl-C during a multi-line continuation (prompt
>>) discard the entire multi-line input and return to the primary prompt?
Files touched
| File | Description |
|---|---|
lua.c |
Modify signal handling in doREPL() / pushline() to distinguish input vs execution context |