1 | <html> |
---|
2 | <head> |
---|
3 | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
---|
4 | <title>How To</title> |
---|
5 | <link rel="stylesheet" href="../boostbook.css" type="text/css"> |
---|
6 | <meta name="generator" content="DocBook XSL Stylesheets V1.69.1"> |
---|
7 | <link rel="start" href="../index.html" title="The Boost C++ Libraries"> |
---|
8 | <link rel="up" href="../program_options.html" title="Chapter 7. Boost.Program_options"> |
---|
9 | <link rel="prev" href="overview.html" title="Library Overview"> |
---|
10 | <link rel="next" href="design.html" title="Design Discussion"> |
---|
11 | </head> |
---|
12 | <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> |
---|
13 | <table cellpadding="2" width="100%"> |
---|
14 | <td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../boost.png"></td> |
---|
15 | <td align="center"><a href="../../../index.htm">Home</a></td> |
---|
16 | <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td> |
---|
17 | <td align="center"><a href="../../../people/people.htm">People</a></td> |
---|
18 | <td align="center"><a href="../../../more/faq.htm">FAQ</a></td> |
---|
19 | <td align="center"><a href="../../../more/index.htm">More</a></td> |
---|
20 | </table> |
---|
21 | <hr> |
---|
22 | <div class="spirit-nav"> |
---|
23 | <a accesskey="p" href="overview.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../program_options.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="design.html"><img src="../images/next.png" alt="Next"></a> |
---|
24 | </div> |
---|
25 | <div class="section" lang="en"> |
---|
26 | <div class="titlepage"><div><div><h3 class="title"> |
---|
27 | <a name="program_options.howto"></a>How To</h3></div></div></div> |
---|
28 | <div class="toc"><dl> |
---|
29 | <dt><span class="section"><a href="howto.html#id2715843">Non-conventional Syntax</a></span></dt> |
---|
30 | <dt><span class="section"><a href="howto.html#id2715898">Response Files</a></span></dt> |
---|
31 | <dt><span class="section"><a href="howto.html#id2715975">Winmain Command Line</a></span></dt> |
---|
32 | <dt><span class="section"><a href="howto.html#id2716014">Option Groups and Hidden Options</a></span></dt> |
---|
33 | <dt><span class="section"><a href="howto.html#id2716150">Custom Validators</a></span></dt> |
---|
34 | <dt><span class="section"><a href="howto.html#id2716238">Unicode Support</a></span></dt> |
---|
35 | <dt><span class="section"><a href="howto.html#id2716386">Allowing Unknown Options</a></span></dt> |
---|
36 | </dl></div> |
---|
37 | <p>This section describes how the library can be used in specific |
---|
38 | situations.</p> |
---|
39 | <div class="section" lang="en"> |
---|
40 | <div class="titlepage"><div><div><h4 class="title"> |
---|
41 | <a name="id2715843"></a>Non-conventional Syntax</h4></div></div></div> |
---|
42 | <p>Sometimes, standard command line syntaxes are not enough. For |
---|
43 | example, the gcc compiler has "-frtti" and -fno-rtti" options, and this |
---|
44 | syntax is not directly supported. |
---|
45 | </p> |
---|
46 | <a class="indexterm" name="id2715851"></a><p>For such cases, the library allows the user to provide an |
---|
47 | <em class="firstterm">additional parser</em> -- a function which will be called on each |
---|
48 | command line element, before any processing by the library. If the |
---|
49 | additional parser recognises the syntax, it returns the option name and |
---|
50 | value, which are used directly. The above example can be handled by the |
---|
51 | following code: |
---|
52 | </p> |
---|
53 | <pre class="programlisting"> |
---|
54 | pair<string, string> reg_foo(const string& s) |
---|
55 | { |
---|
56 | if (s.find("-f") == 0) { |
---|
57 | if (s.substr(2, 3) == "no-") |
---|
58 | return make_pair(s.substr(5), string("false")); |
---|
59 | else |
---|
60 | return make_pair(s.substr(2), string("true")); |
---|
61 | } else { |
---|
62 | return make_pair(string(), string()); |
---|
63 | } |
---|
64 | } |
---|
65 | </pre> |
---|
66 | <p> |
---|
67 | Here's the definition of the additional parser. When parsing the command |
---|
68 | line, we pass the additional parser: |
---|
69 | </p> |
---|
70 | <pre class="programlisting"> |
---|
71 | store(command_line_parser(ac, av).options(desc).extra_parser(reg_foo) |
---|
72 | .run(), vm); |
---|
73 | </pre> |
---|
74 | <p> |
---|
75 | The complete example can be found in the "example/custom_syntax.cpp" |
---|
76 | file. |
---|
77 | </p> |
---|
78 | </div> |
---|
79 | <div class="section" lang="en"> |
---|
80 | <div class="titlepage"><div><div><h4 class="title"> |
---|
81 | <a name="id2715898"></a>Response Files</h4></div></div></div> |
---|
82 | <a class="indexterm" name="id2715902"></a><p>Some operating system have very low limits of the command line |
---|
83 | length. The common way to work around those limitations is using |
---|
84 | <em class="firstterm">response files</em>. A response file is just a |
---|
85 | configuration file which uses the same syntax as the command line. If |
---|
86 | the command line specifies a name of response file to use, it's loaded |
---|
87 | and parsed in addition to the command line. The library does not |
---|
88 | provide direct support for response files, so you'll need to write some |
---|
89 | extra code. |
---|
90 | </p> |
---|
91 | <p> |
---|
92 | First, you need to define an option for the response file: |
---|
93 | </p> |
---|
94 | <pre class="programlisting"> |
---|
95 | ("response-file", value<string>(), |
---|
96 | "can be specified with '@name', too") |
---|
97 | </pre> |
---|
98 | <p>Second, you'll need an additional parser to support the standard syntax |
---|
99 | for specifying response files: "@file": |
---|
100 | </p> |
---|
101 | <pre class="programlisting"> |
---|
102 | pair<string, string> at_option_parser(string const&s) |
---|
103 | { |
---|
104 | if ('@' == s[0]) |
---|
105 | return std::make_pair(string("response-file"), s.substr(1)); |
---|
106 | else |
---|
107 | return pair<string, string>(); |
---|
108 | } |
---|
109 | |
---|
110 | </pre> |
---|
111 | <p>Finally, when the "response-file" option is found, you'll have to |
---|
112 | load that file and pass it to the command line parser. This part is the |
---|
113 | hardest. We'll use the Boost.Tokenizer library, which works but has some |
---|
114 | limitations. You might also consider Boost.StringAlgo. The code is: |
---|
115 | </p> |
---|
116 | <pre class="programlisting"> |
---|
117 | if (vm.count("response-file")) { |
---|
118 | // Load the file and tokenize it |
---|
119 | ifstream ifs(vm["response-file"].as<string>().c_str()); |
---|
120 | if (!ifs) { |
---|
121 | cout << "Could no open the response file\n"; |
---|
122 | return 1; |
---|
123 | } |
---|
124 | // Read the whole file into a string |
---|
125 | stringstream ss; |
---|
126 | ss << ifs.rdbuf(); |
---|
127 | // Split the file content |
---|
128 | char_separator<char> sep(" \n\r"); |
---|
129 | tokenizer<char_separator<char> > tok(ss.str(), sep); |
---|
130 | vector<string> args; |
---|
131 | copy(tok.begin(), tok.end(), back_inserter(args)); |
---|
132 | // Parse the file and store the options |
---|
133 | store(command_line_parser(args).options(desc).run(), vm); |
---|
134 | } |
---|
135 | |
---|
136 | </pre> |
---|
137 | <p> |
---|
138 | The complete example can be found in the "example/response_file.cpp" |
---|
139 | file. |
---|
140 | </p> |
---|
141 | </div> |
---|
142 | <div class="section" lang="en"> |
---|
143 | <div class="titlepage"><div><div><h4 class="title"> |
---|
144 | <a name="id2715975"></a>Winmain Command Line</h4></div></div></div> |
---|
145 | <p>On the Windows operating system, GUI applications receive the |
---|
146 | command line as a single string, not split into elements. For that reason, |
---|
147 | the command line parser cannot be used directly. At least on some |
---|
148 | compilers, it is possible to obtain |
---|
149 | the split command line, but it's not clear if all compilers support the |
---|
150 | same mechanism on all versions of the operating system. The |
---|
151 | <code class="computeroutput">split_winmain</code> function is a portable mechanism provided |
---|
152 | by the library.</p> |
---|
153 | <p>Here's an example of use: |
---|
154 | </p> |
---|
155 | <pre class="programlisting"> |
---|
156 | vector<string> args = split_winmain(lpCmdLine); |
---|
157 | store(command_line_parser(args).options(desc).run(), vm); |
---|
158 | </pre> |
---|
159 | <p> |
---|
160 | The function is an overload for <code class="computeroutput">wchar_t</code> strings, so can |
---|
161 | also be used in Unicode applications. |
---|
162 | </p> |
---|
163 | </div> |
---|
164 | <div class="section" lang="en"> |
---|
165 | <div class="titlepage"><div><div><h4 class="title"> |
---|
166 | <a name="id2716014"></a>Option Groups and Hidden Options</h4></div></div></div> |
---|
167 | <p>Having a single instance of the <code class="computeroutput"><a href="../options_description.html" title="Class options_description">options_description</a></code> class with all |
---|
168 | the program's options can be problematic: |
---|
169 | </p> |
---|
170 | <div class="itemizedlist"><ul type="disc"> |
---|
171 | <li><p>Some options make sense only for specific source, for example, |
---|
172 | configuration files.</p></li> |
---|
173 | <li><p>The user would prefer some structure in the generated help message.</p></li> |
---|
174 | <li><p>Some options shouldn't appear in the generated help message at all.</p></li> |
---|
175 | </ul></div> |
---|
176 | <p>To solve the above issues, the library allows a programmer to create several |
---|
177 | instances of the <code class="computeroutput"><a href="../options_description.html" title="Class options_description">options_description</a></code> class, which can be merged in |
---|
178 | different combinations. The following example will define three groups of |
---|
179 | options: command line specific, and two options group for specific program |
---|
180 | modules, only one of which is shown in the generated help message. |
---|
181 | </p> |
---|
182 | <p>Each group is defined using standard syntax. However, you should |
---|
183 | use reasonable names for each <code class="computeroutput"><a href="../options_description.html" title="Class options_description">options_description</a></code> instance: |
---|
184 | </p> |
---|
185 | <pre class="programlisting"> |
---|
186 | options_description general("General options"); |
---|
187 | general.add_options() |
---|
188 | ("help", "produce a help message") |
---|
189 | ("help-module", value<string>()->implicit(), |
---|
190 | "produce a help for a given module") |
---|
191 | ("version", "output the version number") |
---|
192 | ; |
---|
193 | |
---|
194 | options_description gui("GUI options"); |
---|
195 | gui.add_options() |
---|
196 | ("display", value<string>(), "display to use") |
---|
197 | ; |
---|
198 | |
---|
199 | options_description backend("Backend options"); |
---|
200 | backend.add_options() |
---|
201 | ("num-threads", value<int>(), "the initial number of threads") |
---|
202 | ; |
---|
203 | </pre> |
---|
204 | <p>After declaring options groups, we merge them in two |
---|
205 | combinations. The first will include all options and be used for parsing. The |
---|
206 | second will be used for the "--help" option. |
---|
207 | </p> |
---|
208 | <pre class="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 | </pre> |
---|
219 | <p>What is left is to parse and handle the options: |
---|
220 | </p> |
---|
221 | <pre class="programlisting"> |
---|
222 | variables_map vm; |
---|
223 | store(parse_command_line(ac, av, all), vm); |
---|
224 | |
---|
225 | if (vm.count("help")) |
---|
226 | { |
---|
227 | cout << visible; |
---|
228 | return 0; |
---|
229 | } |
---|
230 | if (vm.count("help-module")) { |
---|
231 | const string& s = vm["help-module"].as<string>(); |
---|
232 | if (s == "gui") { |
---|
233 | cout << gui; |
---|
234 | } else if (s == "backend") { |
---|
235 | cout << backend; |
---|
236 | } else { |
---|
237 | cout << "Unknown module '" |
---|
238 | << s << "' in the --help-module option\n"; |
---|
239 | return 1; |
---|
240 | } |
---|
241 | return 0; |
---|
242 | } |
---|
243 | if (vm.count("num-threads")) { |
---|
244 | cout << "The 'num-threads' options was set to " |
---|
245 | << vm["num-threads"].as<int>() << "\n"; |
---|
246 | } |
---|
247 | </pre> |
---|
248 | <p> |
---|
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 | </p> |
---|
256 | </div> |
---|
257 | <div class="section" lang="en"> |
---|
258 | <div class="titlepage"><div><div><h4 class="title"> |
---|
259 | <a name="id2716150"></a>Custom Validators</h4></div></div></div> |
---|
260 | <p>By default, the conversion of option's value from string into C++ |
---|
261 | type is done using iostreams, which sometimes is not convenient. The |
---|
262 | library allows the user to customize the conversion for specific |
---|
263 | classes. In order to do so, the user should provide suitable overload of |
---|
264 | the <code class="computeroutput">validate</code> function. |
---|
265 | </p> |
---|
266 | <p> |
---|
267 | Let's first define a simple class: |
---|
268 | </p> |
---|
269 | <pre class="programlisting"> |
---|
270 | struct magic_number { |
---|
271 | public: |
---|
272 | magic_number(int n) : n(n) {} |
---|
273 | int n; |
---|
274 | }; |
---|
275 | </pre> |
---|
276 | <p> and then overload the <code class="computeroutput">validate</code> function: |
---|
277 | </p> |
---|
278 | <pre class="programlisting"> |
---|
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_occurence(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("invalid value"); |
---|
300 | } |
---|
301 | } |
---|
302 | |
---|
303 | </pre> |
---|
304 | <p>The function takes four parameters. The first is the storage |
---|
305 | for the value, and in this case is either empty or contains an instance of |
---|
306 | the <code class="computeroutput">magic_number</code> class. The second is the list of strings |
---|
307 | found in the next occurrence of the option. The remaining two parameters |
---|
308 | are needed to workaround the lack of partial template specialization and |
---|
309 | partial function template ordering on some compilers. |
---|
310 | </p> |
---|
311 | <p>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 class="computeroutput">v</code> variable. |
---|
316 | </p> |
---|
317 | <p>The complete example can be found in the "example/regex.cpp" file. |
---|
318 | </p> |
---|
319 | </div> |
---|
320 | <div class="section" lang="en"> |
---|
321 | <div class="titlepage"><div><div><h4 class="title"> |
---|
322 | <a name="id2716238"></a>Unicode Support</h4></div></div></div> |
---|
323 | <p>To use the library with Unicode, you'd need to: |
---|
324 | </p> |
---|
325 | <div class="itemizedlist"><ul type="disc"> |
---|
326 | <li><p>Use Unicode-aware parsers for Unicode input</p></li> |
---|
327 | <li><p>Require Unicode support for options which need it</p></li> |
---|
328 | </ul></div> |
---|
329 | <p>Most of the parsers have Unicode versions. For example, the |
---|
330 | <code class="computeroutput"><a href="../parse_command_line.html" title="Function template parse_command_line">parse_command_line</a></code> function has an overload which takes |
---|
331 | <code class="computeroutput">wchar_t</code> strings, instead of ordinary <code class="computeroutput">char</code>. |
---|
332 | </p> |
---|
333 | <p>Even if some of the parsers are Unicode-aware, it does not mean you |
---|
334 | need to change definition of all the options. In fact, for many options, |
---|
335 | like integer ones, it makes no sense. To make use of Unicode you'll need |
---|
336 | <span class="emphasis"><em>some</em></span> Unicode-aware options. They are different from |
---|
337 | ordinary options in that they accept <code class="computeroutput">wstring</code> input, and |
---|
338 | process it using wide character streams. Creating an Unicode-aware option |
---|
339 | is easy: just use the the <code class="computeroutput">wvalue</code> function instead of the |
---|
340 | regular <code class="computeroutput">value</code>. |
---|
341 | </p> |
---|
342 | <p>When an ascii parser passes data to an ascii option, or a Unicode |
---|
343 | parser passes data to a Unicode option, the data are not changed at |
---|
344 | all. So, the ascii option will see a string in local 8-bit encoding, and |
---|
345 | the Unicode option will see whatever string was passed as the Unicode |
---|
346 | input. |
---|
347 | </p> |
---|
348 | <p>What happens when Unicode data is passed to an ascii option, and |
---|
349 | vice versa? The library automatically performs the conversion from |
---|
350 | Unicode to local 8-bit encoding. For example, if command line is in |
---|
351 | ascii, but you use <code class="computeroutput">wstring</code> options, then the ascii input |
---|
352 | will be converted into Unicode. |
---|
353 | </p> |
---|
354 | <p>To perform the conversion, the library uses the <code class="computeroutput">codecvt<wchar_t, |
---|
355 | char></code> locale facet from the global locale. If |
---|
356 | you want to work with strings that use local 8-bit encoding (as opposed to |
---|
357 | 7-bit ascii subset), your application should start with: |
---|
358 | </p> |
---|
359 | <pre class="programlisting"> |
---|
360 | locale::global(locale("")); |
---|
361 | </pre> |
---|
362 | <p> |
---|
363 | which would set up the conversion facet according to the user's selected |
---|
364 | locale. |
---|
365 | </p> |
---|
366 | <p>It's wise to check the status of the C++ locale support on your |
---|
367 | implementation, though. The quick test involves three steps: |
---|
368 | </p> |
---|
369 | <div class="orderedlist"><ol type="1"> |
---|
370 | <li><p>Go the the "test" directory and build the "test_convert" binary.</p></li> |
---|
371 | <li> |
---|
372 | <p>Set some non-ascii locale in the environmemt. On Linux, one can |
---|
373 | run, for example: </p> |
---|
374 | <pre class="screen"> |
---|
375 | $ export LC_CTYPE=ru_RU.KOI8-R |
---|
376 | </pre> |
---|
377 | </li> |
---|
378 | <li><p>Run the "test_convert" binary with any non-ascii string in the |
---|
379 | selected encoding as its parameter. If you see a list of Unicode codepoints, |
---|
380 | everything's OK. Otherwise, locale support on your system might be |
---|
381 | broken.</p></li> |
---|
382 | </ol></div> |
---|
383 | </div> |
---|
384 | <div class="section" lang="en"> |
---|
385 | <div class="titlepage"><div><div><h4 class="title"> |
---|
386 | <a name="id2716386"></a>Allowing Unknown Options</h4></div></div></div> |
---|
387 | <p>Usually, the library throws an exception on unknown option names. This |
---|
388 | behaviour can be changed. For example, only some part of your application uses |
---|
389 | <a href="../program_options.html" title="Chapter 7. Boost.Program_options">Program_options</a>, and you wish to pass unrecognized options to another part of |
---|
390 | the program, or even to another application.</p> |
---|
391 | <p>To allow unregistered options on the command line, you need to use |
---|
392 | the <code class="computeroutput"><a href="../basic_command_line_parser.html" title="Class template basic_command_line_parser">basic_command_line_parser</a></code> class for parsing (not <code class="computeroutput"><a href="../parse_command_line.html" title="Function template parse_command_line">parse_command_line</a></code>) |
---|
393 | and call the <code class="computeroutput"><a href="../basic_command_line_parser.html#id2491704-bb">allow_unregistered</a></code> |
---|
394 | method of that class: |
---|
395 | </p> |
---|
396 | <pre class="programlisting"> |
---|
397 | parsed_options parsed = |
---|
398 | command_line_parser(argv, argc).options(desc).allow_unregistered().run(); |
---|
399 | </pre> |
---|
400 | <p> |
---|
401 | |
---|
402 | For each token that looks like an option, but does not have a known name, |
---|
403 | an instance of <code class="computeroutput"><a href="../basic_option.html" title="Class template basic_option">basic_option</a></code> will be added to the result. |
---|
404 | The <code class="computeroutput">string_key</code> and <code class="computeroutput">value</code> fields of the instance will contain results |
---|
405 | of syntactic parsing of the token, the <code class="computeroutput">unregistered</code> field will be set to <code class="computeroutput">true</code>, |
---|
406 | and the <code class="computeroutput">original_tokens</code> field will contain the token as it appeared on the command line. |
---|
407 | </p> |
---|
408 | <p>If you want to pass the unrecognized options further, the |
---|
409 | <code class="computeroutput"><a href="../collect_unrecognized.html" title="Function template collect_unrecognized">collect_unrecognized</a></code> function can be used. |
---|
410 | The function will collect original tokens for all unrecognized values, and optionally, all found positional options. |
---|
411 | Say, if your code handles a few options, but does not handles positional options at all, you can use the function like this: |
---|
412 | </p> |
---|
413 | <pre class="programlisting"> |
---|
414 | vector<string> to_pass_further = collect_arguments(parsed.option, include_positional); |
---|
415 | </pre> |
---|
416 | </div> |
---|
417 | </div> |
---|
418 | <table width="100%"><tr> |
---|
419 | <td align="left"></td> |
---|
420 | <td align="right"><small>Copyright © 2002-2004 Vladimir Prus</small></td> |
---|
421 | </tr></table> |
---|
422 | <hr> |
---|
423 | <div class="spirit-nav"> |
---|
424 | <a accesskey="p" href="overview.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../program_options.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="design.html"><img src="../images/next.png" alt="Next"></a> |
---|
425 | </div> |
---|
426 | </body> |
---|
427 | </html> |
---|