aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2018-11-22 16:03:31 +0100
committerEelco Dolstra <edolstra@gmail.com>2019-12-05 20:13:47 +0100
commitf964f428fe6975e06a273e43c3266928a407454f (patch)
tree6f544df14b0bc6ccfa9cd805916fcb9aa93c9b6b /src
parentf1b5c76c1a5f69b795bf0b5c1afb1853f81225ef (diff)
Move Command and MultiCommand to libutil
(cherry picked from commit f70434b1fbbdb0e188718f0c55a8156a7aa08744)
Diffstat (limited to 'src')
-rw-r--r--src/libutil/args.cc69
-rw-r--r--src/libutil/args.hh42
-rw-r--r--src/nix/command.cc74
-rw-r--r--src/nix/command.hh43
-rw-r--r--src/nix/main.cc5
5 files changed, 116 insertions, 117 deletions
diff --git a/src/libutil/args.cc b/src/libutil/args.cc
index 7af2a1bf7..2837dacc9 100644
--- a/src/libutil/args.cc
+++ b/src/libutil/args.cc
@@ -200,4 +200,73 @@ void printTable(std::ostream & out, const Table2 & table)
}
}
+void Command::printHelp(const string & programName, std::ostream & out)
+{
+ Args::printHelp(programName, out);
+
+ auto exs = examples();
+ if (!exs.empty()) {
+ out << "\n";
+ out << "Examples:\n";
+ for (auto & ex : exs)
+ out << "\n"
+ << " " << ex.description << "\n" // FIXME: wrap
+ << " $ " << ex.command << "\n";
+ }
+}
+
+MultiCommand::MultiCommand(const std::vector<ref<Command>> & _commands)
+{
+ for (auto & command : _commands)
+ commands.emplace(command->name(), command);
+
+ expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) {
+ assert(!command);
+ auto i = commands.find(ss[0]);
+ if (i == commands.end())
+ throw UsageError("'%s' is not a recognised command", ss[0]);
+ command = i->second;
+ }});
+}
+
+void MultiCommand::printHelp(const string & programName, std::ostream & out)
+{
+ if (command) {
+ command->printHelp(programName + " " + command->name(), out);
+ return;
+ }
+
+ out << "Usage: " << programName << " <COMMAND> <FLAGS>... <ARGS>...\n";
+
+ out << "\n";
+ out << "Common flags:\n";
+ printFlags(out);
+
+ out << "\n";
+ out << "Available commands:\n";
+
+ Table2 table;
+ for (auto & command : commands) {
+ auto descr = command.second->description();
+ if (!descr.empty())
+ table.push_back(std::make_pair(command.second->name(), descr));
+ }
+ printTable(out, table);
+}
+
+bool MultiCommand::processFlag(Strings::iterator & pos, Strings::iterator end)
+{
+ if (Args::processFlag(pos, end)) return true;
+ if (command && command->processFlag(pos, end)) return true;
+ return false;
+}
+
+bool MultiCommand::processArgs(const Strings & args, bool finish)
+{
+ if (command)
+ return command->processArgs(args, finish);
+ else
+ return Args::processArgs(args, finish);
+}
+
}
diff --git a/src/libutil/args.hh b/src/libutil/args.hh
index f8df39b5c..21f4327c5 100644
--- a/src/libutil/args.hh
+++ b/src/libutil/args.hh
@@ -188,6 +188,48 @@ public:
friend class MultiCommand;
};
+/* A command is an argument parser that can be executed by calling its
+ run() method. */
+struct Command : virtual Args
+{
+ virtual ~Command() { }
+ virtual std::string name() = 0;
+ virtual void prepare() { };
+ virtual void run() = 0;
+
+ struct Example
+ {
+ std::string description;
+ std::string command;
+ };
+
+ typedef std::list<Example> Examples;
+
+ virtual Examples examples() { return Examples(); }
+
+ void printHelp(const string & programName, std::ostream & out) override;
+};
+
+typedef std::map<std::string, ref<Command>> Commands;
+
+/* An argument parser that supports multiple subcommands,
+ i.e. ‘<command> <subcommand>’. */
+class MultiCommand : virtual Args
+{
+public:
+ Commands commands;
+
+ std::shared_ptr<Command> command;
+
+ MultiCommand(const std::vector<ref<Command>> & commands);
+
+ void printHelp(const string & programName, std::ostream & out) override;
+
+ bool processFlag(Strings::iterator & pos, Strings::iterator end) override;
+
+ bool processArgs(const Strings & args, bool finish) override;
+};
+
Strings argvToStrings(int argc, char * * argv);
/* Helper function for rendering argument labels. */
diff --git a/src/nix/command.cc b/src/nix/command.cc
index a40a113db..99848fe73 100644
--- a/src/nix/command.cc
+++ b/src/nix/command.cc
@@ -7,80 +7,6 @@ namespace nix {
std::vector<ref<Command>> * RegisterCommand::commands = 0;
-void Command::printHelp(const string & programName, std::ostream & out)
-{
- Args::printHelp(programName, out);
-
- auto exs = examples();
- if (!exs.empty()) {
- out << "\n";
- out << "Examples:\n";
- for (auto & ex : exs)
- out << "\n"
- << " " << ex.description << "\n" // FIXME: wrap
- << " $ " << ex.command << "\n";
- }
-}
-
-MultiCommand::MultiCommand(const std::vector<ref<Command>> & _commands)
-{
- for (auto & command : _commands)
- commands.emplace(command->name(), command);
-
- expectedArgs.push_back(ExpectedArg{"command", 1, true, [=](std::vector<std::string> ss) {
- assert(!command);
- auto i = commands.find(ss[0]);
- if (i == commands.end())
- throw UsageError("'%s' is not a recognised command", ss[0]);
- command = i->second;
- }});
-}
-
-void MultiCommand::printHelp(const string & programName, std::ostream & out)
-{
- if (command) {
- command->printHelp(programName + " " + command->name(), out);
- return;
- }
-
- out << "Usage: " << programName << " <COMMAND> <FLAGS>... <ARGS>...\n";
-
- out << "\n";
- out << "Common flags:\n";
- printFlags(out);
-
- out << "\n";
- out << "Available commands:\n";
-
- Table2 table;
- for (auto & command : commands) {
- auto descr = command.second->description();
- if (!descr.empty())
- table.push_back(std::make_pair(command.second->name(), descr));
- }
- printTable(out, table);
-
-#if 0
- out << "\n";
- out << "For full documentation, run 'man " << programName << "' or 'man " << programName << "-<COMMAND>'.\n";
-#endif
-}
-
-bool MultiCommand::processFlag(Strings::iterator & pos, Strings::iterator end)
-{
- if (Args::processFlag(pos, end)) return true;
- if (command && command->processFlag(pos, end)) return true;
- return false;
-}
-
-bool MultiCommand::processArgs(const Strings & args, bool finish)
-{
- if (command)
- return command->processArgs(args, finish);
- else
- return Args::processArgs(args, finish);
-}
-
StoreCommand::StoreCommand()
{
}
diff --git a/src/nix/command.hh b/src/nix/command.hh
index be56f8992..aa34301d9 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -11,29 +11,6 @@ struct Value;
class Bindings;
class EvalState;
struct Pos;
-
-/* A command is an argument parser that can be executed by calling its
- run() method. */
-struct Command : virtual Args
-{
- virtual ~Command() { }
- virtual std::string name() = 0;
- virtual void prepare() { };
- virtual void run() = 0;
-
- struct Example
- {
- std::string description;
- std::string command;
- };
-
- typedef std::list<Example> Examples;
-
- virtual Examples examples() { return Examples(); }
-
- void printHelp(const string & programName, std::ostream & out) override;
-};
-
class Store;
/* A command that requires a Nix store. */
@@ -171,26 +148,6 @@ struct StorePathCommand : public InstallablesCommand
void run(ref<Store> store) override;
};
-typedef std::map<std::string, ref<Command>> Commands;
-
-/* An argument parser that supports multiple subcommands,
- i.e. ‘<command> <subcommand>’. */
-class MultiCommand : virtual Args
-{
-public:
- Commands commands;
-
- std::shared_ptr<Command> command;
-
- MultiCommand(const std::vector<ref<Command>> & commands);
-
- void printHelp(const string & programName, std::ostream & out) override;
-
- bool processFlag(Strings::iterator & pos, Strings::iterator end) override;
-
- bool processArgs(const Strings & args, bool finish) override;
-};
-
/* A helper class for registering commands globally. */
struct RegisterCommand
{
diff --git a/src/nix/main.cc b/src/nix/main.cc
index d5cba7fb9..dcf351cf4 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -107,6 +107,11 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
void printHelp(const string & programName, std::ostream & out)
{
MultiCommand::printHelp(programName, out);
+
+#if 0
+ out << "\nFor full documentation, run 'man " << programName << "' or 'man " << programName << "-<COMMAND>'.\n";
+#endif
+
std::cout << "\nNote: this program is EXPERIMENTAL and subject to change.\n";
}