diff --git a/src/nix/command.cc b/src/nix/command.cc index 9a38c77f1..596217775 100644 --- a/src/nix/command.cc +++ b/src/nix/command.cc @@ -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 & 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) { diff --git a/src/nix/command.hh b/src/nix/command.hh index d60c8aeb6..6882db195 100644 --- a/src/nix/command.hh +++ b/src/nix/command.hh @@ -176,20 +176,29 @@ struct StorePathCommand : public InstallablesCommand /* A helper class for registering commands globally. */ struct RegisterCommand { + typedef std::map, std::function()>> Commands; static Commands * commands; - RegisterCommand(const std::string & name, + RegisterCommand(std::vector && name, std::function()> command) { if (!commands) commands = new Commands; commands->emplace(name, command); } + + static nix::Commands getCommandsFor(const std::vector & prefix); }; template static RegisterCommand registerCommand(const std::string & name) { - return RegisterCommand(name, [](){ return make_ref(); }); + return RegisterCommand({name}, [](){ return make_ref(); }); +} + +template +static RegisterCommand registerCommand2(std::vector && name) +{ + return RegisterCommand(std::move(name), [](){ return make_ref(); }); } Buildables build(ref store, Realise mode, diff --git a/src/nix/main.cc b/src/nix/main.cc index a75f8ae65..6d8c66406 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -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";