forked from lix-project/lix
Merge branch 'multiline' of https://github.com/tsion/nix-repl
This commit is contained in:
commit
02daf2ec0b
1 changed files with 27 additions and 11 deletions
38
nix-repl.cc
38
nix-repl.cc
|
@ -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 {
|
||||||
|
|
Loading…
Reference in a new issue