Fix completion of --template

This commit is contained in:
Eelco Dolstra 2020-06-05 14:09:12 +02:00
parent ab54031e04
commit 488ff83e6b
3 changed files with 45 additions and 19 deletions

View file

@ -38,8 +38,6 @@ struct EvalCommand : virtual StoreCommand, MixEvalArgs
ref<EvalState> getEvalState(); ref<EvalState> getEvalState();
std::shared_ptr<EvalState> evalState; std::shared_ptr<EvalState> evalState;
void completeFlakeRef(std::string_view prefix);
}; };
struct MixFlakeOptions : virtual Args struct MixFlakeOptions : virtual Args
@ -205,4 +203,13 @@ struct MixEnvironment : virtual Args {
void setEnviron(); void setEnviron();
}; };
void completeFlakeRef(ref<Store> store, std::string_view prefix);
void completeFlakeRefWithFragment(
ref<EvalState> evalState,
flake::LockFlags lockFlags,
Strings attrPathPrefixes,
const Strings & defaultFlakeAttrPaths,
std::string_view prefix);
} }

View file

@ -33,7 +33,7 @@ public:
.optional = true, .optional = true,
.handler = {&flakeUrl}, .handler = {&flakeUrl},
.completer = {[&](size_t, std::string_view prefix) { .completer = {[&](size_t, std::string_view prefix) {
completeFlakeRef(prefix); completeFlakeRef(getStore(), prefix);
}} }}
}); });
} }
@ -500,6 +500,9 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
std::string templateUrl = "templates"; std::string templateUrl = "templates";
Path destDir; Path destDir;
const Strings attrsPathPrefixes{"templates."};
const LockFlags lockFlags{ .writeLockFile = false };
CmdFlakeInitCommon() CmdFlakeInitCommon()
{ {
addFlag({ addFlag({
@ -509,7 +512,12 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
.labels = {"template"}, .labels = {"template"},
.handler = {&templateUrl}, .handler = {&templateUrl},
.completer = {[&](size_t, std::string_view prefix) { .completer = {[&](size_t, std::string_view prefix) {
completeFlakeRef(prefix); completeFlakeRefWithFragment(
getEvalState(),
lockFlags,
attrsPathPrefixes,
{"defaultTemplate"},
prefix);
}} }}
}); });
} }
@ -525,7 +533,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
auto installable = InstallableFlake( auto installable = InstallableFlake(
evalState, std::move(templateFlakeRef), evalState, std::move(templateFlakeRef),
Strings{templateName == "" ? "defaultTemplate" : templateName}, Strings{templateName == "" ? "defaultTemplate" : templateName},
Strings{"templates."}, { .writeLockFile = false }); Strings(attrsPathPrefixes), lockFlags);
auto cursor = installable.getCursor(*evalState, true); auto cursor = installable.getCursor(*evalState, true);

View file

