aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd/repl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcmd/repl.cc')
-rw-r--r--src/libcmd/repl.cc63
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();
}
}