howto.xml 18 KB

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