diff options
Diffstat (limited to 'nix-repl.cc')
-rw-r--r-- | nix-repl.cc | 96 |
1 files changed, 60 insertions, 36 deletions
diff --git a/nix-repl.cc b/nix-repl.cc index 1b098405fc82..8c4f4017470d 100644 --- a/nix-repl.cc +++ b/nix-repl.cc @@ -19,9 +19,6 @@ using namespace std; using namespace nix; -string programId = "nix-repl"; - - struct NixRepl { string curDir; @@ -38,10 +35,10 @@ struct NixRepl StringSet completions; StringSet::iterator curCompletion; - NixRepl(const Strings & searchPath); + NixRepl(const Strings & searchPath, nix::ref<Store> store); void mainLoop(const Strings & files); void completePrefix(string prefix); - bool getLine(string & line); + bool getLine(string & input, const char * prompt); bool processLine(string line); void loadFile(const Path & path); void initEnv(); @@ -100,13 +97,11 @@ string removeWhitespace(string s) } -NixRepl::NixRepl(const Strings & searchPath) - : state(searchPath) +NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store) + : state(searchPath, store) , staticEnv(false, &state.staticBaseEnv) { curDir = absPath("."); - - store = openStore(); } @@ -123,21 +118,35 @@ void NixRepl::mainLoop(const Strings & files) using_history(); read_history(0); + string input; + while (true) { - string line; - if (!getLine(line)) { + // When continuing input from previous lines, don't print a prompt, just align to the same + // number of chars as the prompt. + const char * prompt = input.empty() ? "nix-repl> " : " "; + if (!getLine(input, prompt)) { std::cout << std::endl; break; } try { - if (!processLine(removeWhitespace(line))) return; + if (!removeWhitespace(input).empty() && !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) { printMsg(lvlError, "error: " + e.msg()); } catch (Interrupted & e) { 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; } } @@ -176,7 +185,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; act.sa_handler = sigintHandler; @@ -185,20 +194,21 @@ bool NixRepl::getLine(string & line) if (sigaction(SIGINT, &act, &old)) throw SysError("installing handler for SIGINT"); - if (sigsetjmp(sigintJmpBuf, 1)) - line = ""; - else { + if (sigsetjmp(sigintJmpBuf, 1)) { + input.clear(); + } else { curRepl = this; rl_completion_entry_function = completerThunk; - char * s = readline("nix-repl> "); + char * s = readline(prompt); if (!s) return false; - line = chomp(string(s)); - free(s); - if (line != "") { - add_history(line.c_str()); + input.append(s); + input.push_back('\n'); + if (!removeWhitespace(s).empty()) { + add_history(s); append_history(1, 0); } + free(s); } _isInterrupted = 0; @@ -297,7 +307,7 @@ bool NixRepl::processLine(string line) string command, arg; if (line[0] == ':') { - size_t p = line.find(' '); + size_t p = line.find_first_of(" \n\r\t"); command = string(line, 0, p); if (p != string::npos) arg = removeWhitespace(string(line, p)); } else { @@ -311,6 +321,7 @@ bool NixRepl::processLine(string line) << " <x> = <expr> Bind expression to variable\n" << " :a <expr> Add attributes from resulting set to scope\n" << " :b <expr> Build derivation\n" + << " :i <expr> Build derivation, then install result into current profile\n" << " :l <path> Load Nix expression and add it to scope\n" << " :p <expr> Evaluate and print expression recursively\n" << " :q Exit nix-repl\n" @@ -341,14 +352,14 @@ bool NixRepl::processLine(string line) std::cout << showType(v) << std::endl; } - else if (command == ":b" || command == ":s") { + else if (command == ":b" || command == ":i" || command == ":s") { Value v; evalString(arg, v); DrvInfo drvInfo(state); if (!getDerivation(state, v, drvInfo, false)) - throw Error("expression does not evaluation to a derivation, so I can't build it"); + throw Error("expression does not evaluate to a derivation, so I can't build it"); Path drvPath = drvInfo.queryDrvPath(); - if (drvPath == "" || !store->isValidPath(drvPath)) + if (drvPath == "" || !state.store->isValidPath(drvPath)) throw Error("expression did not evaluate to a valid derivation"); if (command == ":b") { @@ -361,8 +372,11 @@ bool NixRepl::processLine(string line) for (auto & i : drv.outputs) std::cout << format(" %1% -> %2%") % i.first % i.second.path << std::endl; } - } else + } else if (command == ":i") { + runProgram("nix-env", Strings{"-i", drvPath}); + } else { runProgram("nix-shell", Strings{drvPath}); + } } else if (command == ":p" || command == ":print") { @@ -485,6 +499,19 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m } +std::ostream & printStringValue(std::ostream & str, const char * string) { + str << "\""; + for (const char * i = string; *i; i++) + if (*i == '\"' || *i == '\\') str << "\\" << *i; + else if (*i == '\n') str << "\\n"; + else if (*i == '\r') str << "\\r"; + else if (*i == '\t') str << "\\t"; + else str << *i; + str << "\""; + return str; +} + + // FIXME: lot of cut&paste from Nix's eval.cc. std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen) { @@ -504,14 +531,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m break; case tString: - str << "\""; - for (const char * i = v.string.s; *i; i++) - if (*i == '\"' || *i == '\\') str << "\\" << *i; - else if (*i == '\n') str << "\\n"; - else if (*i == '\r') str << "\\r"; - else if (*i == '\t') str << "\\t"; - else str << *i; - str << "\""; + printStringValue(str, v.string.s); break; case tPath: @@ -559,7 +579,11 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m } for (auto & i : sorted) { - str << i.first << " = "; + if (isVarName(i.first)) + str << i.first; + else + printStringValue(str, i.first.c_str()); + str << " = "; if (hidden.find(i.first) != hidden.end()) str << "«...»"; else if (seen.find(i.second) != seen.end()) @@ -649,7 +673,7 @@ int main(int argc, char * * argv) return true; }); - NixRepl repl(searchPath); + NixRepl repl(searchPath, openStore()); repl.mainLoop(files); }); } |