From 685d9274ebaf37c100dd5ce333f78697b9731ea9 Mon Sep 17 00:00:00 2001 From: dehnert Date: Wed, 24 Sep 2014 11:11:46 +0200 Subject: [PATCH] Help option now takes an argument that is interpreted as a regexp and matched against the module names and option names. Former-commit-id: ff44877a75efb45ed45a3ed748d675a7720f4031 --- src/settings/Option.h | 2 +- src/settings/SettingsManager.cpp | 92 ++++++++++++++++-------- src/settings/SettingsManager.h | 11 ++- src/settings/modules/GeneralSettings.cpp | 4 +- 4 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/settings/Option.h b/src/settings/Option.h index 8f2c2c047..c061be37a 100644 --- a/src/settings/Option.h +++ b/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; } diff --git a/src/settings/SettingsManager.cpp b/src/settings/SettingsManager.cpp index 812578832..d8a900d8b 100644 --- a/src/settings/SettingsManager.cpp +++ b/src/settings/SettingsManager.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -12,7 +14,7 @@ namespace storm { namespace settings { - + SettingsManager::SettingsManager() : modules(), longNameToOptions(), shortNameToOptions(), moduleOptions() { // Register all known settings modules. this->addModule(std::unique_ptr(new modules::GeneralSettings(*this))); @@ -24,7 +26,7 @@ namespace storm { this->addModule(std::unique_ptr(new modules::GlpkSettings(*this))); this->addModule(std::unique_ptr(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> printedOptions; + + // Try to match the regular expression against the known modules. + std::vector 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> 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&& 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