diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index 845b852e95ba12effcba34cdfe05410831623e0d..e4669c657c116817bea78b4af2fb7c656d2b4973 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -40,13 +40,18 @@ License Foam::SLList<Foam::string> Foam::argList::validArgs; Foam::HashTable<Foam::string> Foam::argList::validOptions; Foam::HashTable<Foam::string> Foam::argList::validParOptions; -bool Foam::argList::bannerEnabled(true); +Foam::HashTable<Foam::string> Foam::argList::optionUsage; +bool Foam::argList::bannerEnabled = true; Foam::argList::initValidTables::initValidTables() { - validOptions.set("case", "dir"); - validOptions.set("parallel", ""); + argList::addOption + ( + "case", "DIR", + "specify alternate case directory, default is the cwd" + ); + argList::addBoolOption("parallel", "run in parallel"); validParOptions.set("parallel", ""); Pstream::addValidParOptions(validParOptions); @@ -56,6 +61,93 @@ Foam::argList::initValidTables::initValidTables() Foam::argList::initValidTables dummyInitValidTables; +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +void Foam::argList::addBoolOption +( + const word& opt, + const string& usage +) +{ + addOption(opt, "", usage); +} + + +void Foam::argList::addOption +( + const word& opt, + const string& param, + const string& usage +) +{ + validOptions.set(opt, param); + if (!usage.empty()) + { + optionUsage.set(opt, usage); + } +} + + +void Foam::argList::addUsage +( + const word& opt, + const string& usage +) +{ + if (usage.empty()) + { + optionUsage.erase(opt); + } + else + { + optionUsage.set(opt, usage); + } +} + + +void Foam::argList::removeOption(const word& opt) +{ + validOptions.erase(opt); + optionUsage.erase(opt); +} + + +void Foam::argList::noBanner() +{ + bannerEnabled = false; +} + + +void Foam::argList::noParallel() +{ + optionUsage.erase("parallel"); + validOptions.erase("parallel"); + validParOptions.clear(); +} + + +void Foam::argList::printOptionUsage +( + const label location, + const label padWidth, + const string& str +) +{ + if (!str.empty()) + { + for (label i = location; i < padWidth; ++i) + { + Info<<' '; + } + // we could also add text wrapping if desired + Info<<" " << str.c_str(); + } + Info<< nl; +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + // convert argv -> args_ // transform sequences with "(" ... ")" into string lists in the process bool Foam::argList::regroupArgv(int& argc, char**& argv) @@ -70,14 +162,14 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv) { if (strcmp(argv[argI], "(") == 0) { - listDepth++; + ++listDepth; tmpString += "("; } else if (strcmp(argv[argI], ")") == 0) { if (listDepth) { - listDepth--; + --listDepth; tmpString += ")"; if (listDepth == 0) { @@ -114,19 +206,12 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv) } -// get rootPath_ / globalCase_ from one of the following forms -// * [-case dir] -// * cwd -// -// Also export FOAM_CASE and FOAM_CASENAME environment variables -// so they can be used immediately (eg, in decomposeParDict) -// void Foam::argList::getRootCase() { fileName casePath; // [-case dir] specified - HashTable<string>::iterator iter = options_.find("case"); + HashTable<string>::const_iterator iter = options_.find("case"); if (iter != options_.end()) { @@ -173,14 +258,6 @@ void Foam::argList::getRootCase() setEnv("FOAM_CASE", casePath, true); setEnv("FOAM_CASENAME", casePath.name(), true); } - - -} - - -Foam::stringList::subList Foam::argList::additionalArgs() const -{ - return stringList::subList(args_, args_.size() - 1, 1); } @@ -198,7 +275,7 @@ Foam::argList::argList options_(argc) { // Check if this run is a parallel run by searching for any parallel option - // If found call runPar (might filter argv) + // If found call runPar which might filter argv for (int argI = 0; argI < argc; argI++) { if (argv[argI][0] == '-') @@ -246,13 +323,14 @@ Foam::argList::argList ) ) { - argI++; + ++argI; if (argI >= args_.size()) { FatalError - << "option " << "'-" << optionName << '\'' - << " requires an argument" - << exit(FatalError); + <<"Option '-" << optionName + << "' requires an argument" << endl; + printUsage(); + FatalError.exit(); } argListString += ' '; @@ -270,7 +348,7 @@ Foam::argList::argList { args_[nArgs] = args_[argI]; } - nArgs++; + ++nArgs; } } @@ -412,8 +490,8 @@ Foam::argList::argList bool hadCaseOpt = options_.found("case"); for ( - int slave=Pstream::firstSlave(); - slave<=Pstream::lastSlave(); + int slave = Pstream::firstSlave(); + slave <= Pstream::lastSlave(); slave++ ) { @@ -465,8 +543,8 @@ Foam::argList::argList // Distribute the master's argument list (unaltered) for ( - int slave=Pstream::firstSlave(); - slave<=Pstream::lastSlave(); + int slave = Pstream::firstSlave(); + slave <= Pstream::lastSlave(); slave++ ) { @@ -510,8 +588,8 @@ Foam::argList::argList label procI = 0; for ( - int slave=Pstream::firstSlave(); - slave<=Pstream::lastSlave(); + int slave = Pstream::firstSlave(); + slave <= Pstream::lastSlave(); slave++ ) { @@ -580,53 +658,104 @@ Foam::argList::~argList() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -void Foam::argList::noBanner() -{ - bannerEnabled = false; -} - - -void Foam::argList::noParallel() +Foam::stringList::subList Foam::argList::additionalArgs() const { - validOptions.erase("parallel"); + return stringList::subList(args_, args_.size() - 1, 1); } void Foam::argList::printUsage() const { - Info<< nl - << "Usage: " << executable_; + Info<< "\nUsage: " << executable_ << " [OPTIONS]"; - for - ( - SLList<string>::iterator iter = validArgs.begin(); - iter != validArgs.end(); - ++iter - ) + forAllConstIter(SLList<string>, validArgs, iter) { Info<< " <" << iter().c_str() << '>'; } - for - ( - HashTable<string>::iterator iter = validOptions.begin(); - iter != validOptions.end(); - ++iter - ) + Info<< "\noptions:\n"; + + // min is length of the -srcDoc option + // first get the length of option + param + label padWidth = 6; + + forAllConstIter(HashTable<string>, validOptions, iter) { - Info<< " [-" << iter.key(); + label len = iter().size(); + if (len) + { + len++; // space between option and param + } + + len += iter.key().size(); + if (padWidth < len) + { + padWidth = len; + } + } + + padWidth += 3; // include leading " -" + + wordList opts = validOptions.sortedToc(); + forAll(opts, optI) + { + const word& optionName = opts[optI]; + + HashTable<string>::const_iterator iter = validOptions.find(optionName); + Info<< " -" << optionName; + label len = optionName.size() + 3; // include leading " -" if (iter().size()) { + len += iter().size() + 1; // include space between option and param Info<< ' ' << iter().c_str(); } - Info<< ']'; + HashTable<string>::const_iterator usageIter = + optionUsage.find(optionName); + + if (usageIter != optionUsage.end()) + { + printOptionUsage + ( + len, + padWidth, + usageIter() + ); + } + else + { + Info<< nl; + } } - // place help/doc/srcDoc options of the way at the end, - // but with an extra space to separate it a little - Info<< " [-help] [-doc] [-srcDoc]\n" << endl; + // + // place srcDoc/doc/help options at the end + // + Info<< " -srcDoc"; + printOptionUsage + ( + 9, + padWidth, + "display source code in browser" + ); + + Info<< " -doc"; + printOptionUsage + ( + 6, + padWidth, + "display application documentation in browser" + ); + + Info<< " -help"; + printOptionUsage + ( + 7, + padWidth, + "print the usage" + ); + Info<< endl; } diff --git a/src/OpenFOAM/global/argList/argList.H b/src/OpenFOAM/global/argList/argList.H index 787621396852a4d8b07c50a22383c82dcb5312f7..43594b46f8576ea644c09c19ad36e1c4e761ffab 100644 --- a/src/OpenFOAM/global/argList/argList.H +++ b/src/OpenFOAM/global/argList/argList.H @@ -59,9 +59,10 @@ Description Note - Adjustment of the valid (mandatory) arguments - by directly manipulating the static member argList::validArgs. + by directly manipulating the argList::validArgs static member. - Adjustment of the valid options - by directly manipulating the static member argList::validOptions. + via the addOption/removeOption static methods or by directly + manipulating the argList::validOptions static member. SourceFiles argList.C @@ -114,8 +115,22 @@ class argList sigSegv sigSegv_; - // Private member functions + // Private Member Functions + //- Helper function for printUsage + static void printOptionUsage + ( + const label location, + const label padWidth, + const string& str + ); + + //- get rootPath_ / globalCase_ from one of the following forms + // * [-case dir] + // * cwd + // + // Also export FOAM_CASE and FOAM_CASENAME environment variables + // so they can be used immediately (eg, in decomposeParDict) void getRootCase(); //- Transcribe argv into internal args_ @@ -136,6 +151,9 @@ public: //- A list of valid parallel options static HashTable<string> validParOptions; + //- Short usage information for validOptions + static HashTable<string> optionUsage; + //! @cond ignoreDocumentation class initValidTables { @@ -185,7 +203,7 @@ public: //- Return arguments inline const stringList& args() const; - //- Return additionl arguments, + //- Return additional arguments, // i.e. those additional to the executable itself stringList::subList additionalArgs() const; @@ -241,6 +259,32 @@ public: // Edit + //- Add to a bool option to validOptions with usage information + static void addBoolOption + ( + const word& opt, + const string& usage = "" + ); + + //- Add to an option to validOptions with usage information + // An option with an empty param is a bool option + static void addOption + ( + const word& opt, + const string& param = "", + const string& usage = "" + ); + + //- Add option usage information to optionUsage + static void addUsage + ( + const word& opt, + const string& usage + ); + + //- Remove option from validOptions and from optionUsage + static void removeOption(const word& opt); + //- Disable emitting the banner information static void noBanner();