24#ifndef TCLAP_STD_OUTPUT_H
25#define TCLAP_STD_OUTPUT_H
99 void spacePrint(std::ostream &os,
const std::string &s,
int maxWidth,
100 int indentSpaces,
int secondLineOffset)
const;
103 enum { _usageWidth = 75 };
105 void _partitionGroups(std::list<ArgGroup *> &groups,
106 std::list<ArgGroup *> &exclusiveGroups,
107 std::list<ArgGroup *> &nonExclusiveGroups)
const;
108 void _printShortSwitches(std::ostream &os, std::string &switches,
109 std::list<ArgGroup *> &groups)
const;
110 void _printLongSwitches(std::ostream &os,
111 std::list<ArgGroup *> &groups)
const;
112 void _printShortOptions(std::ostream &os,
113 std::list<ArgGroup *> &groups)
const;
115 std::list<ArgGroup *> &groups)
const;
117 std::list<ArgGroup *> &groups)
const;
119 std::list<ArgGroup *> &groups)
const;
124 void _printLongEntry(std::ostream &os,
const Arg &arg,
bool required,
132 std::cout << std::endl
135 <<
" " << xversion << std::endl
140 std::cout << std::endl
147 std::cout << std::endl << std::endl
154 std::cout << std::endl;
161 <<
" " << e.
argId() << std::endl
162 <<
" " << e.
error() << std::endl
171 std::cerr << std::endl
173 "For complete USAGE and HELP type: ")
176 <<
"help" << std::endl
188 while ((p = s.find_first_of(r)) != std::string::npos) {
194 int lowa = std::tolower(a);
195 int lowb = std::tolower(b);
205inline bool IsVisibleShortSwitch(
const Arg &arg) {
207 arg.isValueRequired() || arg.getFlag() ==
"") &&
211inline bool IsVisibleLongSwitch(
const Arg &arg) {
213 !arg.isValueRequired() && arg.getFlag() ==
"" &&
214 arg.visibleInHelp());
217inline bool IsVisibleOption(
const Arg &arg) {
219 arg.hasLabel() && arg.visibleInHelp());
222inline bool CompareShortID(
const Arg *a,
const Arg *b) {
223 if (a->getFlag() ==
"" && b->getFlag() !=
"") {
226 if (b->getFlag() ==
"" && a->getFlag() !=
"") {
230 return a->shortID() < b->shortID();
234inline bool CompareOptions(std::pair<const Arg *, bool> a,
235 std::pair<const Arg *, bool> b) {
237 if (!a.second && b.second) {
240 if (a.second && !b.second) {
244 return CompareShortID(a.first, b.first);
247inline ArgGroup *FindArgGroup(
const std::list<ArgGroup *> &groups,
249 for (std::list<ArgGroup *>::const_iterator it = groups.begin();
250 it != groups.end(); ++it)
251 if (std::find((*it)->begin(), (*it)->end(), arg) != (*it)->end())
256inline bool HasVisiblePositional(
const ArgGroup &group) {
258 if (!(*it)->hasLabel() && (*it)->visibleInHelp())
return true;
262inline void PrintExclusiveShortGroup(std::ostream &os,
const ArgGroup &group) {
263 os << (group.isRequired() ?
" {" :
" [");
264 std::vector<Arg *> args;
266 if ((*it)->visibleInHelp()) args.push_back(*it);
267 std::sort(args.begin(), args.end(), CompareShortID);
268 const char *separator =
"";
269 for (std::vector<Arg *>::const_iterator it = args.begin();
270 it != args.end(); ++it) {
271 os << separator << (*it)->shortID();
274 os << (group.isRequired() ?
'}' :
']');
294 std::ostream &os)
const {
297 std::ostringstream outp;
301 std::list<ArgGroup *> exclusiveGroups;
302 std::list<ArgGroup *> nonExclusiveGroups;
303 _partitionGroups(argSets, exclusiveGroups, nonExclusiveGroups);
304 _printShortSwitches(outp, switches, nonExclusiveGroups);
305 _printLongSwitches(outp, nonExclusiveGroups);
308 for (std::list<ArgGroup *>::iterator it = exclusiveGroups.begin();
309 it != exclusiveGroups.end(); ++it) {
310 if (!internal::HasVisiblePositional(**it))
311 internal::PrintExclusiveShortGroup(outp, **it);
314 _printShortOptions(outp, nonExclusiveGroups);
315 _printShortOperands(_cmd, outp, argSets);
318 int secondLineOffset =
static_cast<int>(_cmd.
getProgramName().length()) + 2;
319 if (secondLineOffset > _usageWidth / 2) secondLineOffset =
static_cast<int>(_usageWidth / 2);
321 spacePrint(os, outp.str(), _usageWidth, 3, secondLineOffset);
324inline void StdOutput::_partitionGroups(
325 std::list<ArgGroup *> &groups, std::list<ArgGroup *> &exclusiveGroups,
326 std::list<ArgGroup *> &nonExclusiveGroups)
const {
327 for (std::list<ArgGroup *>::iterator sit = groups.begin();
328 sit != groups.end(); ++sit) {
333 if ((*sit)->isExclusive()) {
334 exclusiveGroups.push_back(*sit);
336 nonExclusiveGroups.push_back(*sit);
344 for (std::list<ArgGroup *>::iterator it = exclusiveGroups.begin();
345 it != exclusiveGroups.end();) {
347 nonExclusiveGroups.push_back(*it);
348 it = exclusiveGroups.erase(it);
355inline void StdOutput::_printShortSwitches(
356 std::ostream &os, std::string &switches,
357 std::list<ArgGroup *> &groups)
const {
358 bool hasShortSwitches =
false;
362 for (std::list<ArgGroup *>::iterator sit = groups.begin();
363 sit != groups.end(); ++sit) {
366 if (internal::IsVisibleShortSwitch(**it)) {
367 switches += (*it)->getFlag();
368 hasShortSwitches =
true;
372 std::sort(switches.begin(), switches.end(),
cmpSwitch);
375 if (hasShortSwitches) os <<
" [" << switches <<
']';
378inline void StdOutput::_printLongSwitches(std::ostream &os,
379 std::list<ArgGroup *> &groups)
const {
381 std::vector<Arg *> longSwitches;
382 for (std::list<ArgGroup *>::iterator sit = groups.begin();
383 sit != groups.end(); ++sit) {
387 if (internal::IsVisibleLongSwitch(arg)) {
388 longSwitches.push_back(&arg);
393 std::sort(longSwitches.begin(), longSwitches.end(),
394 internal::CompareShortID);
395 for (std::vector<Arg *>::const_iterator it = longSwitches.begin();
396 it != longSwitches.end(); ++it) {
397 os <<
" [" << (**it).shortID() <<
']';
401inline void StdOutput::_printShortOptions(std::ostream &os,
402 std::list<ArgGroup *> &groups)
const {
404 std::vector<std::pair<const Arg *, bool> > options;
405 for (std::list<ArgGroup *>::iterator sit = groups.begin();
406 sit != groups.end(); ++sit) {
411 bool required = arg.isRequired();
412 if (internal::IsVisibleOption(arg)) {
413 if (visible == 1 && (**sit).isRequired()) {
417 options.push_back(std::make_pair(&arg, required));
422 std::sort(options.begin(), options.end(), internal::CompareOptions);
423 for (std::vector<std::pair<const Arg *, bool> >::const_iterator it =
425 it != options.end(); ++it) {
426 const Arg &arg = *it->first;
427 bool required = it->second;
428 os << (required ?
" " :
" [");
430 os << (required ?
"" :
"]");
434inline void StdOutput::_printShortOperands(
435 CmdLineInterface &cmd, std::ostream &os,
436 std::list<ArgGroup *> &groups)
const {
438 const std::list<Arg *> operands = cmd.getArgList();
439 std::list<ArgGroup *> shown;
440 for (
ArgListIterator it = operands.begin(); it != operands.end(); ++it) {
441 const Arg &arg = **it;
442 if (arg.hasLabel() || !arg.isValueRequired() || !arg.visibleInHelp())
444 ArgGroup *group = internal::FindArgGroup(groups, &arg);
446 if (std::find(shown.begin(), shown.end(), group) == shown.end()) {
447 internal::PrintExclusiveShortGroup(os, *group);
448 shown.push_back(group);
452 bool required = arg.isRequired() ||
454 os << (required ?
" " :
" [") << arg.shortID() << (required ?
"" :
"]");
459 std::ostream &os)
const {
463 _printLabeledGroups(_cmd, os, argSets);
464 _printLongOperands(_cmd, os, argSets);
466 if (!message.empty()) {
473inline void StdOutput::_printLabeledGroups(
474 CmdLineInterface &cmd, std::ostream &os, std::list<ArgGroup *> &groups)
const {
475 for (std::list<ArgGroup *>::iterator sit = groups.begin();
476 sit != groups.end(); ++sit) {
480 bool exclusive = visible > 1 && argGroup.
isExclusive();
481 if (exclusive && internal::HasVisiblePositional(argGroup))
continue;
482 bool forceRequired = visible == 1 && argGroup.
isRequired();
484 _printGroupHeading(cmd, os, argGroup);
490 if (!arg.visibleInHelp()) {
494 if (!arg.hasLabel()) {
498 bool required = arg.isRequired() || forceRequired;
499 _printLongEntry(os, arg, required, exclusive ? 6 : 3);
504inline void StdOutput::_printLongOperands(
505 CmdLineInterface &cmd, std::ostream &os, std::list<ArgGroup *> &groups)
const {
506 const std::list<Arg *> operands = cmd.getArgList();
507 std::list<ArgGroup *> shown;
508 for (
ArgListIterator it = operands.begin(); it != operands.end(); ++it) {
509 const Arg &arg = **it;
510 if (arg.hasLabel() || !arg.visibleInHelp())
continue;
511 ArgGroup *group = internal::FindArgGroup(groups, &arg);
513 if (std::find(shown.begin(), shown.end(), group) != shown.end())
continue;
514 shown.push_back(group);
515 _printExclusiveLongGroup(cmd, os, *group);
518 const bool required = arg.isRequired() ||
520 _printLongEntry(os, arg, required, 3);
524inline void StdOutput::_printExclusiveLongGroup(
525 CmdLineInterface &cmd, std::ostream &os, ArgGroup &group)
const {
526 _printGroupHeading(cmd, os, group);
528 if (!(*member)->visibleInHelp())
continue;
530 spacePrint(os, (*member)->longID(), _usageWidth, 6, 3);
531 spacePrint(os, (*member)->getDescription((*member)->isRequired()), _usageWidth, 8, 0);
536inline void StdOutput::_printGroupHeading(CmdLineInterface &cmd,
538 const ArgGroup &group)
const {
541 ? cmd.translateMessage(
"one_of_group",
"One of:")
542 : cmd.translateMessage(
"either_of_group",
"Either of:"),
546inline void StdOutput::_printLongEntry(std::ostream &os,
const Arg &arg,
547 bool required,
int indent)
const {
548 spacePrint(os, arg.longID(), _usageWidth, indent, 3);
549 spacePrint(os, arg.getDescription(required), _usageWidth, indent + 2, 0);
554inline void fmtPrintLine(std::ostream &os,
const std::string &text,
int maxWidth,
555 int indentSpaces,
int secondLineOffset) {
556 const std::string breakCharacters(
" ,|");
558 indentSpaces = std::max(indentSpaces, 0);
559 secondLineOffset = std::max(secondLineOffset, 0);
560 size_t availableWidth = std::max(maxWidth - indentSpaces, 0);
561 std::string indentString(indentSpaces,
' ');
562 size_t lineStart = 0;
564 size_t textLength = text.length();
566 if (textLength - lineStart <= availableWidth) {
568 os << indentString << text.substr(lineStart) << std::endl;
573 size_t nextBreak = lineEnd;
574 while (nextBreak - lineStart <= availableWidth &&
575 nextBreak != std::string::npos) {
577 nextBreak = text.find_first_of(breakCharacters, lineEnd + 1);
580 if (lineEnd == lineStart) {
583 lineEnd = availableWidth > 0 ? lineStart + availableWidth - 1
587 if (text[lineEnd] !=
' ') {
592 os << indentString << text.substr(lineStart, lineEnd - lineStart) <<
'\n';
595 for (; text[lineEnd] ==
' '; lineEnd++) {
599 if (secondLineOffset != 0) {
601 indentString.insert(indentString.end(), secondLineOffset,
' ');
604 std::min(availableWidth,
static_cast<size_t>(secondLineOffset));
605 secondLineOffset = 0;
612 int maxWidth,
int indentSpaces,
613 int secondLineOffset)
const {
614 std::stringstream ss(s);
616 std::getline(ss, line);
617 fmtPrintLine(os, line, maxWidth, indentSpaces, secondLineOffset);
618 indentSpaces += secondLineOffset;
620 while (std::getline(ss, line)) {
621 fmtPrintLine(os, line, maxWidth, indentSpaces, 0);
A simple class that defines and argument exception.
std::string argId() const
Returns the argument id.
std::string error() const
Returns the error text.
ArgGroup is the base class for implementing groups of arguments that are mutually exclusive (it repla...
virtual bool isExclusive() const =0
Returns true if this argument group is exclusive.
Container::const_iterator const_iterator
Container::iterator iterator
virtual bool isRequired() const =0
Returns true if this argument group is required.
A virtual base class that defines the essential data for all arguments.
static const std::string nameStartString()
static const std::string ignoreNameString()
The name used to identify the ignore rest argument.
static const std::string flagStartString()
The base class that manages the command line definition and passes along the parsing to the appropria...
virtual std::string getVersion() const =0
Returns the version string.
virtual std::string getMessage() const =0
Returns the message string.
virtual bool hasHelpAndVersion() const =0
Indicates whether or not the help and version switches were created automatically.
virtual std::string translateMessage(const std::string &messageId, const std::string &fallback) const =0
Translates a built-in message using the current translator.
virtual std::string getProgramName() const =0
Returns the program name string.
virtual std::list< ArgGroup * > getArgGroups()=0
Returns the list of ArgGroups.
The interface that any output object must implement.
Thrown when TCLAP thinks the program should exit.
A class that isolates any output from the CmdLine object so that it may be easily modified.
void spacePrint(std::ostream &os, const std::string &s, int maxWidth, int indentSpaces, int secondLineOffset) const
This function inserts line breaks and indents long strings according the params input.
virtual void version(CmdLineInterface &c)
Prints the version to stdout.
virtual void failure(CmdLineInterface &c, ArgException &e)
Prints (to stderr) an error message, short usage Can be overridden to produce alternative behavior.
void _shortUsage(CmdLineInterface &c, std::ostream &os) const
Writes a brief usage message with short args.
void _longUsage(CmdLineInterface &c, std::ostream &os) const
Writes a longer usage message with long and short args, provides descriptions and prints message.
virtual void usage(CmdLineInterface &c)
Prints the usage to stdout.
int CountVisibleArgs(const ArgGroup &g)
std::list< Arg * >::const_iterator ArgListIterator
Typedef of an Arg list iterator.
void removeChar(std::string &s, char r)
bool cmpSwitch(const char &a, const char &b)