diff options
Diffstat (limited to 'src/libcmd')
-rw-r--r-- | src/libcmd/command.hh | 2 | ||||
-rw-r--r-- | src/libcmd/common-eval-args.cc | 105 | ||||
-rw-r--r-- | src/libcmd/common-eval-args.hh | 27 | ||||
-rw-r--r-- | src/libcmd/installables.cc | 29 |
4 files changed, 153 insertions, 10 deletions
diff --git a/src/libcmd/command.hh b/src/libcmd/command.hh index 15bc13c6e..84bbb5292 100644 --- a/src/libcmd/command.hh +++ b/src/libcmd/command.hh @@ -135,7 +135,7 @@ struct InstallableCommand : virtual Args, SourceExprCommand std::optional<FlakeRef> getFlakeRefForCompletion() override { - return parseFlakeRef(_installable, absPath(".")); + return parseFlakeRefWithFragment(_installable, absPath(".")).first; } private: diff --git a/src/libcmd/common-eval-args.cc b/src/libcmd/common-eval-args.cc new file mode 100644 index 000000000..5b6e82388 --- /dev/null +++ b/src/libcmd/common-eval-args.cc @@ -0,0 +1,105 @@ +#include "common-eval-args.hh" +#include "shared.hh" +#include "filetransfer.hh" +#include "util.hh" +#include "eval.hh" +#include "fetchers.hh" +#include "registry.hh" +#include "flake/flakeref.hh" +#include "store-api.hh" +#include "command.hh" + +namespace nix { + +MixEvalArgs::MixEvalArgs() +{ + auto category = "Common evaluation options"; + + addFlag({ + .longName = "arg", + .description = "Pass the value *expr* as the argument *name* to Nix functions.", + .category = category, + .labels = {"name", "expr"}, + .handler = {[&](std::string name, std::string expr) { autoArgs[name] = 'E' + expr; }} + }); + + addFlag({ + .longName = "argstr", + .description = "Pass the string *string* as the argument *name* to Nix functions.", + .category = category, + .labels = {"name", "string"}, + .handler = {[&](std::string name, std::string s) { autoArgs[name] = 'S' + s; }}, + }); + + addFlag({ + .longName = "include", + .shortName = 'I', + .description = "Add *path* to the list of locations used to look up `<...>` file names.", + .category = category, + .labels = {"path"}, + .handler = {[&](std::string s) { searchPath.push_back(s); }} + }); + + addFlag({ + .longName = "impure", + .description = "Allow access to mutable paths and repositories.", + .category = category, + .handler = {[&]() { + evalSettings.pureEval = false; + }}, + }); + + addFlag({ + .longName = "override-flake", + .description = "Override the flake registries, redirecting *original-ref* to *resolved-ref*.", + .category = category, + .labels = {"original-ref", "resolved-ref"}, + .handler = {[&](std::string _from, std::string _to) { + auto from = parseFlakeRef(_from, absPath(".")); + auto to = parseFlakeRef(_to, absPath(".")); + fetchers::Attrs extraAttrs; + if (to.subdir != "") extraAttrs["dir"] = to.subdir; + fetchers::overrideRegistry(from.input, to.input, extraAttrs); + }}, + .completer = {[&](size_t, std::string_view prefix) { + completeFlakeRef(openStore(), prefix); + }} + }); + + addFlag({ + .longName = "eval-store", + .description = "The Nix store to use for evaluations.", + .category = category, + .labels = {"store-url"}, + .handler = {&evalStoreUrl}, + }); +} + +Bindings * MixEvalArgs::getAutoArgs(EvalState & state) +{ + auto res = state.buildBindings(autoArgs.size()); + for (auto & i : autoArgs) { + auto v = state.allocValue(); + if (i.second[0] == 'E') + state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), absPath("."))); + else + v->mkString(((std::string_view) i.second).substr(1)); + res.insert(state.symbols.create(i.first), v); + } + return res.finish(); +} + +Path lookupFileArg(EvalState & state, std::string_view s) +{ + if (isUri(s)) { + return state.store->toRealPath( + fetchers::downloadTarball( + state.store, resolveUri(s), "source", false).first.storePath); + } else if (s.size() > 2 && s.at(0) == '<' && s.at(s.size() - 1) == '>') { + Path p(s.substr(1, s.size() - 2)); + return state.findFile(p); + } else + return absPath(std::string(s)); +} + +} diff --git a/src/libcmd/common-eval-args.hh b/src/libcmd/common-eval-args.hh new file mode 100644 index 000000000..03fa226aa --- /dev/null +++ b/src/libcmd/common-eval-args.hh @@ -0,0 +1,27 @@ +#pragma once + +#include "args.hh" + +namespace nix { + +class Store; +class EvalState; +class Bindings; + +struct MixEvalArgs : virtual Args +{ + MixEvalArgs(); + + Bindings * getAutoArgs(EvalState & state); + + Strings searchPath; + + std::optional<std::string> evalStoreUrl; + +private: + std::map<std::string, std::string> autoArgs; +}; + +Path lookupFileArg(EvalState & state, std::string_view s); + +} diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index 05e479739..74c8a6df5 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -1,5 +1,6 @@ #include "globals.hh" #include "installables.hh" +#include "util.hh" #include "command.hh" #include "attr-path.hh" #include "common-eval-args.hh" @@ -100,6 +101,14 @@ MixFlakeOptions::MixFlakeOptions() lockFlags.inputOverrides.insert_or_assign( flake::parseInputPath(inputPath), parseFlakeRef(flakeRef, absPath("."), true)); + }}, + .completer = {[&](size_t n, std::string_view prefix) { + if (n == 0) { + if (auto flakeRef = getFlakeRefForCompletion()) + completeFlakeInputPath(getEvalState(), *flakeRef, prefix); + } else if (n == 1) { + completeFlakeRef(getEvalState()->store, prefix); + } }} }); @@ -194,6 +203,8 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes() void SourceExprCommand::completeInstallable(std::string_view prefix) { if (file) { + completionType = ctAttrs; + evalSettings.pureEval = false; auto state = getEvalState(); Expr *e = state->parseExprFromFile( @@ -222,13 +233,14 @@ void SourceExprCommand::completeInstallable(std::string_view prefix) Value v2; state->autoCallFunction(*autoArgs, v1, v2); - completionType = ctAttrs; - if (v2.type() == nAttrs) { for (auto & i : *v2.attrs) { std::string name = i.name; if (name.find(searchWord) == 0) { - completions->add(i.name); + if (prefix_ == "") + completions->add(name); + else + completions->add(prefix_ + "." + name); } } } @@ -256,10 +268,11 @@ void completeFlakeRefWithFragment( if (hash == std::string::npos) { completeFlakeRef(evalState->store, prefix); } else { + completionType = ctAttrs; + auto fragment = prefix.substr(hash + 1); auto flakeRefS = std::string(prefix.substr(0, hash)); - // FIXME: do tilde expansion. - auto flakeRef = parseFlakeRef(flakeRefS, absPath(".")); + auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath(".")); auto evalCache = openEvalCache(*evalState, std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags))); @@ -271,8 +284,6 @@ void completeFlakeRefWithFragment( flake. */ attrPathPrefixes.push_back(""); - completionType = ctAttrs; - for (auto & attrPathPrefixS : attrPathPrefixes) { auto attrPathPrefix = parseAttrPath(*evalState, attrPathPrefixS); auto attrPathS = attrPathPrefixS + std::string(fragment); @@ -969,10 +980,10 @@ std::optional<FlakeRef> InstallablesCommand::getFlakeRefForCompletion() { if (_installables.empty()) { if (useDefaultInstallables()) - return parseFlakeRef(".", absPath(".")); + return parseFlakeRefWithFragment(".", absPath(".")).first; return {}; } - return parseFlakeRef(_installables.front(), absPath(".")); + return parseFlakeRefWithFragment(_installables.front(), absPath(".")).first; } InstallableCommand::InstallableCommand(bool supportReadOnlyMode) |