diff options
Diffstat (limited to 'src/libcmd/repl.cc')
-rw-r--r-- | src/libcmd/repl.cc | 63 |
1 files changed, 47 insertions, 16 deletions
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index bc5ff9525..ea2f4ebe6 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -49,6 +49,27 @@ extern "C" { namespace nix { +/** + * Returned by `NixRepl::processLine`. + */ +enum class ProcessLineResult { + /** + * The user exited with `:quit`. The REPL should exit. The surrounding + * program or evaluation (e.g., if the REPL was acting as the debugger) + * should also exit. + */ + QuitAll, + /** + * The user exited with `:continue`. The REPL should exit, but the program + * should continue running. + */ + QuitOnce, + /** + * The user did not exit. The REPL should request another line of input. + */ + Continue, +}; + struct NixRepl : AbstractNixRepl #if HAVE_BOEHMGC @@ -72,13 +93,13 @@ struct NixRepl std::function<AnnotatedValues()> getValues); virtual ~NixRepl(); - void mainLoop() override; + ReplExitStatus mainLoop() override; void initEnv() override; StringSet completePrefix(const std::string & prefix); bool getLine(std::string & input, const std::string & prompt); StorePath getDerivationPath(Value & v); - bool processLine(std::string line); + ProcessLineResult processLine(std::string line); void loadFile(const Path & path); void loadFlake(const std::string & flakeRef); @@ -243,7 +264,7 @@ static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positi static bool isFirstRepl = true; -void NixRepl::mainLoop() +ReplExitStatus NixRepl::mainLoop() { if (isFirstRepl) { std::string_view debuggerNotice = ""; @@ -284,15 +305,25 @@ void NixRepl::mainLoop() // When continuing input from previous lines, don't print a prompt, just align to the same // number of chars as the prompt. if (!getLine(input, input.empty() ? "nix-repl> " : " ")) { - // ctrl-D should exit the debugger. + // Ctrl-D should exit the debugger. state->debugStop = false; - state->debugQuit = true; logger->cout(""); - break; + // TODO: Should Ctrl-D exit just the current debugger session or + // the entire program? + return ReplExitStatus::QuitAll; } logger->resume(); try { - if (!removeWhitespace(input).empty() && !processLine(input)) return; + switch (processLine(input)) { + case ProcessLineResult::QuitAll: + return ReplExitStatus::QuitAll; + case ProcessLineResult::QuitOnce: + return ReplExitStatus::Continue; + case ProcessLineResult::Continue: + break; + default: + abort(); + } } catch (ParseError & e) { if (e.msg().find("unexpected end of file") != std::string::npos) { // For parse errors on incomplete input, we continue waiting for the next line of @@ -479,10 +510,11 @@ void NixRepl::loadDebugTraceEnv(DebugTrace & dt) } } -bool NixRepl::processLine(std::string line) +ProcessLineResult NixRepl::processLine(std::string line) { line = trim(line); - if (line == "") return true; + if (line.empty()) + return ProcessLineResult::Continue; _isInterrupted = false; @@ -577,13 +609,13 @@ bool NixRepl::processLine(std::string line) else if (state->debugRepl && (command == ":s" || command == ":step")) { // set flag to stop at next DebugTrace; exit repl. state->debugStop = true; - return false; + return ProcessLineResult::QuitOnce; } else if (state->debugRepl && (command == ":c" || command == ":continue")) { // set flag to run to next breakpoint or end of program; exit repl. state->debugStop = false; - return false; + return ProcessLineResult::QuitOnce; } else if (command == ":a" || command == ":add") { @@ -726,8 +758,7 @@ bool NixRepl::processLine(std::string line) else if (command == ":q" || command == ":quit") { state->debugStop = false; - state->debugQuit = true; - return false; + return ProcessLineResult::QuitAll; } else if (command == ":doc") { @@ -788,7 +819,7 @@ bool NixRepl::processLine(std::string line) } } - return true; + return ProcessLineResult::Continue; } void NixRepl::loadFile(const Path & path) @@ -919,7 +950,7 @@ std::unique_ptr<AbstractNixRepl> AbstractNixRepl::create( } -void AbstractNixRepl::runSimple( +ReplExitStatus AbstractNixRepl::runSimple( ref<EvalState> evalState, const ValMap & extraEnv) { @@ -941,7 +972,7 @@ void AbstractNixRepl::runSimple( for (auto & [name, value] : extraEnv) repl->addVarToScope(repl->state->symbols.create(name), *value); - repl->mainLoop(); + return repl->mainLoop(); } } |