diff options
author | Eelco Dolstra <edolstra@gmail.com> | 2018-11-22 16:03:31 +0100 |
---|---|---|
committer | Eelco Dolstra <edolstra@gmail.com> | 2019-12-05 20:13:47 +0100 |
commit | f964f428fe6975e06a273e43c3266928a407454f (patch) | |
tree | 6f544df14b0bc6ccfa9cd805916fcb9aa93c9b6b /src/libutil/args.cc | |
parent | f1b5c76c1a5f69b795bf0b5c1afb1853f81225ef (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.cc | 69 |
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); +} + } |