mirror of
https://github.com/boostorg/program_options.git
synced 2026-01-19 04:22:15 +00:00
Really make unregistered options to work.
- Add forwarding method allow_unregistered to the basic_command_line parser class. - Add new 'collect_unrecognized' function - Add new field 'original_tokens' to the basic_option class [SVN r31490]
This commit is contained in:
@@ -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<string> 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:
|
||||
-->
|
||||
|
||||
@@ -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>">
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -76,6 +76,15 @@ 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_parsed_options<charT>
|
||||
basic_command_line_parser<charT>::run()
|
||||
@@ -101,6 +110,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,21 @@ 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();
|
||||
private:
|
||||
const options_description* m_desc;
|
||||
};
|
||||
@@ -134,6 +150,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 +212,7 @@ namespace boost { namespace program_options {
|
||||
split_winmain(const std::wstring& cmdline);
|
||||
#endif
|
||||
#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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user