aboutsummaryrefslogtreecommitdiff
path: root/src/libcmd
diff options
context:
space:
mode:
authorMaximilian Bosch <maximilian@mbosch.me>2021-07-03 14:19:10 +0200
committerMaximilian Bosch <maximilian@mbosch.me>2021-07-03 14:19:10 +0200
commit70cb2ffaccb91eff6f4afe2552d0784e279f1fe9 (patch)
treed3d9f66384dc2804957d3d8c9d7f2764c20cf7db /src/libcmd
parent69eb65403ad3e877300a7c0c96411d9d9e27dc69 (diff)
libcmd/installables: implement completion for Nix expressions passed via `-f`
Diffstat (limited to 'src/libcmd')
-rw-r--r--src/libcmd/installables.cc46
1 files changed, 38 insertions, 8 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index fe52912cf..49f063334 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -171,14 +171,44 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
void SourceExprCommand::completeInstallable(std::string_view prefix)
{
- if (file) return; // FIXME
-
- completeFlakeRefWithFragment(
- getEvalState(),
- lockFlags,
- getDefaultFlakeAttrPathPrefixes(),
- getDefaultFlakeAttrPaths(),
- prefix);
+ if (file) {
+ evalSettings.pureEval = false;
+ auto state = getEvalState();
+ Expr *e = state->parseExprFromFile(
+ resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
+ );
+
+ Value root;
+ state->eval(e, root);
+
+ auto autoArgs = getAutoArgs(*state);
+
+ std::string prefix_ = std::string(prefix);
+ auto sep = prefix_.rfind('.');
+ if (sep != std::string::npos) {
+ prefix_.erase(sep);
+ } else {
+ prefix_ = "";
+ }
+
+ Value &v1(*findAlongAttrPath(*state, prefix_, *autoArgs, root).first);
+ state->forceValue(v1);
+ Value v2;
+ state->autoCallFunction(*autoArgs, v1, v2);
+
+ if (v2.type() == nAttrs) {
+ for (auto & i : *v2.attrs) {
+ completions->add(i.name);
+ }
+ }
+ } else {
+ completeFlakeRefWithFragment(
+ getEvalState(),
+ lockFlags,
+ getDefaultFlakeAttrPathPrefixes(),
+ getDefaultFlakeAttrPaths(),
+ prefix);
+ }
}
void completeFlakeRefWithFragment(