|
Boost-Commit : |
From: ghost_at_[hidden]
Date: 2007-08-08 14:40:50
Author: vladimir_prus
Date: 2007-08-08 14:40:48 EDT (Wed, 08 Aug 2007)
New Revision: 38514
URL: http://svn.boost.org/trac/boost/changeset/38514
Log:
Support for 'implicit' options.
Patch from Bryan Green.
Fixes #1131.
Text files modified:
trunk/boost/program_options/detail/value_semantic.hpp | 16 ++++++++++++++--
trunk/boost/program_options/value_semantic.hpp | 36 +++++++++++++++++++++++++++++++++++-
trunk/libs/program_options/example/options_description.cpp | 13 +++++++++++++
trunk/libs/program_options/src/cmdline.cpp | 8 ++++++++
trunk/libs/program_options/test/variable_map_test.cpp | 19 +++++++++++++++++++
5 files changed, 89 insertions(+), 3 deletions(-)
Modified: trunk/boost/program_options/detail/value_semantic.hpp
==============================================================================
--- trunk/boost/program_options/detail/value_semantic.hpp (original)
+++ trunk/boost/program_options/detail/value_semantic.hpp 2007-08-08 14:40:48 EDT (Wed, 08 Aug 2007)
@@ -16,7 +16,13 @@
std::string
typed_value<T, charT>::name() const
{
- if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
+ if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
+ std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]";
+ if (!m_default_value.empty() && !m_default_value_as_text.empty())
+ msg += " (=" + m_default_value_as_text + ")";
+ return msg;
+ }
+ else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
return arg + " (=" + m_default_value_as_text + ")";
} else {
return arg;
@@ -155,7 +161,13 @@
xparse(boost::any& value_store,
const std::vector<std::basic_string<charT> >& new_tokens) const
{
- validate(value_store, new_tokens, (T*)0, 0);
+ // If no tokens were given, and the option accepts an implicit
+ // value, then assign the implicit value as the stored value;
+ // otherwise, validate the user-provided token(s).
+ if (new_tokens.empty() && !m_implicit_value.empty())
+ value_store = m_implicit_value;
+ else
+ validate(value_store, new_tokens, (T*)0, 0);
}
template<class T>
Modified: trunk/boost/program_options/value_semantic.hpp
==============================================================================
--- trunk/boost/program_options/value_semantic.hpp (original)
+++ trunk/boost/program_options/value_semantic.hpp 2007-08-08 14:40:48 EDT (Wed, 08 Aug 2007)
@@ -204,6 +204,38 @@
return this;
}
+ /** Specifies an implicit value, which will be used
+ if the option is given, but without an adjacent value.
+ Using this implies that an explicit value is optional, but if
+ given, must be strictly adjacent to the option, i.e.: '-ovalue'
+ or '--option=value'. Giving '-o' or '--option' will cause the
+ implicit value to be applied.
+ */
+ typed_value* implicit_value(const T &v)
+ {
+ m_implicit_value = boost::any(v);
+ m_implicit_value_as_text =
+ boost::lexical_cast<std::string>(v);
+ return this;
+ }
+
+ /** Specifies an implicit value, which will be used
+ if the option is given, but without an adjacent value.
+ Using this implies that an explicit value is optional, but if
+ given, must be strictly adjacent to the option, i.e.: '-ovalue'
+ or '--option=value'. Giving '-o' or '--option' will cause the
+ implicit value to be applied.
+ Unlike the above overload, the type 'T' need not provide
+ operator<< for ostream, but textual representation of default
+ value must be provided by the user.
+ */
+ typed_value* implicit_value(const T &v, const std::string& textual)
+ {
+ m_implicit_value = boost::any(v);
+ m_implicit_value_as_text = textual;
+ return this;
+ }
+
/** Specifies a function to be called when the final value
is determined. */
typed_value* notifier(function1<void, const T&> f)
@@ -243,7 +275,7 @@
unsigned min_tokens() const
{
- if (m_zero_tokens) {
+ if (m_zero_tokens || !m_implicit_value.empty()) {
return 0;
} else {
return 1;
@@ -301,6 +333,8 @@
// as boost::optional to avoid unnecessary instantiations.
boost::any m_default_value;
std::string m_default_value_as_text;
+ boost::any m_implicit_value;
+ std::string m_implicit_value_as_text;
bool m_composing, m_implicit, m_multitoken, m_zero_tokens;
boost::function1<void, const T&> m_notifier;
};
Modified: trunk/libs/program_options/example/options_description.cpp
==============================================================================
--- trunk/libs/program_options/example/options_description.cpp (original)
+++ trunk/libs/program_options/example/options_description.cpp 2007-08-08 14:40:48 EDT (Wed, 08 Aug 2007)
@@ -26,11 +26,17 @@
{
try {
int opt;
+ int portnum;
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("optimization", po::value<int>(&opt)->default_value(10),
"optimization level")
+ ("verbose,v", po::value<int>()->implicit_value(1),
+ "enable verbosity (optionally specify level)")
+ ("listen,l", po::value<int>(&portnum)->implicit_value(1001)
+ ->default_value(0,"no"),
+ "listen on a port.")
("include-path,I", po::value< vector<string> >(),
"include path")
("input-file", po::value< vector<string> >(), "input file")
@@ -62,7 +68,14 @@
<< vm["input-file"].as< vector<string> >() << "\n";
}
+ if (vm.count("verbose")) {
+ cout << "Verbosity enabled. Level is " << vm["verbose"].as<int>()
+ << "\n";
+ }
+
cout << "Optimization level is " << opt << "\n";
+
+ cout << "Listen port is " << portnum << "\n";
}
catch(exception& e)
{
Modified: trunk/libs/program_options/src/cmdline.cpp
==============================================================================
--- trunk/libs/program_options/src/cmdline.cpp (original)
+++ trunk/libs/program_options/src/cmdline.cpp 2007-08-08 14:40:48 EDT (Wed, 08 Aug 2007)
@@ -329,6 +329,14 @@
max_tokens -= opt.value.size();
+ // A value is optional if min_tokens == 0, but max_tokens > 0.
+ // If a value is optional, it must appear in opt.value (because
+ // it was 'adjacent'. Otherwise, remove the expectation of a
+ // non-adjacent value. (For now, we just check max_tokens == 1,
+ // as there is no current support for max_tokens>1)
+ if (min_tokens == 0 && max_tokens == 1 && opt.value.empty())
+ --max_tokens;
+
// Everything's OK, move the values to the result.
for(;!other_tokens.empty() && max_tokens--; ) {
opt.value.push_back(other_tokens[0]);
Modified: trunk/libs/program_options/test/variable_map_test.cpp
==============================================================================
--- trunk/libs/program_options/test/variable_map_test.cpp (original)
+++ trunk/libs/program_options/test/variable_map_test.cpp 2007-08-08 14:40:48 EDT (Wed, 08 Aug 2007)
@@ -102,6 +102,25 @@
BOOST_CHECK(vm3["vee"].as<string>() == "42");
BOOST_CHECK(vm3["voo"].as<string>() == "1");
BOOST_CHECK(vm3["iii"].as<int>() == 123);
+
+ options_description desc3;
+ desc3.add_options()
+ ("imp", po::value<int>()->implicit_value(100))
+ ("iim", po::value<int>()->implicit_value(200)->default_value(201))
+ ("mmp,m", po::value<int>()->implicit_value(123)->default_value(124))
+ ;
+ char* cmdline6_[] = { "--imp=1", "-m" };
+ vector<string> cmdline6 = sv(cmdline6_,
+ sizeof(cmdline6_)/sizeof(cmdline6_[0]));
+ parsed_options a6 = command_line_parser(cmdline6).options(desc3).run();
+
+ variables_map vm4;
+ store(a6, vm4);
+ notify(vm4);
+ BOOST_REQUIRE(vm4.size() == 3);
+ BOOST_CHECK(vm4["imp"].as<int>() == 1);
+ BOOST_CHECK(vm4["iim"].as<int>() == 201);
+ BOOST_CHECK(vm4["mmp"].as<int>() == 123);
}
int stored_value;
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk