diff --git a/src/storm/settings/Option.cpp b/src/storm/settings/Option.cpp index 338289fe6..1ab2aa23a 100644 --- a/src/storm/settings/Option.cpp +++ b/src/storm/settings/Option.cpp @@ -14,11 +14,11 @@ namespace storm { namespace settings { - Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : Option(moduleName, longOptionName, "", false, optionDescription, isOptionRequired, requireModulePrefix, optionArguments) { + Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, bool isAdvanced, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : Option(moduleName, longOptionName, "", false, optionDescription, isOptionRequired, requireModulePrefix, isAdvanced, optionArguments) { // Intentionally left empty. } - Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : Option(moduleName, longOptionName, shortOptionName, true, optionDescription, isOptionRequired, requireModulePrefix, optionArguments) { + Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, bool isAdvanced, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : Option(moduleName, longOptionName, shortOptionName, true, optionDescription, isOptionRequired, requireModulePrefix, isAdvanced, optionArguments) { // Intentionally left empty. } @@ -85,13 +85,11 @@ namespace storm { std::string const& Option::getLongName() const { return this->longName; } - bool Option::getHasShortName() const { return this->hasShortName; } - std::string const& Option::getShortName() const { return this->shortName; } @@ -108,16 +106,19 @@ namespace storm { return this->isRequired; } - bool Option::getRequiresModulePrefix() const { return this->requireModulePrefix; } + bool Option::getIsAdvanced() const { + return this->isAdvanced; + } + bool Option::getHasOptionBeenSet() const { return this->hasBeenSet; } - Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, bool hasShortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : longName(longOptionName), hasShortName(hasShortOptionName), shortName(shortOptionName), description(optionDescription), moduleName(moduleName), isRequired(isOptionRequired), requireModulePrefix(requireModulePrefix), hasBeenSet(false), arguments(optionArguments), argumentNameMap() { + Option::Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, bool hasShortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, bool isAdvanced, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments) : longName(longOptionName), hasShortName(hasShortOptionName), shortName(shortOptionName), description(optionDescription), moduleName(moduleName), isRequired(isOptionRequired), requireModulePrefix(requireModulePrefix), isAdvanced(isAdvanced), hasBeenSet(false), arguments(optionArguments), argumentNameMap() { // First, do some sanity checks. STORM_LOG_THROW(!longName.empty(), storm::exceptions::IllegalArgumentException, "Unable to construct option with empty name."); STORM_LOG_THROW(!moduleName.empty(), storm::exceptions::IllegalArgumentException, "Unable to construct option with empty module name."); diff --git a/src/storm/settings/Option.h b/src/storm/settings/Option.h index 1adf8ddff..0ff675d21 100644 --- a/src/storm/settings/Option.h +++ b/src/storm/settings/Option.h @@ -40,9 +40,10 @@ namespace storm { * @param isOptionRequired Sets whether the option is required to appear. * @param requireModulePrefix A flag that indicates whether this option requires to be prefixed with the * module name. + * @param isAdvanced A flag that indicates whether this option is only displayed in the advanced help * @param optionArguments The arguments of the option. */ - Option(std::string const& moduleName, std::string const& longOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments = std::vector<std::shared_ptr<ArgumentBase>>()); + Option(std::string const& moduleName, std::string const& longOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, bool isAdvanced, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments = std::vector<std::shared_ptr<ArgumentBase>>()); /*! * Creates an option with the given parameters. @@ -53,10 +54,10 @@ namespace storm { * @param optionDescription The description of the option. * @param isOptionRequired Sets whether the option is required to appear. * @param requireModulePrefix A flag that indicates whether this option requires to be prefixed with the - * module name. + * @param isAdvanced A flag that indicates whether this option is only displayed in the advanced help * @param optionArguments The arguments of the option. */ - Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments = std::vector<std::shared_ptr<ArgumentBase>>()); + Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, bool isAdvanced, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments = std::vector<std::shared_ptr<ArgumentBase>>()); /*! * Checks whether the given option is compatible with the current one. If not, an exception is thrown. @@ -161,6 +162,11 @@ namespace storm { */ bool getHasOptionBeenSet() const; + /*! + * Retrieves whether the option is only displayed in the advanced help. + */ + bool getIsAdvanced() const; + /*! * Retrieves the arguments of the option. * @@ -199,6 +205,9 @@ namespace storm { // A flag that indicates whether this option is required to be prefixed with the module name. bool requireModulePrefix; + // A flag that indicates whether this option is only displayed in the advanced help. + bool isAdvanced; + // A flag that indicates whether this option has been set. bool hasBeenSet; @@ -219,9 +228,10 @@ namespace storm { * @param isOptionRequired Sets whether the option is required to appear. * @param requireModulePrefix A flag that indicates whether this option requires to be prefixed with the * module name. + * @param isAdvanced A flag that indicates whether this option is only displayed in the advanced help * @param optionArguments The arguments of the option. */ - Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, bool hasShortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments = std::vector<std::shared_ptr<ArgumentBase>>()); + Option(std::string const& moduleName, std::string const& longOptionName, std::string const& shortOptionName, bool hasShortOptionName, std::string const& optionDescription, bool isOptionRequired, bool requireModulePrefix, bool isAdvanced, std::vector<std::shared_ptr<ArgumentBase>> const& optionArguments = std::vector<std::shared_ptr<ArgumentBase>>()); /*! * Sets the flag that marks the option as being (un)set. diff --git a/src/storm/settings/OptionBuilder.h b/src/storm/settings/OptionBuilder.h index f6b2bfea1..643b13b3b 100644 --- a/src/storm/settings/OptionBuilder.h +++ b/src/storm/settings/OptionBuilder.h @@ -33,7 +33,7 @@ namespace storm { * @param requireModulePrefix Sets whether this option can only be set by specifying the module name as its prefix. * @param description A description that explains the purpose of this option. */ - OptionBuilder(std::string const& moduleName, std::string const& longName, bool requireModulePrefix, std::string const& description) : longName(longName), shortName(""), hasShortName(false), description(description), moduleName(moduleName), requireModulePrefix(requireModulePrefix), isRequired(false), isBuild(false), arguments(), argumentNameSet() { + OptionBuilder(std::string const& moduleName, std::string const& longName, bool requireModulePrefix, std::string const& description) : longName(longName), shortName(""), hasShortName(false), description(description), moduleName(moduleName), requireModulePrefix(requireModulePrefix), isRequired(false), isAdvanced(false), isBuild(false), arguments(), argumentNameSet() { // Intentionally left empty. } @@ -60,6 +60,14 @@ namespace storm { return *this; } + /*! + * Sets whether the option is only displayed in the advanced help. + */ + OptionBuilder& setIsAdvanced(bool isAdvanced = true) { + this->isAdvanced = isAdvanced; + return *this; + } + /*! * Adds the given argument to the arguments of this option. * @@ -89,9 +97,9 @@ namespace storm { this->isBuild = true; if (this->hasShortName) { - return std::shared_ptr<Option>(new Option(this->moduleName, this->longName, this->shortName, this->description, this->isRequired, this->requireModulePrefix, this->arguments)); + return std::shared_ptr<Option>(new Option(this->moduleName, this->longName, this->shortName, this->description, this->isRequired, this->requireModulePrefix, this->isAdvanced, this->arguments)); } else { - return std::shared_ptr<Option>(new Option(this->moduleName, this->longName, this->description, this->isRequired, this->requireModulePrefix, this->arguments)); + return std::shared_ptr<Option>(new Option(this->moduleName, this->longName, this->description, this->isRequired, this->requireModulePrefix, this->isAdvanced, this->arguments)); } } @@ -116,7 +124,10 @@ namespace storm { // A flag indicating whether the option is required. bool isRequired; - + + // A flag that indicates whether this option is only displayed in the advanced help. + bool isAdvanced; + // A flag indicating whether the builder has already been used to build an option. bool isBuild; diff --git a/src/storm/settings/SettingsManager.cpp b/src/storm/settings/SettingsManager.cpp index 3b8dcfade..099a77f46 100644 --- a/src/storm/settings/SettingsManager.cpp +++ b/src/storm/settings/SettingsManager.cpp @@ -86,13 +86,32 @@ namespace storm { void SettingsManager::handleUnknownOption(std::string const& optionName, bool isShort) const { std::string optionNameWithDashes = (isShort ? "-" : "--") + optionName; storm::utility::string::SimilarStrings similarStrings(optionNameWithDashes, 0.6, false); + std::map<std::string, std::vector<std::string>> similarOptionNames; for (auto const& longOption : longNameToOptions) { - similarStrings.add("--" + longOption.first); + if (similarStrings.add("--" + longOption.first)) { + similarOptionNames["--" + longOption.first].push_back(longOption.first); + } } for (auto const& shortOption : shortNameToOptions) { - similarStrings.add("-" + shortOption.first); + if (similarStrings.add("-" + shortOption.first)) { + for (auto const& option : shortOption.second) { + similarOptionNames["-" + shortOption.first].push_back(option->getLongName()); + } + } + } + std::string errorMessage = "Unknown option '" + optionNameWithDashes + "'."; + if (!similarOptionNames.empty()) { + errorMessage += " " + similarStrings.toDidYouMeanString() + "\n\n"; + std::vector<std::string> sortedSimilarOptionNames; + auto similarStringsList = similarStrings.toList(); + for (auto const& s : similarStringsList) { + for (auto const& longOptionName : similarOptionNames.at(s)) { + sortedSimilarOptionNames.push_back(longOptionName); + } + } + errorMessage += getHelpForSelection({}, sortedSimilarOptionNames, "", "##### Suggested options:"); } - STORM_LOG_THROW(false, storm::exceptions::OptionParserException, "Unknown option '" << optionNameWithDashes << "'. " << similarStrings.toDidYouMeanString()); + STORM_LOG_THROW(false, storm::exceptions::OptionParserException, errorMessage); } void SettingsManager::setFromExplodedString(std::vector<std::string> const& commandLineArguments) { @@ -188,112 +207,184 @@ namespace storm { this->finalizeAllModules(); } - void SettingsManager::printHelp(std::string const& hint) const { + void SettingsManager::printHelp(std::string const& filter) const { STORM_PRINT("usage: " << executableName << " [options]" << std::endl << std::endl); - if (hint == "all") { + if (filter == "frequent" || filter == "all") { + bool includeAdvanced = (filter == "all"); // Find longest option name. - uint_fast64_t maxLength = getPrintLengthOfLongestOption(); + uint_fast64_t maxLength = getPrintLengthOfLongestOption(includeAdvanced); + + std::vector<std::string> invisibleModules; + uint64_t numHidden = 0; for (auto const& moduleName : this->moduleNames) { // Only print for visible modules. if (hasModule(moduleName, true)) { - printHelpForModule(moduleName, maxLength); - }; + STORM_PRINT(getHelpForModule(moduleName, maxLength, includeAdvanced)); + // collect 'hidden' options + if (!includeAdvanced) { + auto moduleIterator = moduleOptions.find(moduleName); + if (moduleIterator != this->moduleOptions.end()) { + bool allAdvanced = true; + for (auto const& option : moduleIterator->second) { + if (!option->getIsAdvanced()) { + allAdvanced = false; + } else { + ++numHidden; + } + } + if (!moduleIterator->second.empty() && allAdvanced) { + invisibleModules.push_back(moduleName); + } + } + } + } + } + if (numHidden > 0) { + STORM_PRINT(numHidden << " hidden options." << std::endl); + } + if (!invisibleModules.empty()) { + STORM_PRINT(invisibleModules.size() << " hidden modules (" << boost::join(invisibleModules, ", ") << ")." << std::endl); + } + if (numHidden > 0 || !invisibleModules.empty()) { + STORM_PRINT(std::endl << "Type 'storm --help modulename' to display all options of a specific module or 'storm --help all' for a complete list of options." << std::endl); } } else { // Create a regular expression from the input hint. - std::regex hintRegex(hint, std::regex_constants::ECMAScript | std::regex_constants::icase); - - // Remember which options we printed, so we don't display options twice. - std::set<std::shared_ptr<Option>> printedOptions; + std::regex hintRegex(filter, std::regex_constants::ECMAScript | std::regex_constants::icase); // 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)) { if (hasModule(moduleName, true)) { - // Only consider visible modules. matchingModuleNames.push_back(moduleName); - maxLengthModules = std::max(maxLengthModules, getPrintLengthOfLongestOption(moduleName)); - - // 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; + std::vector<std::string> matchingOptionNames; for (auto const& optionName : this->longOptionNames) { if (std::regex_search(optionName, hintRegex)) { - auto optionIterator = this->longNameToOptions.find(optionName); - for (auto const& option : optionIterator->second) { - // 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); - } - } + matchingOptionNames.push_back(optionName); } } - // Print the matching modules. - uint_fast64_t maxLength = std::max(maxLengthModules, maxLengthOptions); - if (matchingModuleNames.size() > 0) { - STORM_PRINT("Matching modules for hint '" << hint << "':" << std::endl) - for (auto const& matchingModuleName : matchingModuleNames) { - printHelpForModule(matchingModuleName, maxLength); - } + std::string optionList = getHelpForSelection(matchingModuleNames, matchingOptionNames, "Matching modules for filter '" + filter +"':", "Matching options for filter '" + filter +"':"); + if (optionList.empty()) { + STORM_PRINT("Filter '" << filter << "' did not match any modules or options." << std::endl); + } else { + STORM_PRINT(optionList); } - - // Print the matching options. - if (matchingOptions.size() > 0) { - STORM_PRINT("Matching options for hint '" << hint << "':" << std::endl); - for (auto const& option : matchingOptions) { - STORM_PRINT(std::setw(maxLength) << std::left << *option << std::endl); + } + } + + std::string SettingsManager::getHelpForSelection(std::vector<std::string> const& selectedModuleNames, std::vector<std::string> const& selectedLongOptionNames, std::string modulesHeader, std::string optionsHeader) const { + std::stringstream stream; + + // 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. + uint_fast64_t maxLengthModules = 0; + for (auto const& moduleName : selectedModuleNames) { + maxLengthModules = std::max(maxLengthModules, getPrintLengthOfLongestOption(moduleName, true)); + // 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); + STORM_LOG_ASSERT(optionIterator != this->moduleOptions.end(), "Unable to find selected module " << 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 : selectedLongOptionNames) { + auto optionIterator = this->longNameToOptions.find(optionName); + STORM_LOG_ASSERT(optionIterator != this->longNameToOptions.end(), "Unable to find selected option " << optionName << "."); + for (auto const& option : optionIterator->second) { + // 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); + printedOptions.insert(option); } } - - if (matchingModuleNames.empty() && matchingOptions.empty()) { - STORM_PRINT("Hint '" << hint << "' did not match any modules or options." << std::endl); + } + + // Print the matching modules. + uint_fast64_t maxLength = std::max(maxLengthModules, maxLengthOptions); + if (selectedModuleNames.size() > 0) { + if (modulesHeader != "") { + stream << modulesHeader << std::endl; + } + for (auto const& matchingModuleName : selectedModuleNames) { + stream << getHelpForModule(matchingModuleName, maxLength, true); + } + } + + // Print the matching options. + if (matchingOptions.size() > 0) { + if (optionsHeader != "") { + stream << optionsHeader << std::endl; + } + for (auto const& option : matchingOptions) { + stream << std::setw(maxLength) << std::left << *option << std::endl; } } + return stream.str(); } - void SettingsManager::printHelpForModule(std::string const& moduleName, uint_fast64_t maxLength) const { + std::string SettingsManager::getHelpForModule(std::string const& moduleName, uint_fast64_t maxLength, bool includeAdvanced) const { auto moduleIterator = moduleOptions.find(moduleName); if(moduleIterator == this->moduleOptions.end()) { - return; + return ""; } //STORM_LOG_THROW(moduleIterator != moduleOptions.end(), storm::exceptions::IllegalFunctionCallException, "Cannot print help for unknown module '" << moduleName << "'."); - STORM_PRINT("##### Module '" << moduleName << "' " << std::string(std::min(maxLength, maxLength - moduleName.length() - 16), '#') << std::endl); - - // 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); + // Check whether there is at least one (enabled) option in this module + uint64_t numOfOptions = 0; for (auto const& option : moduleIterator->second) { - STORM_PRINT(std::setw(maxLength) << std::left << *option << std::endl); + if (includeAdvanced || !option->getIsAdvanced()) { + ++numOfOptions; + } } - STORM_PRINT(std::endl); + + std::stringstream stream; + if (numOfOptions > 0) { + std::string displayedModuleName = "'" + moduleName + "'"; + if (!includeAdvanced) { + displayedModuleName += " (" + std::to_string(numOfOptions) + "/" + std::to_string(moduleIterator->second.size()) + " shown)"; + } + stream << "##### Module " << displayedModuleName << " " << std::string(std::min(maxLength, maxLength - displayedModuleName.length() - 14), '#') << std::endl; + + // 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); + + for (auto const& option : moduleIterator->second) { + if (includeAdvanced || !option->getIsAdvanced()) { + stream << std::setw(maxLength) << std::left << *option << std::endl; + } + } + stream << std::endl; + } + return stream.str(); } - uint_fast64_t SettingsManager::getPrintLengthOfLongestOption() const { + uint_fast64_t SettingsManager::getPrintLengthOfLongestOption(bool includeAdvanced) const { uint_fast64_t length = 0; for (auto const& moduleName : this->moduleNames) { - length = std::max(getPrintLengthOfLongestOption(moduleName), length); + length = std::max(getPrintLengthOfLongestOption(moduleName, includeAdvanced), length); } return length; } - uint_fast64_t SettingsManager::getPrintLengthOfLongestOption(std::string const& moduleName) const { + uint_fast64_t SettingsManager::getPrintLengthOfLongestOption(std::string const& moduleName, bool includeAdvanced) const { auto moduleIterator = modules.find(moduleName); STORM_LOG_THROW(moduleIterator != modules.end(), storm::exceptions::IllegalFunctionCallException, "Unable to retrieve option length of unknown module '" << moduleName << "'."); - return moduleIterator->second->getPrintLengthOfLongestOption(); + return moduleIterator->second->getPrintLengthOfLongestOption(includeAdvanced); } void SettingsManager::addModule(std::unique_ptr<modules::ModuleSettings>&& moduleSettings, bool doRegister) { @@ -387,10 +478,11 @@ namespace storm { bool conversionOk = argument.setFromStringValue(argumentCache[i]); STORM_LOG_THROW(conversionOk, storm::exceptions::OptionParserException, "Value '" << argumentCache[i] << "' is invalid for argument <" << argument.getName() << "> of option:\n" << *option); } - + // In case there are optional arguments that were not set, we set them to their default value. for (uint_fast64_t i = argumentCache.size(); i < option->getArgumentCount(); ++i) { ArgumentBase& argument = option->getArgument(i); + STORM_LOG_THROW(argument.getHasDefaultValue() || argument.getIsOptional(), storm::exceptions::OptionParserException, "Non-optional argument <" << argument.getName() << "> of option:\n" << *option); argument.setFromDefaultValue(); } diff --git a/src/storm/settings/SettingsManager.h b/src/storm/settings/SettingsManager.h index 4335f7d28..96637153b 100644 --- a/src/storm/settings/SettingsManager.h +++ b/src/storm/settings/SettingsManager.h @@ -70,21 +70,24 @@ namespace storm { void handleUnknownOption(std::string const& optionName, bool isShort) const; /*! - * 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 + * This function prints a help message to the standard output. A string can be given as a filter. + * If it is 'frequent', only the options that are not flagged as advanced will be shown. + * 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 A regular expression to restrict the help output or "all" for the full help text. + * @param filter A regular expression to restrict the help output or "all" for the full help text. */ - void printHelp(std::string const& hint = "all") const; + void printHelp(std::string const& filter = "frequent") const; /*! * This function prints a help message for the specified module to the standard output. * * @param moduleName The name of the module for which to show the help. * @param maxLength The maximal length of an option name (necessary for proper alignment). + * @param includeAdvanced if set, also includes options flagged as advanced. */ - void printHelpForModule(std::string const& moduleName, uint_fast64_t maxLength = 30) const; + std::string getHelpForModule(std::string const& moduleName, uint_fast64_t maxLength = 30, bool includeAdvanced = true) const; /*! * Retrieves the only existing instance of a settings manager. @@ -144,7 +147,17 @@ namespace storm { * This destructor is private, since we need to forbid explicit destruction of the manager. */ virtual ~SettingsManager(); - + + /*! + * This function prints a help message to the standard output. + * + * @param moduleFilter only modules where this function returns true are included + * @param optionFilter only options where this function returns true are included + * @return true if at least one module or option matched the filter. + * + */ + std::string getHelpForSelection(std::vector<std::string> const& selectedModuleNames, std::vector<std::string> const& selectedLongOptionNames, std::string modulesHeader = "", std::string optionsHeader = "") const; + // The name of the tool std::string name; std::string executableName; @@ -213,17 +226,19 @@ namespace storm { /*! * Retrieves the (print) length of the longest option of all modules. * + * @param includeAdvanced if set, also includes options flagged as advanced. * @return The length of the longest option. */ - uint_fast64_t getPrintLengthOfLongestOption() const; + uint_fast64_t getPrintLengthOfLongestOption(bool includeAdvanced) const; /*! * Retrieves the (print) length of the longest option in the given module, so we can align the options. * * @param moduleName The module name for which to retrieve the length of the longest option. + * @param includeAdvanced if set, also includes options flagged as advanced. * @return The length of the longest option name. */ - uint_fast64_t getPrintLengthOfLongestOption(std::string const& moduleName) const; + uint_fast64_t getPrintLengthOfLongestOption(std::string const& moduleName, bool includeAdvanced) const; /*! * Parses the given file and stores the settings in the returned map. diff --git a/src/storm/settings/modules/GeneralSettings.cpp b/src/storm/settings/modules/GeneralSettings.cpp index 63c5e21bf..ee35e0fa0 100644 --- a/src/storm/settings/modules/GeneralSettings.cpp +++ b/src/storm/settings/modules/GeneralSettings.cpp @@ -34,8 +34,8 @@ namespace storm { const std::string GeneralSettings::soundOptionName = "sound"; GeneralSettings::GeneralSettings() : ModuleSettings(moduleName) { - this->addOption(storm::settings::OptionBuilder(moduleName, helpOptionName, false, "Shows all available options, arguments and descriptions.").setShortName(helpOptionShortName) - .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, helpOptionName, false, "Shows available options, arguments and descriptions.").setShortName(helpOptionShortName) + .addArgument(storm::settings::ArgumentBuilder::createStringArgument("filter", "'frequent' for frequently used options, 'all' for the complete help, or a regular expression to show help for all matching entities.").setDefaultValueString("frequent").build()).build()); this->addOption(storm::settings::OptionBuilder(moduleName, versionOptionName, false, "Prints the version information.").build()); this->addOption(storm::settings::OptionBuilder(moduleName, verboseOptionName, false, "Enables more verbose output.").setShortName(verboseOptionShortName).build()); this->addOption(storm::settings::OptionBuilder(moduleName, showProgressOptionName, false, "Sets when additional information (if available) about the progress is printed.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("delay", "The delay to wait (in seconds) between emitting information (0 means never print progress).").setDefaultValueUnsignedInteger(5).build()).build()); @@ -57,8 +57,8 @@ namespace storm { return this->getOption(versionOptionName).getHasOptionBeenSet(); } - std::string GeneralSettings::getHelpModuleName() const { - return this->getOption(helpOptionName).getArgumentByName("hint").getValueAsString(); + std::string GeneralSettings::getHelpFilterExpression() const { + return this->getOption(helpOptionName).getArgumentByName("filter").getValueAsString(); } bool GeneralSettings::isVerboseSet() const { diff --git a/src/storm/settings/modules/GeneralSettings.h b/src/storm/settings/modules/GeneralSettings.h index 00553ef27..209cedfe0 100644 --- a/src/storm/settings/modules/GeneralSettings.h +++ b/src/storm/settings/modules/GeneralSettings.h @@ -41,7 +41,7 @@ namespace storm { * * @return The name of the module for which to show the help or "all". */ - std::string getHelpModuleName() const; + std::string getHelpFilterExpression() const; /*! * Retrieves whether the verbose option was set. diff --git a/src/storm/settings/modules/ModuleSettings.cpp b/src/storm/settings/modules/ModuleSettings.cpp index a938e42db..528535ec2 100644 --- a/src/storm/settings/modules/ModuleSettings.cpp +++ b/src/storm/settings/modules/ModuleSettings.cpp @@ -69,10 +69,12 @@ namespace storm { this->options.push_back(option); } - uint_fast64_t ModuleSettings::getPrintLengthOfLongestOption() const { + uint_fast64_t ModuleSettings::getPrintLengthOfLongestOption(bool includeAdvanced) const { uint_fast64_t length = 0; for (auto const& option : this->options) { - length = std::max(length, option->getPrintLength()); + if (includeAdvanced || !option->getIsAdvanced()) { + length = std::max(length, option->getPrintLength()); + } } return length; } diff --git a/src/storm/settings/modules/ModuleSettings.h b/src/storm/settings/modules/ModuleSettings.h index 4bda74eb0..7612eb39c 100644 --- a/src/storm/settings/modules/ModuleSettings.h +++ b/src/storm/settings/modules/ModuleSettings.h @@ -72,9 +72,10 @@ namespace storm { /*! * Retrieves the (print) length of the longest option. * + * @param includeAdvanced if set, also includes options flagged as advanced. * @return The length of the longest option. */ - uint_fast64_t getPrintLengthOfLongestOption() const; + uint_fast64_t getPrintLengthOfLongestOption(bool includeAdvanced) const; /*! * Restores the default values for all arguments of all options. diff --git a/src/storm/utility/string.cpp b/src/storm/utility/string.cpp index 46010525f..f3efcd710 100644 --- a/src/storm/utility/string.cpp +++ b/src/storm/utility/string.cpp @@ -36,9 +36,9 @@ namespace storm { if (size == 0) { return ""; } else if (size == 1) { - return "Did you mean " + result + " ?"; + return "Did you mean '" + result + "'?"; } else { - return "Did you mean any of [ " + result + " ] ?"; + return "Did you mean any of [" + result + "] ?"; } }