Allow registering subcommands of subcommands

This commit is contained in:
Eelco Dolstra 2020-12-03 17:55:27 +01:00
parent b2d6c6161e
commit 5781f45c46
3 changed files with 27 additions and 4 deletions

View File

@ -11,7 +11,21 @@ extern char * * environ __attribute__((weak));
namespace nix {
Commands * RegisterCommand::commands = nullptr;
RegisterCommand::Commands * RegisterCommand::commands = nullptr;
nix::Commands RegisterCommand::getCommandsFor(const std::vector<std::string> & prefix)
{
nix::Commands res;
for (auto & [name, command] : *RegisterCommand::commands)
if (name.size() == prefix.size() + 1) {
bool equal = true;
for (size_t i = 0; i < prefix.size(); ++i)
if (name[i] != prefix[i]) equal = false;
if (equal)
res.insert_or_assign(name[prefix.size()], command);
}
return res;
}
void NixMultiCommand::printHelp(const string & programName, std::ostream & out)
{

View File

@ -176,20 +176,29 @@ struct StorePathCommand : public InstallablesCommand
/* A helper class for registering commands globally. */
struct RegisterCommand
{
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
static Commands * commands;
RegisterCommand(const std::string & name,
RegisterCommand(std::vector<std::string> && name,
std::function<ref<Command>()> command)
{
if (!commands) commands = new Commands;
commands->emplace(name, command);
}
static nix::Commands getCommandsFor(const std::vector<std::string> & prefix);
};
template<class T>
static RegisterCommand registerCommand(const std::string & name)
{
return RegisterCommand(name, [](){ return make_ref<T>(); });
return RegisterCommand({name}, [](){ return make_ref<T>(); });
}
template<class T>
static RegisterCommand registerCommand2(std::vector<std::string> && name)
{
return RegisterCommand(std::move(name), [](){ return make_ref<T>(); });
}
Buildables build(ref<Store> store, Realise mode,

View File

@ -59,7 +59,7 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
bool useNet = true;
bool refresh = false;
NixArgs() : MultiCommand(*RegisterCommand::commands), MixCommonArgs("nix")
NixArgs() : MultiCommand(RegisterCommand::getCommandsFor({})), MixCommonArgs("nix")
{
categories.clear();
categories[Command::catDefault] = "Main commands";