Browse Source

Help option now takes an argument that is interpreted as a regexp and matched against the module names and option names.

Former-commit-id: ff44877a75
tempestpy_adaptions
dehnert 10 years ago
parent
commit
685d9274eb
  1. 2
      src/settings/Option.h
  2. 92
      src/settings/SettingsManager.cpp
  3. 11
      src/settings/SettingsManager.h
  4. 4
      src/settings/modules/GeneralSettings.cpp

2
src/settings/Option.h

@ -142,7 +142,7 @@ namespace storm {
*/
ArgumentBase const& getArgumentByName(std::string const& argumentName) const {
auto argumentIterator = this->argumentNameMap.find(argumentName);
LOG_THROW(argumentIterator != this->argumentNameMap.end(), storm::exceptions::IllegalArgumentException, "Unable to retrieve argument with unknown name " << argumentName << ".");
LOG_THROW(argumentIterator != this->argumentNameMap.end(), storm::exceptions::IllegalArgumentException, "Unable to retrieve argument with unknown name '" << argumentName << "'.");
return *argumentIterator->second;
}

92
src/settings/SettingsManager.cpp

@ -4,6 +4,8 @@
#include <cctype>
#include <mutex>
#include <iomanip>
#include <regex>
#include <set>
#include <boost/algorithm/string.hpp>
#include <boost/io/ios_state.hpp>
@ -12,7 +14,7 @@
namespace storm {
namespace settings {
SettingsManager::SettingsManager() : modules(), longNameToOptions(), shortNameToOptions(), moduleOptions() {
// Register all known settings modules.
this->addModule(std::unique_ptr<modules::ModuleSettings>(new modules::GeneralSettings(*this)));
@ -24,7 +26,7 @@ namespace storm {
this->addModule(std::unique_ptr<modules::ModuleSettings>(new modules::GlpkSettings(*this)));
this->addModule(std::unique_ptr<modules::ModuleSettings>(new modules::GurobiSettings(*this)));
}
SettingsManager::~SettingsManager() {
// Intentionally left empty.
}
@ -110,7 +112,7 @@ namespace storm {
void SettingsManager::setFromConfigurationFile(std::string const& configFilename) {
LOG_ASSERT(false, "Not yet implemented");
}
void SettingsManager::printHelp(std::string const& hint) const {
std::cout << "usage: storm [options]" << std::endl << std::endl;
@ -121,32 +123,63 @@ namespace storm {
printHelpForModule(moduleName, maxLength);
}
} else {
auto moduleIterator = this->modules.find(hint);
// Create a regular expression from the input hint.
std::regex hintRegex(hint, std::regex_constants::ECMAScript | std::regex_constants::icase);
// If the supplied information is a module, print the help text of the module.
if (moduleIterator != this->modules.end()) {
uint_fast64_t maxLength = getPrintLengthOfLongestOption(hint);
printHelpForModule(hint, maxLength);
} else {
auto optionIterator = this->longNameToOptions.find(hint);
if (optionIterator != this->longNameToOptions.end()) {
// Save the flags for std::cout so we can manipulate them and be sure they will be restored as soon as this
// stream goes out of scope.
boost::io::ios_flags_saver out(std::cout);
// Remember which options we printed, so we don't display options twice.
std::set<std::shared_ptr<Option>> printedOptions;
// Try to match the regular expression against the known modules.
std::vector<std::string> matchingModuleNames;
uint_fast64_t maxLengthModules = 0;
for (auto const& moduleName : this->moduleNames) {
if (std::regex_search(moduleName, hintRegex)) {
matchingModuleNames.push_back(moduleName);
maxLengthModules = std::max(maxLengthModules, getPrintLengthOfLongestOption(moduleName));
std::cout << "Matching options:" << std::endl;
uint_fast64_t maxLength = 0;
for (auto const& option : optionIterator->second) {
maxLength = std::max(maxLength, option->getPrintLength());
}
// Add all options of this module to the list of printed options so we don't print them twice.
auto optionIterator = this->moduleOptions.find(moduleName);
printedOptions.insert(optionIterator->second.begin(), optionIterator->second.end());
}
}
// Try to match the regular expression against the known options.
std::vector<std::shared_ptr<Option>> matchingOptions;
uint_fast64_t maxLengthOptions = 0;
for (auto const& optionName : this->longOptionNames) {
if (std::regex_search(optionName, hintRegex)) {
auto optionIterator = this->longNameToOptions.find(optionName);
for (auto const& option : optionIterator->second) {
std::cout << std::setw(maxLength) << std::left << *option << std::endl;
// Only add the option if we have not already added it to the list of options that is going
// to be printed anyway.
if (printedOptions.find(option) == printedOptions.end()) {
maxLengthOptions = std::max(maxLengthOptions, option->getPrintLength());
matchingOptions.push_back(option);
}
}
} else {
LOG_THROW(false, storm::exceptions::IllegalArgumentValueException, "Unable to show help for unknown entity '" << hint << "'.");
}
}
// Print the matching modules.
uint_fast64_t maxLength = std::max(maxLengthModules, maxLengthOptions);
if (matchingModuleNames.size() > 0) {
std::cout << "Matching modules for hint '" << hint << "':" << std::endl;
for (auto const& matchingModuleName : matchingModuleNames) {
printHelpForModule(matchingModuleName, maxLength);
}
}
// Print the matching options.
if (matchingOptions.size() > 0) {
std::cout << "Matching options for hint '" << hint << "':" << std::endl;
for (auto const& option : matchingOptions) {
std::cout << std::setw(maxLength) << std::left << *option << std::endl;
}
}
if (matchingModuleNames.empty() && matchingOptions.empty()) {
std::cout << "Hint '" << hint << "' did not match any modules or options." << std::endl;
}
}
}
@ -168,7 +201,7 @@ namespace storm {
}
std::cout << std::endl;
}
uint_fast64_t SettingsManager::getPrintLengthOfLongestOption() const {
uint_fast64_t length = 0;
for (auto const& moduleName : this->moduleNames) {
@ -186,7 +219,7 @@ namespace storm {
void SettingsManager::addModule(std::unique_ptr<modules::ModuleSettings>&& moduleSettings) {
auto moduleIterator = this->modules.find(moduleSettings->getModuleName());
LOG_THROW(moduleIterator == this->modules.end(), storm::exceptions::IllegalFunctionCallException, "Unable to register module '" << moduleSettings->getModuleName() << "' because a module with the same name already exists.");
// Take over the module settings object.
std::string const& moduleName = moduleSettings->getModuleName();
this->moduleNames.push_back(moduleName);
@ -200,7 +233,7 @@ namespace storm {
this->addOption(option);
}
}
void SettingsManager::addOption(std::shared_ptr<Option> const& option) {
// First, we register to which module the given option belongs.
auto moduleOptionIterator = this->moduleOptions.find(option->getModuleName());
@ -217,6 +250,7 @@ namespace storm {
}
// For the prefixed name, we don't need a compatibility check, because a module is not allowed to register the same option twice.
addOptionToMap(option->getModuleName() + ":" + option->getLongName(), option, this->longNameToOptions);
longOptionNames.push_back(option->getModuleName() + ":" + option->getLongName());
if (option->getHasShortName()) {
if (!option->getRequiresModulePrefix()) {
@ -227,7 +261,7 @@ namespace storm {
addOptionToMap(option->getModuleName() + ":" + option->getShortName(), option, this->shortNameToOptions);
}
}
modules::ModuleSettings const& SettingsManager::getModule(std::string const& moduleName) const {
auto moduleIterator = this->modules.find(moduleName);
LOG_THROW(moduleIterator != this->modules.end(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve unknown module '" << moduleName << "'.");
@ -260,7 +294,7 @@ namespace storm {
// Iterate over all options and set the arguments.
for (auto& option : optionIterator->second) {
option->setHasOptionBeenSet();
LOG_THROW(option->getArgumentCount() <= argumentCache.size(), storm::exceptions::OptionParserException, "Unknown option '" << optionName << "'.");
LOG_THROW(argumentCache.size() <= option->getArgumentCount(), storm::exceptions::OptionParserException, "Too many arguments for option '" << optionName << "'.");
// Now set the provided argument values one by one.
for (uint_fast64_t i = 0; i < argumentCache.size(); ++i) {
@ -314,7 +348,7 @@ namespace storm {
storm::settings::modules::CuddSettings const& cuddSettings() {
return dynamic_cast<storm::settings::modules::CuddSettings const&>(manager().getModule(storm::settings::modules::CuddSettings::moduleName));
}
storm::settings::modules::GmmxxEquationSolverSettings const& gmmxxEquationSolverSettings() {
return dynamic_cast<storm::settings::modules::GmmxxEquationSolverSettings const&>(manager().getModule(storm::settings::modules::GmmxxEquationSolverSettings::moduleName));
}

11
src/settings/SettingsManager.h

@ -74,10 +74,11 @@ namespace storm {
void setFromConfigurationFile(std::string const& configFilename);
/*!
* This function prints a help message to the standard output. Optionally, a string can be given that either
* identifies a module or some options to cut down the help text.
* This function prints a help message to the standard output. Optionally, a string can be given as a hint.
* If it is 'all', the complete help is shown. Otherwise, the string is interpreted as a regular expression
* and matched against the known modules and options to restrict the help output.
*
* @param hint The name of a module, some options or "all" for the full help text.
* @param hint A regular expression to restrict the help output or "all" for the full help text.
*/
void printHelp(std::string const& hint = "all") const;
@ -144,6 +145,10 @@ namespace storm {
// A mapping of module names to the corresponding options.
std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>> moduleOptions;
// A list of long option names to keep the order in which they were registered. This is, for example, used
// to match the regular expression given to the help option against the option names.
std::vector<std::string> longOptionNames;
/*!
* Adds the given option to the known options.
*

4
src/settings/modules/GeneralSettings.cpp

@ -38,7 +38,7 @@ namespace storm {
GeneralSettings::GeneralSettings(storm::settings::SettingsManager& settingsManager) : ModuleSettings(settingsManager, moduleName) {
this->addOption(storm::settings::OptionBuilder(moduleName, helpOptionName, false, "Shows all available options, arguments and descriptions.").setShortName(helpOptionShortName)
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("module", "The module for which to show the help or 'all' for all modules.").setDefaultValueString("all").build()).build());
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("hint", "A regular expression to show help for all matching entities or 'all' for the complete help.").setDefaultValueString("all").build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, verboseOptionName, false, "Enables more verbose output.").setShortName(verboseOptionShortName).build());
this->addOption(storm::settings::OptionBuilder(moduleName, precisionOptionName, false, "The internally used precision.").setShortName(precisionOptionShortName)
.addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to use.").setDefaultValueDouble(1e-06).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build());
@ -84,7 +84,7 @@ namespace storm {
}
std::string GeneralSettings::getHelpModuleName() const {
return this->getOption(helpOptionName).getArgumentByName("module").getValueAsString();
return this->getOption(helpOptionName).getArgumentByName("hint").getValueAsString();
}
bool GeneralSettings::isVerboseSet() const {

Loading…
Cancel
Save