aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-02-03 22:42:36 -0500
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-02-20 09:45:29 -0500
commit1bd03ad100e8813751b6c08b0c21ae8cf5a9c21d (patch)
tree2e625eda7966d2e10bf7316ae8fa352eaa100b27 /src/libcmd
parent57a2e46ee0890093c9882f961d7d95c56d7c0ad5 (diff)
Split out `CmdRepl` and `editorFor`
The REPL itself and the `nix repl` CLI are conceptually different things, and thus deserve to be in different files.
Diffstat (limited to 'src/libcmd')
-rw-r--r--src/libcmd/command.cc17
-rw-r--r--src/libcmd/command.hh8
-rw-r--r--src/libcmd/editor-for.cc20
-rw-r--r--src/libcmd/editor-for.hh11
-rw-r--r--src/libcmd/local.mk2
-rw-r--r--src/libcmd/repl.cc128
-rw-r--r--src/libcmd/repl.hh39
7 files changed, 102 insertions, 123 deletions
diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc
index 517cdf617..ab51c229d 100644
--- a/src/libcmd/command.cc
+++ b/src/libcmd/command.cc
@@ -4,6 +4,7 @@
#include "derivations.hh"
#include "nixexpr.hh"
#include "profiles.hh"
+#include "repl.hh"
#include <nlohmann/json.hpp>
@@ -121,7 +122,7 @@ ref<EvalState> EvalCommand::getEvalState()
;
if (startReplOnEvalErrors) {
- evalState->debugRepl = &runRepl;
+ evalState->debugRepl = &AbstractNixRepl::runSimple;
};
}
return ref<EvalState>(evalState);
@@ -218,20 +219,6 @@ void StorePathCommand::run(ref<Store> store, std::vector<StorePath> && storePath
run(store, *storePaths.begin());
}
-Strings editorFor(const Path & file, uint32_t line)
-{
- auto editor = getEnv("EDITOR").value_or("cat");
- auto args = tokenizeString<Strings>(editor);
- if (line > 0 && (
- editor.find("emacs") != std::string::npos ||
- editor.find("nano") != std::string::npos ||
- editor.find("vim") != std::string::npos ||
- editor.find("kak") != std::string::npos))
- args.push_back(fmt("+%d", line));
- args.push_back(file);
- return args;
-}
-
MixProfile::MixProfile()
{
addFlag({
diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh
index d16bdbc4b..1516daa00 100644
--- a/src/libcmd/command.hh
+++ b/src/libcmd/command.hh
@@ -231,10 +231,6 @@ static RegisterCommand registerCommand2(std::vector<std::string> && name)
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
}
-/* Helper function to generate args that invoke $EDITOR on
- filename:lineno. */
-Strings editorFor(const Path & file, uint32_t line);
-
struct MixProfile : virtual StoreCommand
{
std::optional<Path> profile;
@@ -284,8 +280,4 @@ void printClosureDiff(
const StorePath & afterPath,
std::string_view indent);
-
-void runRepl(
- ref<EvalState> evalState,
- const ValMap & extraEnv);
}
diff --git a/src/libcmd/editor-for.cc b/src/libcmd/editor-for.cc
new file mode 100644
index 000000000..f674f32bd
--- /dev/null
+++ b/src/libcmd/editor-for.cc
@@ -0,0 +1,20 @@
+#include "util.hh"
+#include "editor-for.hh"
+
+namespace nix {
+
+Strings editorFor(const Path & file, uint32_t line)
+{
+ auto editor = getEnv("EDITOR").value_or("cat");
+ auto args = tokenizeString<Strings>(editor);
+ if (line > 0 && (
+ editor.find("emacs") != std::string::npos ||
+ editor.find("nano") != std::string::npos ||
+ editor.find("vim") != std::string::npos ||
+ editor.find("kak") != std::string::npos))
+ args.push_back(fmt("+%d", line));
+ args.push_back(file);
+ return args;
+}
+
+}
diff --git a/src/libcmd/editor-for.hh b/src/libcmd/editor-for.hh
new file mode 100644
index 000000000..8fbd08792
--- /dev/null
+++ b/src/libcmd/editor-for.hh
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "types.hh"
+
+namespace nix {
+
+/* Helper function to generate args that invoke $EDITOR on
+ filename:lineno. */
+Strings editorFor(const Path & file, uint32_t line);
+
+}
diff --git a/src/libcmd/local.mk b/src/libcmd/local.mk
index 152bc388d..541a7d2ba 100644
--- a/src/libcmd/local.mk
+++ b/src/libcmd/local.mk
@@ -6,7 +6,7 @@ libcmd_DIR := $(d)
libcmd_SOURCES := $(wildcard $(d)/*.cc)
-libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers -I src/nix
+libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers
libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) -pthread
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc
index 4158439b6..7c7d13659 100644
--- a/src/libcmd/repl.cc
+++ b/src/libcmd/repl.cc
@@ -19,6 +19,8 @@ extern "C" {
}
#endif
+#include "repl.hh"
+
#include "ansicolor.hh"
#include "shared.hh"
#include "eval.hh"
@@ -31,7 +33,9 @@ extern "C" {
#include "get-drvs.hh"
#include "derivations.hh"
#include "globals.hh"
-#include "command.hh"
+#include "flake/flake.hh"
+#include "flake/lockfile.hh"
+#include "editor-for.hh"
#include "finally.hh"
#include "markdown.hh"
#include "local-fs-store.hh"
@@ -45,18 +49,16 @@ extern "C" {
namespace nix {
struct NixRepl
+ : AbstractNixRepl,
#if HAVE_BOEHMGC
- : gc
+ gc
#endif
{
std::string curDir;
- ref<EvalState> state;
- Bindings * autoArgs;
size_t debugTraceIndex;
Strings loadedFiles;
- typedef std::vector<std::pair<Value*,std::string>> AnnotatedValues;
std::function<AnnotatedValues()> getValues;
const static int envSize = 32768;
@@ -69,8 +71,11 @@ struct NixRepl
NixRepl(const Strings & searchPath, nix::ref<Store> store,ref<EvalState> state,
std::function<AnnotatedValues()> getValues);
- ~NixRepl();
- void mainLoop();
+ virtual ~NixRepl();
+
+ void mainLoop() override;
+ void initEnv() override;
+
StringSet completePrefix(const std::string & prefix);
bool getLine(std::string & input, const std::string & prompt);
StorePath getDerivationPath(Value & v);
@@ -78,7 +83,6 @@ struct NixRepl
void loadFile(const Path & path);
void loadFlake(const std::string & flakeRef);
- void initEnv();
void loadFiles();
void reloadFiles();
void addAttrsToScope(Value & attrs);
@@ -92,7 +96,6 @@ struct NixRepl
std::ostream & printValue(std::ostream & str, Value & v, unsigned int maxDepth, ValuesSeen & seen);
};
-
std::string removeWhitespace(std::string s)
{
s = chomp(s);
@@ -104,7 +107,7 @@ std::string removeWhitespace(std::string s)
NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store, ref<EvalState> state,
std::function<NixRepl::AnnotatedValues()> getValues)
- : state(state)
+ : AbstractNixRepl(state)
, debugTraceIndex(0)
, getValues(getValues)
, staticEnv(new StaticEnv(false, state->staticBaseEnv.get()))
@@ -1029,8 +1032,22 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
return str;
}
-void runRepl(
- ref<EvalState>evalState,
+
+std::unique_ptr<AbstractNixRepl> AbstractNixRepl::create(
+ const Strings & searchPath, nix::ref<Store> store, ref<EvalState> state,
+ std::function<AnnotatedValues()> getValues)
+{
+ return std::make_unique<NixRepl>(
+ searchPath,
+ openStore(),
+ state,
+ getValues
+ );
+}
+
+
+void AbstractNixRepl::runSimple(
+ ref<EvalState> evalState,
const ValMap & extraEnv)
{
auto getValues = [&]()->NixRepl::AnnotatedValues{
@@ -1054,91 +1071,4 @@ void runRepl(
repl->mainLoop();
}
-struct CmdRepl : InstallablesCommand
-{
- CmdRepl() {
- evalSettings.pureEval = false;
- }
-
- void prepare() override
- {
- if (!settings.isExperimentalFeatureEnabled(Xp::ReplFlake) && !(file) && this->_installables.size() >= 1) {
- warn("future versions of Nix will require using `--file` to load a file");
- if (this->_installables.size() > 1)
- warn("more than one input file is not currently supported");
- auto filePath = this->_installables[0].data();
- file = std::optional(filePath);
- _installables.front() = _installables.back();
- _installables.pop_back();
- }
- installables = InstallablesCommand::load();
- }
-
- std::vector<std::string> files;
-
- Strings getDefaultFlakeAttrPaths() override
- {
- return {""};
- }
-
- bool useDefaultInstallables() override
- {
- return file.has_value() or expr.has_value();
- }
-
- bool forceImpureByDefault() override
- {
- return true;
- }
-
- std::string description() override
- {
- return "start an interactive environment for evaluating Nix expressions";
- }
-
- std::string doc() override
- {
- return
- #include "repl.md"
- ;
- }
-
- void run(ref<Store> store) override
- {
- auto state = getEvalState();
- auto getValues = [&]()->NixRepl::AnnotatedValues{
- auto installables = load();
- NixRepl::AnnotatedValues values;
- for (auto & installable: installables){
- auto what = installable->what();
- if (file){
- auto [val, pos] = installable->toValue(*state);
- auto what = installable->what();
- state->forceValue(*val, pos);
- auto autoArgs = getAutoArgs(*state);
- auto valPost = state->allocValue();
- state->autoCallFunction(*autoArgs, *val, *valPost);
- state->forceValue(*valPost, pos);
- values.push_back( {valPost, what });
- } else {
- auto [val, pos] = installable->toValue(*state);
- values.push_back( {val, what} );
- }
- }
- return values;
- };
- auto repl = std::make_unique<NixRepl>(
- searchPath,
- openStore(),
- state,
- getValues
- );
- repl->autoArgs = getAutoArgs(*repl->state);
- repl->initEnv();
- repl->mainLoop();
- }
-};
-
-static auto rCmdRepl = registerCommand<CmdRepl>("repl");
-
}
diff --git a/src/libcmd/repl.hh b/src/libcmd/repl.hh
new file mode 100644
index 000000000..dfccc93e7
--- /dev/null
+++ b/src/libcmd/repl.hh
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "eval.hh"
+
+#if HAVE_BOEHMGC
+#define GC_INCLUDE_NEW
+#include <gc/gc_cpp.h>
+#endif
+
+namespace nix {
+
+struct AbstractNixRepl
+{
+ ref<EvalState> state;
+ Bindings * autoArgs;
+
+ AbstractNixRepl(ref<EvalState> state)
+ : state(state)
+ { }
+
+ virtual ~AbstractNixRepl()
+ { }
+
+ typedef std::vector<std::pair<Value*,std::string>> AnnotatedValues;
+
+ static std::unique_ptr<AbstractNixRepl> create(
+ const Strings & searchPath, nix::ref<Store> store, ref<EvalState> state,
+ std::function<AnnotatedValues()> getValues);
+
+ static void runSimple(
+ ref<EvalState> evalState,
+ const ValMap & extraEnv);
+
+ virtual void initEnv() = 0;
+
+ virtual void mainLoop() = 0;
+};
+
+}