diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-09-06T11·01+0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-09-06T11·01+0200 |
commit | 4fb82d3d800be9a53631c3c8a3321a359306d835 (patch) | |
tree | 0749f81754eaa036af6a30cd60da6570411c9a88 | |
parent | 504563ea4431f765028dc0ccacd5ee834d0d8a91 (diff) |
Handle SIGINT to cancel the current line
-rw-r--r-- | nix-repl.cc | 42 |
1 files changed, 37 insertions, 5 deletions
diff --git a/nix-repl.cc b/nix-repl.cc index 0b84834491e7..bb205211793f 100644 --- a/nix-repl.cc +++ b/nix-repl.cc @@ -1,6 +1,8 @@ #include <iostream> #include <cstdlib> +#include <setjmp.h> + #include <readline/readline.h> #include <readline/history.h> @@ -42,13 +44,41 @@ void printHelp() } +/* Apparently, the only way to get readline() to return on Ctrl-C + (SIGINT) is to use siglongjmp(). That's fucked up... */ +static sigjmp_buf sigintJmpBuf; + + +static void sigintHandler(int signo) +{ + siglongjmp(sigintJmpBuf, 1); +} + + bool getLine(string & line) { - char * s = readline("nix-repl> "); - if (!s) return false; - line = chomp(string(s)); - free(s); - if (line != "") add_history(line.c_str()); + struct sigaction act, old; + act.sa_handler = sigintHandler; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + if (sigaction(SIGINT, &act, &old)) + throw SysError("installing handler for SIGINT"); + + if (sigsetjmp(sigintJmpBuf, 1)) + line = ""; + else { + char * s = readline("nix-repl> "); + if (!s) return false; + line = chomp(string(s)); + free(s); + if (line != "") add_history(line.c_str()); + } + + _isInterrupted = 0; + + if (sigaction(SIGINT, &old, 0)) + throw SysError("restoring handler for SIGINT"); + return true; } @@ -98,6 +128,8 @@ void NixRepl::mainLoop() void NixRepl::processLine(string line) { + if (line == "") return; + if (string(line, 0, 2) == ":a") { Value v; evalString(string(line, 2), v); |