diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2021-07-05 21:50:15 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-05 21:50:15 +0200 |
commit | 0a8845720ea2c04b4d5ca94ecd0176501dcc49ae (patch) | |
tree | 76041233b8d6eb99962df087e4e24f5f8337b33e /src | |
parent | 1f930841495548b5e111946819b84bf9a10f47a9 (diff) | |
parent | 3c5f69bb60f858f471121adaf172edb47628188e (diff) |
Merge pull request #4980 from Ma27/file-attr-completion
libcmd/installables: implement completion for Nix expressions passed via `-f`
Diffstat (limited to 'src')
-rw-r--r-- | src/libcmd/installables.cc | 52 |
1 files changed, 44 insertions, 8 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index fe52912cf..5f263061b 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -171,14 +171,50 @@ 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('.'); + std::string searchWord; + if (sep != std::string::npos) { + searchWord = prefix_.substr(sep, std::string::npos); + prefix_ = prefix_.substr(0, sep); + } else { + searchWord = prefix_; + 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) { + std::string name = i.name; + if (name.find(searchWord) == 0) { + completions->add(i.name); + } + } + } + } else { + completeFlakeRefWithFragment( + getEvalState(), + lockFlags, + getDefaultFlakeAttrPathPrefixes(), + getDefaultFlakeAttrPaths(), + prefix); + } } void completeFlakeRefWithFragment( |