void HelpFormatter::formatOption(std::ostream& ostr, const Option& option, int width) const { int shortLen = (int) option.shortName().length(); int fullLen = (int) option.fullName().length(); int n = 0; if (_unixStyle && shortLen > 0) { ostr << shortPrefix() << option.shortName(); n += (int) shortPrefix().length() + (int) option.shortName().length(); if (option.takesArgument()) { if (!option.argumentRequired()) { ostr << '['; ++n; } ostr << option.argumentName(); n += (int) option.argumentName().length(); if (!option.argumentRequired()) { ostr << ']'; ++n; } } if (fullLen > 0) { ostr << ", "; n += 2; } } if (fullLen > 0) { ostr << longPrefix() << option.fullName(); n += (int) longPrefix().length() + (int) option.fullName().length(); if (option.takesArgument()) { if (!option.argumentRequired()) { ostr << '['; ++n; } ostr << '='; ++n; ostr << option.argumentName(); n += (int) option.argumentName().length(); if (!option.argumentRequired()) { ostr << ']'; ++n; } } } while (n < width) { ostr << ' '; ++n; } }
void OptionTest::testOption() { Option incOpt = Option("include-dir", "I", "specify an include search path") .required(false) .repeatable(true) .argument("path"); Option libOpt = Option("library-dir", "L", "specify a library search path", false) .repeatable(true) .argument("path"); Option outOpt = Option("output", "o", "specify the output file", true) .argument("file", true); Option vrbOpt = Option("verbose", "v") .description("enable verbose mode") .required(false) .repeatable(false); Option optOpt = Option("optimize", "O") .description("enable optimization") .required(false) .repeatable(false) .argument("level", false); assert (incOpt.shortName() == "I"); assert (incOpt.fullName() == "include-dir"); assert (incOpt.repeatable()); assert (!incOpt.required()); assert (incOpt.argumentName() == "path"); assert (incOpt.argumentRequired()); assert (incOpt.takesArgument()); assert (libOpt.shortName() == "L"); assert (libOpt.fullName() == "library-dir"); assert (libOpt.repeatable()); assert (!libOpt.required()); assert (libOpt.argumentName() == "path"); assert (libOpt.argumentRequired()); assert (incOpt.takesArgument()); assert (outOpt.shortName() == "o"); assert (outOpt.fullName() == "output"); assert (!outOpt.repeatable()); assert (outOpt.required()); assert (outOpt.argumentName() == "file"); assert (outOpt.argumentRequired()); assert (incOpt.takesArgument()); assert (vrbOpt.shortName() == "v"); assert (vrbOpt.fullName() == "verbose"); assert (!vrbOpt.repeatable()); assert (!vrbOpt.required()); assert (!vrbOpt.argumentRequired()); assert (!vrbOpt.takesArgument()); assert (optOpt.shortName() == "O"); assert (optOpt.fullName() == "optimize"); assert (!optOpt.repeatable()); assert (!optOpt.required()); assert (optOpt.argumentName() == "level"); assert (optOpt.takesArgument()); assert (!optOpt.argumentRequired()); }
void Command::help() { // Build command name string commandName = _name; Command *command = this->parentCommand(); while (command) { commandName = command->name() + " " + commandName; command = command->parentCommand(); } // Build usage int offset = 0; if (_options.size() > 0) { vector<string> elements; // Add optinos for (int i = 0; i < _options.size(); i++) { Option option = _options[i]; string element = "["; if (option.shortName() != "") { element += "-" + option.shortName(); if (option.longName() != "") { element += "|--" + option.longName(); } } else { element += "--" + option.longName(); } switch (option.argumentType()) { case Option::ArgumentType::Required: element += " <" + option.argumentName() + ">"; break; case Option::ArgumentType::Optional: element += " [<" + option.argumentName() + ">]"; break; case Option::ArgumentType::NoArgument: break; } element += "]"; elements.push_back(element); } // Calculate width int maximumLineWidth = 80; string header = "usage: " + commandName; offset = min(20, (int)header.size()); // Show usage int i = 0; string line = header; while (i < elements.size()) { if (line.size() + 1 + elements[i].size() > maximumLineWidth) { cout << line << endl; line = ""; for (int j = 0; j < offset; j++) { line += " "; } } line += " " + elements[i]; i++; } if (line != "") { cout << line << endl; } } else { cout << "usage: " + commandName; } // Check whether the command has subcommands if (_subcommands.size() == 0) { cout << endl; return; } // Show command usage for (int i = 0; i < offset; i++) { cout << " "; } cout << " <command> [<args>]" << endl; // Get max command length vector<Command> subcommands = _subcommands; int maximumCommandLength = 0; for (auto it = subcommands.begin(); it != subcommands.end(); ++it) { if ((int)it->name().size() > maximumCommandLength) { maximumCommandLength = (int)it->name().size(); } } // Show commands cout << endl << "commands:" << endl; for (auto it = subcommands.begin(); it != subcommands.end(); ++it) { cout << " " << it->name(); for (int i = 0; i < (maximumCommandLength + 3 - (int)it->name().size()); i++) { cout << " "; } cout << it->description() << endl; } }