aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/args.cc
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/libutil/args.cc
parentf1b5c76c1a5f69b795bf0b5c1afb1853f81225ef (diff)
Move Command and MultiCommand to libutil
(cherry picked from commit f70434b1fbbdb0e188718f0c55a8156a7aa08744)
Diffstat (limited to 'src/libutil/args.cc')
-rw-r--r--src/libutil/args.cc69
1 files changed, 69 insertions, 0 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);
+}
+
}