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 { 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) 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. */ /* A helper class for registering commands globally. */
struct RegisterCommand struct RegisterCommand
{ {
typedef std::map<std::vector<std::string>, std::function<ref<Command>()>> Commands;
static Commands * commands; static Commands * commands;
RegisterCommand(const std::string & name, RegisterCommand(std::vector<std::string> && name,
std::function<ref<Command>()> command) std::function<ref<Command>()> command)
{ {
if (!commands) commands = new Commands; if (!commands) commands = new Commands;
commands->emplace(name, command); commands->emplace(name, command);
} }
static nix::Commands getCommandsFor(const std::vector<std::string> & prefix);
}; };
template<class T> template<class T>
static RegisterCommand registerCommand(const std::string & name) 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, Buildables build(ref<Store> store, Realise mode,

View file

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