forked from lix-project/lix
repl: allow loading installables from CLI
repl: search installable with findAlongAttrPath repl: refactor handling of args repl: temp
This commit is contained in:
parent
06d57ce759
commit
81567a0962
|
@ -132,6 +132,7 @@ struct InstallableCommand : virtual Args, SourceExprCommand
|
||||||
InstallableCommand(bool supportReadOnlyMode = false);
|
InstallableCommand(bool supportReadOnlyMode = false);
|
||||||
|
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
|
std::shared_ptr<Installable> load();
|
||||||
|
|
||||||
std::optional<FlakeRef> getFlakeRefForCompletion() override
|
std::optional<FlakeRef> getFlakeRefForCompletion() override
|
||||||
{
|
{
|
||||||
|
|
|
@ -1054,10 +1054,13 @@ InstallableCommand::InstallableCommand(bool supportReadOnlyMode)
|
||||||
}}
|
}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
std::shared_ptr<Installable> InstallableCommand::load() {
|
||||||
|
return parseInstallable(getStore(), _installable);
|
||||||
|
}
|
||||||
|
|
||||||
void InstallableCommand::prepare()
|
void InstallableCommand::prepare()
|
||||||
{
|
{
|
||||||
installable = parseInstallable(getStore(), _installable);
|
installable = load();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern "C" {
|
||||||
#include "ansicolor.hh"
|
#include "ansicolor.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
|
#include "eval-cache.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
#include "attr-path.hh"
|
#include "attr-path.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
|
@ -42,16 +43,20 @@ extern "C" {
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
typedef std::vector<std::shared_ptr<Installable>> Installables;
|
||||||
|
|
||||||
struct NixRepl
|
struct NixRepl
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
: gc
|
: gc
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
std::string curDir;
|
std::string curDir;
|
||||||
std::unique_ptr<EvalState> state;
|
ref<EvalState> state;
|
||||||
Bindings * autoArgs;
|
Bindings * autoArgs;
|
||||||
|
|
||||||
Strings loadedFiles;
|
Strings loadedFiles;
|
||||||
|
typedef std::vector<std::pair<Value*,std::string>> AnnotatedValues;
|
||||||
|
std::function<AnnotatedValues()> getValues;
|
||||||
|
|
||||||
const static int envSize = 32768;
|
const static int envSize = 32768;
|
||||||
StaticEnv staticEnv;
|
StaticEnv staticEnv;
|
||||||
|
@ -61,13 +66,16 @@ struct NixRepl
|
||||||
|
|
||||||
const Path historyFile;
|
const Path historyFile;
|
||||||
|
|
||||||
NixRepl(const Strings & searchPath, nix::ref<Store> store);
|
NixRepl(const Strings & searchPath, nix::ref<Store> store,ref<EvalState> state,
|
||||||
|
std::function<AnnotatedValues()> getValues);
|
||||||
~NixRepl();
|
~NixRepl();
|
||||||
void mainLoop(const std::vector<std::string> & files);
|
void mainLoop();
|
||||||
StringSet completePrefix(const std::string & prefix);
|
StringSet completePrefix(const std::string & prefix);
|
||||||
bool getLine(std::string & input, const std::string &prompt);
|
bool getLine(std::string & input, const std::string &prompt);
|
||||||
StorePath getDerivationPath(Value & v);
|
StorePath getDerivationPath(Value & v);
|
||||||
bool processLine(std::string line);
|
bool processLine(std::string line);
|
||||||
|
|
||||||
|
void loadInstallable(Installable & installable);
|
||||||
void loadFile(const Path & path);
|
void loadFile(const Path & path);
|
||||||
void loadFlake(const std::string & flakeRef);
|
void loadFlake(const std::string & flakeRef);
|
||||||
void initEnv();
|
void initEnv();
|
||||||
|
@ -92,8 +100,10 @@ std::string removeWhitespace(std::string s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store)
|
NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store,ref<EvalState> state,
|
||||||
: state(std::make_unique<EvalState>(searchPath, store))
|
std::function<NixRepl::AnnotatedValues()> getValues)
|
||||||
|
: state(state)
|
||||||
|
, getValues(getValues)
|
||||||
, staticEnv(false, &state->staticBaseEnv)
|
, staticEnv(false, &state->staticBaseEnv)
|
||||||
, historyFile(getDataDir() + "/nix/repl-history")
|
, historyFile(getDataDir() + "/nix/repl-history")
|
||||||
{
|
{
|
||||||
|
@ -198,16 +208,12 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NixRepl::mainLoop(const std::vector<std::string> & files)
|
void NixRepl::mainLoop()
|
||||||
{
|
{
|
||||||
std::string error = ANSI_RED "error:" ANSI_NORMAL " ";
|
std::string error = ANSI_RED "error:" ANSI_NORMAL " ";
|
||||||
notice("Welcome to Nix " + nixVersion + ". Type :? for help.\n");
|
notice("Welcome to Nix " + nixVersion + ". Type :? for help.\n");
|
||||||
|
|
||||||
for (auto & i : files)
|
|
||||||
loadedFiles.push_back(i);
|
|
||||||
|
|
||||||
reloadFiles();
|
reloadFiles();
|
||||||
if (!loadedFiles.empty()) notice("");
|
|
||||||
|
|
||||||
// Allow nix-repl specific settings in .inputrc
|
// Allow nix-repl specific settings in .inputrc
|
||||||
rl_readline_name = "nix-repl";
|
rl_readline_name = "nix-repl";
|
||||||
|
@ -630,6 +636,11 @@ bool NixRepl::processLine(std::string line)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NixRepl::loadInstallable(Installable & installable)
|
||||||
|
{
|
||||||
|
auto [val, pos] = installable.toValue(*state);
|
||||||
|
addAttrsToScope(*val);
|
||||||
|
}
|
||||||
|
|
||||||
void NixRepl::loadFile(const Path & path)
|
void NixRepl::loadFile(const Path & path)
|
||||||
{
|
{
|
||||||
|
@ -646,11 +657,11 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||||
if (flakeRefS.empty())
|
if (flakeRefS.empty())
|
||||||
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
|
throw Error("cannot use ':load-flake' without a path specified. (Use '.' for the current working directory.)");
|
||||||
|
|
||||||
auto [flakeRef, fragment] = parseFlakeRefWithFragment(flakeRefS, absPath("."), true);
|
auto flakeRef = parseFlakeRef(flakeRefS, absPath("."), true);
|
||||||
if (evalSettings.pureEval && !flakeRef.input.isLocked())
|
if (evalSettings.pureEval && !flakeRef.input.isLocked())
|
||||||
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
|
throw Error("cannot use ':load-flake' on locked flake reference '%s' (use --impure to override)", flakeRefS);
|
||||||
|
|
||||||
auto v = state->allocValue();
|
Value v;
|
||||||
|
|
||||||
flake::callFlake(*state,
|
flake::callFlake(*state,
|
||||||
flake::lockFlake(*state, flakeRef,
|
flake::lockFlake(*state, flakeRef,
|
||||||
|
@ -659,17 +670,8 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
|
||||||
.useRegistries = !evalSettings.pureEval,
|
.useRegistries = !evalSettings.pureEval,
|
||||||
.allowMutable = !evalSettings.pureEval,
|
.allowMutable = !evalSettings.pureEval,
|
||||||
}),
|
}),
|
||||||
*v);
|
v);
|
||||||
|
addAttrsToScope(v);
|
||||||
auto f = v->attrs->get(state->symbols.create(fragment));
|
|
||||||
|
|
||||||
if (f == 0) {
|
|
||||||
warn("no attribute %s, nothing loaded", fragment);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
fragment != "" ? addAttrsToScope(*f->value) : addAttrsToScope(*v);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -693,15 +695,14 @@ void NixRepl::reloadFiles()
|
||||||
Strings old = loadedFiles;
|
Strings old = loadedFiles;
|
||||||
loadedFiles.clear();
|
loadedFiles.clear();
|
||||||
|
|
||||||
bool first = true;
|
|
||||||
for (auto & i : old) {
|
for (auto & i : old) {
|
||||||
if (!first) notice("");
|
|
||||||
first = false;
|
|
||||||
notice("Loading '%1%'...", i);
|
notice("Loading '%1%'...", i);
|
||||||
|
loadFile(i);
|
||||||
|
}
|
||||||
|
|
||||||
settings.isExperimentalFeatureEnabled(Xp::Flakes)
|
for (auto & [i,what] : getValues()) {
|
||||||
? loadFlake(i)
|
notice("Loading Installable '%1%'...", what);
|
||||||
: loadFile(i);
|
addAttrsToScope(*i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,17 +899,20 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CmdRepl : StoreCommand, MixEvalArgs
|
struct CmdRepl : InstallableCommand
|
||||||
{
|
{
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
|
Strings getDefaultFlakeAttrPathPrefixes()
|
||||||
|
override {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
Strings getDefaultFlakeAttrPaths()
|
||||||
|
override {
|
||||||
|
return {""};
|
||||||
|
}
|
||||||
|
|
||||||
CmdRepl()
|
CmdRepl()
|
||||||
{
|
{
|
||||||
expectArgs({
|
|
||||||
.label = "files",
|
|
||||||
.handler = {&files},
|
|
||||||
.completer = completePath
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string description() override
|
std::string description() override
|
||||||
|
@ -925,10 +929,19 @@ struct CmdRepl : StoreCommand, MixEvalArgs
|
||||||
|
|
||||||
void run(ref<Store> store) override
|
void run(ref<Store> store) override
|
||||||
{
|
{
|
||||||
|
|
||||||
evalSettings.pureEval = false;
|
evalSettings.pureEval = false;
|
||||||
auto repl = std::make_unique<NixRepl>(searchPath, openStore());
|
auto state = getEvalState();
|
||||||
|
auto repl = std::make_unique<NixRepl>(searchPath, openStore(),state
|
||||||
|
,[&]()->NixRepl::AnnotatedValues{
|
||||||
|
auto installable = load();
|
||||||
|
auto [val, pos] = installable->toValue(*state);
|
||||||
|
auto what = installable->what();
|
||||||
|
return { {val,what} };
|
||||||
|
}
|
||||||
|
);
|
||||||
repl->autoArgs = getAutoArgs(*repl->state);
|
repl->autoArgs = getAutoArgs(*repl->state);
|
||||||
repl->mainLoop(files);
|
repl->mainLoop();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue