Make Ctrl-C clear line and re-prompt in REPL instead of exiting
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.
This commit is contained in:
28
lua.c
28
lua.c
@@ -37,6 +37,11 @@ static lua_State *globalL = NULL;
|
||||
|
||||
static const char *progname = LUA_PROGNAME;
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
static volatile sig_atomic_t sigint_in_repl = 0;
|
||||
static sigjmp_buf repl_jmp;
|
||||
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
@@ -81,6 +86,16 @@ static void laction (int i) {
|
||||
}
|
||||
|
||||
|
||||
static void repl_sigint_handler (int i) {
|
||||
if (sigint_in_repl) {
|
||||
sigint_in_repl = 0;
|
||||
siglongjmp(repl_jmp, 1);
|
||||
}
|
||||
signal(i, SIG_DFL);
|
||||
raise(i);
|
||||
}
|
||||
|
||||
|
||||
static void print_usage (const char *badoption) {
|
||||
lua_writestringerror("%s: ", progname);
|
||||
if (badoption[1] == 'e' || badoption[1] == 'l')
|
||||
@@ -566,8 +581,11 @@ static int incomplete (lua_State *L, int status) {
|
||||
static int pushline (lua_State *L, int firstline) {
|
||||
char buffer[LUA_MAXINPUT];
|
||||
size_t l;
|
||||
char *b;
|
||||
const char *prmt = get_prompt(L, firstline);
|
||||
char *b = lua_readline(buffer, prmt);
|
||||
sigint_in_repl = 1;
|
||||
b = lua_readline(buffer, prmt);
|
||||
sigint_in_repl = 0;
|
||||
lua_pop(L, 1); /* remove prompt */
|
||||
if (b == NULL)
|
||||
return 0; /* no input */
|
||||
@@ -678,11 +696,19 @@ static void doREPL (lua_State *L) {
|
||||
const char *oldprogname = progname;
|
||||
progname = NULL; /* no 'progname' on errors in interactive mode */
|
||||
lua_initreadline(L);
|
||||
setsignal(SIGINT, repl_sigint_handler);
|
||||
if (sigsetjmp(repl_jmp, 1)) {
|
||||
/* Ctrl-C during input — print newline, clear stack, re-prompt */
|
||||
lua_writestringerror("%s", "\n");
|
||||
lua_settop(L, 0);
|
||||
setsignal(SIGINT, repl_sigint_handler);
|
||||
}
|
||||
while ((status = loadline(L)) != -1) {
|
||||
if (status == LUA_OK)
|
||||
status = docall(L, 0, LUA_MULTRET);
|
||||
if (status == LUA_OK) l_print(L);
|
||||
else report(L, status);
|
||||
setsignal(SIGINT, repl_sigint_handler); /* re-install after docall */
|
||||
}
|
||||
lua_settop(L, 0); /* clear stack */
|
||||
lua_writeline();
|
||||
|
||||
Reference in New Issue
Block a user