forked from lix-project/lix
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.
This commit is contained in:
parent
57a2e46ee0
commit
1bd03ad100
|
@ -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({
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
20
src/libcmd/editor-for.cc
Normal file
20
src/libcmd/editor-for.cc
Normal file
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
11
src/libcmd/editor-for.hh
Normal file
11
src/libcmd/editor-for.hh
Normal file
|
@ -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);
|
||||
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
|
39
src/libcmd/repl.hh
Normal file
39
src/libcmd/repl.hh
Normal file
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
#include "eval.hh"
|
||||
#include "attr-path.hh"
|
||||
#include "progress-bar.hh"
|
||||
#include "editor-for.hh"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
95
src/nix/repl.cc
Normal file
95
src/nix/repl.cc
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include "eval.hh"
|
||||
#include "globals.hh"
|
||||
#include "command.hh"
|
||||
#include "repl.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
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 = [&]()->AbstractNixRepl::AnnotatedValues{
|
||||
auto installables = load();
|
||||
AbstractNixRepl::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 = AbstractNixRepl::create(
|
||||
searchPath,
|
||||
openStore(),
|
||||
state,
|
||||
getValues
|
||||
);
|
||||
repl->autoArgs = getAutoArgs(*repl->state);
|
||||
repl->initEnv();
|
||||
repl->mainLoop();
|
||||
}
|
||||
};
|
||||
|
||||
static auto rCmdRepl = registerCommand<CmdRepl>("repl");
|
||||
|
||||
}
|
Loading…
Reference in a new issue