Compare commits

...

4 Commits

Author SHA1 Message Date
nobody
c8f95dbda3 This commit was manufactured by cvs2svn to create tag
'Version_1_33_1'.

[SVN r31916]
2005-12-05 14:04:06 +00:00
Vladimir Prus
81aff160d0 Merge fixes for unregisted options and inaccessible 'style_parser' method
from trunk to RC_1_33_0.


[SVN r31615]
2005-11-10 08:46:56 +00:00
Dave Abrahams
705e79b5ee merged from trunk
[SVN r30560]
2005-08-12 19:50:06 +00:00
nobody
3ae92db179 This commit was manufactured by cvs2svn to create branch 'RC_1_33_0'.
[SVN r30300]
2005-07-28 18:22:24 +00:00
9 changed files with 174 additions and 9 deletions

View File

@@ -398,13 +398,49 @@ $ export LC_CTYPE=ru_RU.KOI8-R
</section>
<section>
<title>Allowing Unknown Options</title>
<para>Usually, the library throws an exception on unknown option names. This
behaviour can be changed. For example, only some part of your application uses
<libraryname>Program_options</libraryname>, and you wish to pass unrecognized options to another part of
the program, or even to another application.</para>
<para>To allow unregistered options on the command line, you need to use
the &basic_command_line_parser; class for parsing (not &parse_command_line;)
and call the <methodname alt="boost::program_options::basic_command_line_parser::allow_unregistered">allow_unregistered</methodname>
method of that class:
<programlisting>
parsed_options parsed =
command_line_parser(argv, argc).options(desc).allow_unregistered().run();
</programlisting>
For each token that looks like an option, but does not have a known name,
an instance of &basic_option; will be added to the result.
The <code>string_key</code> and <code>value</code> fields of the instance will contain results
of syntactic parsing of the token, the <code>unregistered</code> field will be set to <code>true</code>,
and the <code>original_tokens</code> field will contain the token as it appeared on the command line.
</para>
<para>If you want to pass the unrecognized options further, the
<functionname alt="boost::program_options::collect_unrecognized">collect_unrecognized</functionname> function can be used.
The function will collect original tokens for all unrecognized values, and optionally, all found positional options.
Say, if your code handles a few options, but does not handles positional options at all, you can use the function like this:
<programlisting>
vector&lt;string&gt; to_pass_further = collect_arguments(parsed.option, include_positional);
</programlisting>
</para>
</section>
</section>
<!--
Local Variables:
mode: xml
sgml-indent-data: t
sgml-parent-document: ("program_options.xml" "section")
mode: nxml
sgml-indent-data: t
sgml-parent-document: ("userman.xml" "chapter")
sgml-set-face: t
End:
-->

View File

@@ -1,6 +1,6 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../../doc/html/program_option.html">
<meta http-equiv="refresh" content="0; URL=../../../doc/html/program_options.html">
</head>
<body>
Automatic redirection failed, please go to

View File

@@ -37,3 +37,10 @@
<!ENTITY command_line_parser
"<classname alt='boost::program_options::command_line_parser'>command_line_parser</classname>">
<!ENTITY basic_command_line_parser
"<classname alt='boost::program_options::basic_command_line_parser'>basic_command_line_parser</classname>">
<!ENTITY basic_option
"<classname alt='boost::program_options::basic_option'>basic_option</classname>">

View File

@@ -1,4 +1,6 @@
Make parse_config_file("foo.cfg", desc) work.
Document handling of positional options which depends on precedding options.
I.e scanning the parsed options and creating new variables_map when we see
a positional option. (Email from Tony).

View File

@@ -76,6 +76,24 @@ namespace boost { namespace program_options {
return *this;
}
template<class charT>
basic_command_line_parser<charT>&
basic_command_line_parser<charT>::allow_unregistered()
{
detail::cmdline::allow_unregistered();
return *this;
}
template<class charT>
basic_command_line_parser<charT>&
basic_command_line_parser<charT>::extra_style_parser(style_parser s)
{
detail::cmdline::extra_style_parser(s);
return *this;
}
template<class charT>
basic_parsed_options<charT>
basic_command_line_parser<charT>::run()
@@ -101,6 +119,26 @@ namespace boost { namespace program_options {
style(style).extra_parser(ext).run();
}
template<class charT>
std::vector< std::basic_string<charT> >
collect_unrecognized(const std::vector< basic_option<charT> >& options,
enum collect_unrecognized_mode mode)
{
std::vector< std::basic_string<charT> > result;
for(unsigned i = 0; i < options.size(); ++i)
{
if (options[i].unregistered ||
(mode == include_positional && options[i].position_key != -1))
{
copy(options[i].original_tokens.begin(),
options[i].original_tokens.end(),
back_inserter(result));
}
}
return result;
}
}}
#endif

View File

@@ -41,10 +41,16 @@ namespace boost { namespace program_options {
int position_key;
/** Option's value */
std::vector< std::basic_string<charT> > value;
/** The original unchanged tokens this option was
created from. */
std::vector< std::basic_string<charT> > original_tokens;
/** True if option was not recognized. In that case,
'string_key' and 'value' are results of purely
syntactic parsing of source. */
syntactic parsing of source. The original tokens can be
recovered from the "original_tokens" member.
*/
bool unregistered;
};
typedef basic_option<char> option;
typedef basic_option<wchar_t> woption;

View File

@@ -73,13 +73,16 @@ namespace boost { namespace program_options {
/** Command line parser.
The class allows one to specify all the information needed for parsing
and to parser the parse the command line. It is primarily needed to
and to parse the command line. It is primarily needed to
emulate named function parameters -- a regular function with 5
parameters will be hard to use and creating overloads with a smaller
nuber of parameters will be confusing.
For the most common case, the function parse_command_line is a better
alternative.
There are two typedefs -- command_line_parser and wcommand_line_parser,
for charT == char and charT == wchar_t cases.
*/
template<class charT>
class basic_command_line_parser : private detail::cmdline {
@@ -90,7 +93,7 @@ namespace boost { namespace program_options {
basic_command_line_parser(const std::vector<
std::basic_string<charT> >& args);
/** Creates a command line parser for the specified arguments
list. The parameter should be the same as passes to 'main'.
list. The parameters should be the same as passed to 'main'.
*/
basic_command_line_parser(int argc, charT* argv[]);
@@ -104,8 +107,26 @@ namespace boost { namespace program_options {
basic_command_line_parser& style(int);
/** Sets the extra parsers. */
basic_command_line_parser& extra_parser(ext_parser);
/** Parses the options and returns the result of parsing.
Throws on error.
*/
basic_parsed_options<charT> run();
/** Specifies that unregistered options are allowed and should
be passed though. For each command like token that looks
like an option but does not contain a recognized name, an
instance of basic_option<charT> will be added to result,
with 'unrecognized' field set to 'true'. It's possible to
collect all unrecognized options with the 'collect_unrecognized'
funciton.
*/
basic_command_line_parser& allow_unregistered();
using detail::cmdline::style_parser;
basic_command_line_parser& extra_style_parser(style_parser s);
private:
const options_description* m_desc;
};
@@ -134,6 +155,22 @@ namespace boost { namespace program_options {
basic_parsed_options<charT>
parse_config_file(std::basic_istream<charT>&, const options_description&);
/** Controls if the 'collect_unregistered' function should
include positional options, or not. */
enum collect_unrecognized_mode
{ include_positional, exclude_positional };
/** Collects the original tokens for all named options with
'unregistered' flag set. If 'mode' is 'include_positional'
also collects all positional options.
Returns the vector of origianl tokens for all collected
options.
*/
template<class charT>
std::vector< std::basic_string<charT> >
collect_unrecognized(const std::vector< basic_option<charT> >& options,
enum collect_unrecognized_mode mode);
/** Parse environment.
For each environment variable, the 'name_mapper' function is called to
@@ -180,6 +217,7 @@ namespace boost { namespace program_options {
split_winmain(const std::wstring& cmdline);
#endif
#endif
}}

View File

@@ -83,7 +83,7 @@ namespace boost { namespace program_options {
namespace boost { namespace program_options { namespace detail {
// vc6 needs this, but borland chokes when this is added.
#if BOOST_WORKAROUND(_MSC_VER, <= 1200)
#if BOOST_WORKAROUND(_MSC_VER, < 1300)
using namespace std;
using namespace program_options;
#endif
@@ -248,6 +248,7 @@ namespace boost { namespace program_options { namespace detail {
if (!ok) {
option opt;
opt.value.push_back(args[0]);
opt.original_tokens.push_back(args[0]);
result.push_back(opt);
args.erase(args.begin());
}
@@ -331,6 +332,7 @@ namespace boost { namespace program_options { namespace detail {
// Everything's OK, move the values to the result.
for(;!other_tokens.empty() && max_tokens--; ) {
opt.value.push_back(other_tokens[0]);
opt.original_tokens.push_back(other_tokens[0]);
other_tokens.erase(other_tokens.begin());
}
}
@@ -368,6 +370,7 @@ namespace boost { namespace program_options { namespace detail {
opt.string_key = name;
if (!adjacent.empty())
opt.value.push_back(adjacent);
opt.original_tokens.push_back(tok);
result.push_back(opt);
args.erase(args.begin());
}
@@ -416,6 +419,7 @@ namespace boost { namespace program_options { namespace detail {
option opt;
opt.string_key = name;
opt.original_tokens.push_back(tok);
if (!adjacent.empty())
opt.value.push_back(adjacent);
result.push_back(opt);
@@ -442,6 +446,7 @@ namespace boost { namespace program_options { namespace detail {
opt.string_key = name;
if (!adjacent.empty())
opt.value.push_back(adjacent);
opt.original_tokens.push_back(tok);
result.push_back(opt);
args.erase(args.begin());
}

View File

@@ -190,6 +190,38 @@ void test_environment()
//TODO: since 'bar' does not allow a value, it cannot appear in environemt,
// which already has a value.
}
void test_unregistered()
{
options_description desc;
char* cmdline1_[] = { "--foo=12", "--bar", "1"};
vector<string> cmdline1 = sv(cmdline1_,
sizeof(cmdline1_)/sizeof(cmdline1_[0]));
vector<option> a1 =
command_line_parser(cmdline1).options(desc).allow_unregistered().run()
.options;
BOOST_REQUIRE(a1.size() == 3);
BOOST_CHECK(a1[0].string_key == "foo");
BOOST_CHECK(a1[0].unregistered == true);
BOOST_REQUIRE(a1[0].value.size() == 1);
BOOST_CHECK(a1[0].value[0] == "12");
BOOST_CHECK(a1[1].string_key == "bar");
BOOST_CHECK(a1[1].unregistered == true);
BOOST_CHECK(a1[2].string_key == "");
BOOST_CHECK(a1[2].unregistered == false);
vector<string> a2 = collect_unrecognized(a1, include_positional);
BOOST_CHECK(a2[0] == "--foo=12");
BOOST_CHECK(a2[1] == "--bar");
BOOST_CHECK(a2[2] == "1");
}
int test_main(int, char* [])
@@ -197,6 +229,7 @@ int test_main(int, char* [])
test_command_line();
test_config_file();
test_environment();
test_unregistered();
return 0;
}