This commit is contained in:
Eelco Dolstra 2016-02-18 19:33:46 +01:00
commit 02daf2ec0b

View file

@ -41,7 +41,7 @@ struct NixRepl
NixRepl(const Strings & searchPath); NixRepl(const Strings & searchPath);
void mainLoop(const Strings & files); void mainLoop(const Strings & files);
void completePrefix(string prefix); void completePrefix(string prefix);
bool getLine(string & line); bool getLine(string & input, const char * prompt);
bool processLine(string line); bool processLine(string line);
void loadFile(const Path & path); void loadFile(const Path & path);
void initEnv(); void initEnv();
@ -96,21 +96,35 @@ void NixRepl::mainLoop(const Strings & files)
using_history(); using_history();
read_history(0); read_history(0);
string input;
while (true) { while (true) {
string line; // When continuing input from previous lines, don't print a prompt, just align to the same
if (!getLine(line)) { // number of chars as the prompt.
const char * prompt = input.empty() ? "nix-repl> " : " ";
if (!getLine(input, prompt)) {
std::cout << std::endl; std::cout << std::endl;
break; break;
} }
try { try {
if (!processLine(removeWhitespace(line))) return; if (!processLine(input)) return;
} catch (ParseError & e) {
if (e.msg().find("unexpected $end") != std::string::npos) {
// For parse errors on incomplete input, we continue waiting for the next line of
// input without clearing the input so far.
continue;
} else {
printMsg(lvlError, "error: " + e.msg());
}
} catch (Error & e) { } catch (Error & e) {
printMsg(lvlError, "error: " + e.msg()); printMsg(lvlError, "error: " + e.msg());
} catch (Interrupted & e) { } catch (Interrupted & e) {
printMsg(lvlError, "error: " + e.msg()); printMsg(lvlError, "error: " + e.msg());
} }
// We handled the current input fully, so we should clear it and read brand new input.
input.clear();
std::cout << std::endl; std::cout << std::endl;
} }
} }
@ -149,7 +163,7 @@ char * completerThunk(const char * s, int state)
} }
bool NixRepl::getLine(string & line) bool NixRepl::getLine(string & input, const char * prompt)
{ {
struct sigaction act, old; struct sigaction act, old;
act.sa_handler = sigintHandler; act.sa_handler = sigintHandler;
@ -158,15 +172,17 @@ bool NixRepl::getLine(string & line)
if (sigaction(SIGINT, &act, &old)) if (sigaction(SIGINT, &act, &old))
throw SysError("installing handler for SIGINT"); throw SysError("installing handler for SIGINT");
if (sigsetjmp(sigintJmpBuf, 1)) if (sigsetjmp(sigintJmpBuf, 1)) {
line = ""; input.clear();
else { } else {
curRepl = this; curRepl = this;
rl_completion_entry_function = completerThunk; rl_completion_entry_function = completerThunk;
char * s = readline("nix-repl> "); char * s = readline(prompt);
if (!s) return false; if (!s) return false;
line = chomp(string(s)); string line = chomp(string(s));
input.append(removeWhitespace(line));
input.push_back('\n');
free(s); free(s);
if (line != "") { if (line != "") {
add_history(line.c_str()); add_history(line.c_str());
@ -270,7 +286,7 @@ bool NixRepl::processLine(string line)
string command, arg; string command, arg;
if (line[0] == ':') { if (line[0] == ':') {
size_t p = line.find(' '); size_t p = line.find_first_of(" \n\r\t");
command = string(line, 0, p); command = string(line, 0, p);
if (p != string::npos) arg = removeWhitespace(string(line, p)); if (p != string::npos) arg = removeWhitespace(string(line, p));
} else { } else {