@ -111,6 +111,21 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
{ {
if (file) return; // FIXME if (file) return; // FIXME
completeFlakeRefWithFragment(
getEvalState(),
lockFlags,
getDefaultFlakeAttrPathPrefixes(),
getDefaultFlakeAttrPaths(),
prefix);
}
void completeFlakeRefWithFragment(
ref<EvalState> evalState,
flake::LockFlags lockFlags,
Strings attrPathPrefixes,
const Strings & defaultFlakeAttrPaths,
std::string_view prefix)
{
/* Look for flake output attributes that match the /* Look for flake output attributes that match the
prefix. */ prefix. */
try { try {
@ -121,10 +136,8 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
// FIXME: do tilde expansion. // FIXME: do tilde expansion.
auto flakeRef = parseFlakeRef(flakeRefS, absPath(".")); auto flakeRef = parseFlakeRef(flakeRefS, absPath("."));
auto state = getEvalState(); auto evalCache = openEvalCache(*evalState,
std::make_shared<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags)),
auto evalCache = openEvalCache(*state,
std::make_shared<flake::LockedFlake>(lockFlake(*state, flakeRef, lockFlags)),
true); true);
auto root = evalCache->getRoot(); auto root = evalCache->getRoot();
@ -132,13 +145,12 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
/* Complete 'fragment' relative to all the /* Complete 'fragment' relative to all the
attrpath prefixes as well as the root of the attrpath prefixes as well as the root of the
flake. */ flake. */
auto attrPathPrefixes = getDefaultFlakeAttrPathPrefixes();
attrPathPrefixes.push_back(""); attrPathPrefixes.push_back("");
for (auto & attrPathPrefixS : attrPathPrefixes) { for (auto & attrPathPrefixS : attrPathPrefixes) {
auto attrPathPrefix = parseAttrPath(*state, attrPathPrefixS); auto attrPathPrefix = parseAttrPath(*evalState, attrPathPrefixS);
auto attrPathS = attrPathPrefixS + std::string(fragment); auto attrPathS = attrPathPrefixS + std::string(fragment);
auto attrPath = parseAttrPath(*state, attrPathS); auto attrPath = parseAttrPath(*evalState, attrPathS);
std::string lastAttr; std::string lastAttr;
if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) { if (!attrPath.empty() && !hasSuffix(attrPathS, ".")) {
@ -149,8 +161,7 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
auto attr = root->findAlongAttrPath(attrPath); auto attr = root->findAlongAttrPath(attrPath);
if (!attr) continue; if (!attr) continue;
auto attrs = attr->getAttrs(); for (auto & attr2 : attr->getAttrs()) {
for (auto & attr2 : attrs) {
if (hasPrefix(attr2, lastAttr)) { if (hasPrefix(attr2, lastAttr)) {
auto attrPath2 = attr->getAttrPath(attr2); auto attrPath2 = attr->getAttrPath(attr2);
/* Strip the attrpath prefix. */ /* Strip the attrpath prefix. */
@ -163,8 +174,8 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
/* And add an empty completion for the default /* And add an empty completion for the default
attrpaths. */ attrpaths. */
if (fragment.empty()) { if (fragment.empty()) {
for (auto & attrPath : getDefaultFlakeAttrPaths()) { for (auto & attrPath : defaultFlakeAttrPaths) {
auto attr = root->findAlongAttrPath(parseAttrPath(*state, attrPath)); auto attr = root->findAlongAttrPath(parseAttrPath(*evalState, attrPath));
if (!attr) continue; if (!attr) continue;
completions->insert(flakeRefS + "#"); completions->insert(flakeRefS + "#");
} }
@ -174,7 +185,7 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
warn(e.msg()); warn(e.msg());
} }
completeFlakeRef(prefix); completeFlakeRef(evalState->store, prefix);
} }
ref<EvalState> EvalCommand::getEvalState() ref<EvalState> EvalCommand::getEvalState()
@ -184,7 +195,7 @@ ref<EvalState> EvalCommand::getEvalState()
return ref<EvalState>(evalState); return ref<EvalState>(evalState);
} }
void EvalCommand::completeFlakeRef(std::string_view prefix) void completeFlakeRef(ref<Store> store, std::string_view prefix)
{ {
if (prefix == "") if (prefix == "")
completions->insert("."); completions->insert(".");
@ -192,7 +203,7 @@ void EvalCommand::completeFlakeRef(std::string_view prefix)
completeDir(0, prefix); completeDir(0, prefix);
/* Look for registry entries that match the prefix. */ /* Look for registry entries that match the prefix. */
for (auto & registry : fetchers::getRegistries(getStore())) { for (auto & registry : fetchers::getRegistries(store)) {
for (auto & entry : registry->entries) { for (auto & entry : registry->entries) {
auto from = entry.from.to_string(); auto from = entry.from.to_string();
if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) { if (!hasPrefix(prefix, "flake:") && hasPrefix(from, "flake:")) {