19 #include <basis/tclap/Arg.h> 20 #include <basis/tclap/ArgException.h> 21 #include <basis/tclap/StdOutput.h> 22 #include <basis/tclap/Visitor.h> 23 #include <basis/tclap/VersionVisitor.h> 24 #include <basis/tclap/XorHandler.h> 47 class StdOutput :
public TCLAP::CmdLineOutput
59 StdOutput(CmdLine* cmd);
68 virtual void usage(TCLAP::CmdLineInterface&);
73 virtual void help(TCLAP::CmdLineInterface&);
78 virtual void version(TCLAP::CmdLineInterface&);
93 CmdLine* getCmdLine() {
return _cmd; }
102 void updateTerminalInfo();
120 string getTypeDescription(
TCLAP::Arg* arg)
const;
130 string getArgumentID(
TCLAP::Arg* arg,
bool all =
false)
const;
139 void printArgumentHelp(ostream& os,
TCLAP::Arg* arg,
bool indentFirstLine =
true)
const;
147 void printUsage(ostream& os,
bool heading =
true)
const;
154 void printDescription(ostream& os)
const;
163 void printArguments(ostream& os,
bool all)
const;
170 void printExample(ostream& os)
const;
177 void printContact(ostream& os)
const;
184 set<string> _stdargs;
194 StdOutput::StdOutput(CmdLine* cmd)
199 _stdargs.insert(
"ignore_rest");
200 _stdargs.insert(
"verbose");
201 _stdargs.insert(
"help");
202 _stdargs.insert(
"helpshort");
203 _stdargs.insert(
"helpxml");
204 _stdargs.insert(
"helpman");
205 _stdargs.insert(
"version");
213 void StdOutput::usage(TCLAP::CmdLineInterface&)
215 updateTerminalInfo();
217 printUsage(cout,
false);
223 void StdOutput::help(TCLAP::CmdLineInterface&)
225 updateTerminalInfo();
228 printDescription(cout);
229 printArguments(cout,
true);
236 void StdOutput::version(TCLAP::CmdLineInterface&)
238 std::string name = _cmd->getProgramName();
239 std::string project = _cmd->getProjectName();
240 std::string version = _cmd->getVersion();
241 std::string copyright = _cmd->getCopyright();
242 std::string license = _cmd->getLicense();
246 if (!project.empty()) cout <<
" (" << project <<
")";
247 cout <<
" " << version;
250 if (!copyright.empty()) {
251 cout <<
"Copyright (c) " << copyright <<
". All rights reserved." << endl;
253 if (!license.empty()) cout << license << endl;
259 if (!e.argId().empty() && e.argId() !=
" ") cerr << e.argId() <<
", ";
260 cerr << e.error() << endl;
261 cerr <<
"See --help for a list of available and required arguments." << endl;
270 inline void StdOutput::updateTerminalInfo()
275 if (columns > 40) _columns = columns;
279 inline bool StdOutput::isUnlabeledArg(
TCLAP::Arg* arg)
const 281 const string id = arg->longID();
282 string::size_type pos =
id.find(TCLAP::Arg::nameStartString() + arg->getName());
283 return pos == string::npos;
287 inline string StdOutput::getTypeDescription(
TCLAP::Arg* arg)
const 289 string typedesc = arg->shortID();
290 string::size_type start = typedesc.find (
'<');
291 string::size_type end = typedesc.rfind(
'>');
292 if (start != string::npos && end != string::npos) {
293 return typedesc.substr(start + 1, end - start - 1);
300 inline string StdOutput::getArgumentID(
TCLAP::Arg* arg,
bool all)
const 303 const bool option = !isUnlabeledArg(arg);
305 if (all && arg->getFlag() !=
"") {
306 id += TCLAP::Arg::flagStartString() + arg->getFlag();
309 id += TCLAP::Arg::nameStartString() + arg->getName();
311 if (arg->isValueRequired()) {
312 if (option)
id += TCLAP::Arg::delimiter();
313 id += getTypeDescription(arg);
320 void StdOutput::printArgumentHelp(ostream& os,
TCLAP::Arg* arg,
bool indentFirstLine)
const 322 string id = getArgumentID(arg,
true);
323 string desc = arg->getDescription();
324 if (desc.compare (0, 12,
"(required) ") == 0) desc.erase(0, 12);
325 if (desc.compare (0, 15,
"(OR required) ") == 0) desc.erase(0, 15);
334 void StdOutput::printUsage(ostream& os,
bool heading)
const 337 list<TCLAP::Arg*> args = _cmd->getArgList();
338 TCLAP::XorHandler& xorhandler = _cmd->getXorHandler();
339 vector< vector<TCLAP::Arg*> > xors = xorhandler.getXorList();
342 vector< vector<TCLAP::Arg*> > reqxors;
343 vector< vector<TCLAP::Arg*> > optxors;
344 for (
int i = 0;
static_cast<unsigned int>(i) < xors.size(); i++) {
345 if (xors[i].size() > 0) {
346 if (xors[i][0]->isRequired()) reqxors.push_back(xors[i]);
347 else optxors.push_back(xors[i]);
350 list<TCLAP::Arg*> reqargs, reqposargs;
351 list<TCLAP::Arg*> optargs, optposargs;
352 for (TCLAP::ArgListIterator it = args.begin(); it != args.end(); it++) {
353 if (_stdargs.find((*it)->getName()) == _stdargs.end()
354 && !xorhandler.contains((*it))) {
355 if (isUnlabeledArg(*it)) {
356 if ((*it)->isRequired()) {
357 (*it)->addToList(reqposargs);
359 (*it)->addToList(optposargs);
362 if ((*it)->isRequired()) {
363 (*it)->addToList(reqargs);
365 (*it)->addToList(optargs);
372 string s = exec_name;
375 for (
int i = 0;
static_cast<unsigned int>(i) < optxors.size(); i++) {
377 for (TCLAP::ArgVectorIterator it = optxors[i].begin();
378 it != optxors[i].end(); it++) {
379 id = getArgumentID(*it);
381 if ((*it)->acceptsMultipleValues() &&
id.find(
"...") == string::npos) {
386 s[s.length() - 1] =
']';
388 for (TCLAP::ArgListIterator it = optargs.begin(); it != optargs.end(); it++) {
389 id = getArgumentID(*it);
393 if ((*it)->acceptsMultipleValues() &&
id.find(
"...") == string::npos) {
398 for (
int i = 0;
static_cast<unsigned int>(i) < reqxors.size(); i++) {
400 for (TCLAP::ArgVectorIterator it = reqxors[i].begin();
401 it != reqxors[i].end(); it++) {
402 id = getArgumentID(*it);
404 if ((*it)->acceptsMultipleValues() &&
id.find(
"...") == string::npos) {
409 s[s.length() - 1] =
')';
411 for (TCLAP::ArgListIterator it = reqargs.begin(); it != reqargs.end(); it++) {
412 id = getArgumentID(*it);
415 if ((*it)->acceptsMultipleValues() &&
id.find(
"...") == string::npos) {
420 for (TCLAP::ArgListIterator it = reqposargs.begin(); it != reqposargs.end(); it++) {
421 id = getArgumentID(*it);
424 if ((*it)->acceptsMultipleValues() &&
id.find(
"...") == string::npos) {
429 for (TCLAP::ArgListIterator it = optposargs.begin(); it != optposargs.end(); it++) {
430 id = getArgumentID(*it);
434 if ((*it)->acceptsMultipleValues() &&
id.find(
"...") == string::npos) {
442 os <<
"SYNOPSIS" << endl;
444 int offset =
static_cast<int>(exec_name.length()) + 1;
445 if (offset > _columns / 2) offset = 8;
447 print_wrapped(os, exec_name +
" [-h|--help|--helpshort|--helpxml|--helpman|--version]", _columns, 4, offset);
451 void StdOutput::printDescription(ostream& os)
const 453 if (_cmd->getMessage() !=
"") {
455 os <<
"DESCRIPTION" << endl;
461 void StdOutput::printArguments(ostream& os,
bool all)
const 463 list<TCLAP::Arg*> args = _cmd->getArgList();
464 TCLAP::XorHandler& xorhandler = _cmd->getXorHandler();
465 vector< vector<TCLAP::Arg*> > xors = xorhandler.getXorList();
468 vector< vector<TCLAP::Arg*> > reqxors;
469 vector< vector<TCLAP::Arg*> > optxors;
470 for (
int i = 0;
static_cast<unsigned int>(i) < xors.size(); i++) {
471 if (xors[i].size() > 0) {
472 if (xors[i][0]->isRequired()) reqxors.push_back(xors[i]);
473 else optxors.push_back(xors[i]);
476 list<TCLAP::Arg*> reqargs, reqposargs;
477 list<TCLAP::Arg*> optargs, optposargs;
478 list<TCLAP::Arg*> stdargs;
479 for (TCLAP::ArgListIterator it = args.begin(); it != args.end(); it++) {
480 if (_stdargs.find((*it)->getName()) != _stdargs.end()) {
481 (*it)->addToList(stdargs);
482 }
else if (!xorhandler.contains((*it))) {
483 if (isUnlabeledArg(*it)) {
484 if ((*it)->isRequired()) {
485 (*it)->addToList(reqposargs);
487 (*it)->addToList(optposargs);
490 if ((*it)->isRequired()) {
491 (*it)->addToList(reqargs);
493 (*it)->addToList(optargs);
500 if (xors.empty() && reqargs.empty() && optargs.empty()) {
505 os <<
"OPTIONS" << endl;
508 if (!reqxors.empty() || !reqargs.empty() || !reqposargs.empty()) {
509 os <<
" Required arguments:" << endl;
510 for (TCLAP::ArgListIterator it = reqposargs.begin(); it != reqposargs.end(); it++) {
511 if (it != reqposargs.begin()) os << endl;
512 printArgumentHelp(os, *it);
514 for (
int i = 0;
static_cast<unsigned int>(i) < reqxors.size(); i++) {
515 if (i > 0 || !reqposargs.empty()) os << endl;
516 for (TCLAP::ArgVectorIterator it = reqxors[i].begin();
517 it != reqxors[i].end(); it++) {
518 if (it != reqxors[i].begin()) {
520 printArgumentHelp(os, *it,
false);
522 printArgumentHelp(os, *it);
526 for (TCLAP::ArgListIterator it = reqargs.begin(); it != reqargs.end(); it++) {
527 if (!reqxors.empty() || it != reqargs.begin()) os << endl;
528 printArgumentHelp(os, *it);
533 if (!optxors.empty() || !optargs.empty()) {
534 if (!reqxors.empty() || !reqargs.empty() || !reqposargs.empty()) {
537 os <<
" Optional arguments:" << endl;
538 for (TCLAP::ArgListIterator it = optposargs.begin(); it != optposargs.end(); it++) {
539 if (it != optposargs.begin()) os << endl;
540 printArgumentHelp(os, *it);
542 for (
int i = 0;
static_cast<unsigned int>(i) < optxors.size(); i++) {
543 if (i > 0 || !optposargs.empty()) os << endl;
544 for (TCLAP::ArgVectorIterator it = optxors[i].begin();
545 it != optxors[i].end(); it++) {
546 if (it != optxors[i].begin()) {
548 printArgumentHelp(os, *it,
false);
550 printArgumentHelp(os, *it);
554 for (TCLAP::ArgListIterator it = optargs.begin(); it != optargs.end(); it++) {
555 if (!optxors.empty() || it != optargs.begin()) os << endl;
556 printArgumentHelp(os, *it);
561 if (all && !stdargs.empty()) {
562 if (!xors.empty() || !reqargs.empty() || !optargs.empty()) {
565 os <<
" Standard arguments:" << endl;
566 for (TCLAP::ArgListIterator it = stdargs.begin(); it != stdargs.end(); it++) {
567 if (it != stdargs.begin()) os << endl;
568 printArgumentHelp(os, *it);
574 void StdOutput::printExample(ostream& os)
const 577 const vector<string>& examples = _cmd->getExamples();
579 if (!examples.empty()) {
581 os <<
"EXAMPLE" << endl;
582 for (vector<string>::const_iterator it = examples.begin();
583 it != examples.end(); ++it) {
584 if (it != examples.begin()) os << endl;
585 string example = *it;
586 string::size_type pos;
589 while ((pos = example.find(
"EXECNAME", pos)) != string::npos) {
590 example.replace(pos, 8, exec_name);
594 while ((pos = example.find(
"EXENAME", pos)) != string::npos) {
595 example.replace(pos, 7, exec_name);
603 void StdOutput::printContact(ostream& os)
const 605 if (_cmd->getContact() !=
"") {
607 os <<
"CONTACT" << endl;
619 class HelpVisitor:
public TCLAP::Visitor
631 HelpVisitor(StdOutput* out,
bool all =
true)
647 if (_all) _out->help (*(_out->getCmdLine()));
648 else _out->usage(*(_out->getCmdLine()));
664 HelpVisitor(
const HelpVisitor&);
665 HelpVisitor& operator=(
const HelpVisitor&);
676 class XmlVisitor:
public TCLAP::Visitor
699 cerr <<
"Not implemented yet! Use --help instead." << endl;
713 XmlVisitor(
const XmlVisitor&);
714 XmlVisitor& operator=(
const XmlVisitor&);
725 class ManPageVisitor:
public TCLAP::Visitor
748 cerr <<
"Not implemented yet! Use --help instead." << endl;
762 ManPageVisitor(
const ManPageVisitor&);
763 ManPageVisitor& operator=(
const ManPageVisitor&);
773 const std::string& project,
775 const std::string& example,
776 const std::string& version,
777 const std::string& copyright,
778 const std::string& license,
779 const std::string& contact,
782 TCLAP::
CmdLine(description,
' ', version, false),
786 _copyright(copyright),
790 if (example !=
"")
_examples.push_back(example);
796 const std::string& project,
797 const std::string& description,
798 const std::vector<std::string>& examples,
799 const std::string& version,
800 const std::string& copyright,
801 const std::string& license,
802 const std::string& contact,
805 TCLAP::
CmdLine(description,
' ', version, false),
821 StdOutput* output =
new StdOutput(
this);
822 if (_output)
delete _output;
826 ClearContainer(_argDeleteOnExitList);
827 ClearContainer(_visitorDeleteOnExitList);
828 TCLAP::CmdLine::_argList.clear();
833 v =
new TCLAP::IgnoreRestVisitor();
835 TCLAP::Arg::flagStartString(), TCLAP::Arg::ignoreNameString(),
836 "Ignores the rest of the labeled arguments.",
839 deleteOnExit(ignore);
843 v =
new HelpVisitor(output,
true);
845 "h",
"help",
"Display help and exit.",
false, v);
850 v =
new HelpVisitor(output,
false);
852 "",
"helpshort",
"Display short help and exit.",
false, v);
854 deleteOnExit(helpshort);
857 v =
new XmlVisitor();
859 "",
"helpxml",
"Display help in XML format and exit.",
false, v);
861 deleteOnExit(helpxml);
864 v =
new ManPageVisitor();
866 "",
"helpman",
"Display help as man page and exit.",
false, v);
868 deleteOnExit(helpman);
871 v =
new TCLAP::VersionVisitor(
this, &_output);
873 "",
"version",
"Display version information and exit.",
false, v);
883 TCLAP::CmdLine::add(a);
889 TCLAP::CmdLine::add(a);
895 vector<TCLAP::Arg*> xors;
904 _output->usage(*const_cast<CmdLine*>(
this));
910 StdOutput* output =
dynamic_cast<StdOutput*
>(_output);
911 if (output) output ->help (*const_cast<CmdLine*>(
this));
912 else _output->usage(*const_cast<CmdLine*>(
this));
918 _output->version(*const_cast<CmdLine*>(
this));
925 bool required =
false;
926 for (TCLAP::ArgVectorIterator it = xors.begin(); it != xors.end(); ++it) {
927 if ((*it)->isRequired()) required =
true;
929 for (TCLAP::ArgVectorIterator it = xors.begin(); it != xors.end(); ++it) {
930 if (required) (*it)->forceRequired();
931 (*it)->setRequireLabel(
"OR required");
939 vector<string> args(argc);
940 for (
int i = 0; i < argc; i++) args[i] = argv[i];
947 bool shouldExit =
false;
952 args.erase(args.begin());
954 int requiredCount = 0;
955 for (
int i = 0;
static_cast<unsigned int>(i) < args.size(); i++) {
956 bool matched =
false;
957 for (TCLAP::ArgListIterator it = _argList.begin(); it != _argList.end(); it++) {
958 if ((*it)->processArg(&i, args)) {
964 if (!matched && _emptyCombined(args[i])) matched =
true;
965 if (!matched && !TCLAP::Arg::ignoreRest()) {
970 if (requiredCount < _numRequired) {
972 for (TCLAP::ArgListIterator it = _argList.begin(); it != _argList.end(); it++) {
973 if ((*it)->isRequired() && !(*it)->isSet()) {
974 args += (*it)->getName();
978 args = args.substr(0, args.length() - 2);
979 string msg = string(
"Not all required arguments specified, missing: ") + args;
982 if (requiredCount > _numRequired) {
987 if (!_handleExceptions)
throw;
989 _output->failure(*
this, e);
991 estat = ee.getExitStatus();
995 if (!_handleExceptions)
throw;
996 estat = ee.getExitStatus();
1000 if (shouldExit) exit(estat);
void xorAdd(Arg &a, Arg &b)
Add two Args that will be xor'd.
Basic exceptions and related helper macros.
void setup(bool stdargs)
Set up command-line object.
XorHandler _xorHandler
Customized XorHandler.
void parse(int argc, const char *const *argv)
Parses the command line.
void print_usage() const
Print short help, i.e., usage information.
TCLAP::SwitchArg SwitchArg
Switch to enable/disable option.
std::string _name
Program name.
std::string _project
Name of project.
std::string exename()
Get name of executable.
std::string _copyright
Program copyright.
CmdLine(const std::string &name, const std::string &project, const std::string &description, const std::string &example, const std::string &version, const std::string ©right="Copyright (c) University of Pennsylvania." " All rights reserved.", const std::string &license="See http://www.rad.upenn.edu/sbia/software/license.html" " or COPYING file.", const std::string &contact="SBIA Group <sbia-software at uphs.upenn.edu>", bool stdargs=true)
Constructor.
std::ostream & print_wrapped(std::ostream &os, const std::string &text, int width, int indent, int offset)
Print text, wrapped at a fixed maximum number of columns.
TCLAP::ArgException ArgException
Exception thrown by command-line parsing library.
int check(const Arg *a)
Checks whether the specified Arg is in one of the xor lists.
Operating system dependent functions.
TCLAP::Arg Arg
Base type of command-line arguments.
Manages command line definition and parsing of arguments.
std::string _contact
Contact information.
std::string _license
Program license.
Handles lists of Arg's that are to be XOR'd on the command-line.
void add(Arg &a)
Adds an argument to the list of arguments to be parsed.
int get_terminal_columns()
Get maximum number of columns of terminal window.
void print_help() const
Print help.
Manages command line definition and parsing of arguments.
std::vector< std::string > _examples
Program usage example.
TCLAP::ExitException ExitException
Exception thrown by command-line parsing library to indicate that program should exit with the given ...
void print_version() const
Print version information.
TCLAP::CmdLineParseException CmdLineParseException
Exception thrown on command-line parsing error.
virtual std::string description() const