Commit ca7acea5 authored by Mark Olesen's avatar Mark Olesen
Browse files

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()
parent 51fd6327
......@@ -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;
}
......
......@@ -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();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment