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:
@@ -1,6 +1,6 @@
|
|||||||
# Issue #11 — Ctrl-C REPL behaviour
|
# Issue #11 — Ctrl-C REPL behaviour
|
||||||
|
|
||||||
**Status:** open
|
**Status:** resolved
|
||||||
|
|
||||||
## Problem
|
## Problem
|
||||||
|
|
||||||
|
|||||||
28
lua.c
28
lua.c
@@ -37,6 +37,11 @@ static lua_State *globalL = NULL;
|
|||||||
|
|
||||||
static const char *progname = LUA_PROGNAME;
|
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) /* { */
|
#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) {
|
static void print_usage (const char *badoption) {
|
||||||
lua_writestringerror("%s: ", progname);
|
lua_writestringerror("%s: ", progname);
|
||||||
if (badoption[1] == 'e' || badoption[1] == 'l')
|
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) {
|
static int pushline (lua_State *L, int firstline) {
|
||||||
char buffer[LUA_MAXINPUT];
|
char buffer[LUA_MAXINPUT];
|
||||||
size_t l;
|
size_t l;
|
||||||
|
char *b;
|
||||||
const char *prmt = get_prompt(L, firstline);
|
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 */
|
lua_pop(L, 1); /* remove prompt */
|
||||||
if (b == NULL)
|
if (b == NULL)
|
||||||
return 0; /* no input */
|
return 0; /* no input */
|
||||||
@@ -678,11 +696,19 @@ static void doREPL (lua_State *L) {
|
|||||||
const char *oldprogname = progname;
|
const char *oldprogname = progname;
|
||||||
progname = NULL; /* no 'progname' on errors in interactive mode */
|
progname = NULL; /* no 'progname' on errors in interactive mode */
|
||||||
lua_initreadline(L);
|
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) {
|
while ((status = loadline(L)) != -1) {
|
||||||
if (status == LUA_OK)
|
if (status == LUA_OK)
|
||||||
status = docall(L, 0, LUA_MULTRET);
|
status = docall(L, 0, LUA_MULTRET);
|
||||||
if (status == LUA_OK) l_print(L);
|
if (status == LUA_OK) l_print(L);
|
||||||
else report(L, status);
|
else report(L, status);
|
||||||
|
setsignal(SIGINT, repl_sigint_handler); /* re-install after docall */
|
||||||
}
|
}
|
||||||
lua_settop(L, 0); /* clear stack */
|
lua_settop(L, 0); /* clear stack */
|
||||||
lua_writeline();
|
lua_writeline();
|
||||||
|
|||||||
Reference in New Issue
Block a user