diff --git a/src/base/program_options.cpp b/src/base/program_options.cpp index 3383ef6fa..a234e92ca 100644 --- a/src/base/program_options.cpp +++ b/src/base/program_options.cpp @@ -134,7 +134,7 @@ void ProgramOptions::parse(int argc, const char* argv[]) if (i+1 >= argc) { stringstream msg; msg << "Missing value in '--" << optionName - << "'=VALUE option specification"; + << "=" << option->getValueName() << "' option specification"; throw ProgramOptionNeedsValue(msg.str()); } optionValue = argv[++i]; @@ -173,7 +173,10 @@ std::ostream& operator<<(std::ostream& os, const base::ProgramOptions& po) for (base::ProgramOptions::OptionList::const_iterator it=po.options().begin(), end=po.options().end(); it != end; ++it) { const base::ProgramOptions::Option* option = *it; - size_t optionWidth = std::min(26, 6+option->name().size()+1); + size_t optionWidth = + std::min(26, 6+option->name().size()+1+ + (option->doesRequireValue() ? option->getValueName().size()+1: 0)); + if (maxOptionWidth < optionWidth) maxOptionWidth = optionWidth; } @@ -181,13 +184,16 @@ std::ostream& operator<<(std::ostream& os, const base::ProgramOptions& po) for (base::ProgramOptions::OptionList::const_iterator it=po.options().begin(), end=po.options().end(); it != end; ++it) { const base::ProgramOptions::Option* option = *it; - size_t optionWidth = 6+option->name().size()+1; + size_t optionWidth = 6+option->name().size()+1+ + (option->doesRequireValue() ? option->getValueName().size()+1: 0); if (option->mnemonic() != 0) os << setw(3) << '-' << option->mnemonic() << ", "; else os << setw(6) << ' '; os << "--" << option->name(); + if (option->doesRequireValue()) + os << " " << option->getValueName(); if (!option->description().empty()) { bool multilines = (option->description().find('\n') != string::npos); diff --git a/src/base/program_options.h b/src/base/program_options.h index b284c18cf..7872078a1 100644 --- a/src/base/program_options.h +++ b/src/base/program_options.h @@ -39,20 +39,23 @@ namespace base { Option(const std::string& name) : m_name(name) , m_mnemonic(0) - , m_enabled(false) - , m_requiresValue(false) { + , m_enabled(false) { } // Getters const std::string& name() const { return m_name; } const std::string& description() const { return m_description; } const std::string& value() const { return m_value; } + const std::string& getValueName() const { return m_valueName; } char mnemonic() const { return m_mnemonic; } bool enabled() const { return m_enabled; } - bool doesRequireValue() const { return m_requiresValue; } + bool doesRequireValue() const { return !m_valueName.empty(); } // Setters Option& description(const std::string& desc) { m_description = desc; return *this; } Option& mnemonic(char mnemonic) { m_mnemonic = mnemonic; return *this; } - Option& requiresValue() { m_requiresValue = true; return *this; } + Option& requiresValue(const std::string& valueName) { + m_valueName = valueName; + return *this; + } private: void setValue(const std::string& value) { m_value = value; } void setEnabled(bool enabled) { m_enabled = enabled; } @@ -60,9 +63,9 @@ namespace base { std::string m_name; // Name of the option (e.g. "help" for "--help") std::string m_description; // Description of the option (this can be used when the help is printed). std::string m_value; // The value specified by the user in the command line. + std::string m_valueName; // Empty if this option doesn't require a value, or the name of the expected value. char m_mnemonic; // One character that can be used in the command line to use this option. bool m_enabled; // True if the user specified this argument. - bool m_requiresValue; // True if this option needs another argument. friend class ProgramOptions; }; diff --git a/src/base/program_options_unittest.cpp b/src/base/program_options_unittest.cpp index bb1f05c49..923b06c4b 100644 --- a/src/base/program_options_unittest.cpp +++ b/src/base/program_options_unittest.cpp @@ -16,7 +16,7 @@ TEST(ProgramOptions, OptionMembers) ProgramOptions::Option& help = po.add("help").mnemonic('h').description("Show the help"); ProgramOptions::Option& output = - po.add("output").mnemonic('O').requiresValue(); + po.add("output").mnemonic('O').requiresValue("OUTPUT"); EXPECT_EQ("help", help.name()); EXPECT_EQ("Show the help", help.description()); @@ -35,7 +35,7 @@ TEST(ProgramOptions, Reset) { ProgramOptions po; ProgramOptions::Option& help = po.add("help"); - ProgramOptions::Option& file = po.add("file").requiresValue(); + ProgramOptions::Option& file = po.add("file").requiresValue("FILE"); EXPECT_FALSE(help.enabled()); EXPECT_FALSE(file.enabled()); EXPECT_EQ("", file.value()); @@ -56,8 +56,8 @@ TEST(ProgramOptions, Parse) { ProgramOptions po; ProgramOptions::Option& help = po.add("help").mnemonic('?'); - ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue(); - ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue(); + ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue("INPUT"); + ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue("OUTPUT"); const char* argv1[] = { "program.exe", "-?" }; po.parse(2, argv1); @@ -111,8 +111,8 @@ TEST(ProgramOptions, ParseErrors) { ProgramOptions po; ProgramOptions::Option& help = po.add("help").mnemonic('?'); - ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue(); - ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue(); + ProgramOptions::Option& input = po.add("input").mnemonic('i').requiresValue("INPUT"); + ProgramOptions::Option& output = po.add("output").mnemonic('o').requiresValue("OUTPUT"); const char* argv1[] = { "program.exe", "--input" }; EXPECT_THROW(po.parse(2, argv1), ProgramOptionNeedsValue);