Complete flake inputs for all given flakes

Allow `nix build flake1 flake2 --update-input <Tab>` to complete the
inputs of both flakes.

Also do tilde expansion so that `nix build ~/flake --update-input <Tab>`
works.
This commit is contained in:
Naïm Favier 2022-06-19 17:54:27 +02:00
parent 7e301fd74e
commit d6d0e781bb
No known key found for this signature in database
GPG key ID: 95AFCE8211908325
3 changed files with 24 additions and 24 deletions

View file

@ -79,8 +79,10 @@ struct MixFlakeOptions : virtual Args, EvalCommand
MixFlakeOptions();
virtual std::optional<FlakeRef> getFlakeRefForCompletion()
virtual std::vector<std::string> getFlakesForCompletion()
{ return {}; }
void completeFlakeInput(std::string_view prefix);
};
struct SourceExprCommand : virtual Args, MixFlakeOptions
@ -119,7 +121,7 @@ struct InstallablesCommand : virtual Args, SourceExprCommand
virtual bool useDefaultInstallables() { return true; }
std::optional<FlakeRef> getFlakeRefForCompletion() override;
std::vector<std::string> getFlakesForCompletion() override;
private:
@ -135,9 +137,9 @@ struct InstallableCommand : virtual Args, SourceExprCommand
void prepare() override;
std::optional<FlakeRef> getFlakeRefForCompletion() override
std::vector<std::string> getFlakesForCompletion() override
{
return parseFlakeRefWithFragment(_installable, absPath(".")).first;
return {_installable};
}
private:

View file

@ -23,15 +23,16 @@
namespace nix {
void completeFlakeInputPath(
ref<EvalState> evalState,
const FlakeRef & flakeRef,
std::string_view prefix)
void MixFlakeOptions::completeFlakeInput(std::string_view prefix)
{
auto evalState = getEvalState();
for (auto & flakeRefS : getFlakesForCompletion()) {
auto flakeRef = parseFlakeRefWithFragment(expandTilde(flakeRefS), absPath(".")).first;
auto flake = flake::getFlake(*evalState, flakeRef, true);
for (auto & input : flake.inputs)
if (hasPrefix(input.first, prefix))
completions->add(input.first);
}
}
MixFlakeOptions::MixFlakeOptions()
@ -86,8 +87,7 @@ MixFlakeOptions::MixFlakeOptions()
lockFlags.inputUpdates.insert(flake::parseInputPath(s));
}},
.completer = {[&](size_t, std::string_view prefix) {
if (auto flakeRef = getFlakeRefForCompletion())
completeFlakeInputPath(getEvalState(), *flakeRef, prefix);
completeFlakeInput(prefix);
}}
});
@ -103,12 +103,10 @@ MixFlakeOptions::MixFlakeOptions()
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) {
if (n == 0)
completeFlakeInput(prefix);
else if (n == 1)
completeFlakeRef(getEvalState()->store, prefix);
}
}}
});
@ -1043,14 +1041,14 @@ void InstallablesCommand::prepare()
installables = parseInstallables(getStore(), _installables);
}
std::optional<FlakeRef> InstallablesCommand::getFlakeRefForCompletion()
std::vector<std::string> InstallablesCommand::getFlakesForCompletion()
{
if (_installables.empty()) {
if (useDefaultInstallables())
return parseFlakeRefWithFragment(".", absPath(".")).first;
return {"."};
return {};
}
return parseFlakeRefWithFragment(_installables.front(), absPath(".")).first;
return _installables;
}
InstallableCommand::InstallableCommand(bool supportReadOnlyMode)

View file

@ -50,9 +50,9 @@ public:
return flake::lockFlake(*getEvalState(), getFlakeRef(), lockFlags);
}
std::optional<FlakeRef> getFlakeRefForCompletion() override
std::vector<std::string> getFlakesForCompletion() override
{
return getFlakeRef();
return {flakeUrl};
}
};