]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | <?xml version="1.0" standalone="yes"?> |
2 | <!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" | |
3 | "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" | |
4 | [ | |
5 | <!ENTITY % entities SYSTEM "program_options.ent" > | |
6 | %entities; | |
7 | ]> | |
8 | <section id="program_options.howto"> | |
9 | ||
10 | <title>How To</title> | |
11 | ||
12 | <para>This section describes how the library can be used in specific | |
13 | situations.</para> | |
14 | ||
15 | <!-- | |
16 | ||
17 | validators | |
18 | positional options | |
19 | options groups/hidden options | |
20 | ||
21 | --> | |
22 | <section> | |
23 | <title>Non-conventional Syntax</title> | |
24 | ||
25 | <para>Sometimes, standard command line syntaxes are not enough. For | |
26 | example, the gcc compiler has "-frtti" and -fno-rtti" options, and this | |
27 | syntax is not directly supported. | |
28 | </para> | |
29 | ||
30 | <indexterm><primary>additional parser</primary></indexterm> | |
31 | <para>For such cases, the library allows the user to provide an | |
32 | <firstterm>additional parser</firstterm> -- a function which will be called on each | |
33 | command line element, before any processing by the library. If the | |
34 | additional parser recognises the syntax, it returns the option name and | |
35 | value, which are used directly. The above example can be handled by the | |
36 | following code: | |
37 | </para> | |
38 | ||
39 | <para> | |
40 | <programlisting> | |
41 | pair<string, string> reg_foo(const string& s) | |
42 | { | |
43 | if (s.find("-f") == 0) { | |
44 | if (s.substr(2, 3) == "no-") | |
45 | return make_pair(s.substr(5), string("false")); | |
46 | else | |
47 | return make_pair(s.substr(2), string("true")); | |
48 | } else { | |
49 | return make_pair(string(), string()); | |
50 | } | |
51 | } | |
52 | </programlisting> | |
53 | Here's the definition of the additional parser. When parsing the command | |
54 | line, we pass the additional parser: | |
55 | <programlisting> | |
56 | store(command_line_parser(ac, av).options(desc).extra_parser(reg_foo) | |
57 | .run(), vm); | |
58 | </programlisting> | |
59 | The complete example can be found in the "example/custom_syntax.cpp" | |
60 | file. | |
61 | </para> | |
62 | </section> | |
63 | ||
64 | <section> | |
65 | <title>Response Files</title> | |
66 | ||
67 | <indexterm><primary>response files</primary></indexterm> | |
68 | ||
69 | <para>Some operating system have very low limits of the command line | |
70 | length. The common way to work around those limitations is using | |
71 | <firstterm>response files</firstterm>. A response file is just a | |
72 | configuration file which uses the same syntax as the command line. If | |
73 | the command line specifies a name of response file to use, it's loaded | |
74 | and parsed in addition to the command line. The library does not | |
75 | provide direct support for response files, so you'll need to write some | |
76 | extra code. | |
77 | </para> | |
78 | ||
79 | <para> | |
80 | First, you need to define an option for the response file: | |
81 | <programlisting> | |
82 | ("response-file", value<string>(), | |
83 | "can be specified with '@name', too") | |
84 | </programlisting> | |
85 | </para> | |
86 | ||
87 | <para>Second, you'll need an additional parser to support the standard syntax | |
88 | for specifying response files: "@file": | |
89 | <programlisting><![CDATA[ | |
90 | pair<string, string> at_option_parser(string const&s) | |
91 | { | |
92 | if ('@' == s[0]) | |
93 | return std::make_pair(string("response-file"), s.substr(1)); | |
94 | else | |
95 | return pair<string, string>(); | |
96 | } | |
97 | ]]> | |
98 | </programlisting> | |
99 | </para> | |
100 | ||
101 | <para>Finally, when the "response-file" option is found, you'll have to | |
102 | load that file and pass it to the command line parser. This part is the | |
103 | hardest. We'll use the Boost.Tokenizer library, which works but has some | |
104 | limitations. You might also consider Boost.StringAlgo. The code is: | |
105 | <programlisting><![CDATA[ | |
106 | if (vm.count("response-file")) { | |
107 | // Load the file and tokenize it | |
108 | ifstream ifs(vm["response-file"].as<string>().c_str()); | |
109 | if (!ifs) { | |
110 | cout << "Could not open the response file\n"; | |
111 | return 1; | |
112 | } | |
113 | // Read the whole file into a string | |
114 | stringstream ss; | |
115 | ss << ifs.rdbuf(); | |
116 | // Split the file content | |
117 | char_separator<char> sep(" \n\r"); | |
118 | std::string ResponsefileContents( ss.str() ); | |
119 | tokenizer<char_separator<char> > tok(ResponsefileContents, sep); | |
120 | vector<string> args; | |
121 | copy(tok.begin(), tok.end(), back_inserter(args)); | |
122 | // Parse the file and store the options | |
123 | store(command_line_parser(args).options(desc).run(), vm); | |
124 | } | |
125 | ]]> | |
126 | </programlisting> | |
127 | The complete example can be found in the "example/response_file.cpp" | |
128 | file. | |
129 | </para> | |
130 | ||
131 | </section> | |
132 | ||
133 | <section> | |
134 | <title>Winmain Command Line</title> | |
135 | ||
136 | <para>On the Windows operating system, GUI applications receive the | |
137 | command line as a single string, not split into elements. For that reason, | |
138 | the command line parser cannot be used directly. At least on some | |
139 | compilers, it is possible to obtain | |
140 | the split command line, but it's not clear if all compilers support the | |
141 | same mechanism on all versions of the operating system. The | |
142 | <code>split_winmain</code> function is a portable mechanism provided | |
143 | by the library.</para> | |
144 | ||
145 | <para>Here's an example of use: | |
146 | <programlisting> | |
147 | vector<string> args = split_winmain(lpCmdLine); | |
148 | store(command_line_parser(args).options(desc).run(), vm); | |
149 | </programlisting> | |
150 | The <code>split_winmain</code> function is overloaded for <code>wchar_t</code> strings, so can | |
151 | also be used in Unicode applications. | |
152 | </para> | |
153 | ||
154 | </section> | |
155 | ||
156 | <section> | |
157 | <title>Option Groups and Hidden Options</title> | |
158 | ||
159 | <para>Having a single instance of the &options_description; class with all | |
160 | the program's options can be problematic: | |
161 | <itemizedlist> | |
162 | <listitem> | |
163 | <para>Some options make sense only for specific source, for example, | |
164 | configuration files.</para> | |
165 | </listitem> | |
166 | <listitem> | |
167 | <para>The user would prefer some structure in the generated help message.</para> | |
168 | </listitem> | |
169 | <listitem> | |
170 | <para>Some options shouldn't appear in the generated help message at all.</para> | |
171 | </listitem> | |
172 | </itemizedlist> | |
173 | </para> | |
174 | ||
175 | <para>To solve the above issues, the library allows a programmer to create several | |
176 | instances of the &options_description; class, which can be merged in | |
177 | different combinations. The following example will define three groups of | |
178 | options: command line specific, and two options group for specific program | |
179 | modules, only one of which is shown in the generated help message. | |
180 | </para> | |
181 | ||
182 | <para>Each group is defined using standard syntax. However, you should | |
183 | use reasonable names for each &options_description; instance: | |
184 | <programlisting><![CDATA[ | |
185 | options_description general("General options"); | |
186 | general.add_options() | |
187 | ("help", "produce a help message") | |
188 | ("help-module", value<string>(), | |
189 | "produce a help for a given module") | |
190 | ("version", "output the version number") | |
191 | ; | |
192 | ||
193 | options_description gui("GUI options"); | |
194 | gui.add_options() | |
195 | ("display", value<string>(), "display to use") | |
196 | ; | |
197 | ||
198 | options_description backend("Backend options"); | |
199 | backend.add_options() | |
200 | ("num-threads", value<int>(), "the initial number of threads") | |
201 | ; | |
202 | ]]></programlisting> | |
203 | </para> | |
204 | ||
205 | <para>After declaring options groups, we merge them in two | |
206 | combinations. The first will include all options and be used for parsing. The | |
207 | second will be used for the "--help" option. | |
208 | <programlisting> | |
209 | // Declare an options description instance which will include | |
210 | // all the options | |
211 | options_description all("Allowed options"); | |
212 | all.add(general).add(gui).add(backend); | |
213 | ||
214 | // Declare an options description instance which will be shown | |
215 | // to the user | |
216 | options_description visible("Allowed options"); | |
217 | visible.add(general).add(gui); | |
218 | </programlisting> | |
219 | </para> | |
220 | ||
221 | <para>What is left is to parse and handle the options: | |
222 | <programlisting><![CDATA[ | |
223 | variables_map vm; | |
224 | store(parse_command_line(ac, av, all), vm); | |
225 | ||
226 | if (vm.count("help")) | |
227 | { | |
228 | cout << visible; | |
229 | return 0; | |
230 | } | |
231 | if (vm.count("help-module")) { | |
232 | const string& s = vm["help-module"].as<string>(); | |
233 | if (s == "gui") { | |
234 | cout << gui; | |
235 | } else if (s == "backend") { | |
236 | cout << backend; | |
237 | } else { | |
238 | cout << "Unknown module '" | |
239 | << s << "' in the --help-module option\n"; | |
240 | return 1; | |
241 | } | |
242 | return 0; | |
243 | } | |
244 | if (vm.count("num-threads")) { | |
245 | cout << "The 'num-threads' options was set to " | |
246 | << vm["num-threads"].as<int>() << "\n"; | |
247 | } | |
248 | ]]></programlisting> | |
249 | When parsing the command line, all options are allowed. The "--help" | |
250 | message, however, does not include the "Backend options" group -- the | |
251 | options in that group are hidden. The user can explicitly force the | |
252 | display of that options group by passing "--help-module backend" | |
253 | option. The complete example can be found in the | |
254 | "example/option_groups.cpp" file. | |
255 | </para> | |
256 | ||
257 | </section> | |
258 | ||
259 | <section> | |
260 | <title>Custom Validators</title> | |
261 | ||
262 | <para>By default, the conversion of option's value from string into C++ | |
263 | type is done using iostreams, which sometimes is not convenient. The | |
264 | library allows the user to customize the conversion for specific | |
265 | classes. In order to do so, the user should provide suitable overload of | |
266 | the <code>validate</code> function. | |
267 | </para> | |
268 | ||
269 | <para> | |
270 | Let's first define a simple class: | |
271 | <programlisting><![CDATA[ | |
272 | struct magic_number { | |
273 | public: | |
274 | magic_number(int n) : n(n) {} | |
275 | int n; | |
276 | }; | |
277 | ]]></programlisting> and then overload the <code>validate</code> function: | |
278 | <programlisting><![CDATA[ | |
279 | void validate(boost::any& v, | |
280 | const std::vector<std::string>& values, | |
281 | magic_number* target_type, int) | |
282 | { | |
283 | static regex r("\\d\\d\\d-(\\d\\d\\d)"); | |
284 | ||
285 | using namespace boost::program_options; | |
286 | ||
287 | // Make sure no previous assignment to 'a' was made. | |
288 | validators::check_first_occurrence(v); | |
289 | // Extract the first string from 'values'. If there is more than | |
290 | // one string, it's an error, and exception will be thrown. | |
291 | const string& s = validators::get_single_string(values); | |
292 | ||
293 | // Do regex match and convert the interesting part to | |
294 | // int. | |
295 | smatch match; | |
296 | if (regex_match(s, match, r)) { | |
297 | v = any(magic_number(lexical_cast<int>(match[1]))); | |
298 | } else { | |
299 | throw validation_error(validation_error::invalid_option_value); | |
300 | } | |
301 | } | |
302 | ]]> | |
303 | </programlisting>The function takes four parameters. The first is the storage | |
304 | for the value, and in this case is either empty or contains an instance of | |
305 | the <code>magic_number</code> class. The second is the list of strings | |
306 | found in the next occurrence of the option. The remaining two parameters | |
307 | are needed to workaround the lack of partial template specialization and | |
308 | partial function template ordering on some compilers. | |
309 | </para> | |
310 | ||
311 | <para>The function first checks that we don't try to assign to the same | |
312 | option twice. Then it checks that only a single string was passed | |
313 | in. Next the string is verified with the help of the Boost.Regex | |
314 | library. If that test is passed, the parsed value is stored into the | |
315 | <code>v</code> variable. | |
316 | </para> | |
317 | ||
318 | <para>The complete example can be found in the "example/regex.cpp" file. | |
319 | </para> | |
320 | ||
321 | ||
322 | </section> | |
323 | ||
324 | <section> | |
325 | <title>Unicode Support</title> | |
326 | ||
327 | <para>To use the library with Unicode, you'd need to: | |
328 | <itemizedlist> | |
329 | <listitem> | |
330 | <para>Use Unicode-aware parsers for Unicode input</para> | |
331 | </listitem> | |
332 | <listitem> | |
333 | <para>Require Unicode support for options which need it</para> | |
334 | </listitem> | |
335 | </itemizedlist> | |
336 | </para> | |
337 | ||
338 | <para>Most of the parsers have Unicode versions. For example, the | |
339 | &parse_command_line; function has an overload which takes | |
340 | <code>wchar_t</code> strings, instead of ordinary <code>char</code>. | |
341 | </para> | |
342 | ||
343 | <para>Even if some of the parsers are Unicode-aware, it does not mean you | |
344 | need to change definition of all the options. In fact, for many options, | |
345 | like integer ones, it makes no sense. To make use of Unicode you'll need | |
346 | <emphasis>some</emphasis> Unicode-aware options. They are different from | |
347 | ordinary options in that they accept <code>wstring</code> input, and | |
348 | process it using wide character streams. Creating an Unicode-aware option | |
349 | is easy: just use the the <code>wvalue</code> function instead of the | |
350 | regular <code>value</code>. | |
351 | </para> | |
352 | ||
353 | <para>When an ascii parser passes data to an ascii option, or a Unicode | |
354 | parser passes data to a Unicode option, the data are not changed at | |
355 | all. So, the ascii option will see a string in local 8-bit encoding, and | |
356 | the Unicode option will see whatever string was passed as the Unicode | |
357 | input. | |
358 | </para> | |
359 | ||
360 | <para>What happens when Unicode data is passed to an ascii option, and | |
361 | vice versa? The library automatically performs the conversion from | |
362 | Unicode to local 8-bit encoding. For example, if command line is in | |
363 | ascii, but you use <code>wstring</code> options, then the ascii input | |
364 | will be converted into Unicode. | |
365 | </para> | |
366 | ||
367 | <para>To perform the conversion, the library uses the <code>codecvt<wchar_t, | |
368 | char></code> locale facet from the global locale. If | |
369 | you want to work with strings that use local 8-bit encoding (as opposed to | |
370 | 7-bit ascii subset), your application should start with: | |
371 | <programlisting> | |
372 | locale::global(locale("")); | |
373 | </programlisting> | |
374 | which would set up the conversion facet according to the user's selected | |
375 | locale. | |
376 | </para> | |
377 | ||
378 | <para>It's wise to check the status of the C++ locale support on your | |
379 | implementation, though. The quick test involves three steps: | |
380 | <orderedlist> | |
381 | <listitem> | |
382 | <para>Go the the "test" directory and build the "test_convert" binary.</para> | |
383 | </listitem> | |
384 | <listitem> | |
385 | <para>Set some non-ascii locale in the environment. On Linux, one can | |
386 | run, for example: <screen> | |
387 | $ export LC_CTYPE=ru_RU.KOI8-R | |
388 | </screen> | |
389 | </para> | |
390 | </listitem> | |
391 | <listitem> | |
392 | <para>Run the "test_convert" binary with any non-ascii string in the | |
393 | selected encoding as its parameter. If you see a list of Unicode codepoints, | |
394 | everything's OK. Otherwise, locale support on your system might be | |
395 | broken.</para> | |
396 | </listitem> | |
397 | </orderedlist> | |
398 | </para> | |
399 | ||
400 | </section> | |
401 | ||
402 | <section> | |
403 | <title>Allowing Unknown Options</title> | |
404 | ||
405 | <para>Usually, the library throws an exception on unknown option names. This | |
406 | behaviour can be changed. For example, only some part of your application uses | |
407 | <libraryname>Program_options</libraryname>, and you wish to pass unrecognized options to another part of | |
408 | the program, or even to another application.</para> | |
409 | ||
410 | <para>To allow unregistered options on the command line, you need to use | |
411 | the &basic_command_line_parser; class for parsing (not &parse_command_line;) | |
412 | and call the <methodname alt="boost::program_options::basic_command_line_parser::allow_unregistered">allow_unregistered</methodname> | |
413 | method of that class: | |
414 | <programlisting> | |
415 | parsed_options parsed = | |
416 | command_line_parser(argc, argv).options(desc).allow_unregistered().run(); | |
417 | </programlisting> | |
418 | ||
419 | For each token that looks like an option, but does not have a known name, | |
420 | an instance of &basic_option; will be added to the result. | |
421 | The <code>string_key</code> and <code>value</code> fields of the instance will contain results | |
422 | of syntactic parsing of the token, the <code>unregistered</code> field will be set to <code>true</code>, | |
423 | and the <code>original_tokens</code> field will contain the token as it appeared on the command line. | |
424 | </para> | |
425 | ||
426 | <para>If you want to pass the unrecognized options further, the | |
427 | <functionname alt="boost::program_options::collect_unrecognized">collect_unrecognized</functionname> function can be used. | |
428 | The function will collect original tokens for all unrecognized values, and optionally, all found positional options. | |
429 | Say, if your code handles a few options, but does not handle positional options at all, you can use the function like this: | |
430 | <programlisting> | |
431 | vector<string> to_pass_further = collect_unrecognized(parsed.options, include_positional); | |
432 | </programlisting> | |
433 | ||
434 | </para> | |
435 | ||
436 | </section> | |
437 | ||
438 | </section> | |
439 | ||
440 | <!-- | |
441 | Local Variables: | |
442 | mode: nxml | |
443 | sgml-indent-data: t | |
444 | sgml-parent-document: ("userman.xml" "chapter") | |
445 | sgml-set-face: t | |
446 | End: | |
447 | --> |