argList fixes/enhancements

- bugfix: noParallel() didn't remove 'parallel' from validParOptions
  allowing it to sneak through to the Pstream layer.
  noParallel() now clears the entire validParOptions as well

- new convenience methods
  * addOption()
  * removeOption()
  * addBoolOption() - as per addOption(), but for bool options (no param)

- printUsage() output format
  * options sorted alphabetically
  * options listed on separate lines for better readability

- new optionUsage static member for short usage information about
  an option
  * corresponding addUsage() method or provide usage information
    in addOption() / addBoolOption()
This commit is contained in:
Mark Olesen
2009-12-03 09:32:30 +01:00
parent 51fd6327a6
commit ca7acea5f4
2 changed files with 237 additions and 64 deletions

View File

@ -40,13 +40,18 @@ License
Foam::SLList<Foam::string> Foam::argList::validArgs; Foam::SLList<Foam::string> Foam::argList::validArgs;
Foam::HashTable<Foam::string> Foam::argList::validOptions; Foam::HashTable<Foam::string> Foam::argList::validOptions;
Foam::HashTable<Foam::string> Foam::argList::validParOptions; 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() Foam::argList::initValidTables::initValidTables()
{ {
validOptions.set("case", "dir"); argList::addOption
validOptions.set("parallel", ""); (
"case", "DIR",
"specify alternate case directory, default is the cwd"
);
argList::addBoolOption("parallel", "run in parallel");
validParOptions.set("parallel", ""); validParOptions.set("parallel", "");
Pstream::addValidParOptions(validParOptions); Pstream::addValidParOptions(validParOptions);
@ -56,6 +61,93 @@ Foam::argList::initValidTables::initValidTables()
Foam::argList::initValidTables dummyInitValidTables; 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_ // convert argv -> args_
// transform sequences with "(" ... ")" into string lists in the process // transform sequences with "(" ... ")" into string lists in the process
bool Foam::argList::regroupArgv(int& argc, char**& argv) 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) if (strcmp(argv[argI], "(") == 0)
{ {
listDepth++; ++listDepth;
tmpString += "("; tmpString += "(";
} }
else if (strcmp(argv[argI], ")") == 0) else if (strcmp(argv[argI], ")") == 0)
{ {
if (listDepth) if (listDepth)
{ {
listDepth--; --listDepth;
tmpString += ")"; tmpString += ")";
if (listDepth == 0) 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() void Foam::argList::getRootCase()
{ {
fileName casePath; fileName casePath;
// [-case dir] specified // [-case dir] specified
HashTable<string>::iterator iter = options_.find("case"); HashTable<string>::const_iterator iter = options_.find("case");
if (iter != options_.end()) if (iter != options_.end())
{ {
@ -173,14 +258,6 @@ void Foam::argList::getRootCase()
setEnv("FOAM_CASE", casePath, true); setEnv("FOAM_CASE", casePath, true);
setEnv("FOAM_CASENAME", casePath.name(), 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) options_(argc)
{ {
// Check if this run is a parallel run by searching for any parallel option // 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++) for (int argI = 0; argI < argc; argI++)
{ {
if (argv[argI][0] == '-') if (argv[argI][0] == '-')
@ -246,13 +323,14 @@ Foam::argList::argList
) )
) )
{ {
argI++; ++argI;
if (argI >= args_.size()) if (argI >= args_.size())
{ {
FatalError FatalError
<< "option " << "'-" << optionName << '\'' <<"Option '-" << optionName
<< " requires an argument" << "' requires an argument" << endl;
<< exit(FatalError); printUsage();
FatalError.exit();
} }
argListString += ' '; argListString += ' ';
@ -270,7 +348,7 @@ Foam::argList::argList
{ {
args_[nArgs] = args_[argI]; args_[nArgs] = args_[argI];
} }
nArgs++; ++nArgs;
} }
} }
@ -412,8 +490,8 @@ Foam::argList::argList
bool hadCaseOpt = options_.found("case"); bool hadCaseOpt = options_.found("case");
for for
( (
int slave=Pstream::firstSlave(); int slave = Pstream::firstSlave();
slave<=Pstream::lastSlave(); slave <= Pstream::lastSlave();
slave++ slave++
) )
{ {
@ -465,8 +543,8 @@ Foam::argList::argList
// Distribute the master's argument list (unaltered) // Distribute the master's argument list (unaltered)
for for
( (
int slave=Pstream::firstSlave(); int slave = Pstream::firstSlave();
slave<=Pstream::lastSlave(); slave <= Pstream::lastSlave();
slave++ slave++
) )
{ {
@ -510,8 +588,8 @@ Foam::argList::argList
label procI = 0; label procI = 0;
for for
( (
int slave=Pstream::firstSlave(); int slave = Pstream::firstSlave();
slave<=Pstream::lastSlave(); slave <= Pstream::lastSlave();
slave++ slave++
) )
{ {
@ -580,53 +658,104 @@ Foam::argList::~argList()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::argList::noBanner() Foam::stringList::subList Foam::argList::additionalArgs() const
{ {
bannerEnabled = false; return stringList::subList(args_, args_.size() - 1, 1);
}
void Foam::argList::noParallel()
{
validOptions.erase("parallel");
} }
void Foam::argList::printUsage() const void Foam::argList::printUsage() const
{ {
Info<< nl Info<< "\nUsage: " << executable_ << " [OPTIONS]";
<< "Usage: " << executable_;
for forAllConstIter(SLList<string>, validArgs, iter)
(
SLList<string>::iterator iter = validArgs.begin();
iter != validArgs.end();
++iter
)
{ {
Info<< " <" << iter().c_str() << '>'; Info<< " <" << iter().c_str() << '>';
} }
for Info<< "\noptions:\n";
(
HashTable<string>::iterator iter = validOptions.begin(); // min is length of the -srcDoc option
iter != validOptions.end(); // first get the length of option + param
++iter 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()) if (iter().size())
{ {
len += iter().size() + 1; // include space between option and param
Info<< ' ' << iter().c_str(); 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 // place srcDoc/doc/help options at the end
Info<< " [-help] [-doc] [-srcDoc]\n" << endl; //
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;
} }

View File

@ -59,9 +59,10 @@ Description
Note Note
- Adjustment of the valid (mandatory) arguments - 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 - 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 SourceFiles
argList.C argList.C
@ -114,8 +115,22 @@ class argList
sigSegv sigSegv_; 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(); void getRootCase();
//- Transcribe argv into internal args_ //- Transcribe argv into internal args_
@ -136,6 +151,9 @@ public:
//- A list of valid parallel options //- A list of valid parallel options
static HashTable<string> validParOptions; static HashTable<string> validParOptions;
//- Short usage information for validOptions
static HashTable<string> optionUsage;
//! @cond ignoreDocumentation //! @cond ignoreDocumentation
class initValidTables class initValidTables
{ {
@ -185,7 +203,7 @@ public:
//- Return arguments //- Return arguments
inline const stringList& args() const; inline const stringList& args() const;
//- Return additionl arguments, //- Return additional arguments,
// i.e. those additional to the executable itself // i.e. those additional to the executable itself
stringList::subList additionalArgs() const; stringList::subList additionalArgs() const;
@ -241,6 +259,32 @@ public:
// Edit // 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 //- Disable emitting the banner information
static void noBanner(); static void noBanner();