1 // ==========================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2015, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 // its contributors may be used to endorse or promote products derived
17 // from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32
33 #ifndef SEQAN_INCLUDE_ARG_PARSE_ARGUMENT_PARSER_H_
34 #define SEQAN_INCLUDE_ARG_PARSE_ARGUMENT_PARSER_H_
35
36 #include <seqan/map.h>
37 #include <seqan/sequence.h>
38 #include <seqan/stream.h>
39
40 #include <seqan/arg_parse/arg_parse_type_support.h>
41 #include <seqan/arg_parse/arg_parse_argument.h>
42 #include <seqan/arg_parse/arg_parse_option.h>
43
44 #include <seqan/arg_parse/tool_doc.h>
45
46 #include <iostream>
47 #include <string>
48 #include <vector>
49 #include <map>
50
51 namespace seqan {
52
53 // ==========================================================================
54 // Forwards
55 // ==========================================================================
56
57 // friend declaration to make addOption() and hideOption() available
58 // in ArgumentParser::init()
59 class ArgumentParser;
60 class ArgParseOption;
61 void addOption(ArgumentParser & me, ArgParseOption const & opt);
62 void hideOption(ArgumentParser & me, std::string const & name, bool hide);
63 void setValidValues(ArgumentParser & me, std::string const & name, std::string const & values);
64
65 // Required in addOption() and addArgument().
66 inline void hideOption(ArgumentParser & me, std::string const & name, bool hide = true);
67 inline ArgParseOption & getOption(ArgumentParser & me, std::string const & name);
68 inline void setValidValues(ArgumentParser & me, std::string const & name, std::vector<std::string> const & values);
69 inline ArgParseArgument & getArgument(ArgumentParser & me, unsigned position);
70
71 // ==========================================================================
72 // Tags, Classes, Enums
73 // ==========================================================================
74
75 /*!
76 * @class ArgumentParser
77 * @headerfile <seqan/arg_parse.h>
78 * @brief Parse the command line.
79 *
80 * @signature class ArgumentParser;
81 *
82 * Options are stored as @link ArgParseOption @endlink and @link ArgParseArgument @endlink objects.
83 *
84 * @section Remarks
85 *
86 * See the documentation of @link ToolDoc @endlink on how to format text. Wherever possible, formatting is added
87 * automatically for you. You have to use formatting in the following places: (1) usage lines, (2) option help texts,
88 * (3) description and additional text sections.
89 *
90 * @section Examples
91 *
92 * The following gives a simple example of how to use the ArgumentParser class.
93 *
94 * @include demos/arg_parse/argument_parser.cpp
95 *
96 * @code{.console}
97 * $ demo_arg_parse_argument_parser in.fa out.txt --id 0
98 * Built target seqan_core
99 * Built target demo_arg_parse
100 * Verbose: off
101 * Identity: 0
102 * Input-File: in.fa
103 * Output-File: out.txt
104 * @endcode
105 *
106 * @see ArgParseArgument
107 * @see ArgParseOption
108 * @see ToolDoc
109 */
110
111 /*!
112 * @fn ArgumentParser::ArgumentParser
113 * @brief Constructor
114 *
115 * @signature ArgumentParser::ArgumentParser([appName]);
116 *
117 * @param[in] appName The name of the application (<tt>std::string</tt>), defaults to <tt>argv[0]</tt>.
118 */
119
120 /*!
121 * @enum ArgumentParser::ParseResult
122 * @brief Argument parsing result.
123 *
124 * @signature enum ArgumentParser::ParseResult;
125 *
126 * @val ArgumentParser::ParseResult ArgumentParser::PARSE_OK;
127 * @brief Parsing the program's arguments was successful and no builtin command was triggered.
128 *
129 * @val ArgumentParser::ParseResult ArgumentParser::PARSE_ERROR;
130 * @brief There were errors parsing the arguments.
131 *
132 * @val ArgumentParser::ParseResult ArgumentParser::PARSE_HELP;
133 * @brief Parsing was successful, built-in <tt>--help</tt> option was used.
134 *
135 * @val ArgumentParser::ParseResult ArgumentParser::PARSE_VERSION;
136 * @brief Parsing was successful, built-in <tt>--version</tt> option was used.
137 *
138 * @val ArgumentParser::ParseResult ArgumentParser::PARSE_WRITE_CTD;
139 * @brief Parsing was successful, built-in <tt>--write-ctd</tt> option was used.
140 *
141 * @val ArgumentParser::ParseResult ArgumentParser::PARSE_EXPORT_HELP;
142 * @brief Parsing was successful, built-in <tt>--export-help</tt> option was used.
143 */
144
145 class ArgumentParser
146 {
147 public:
148
149 // ----------------------------------------------------------------------------
150 // Enum ParseResult
151 // ----------------------------------------------------------------------------
152
153 // will be used as return value of parse(..) to indicate whether parsing worked
154 enum ParseResult
155 {
156 PARSE_OK,
157 PARSE_ERROR,
158 PARSE_HELP,
159 PARSE_VERSION,
160 PARSE_WRITE_CTD,
161 PARSE_EXPORT_HELP
162 };
163
164 // ----------------------------------------------------------------------------
165 // Class Typedefs
166 // ----------------------------------------------------------------------------
167
168 typedef std::vector<ArgParseOption> TOptionMap;
169 typedef std::vector<ArgParseArgument> TArgumentMap;
170 typedef Size<TOptionMap>::Type TOptionMapSize;
171 typedef Size<TArgumentMap>::Type TArgumentMapSize;
172
173 typedef std::map<std::string, TOptionMapSize> TStringMap;
174 typedef std::vector<std::string> TValueMap;
175
176 // ----------------------------------------------------------------------------
177 // Mapping of option names to options
178 // ----------------------------------------------------------------------------
179
180 TStringMap shortNameMap;
181 TStringMap longNameMap;
182 TOptionMap optionMap;
183 TArgumentMap argumentList;
184
185 // ----------------------------------------------------------------------------
186 // Documentation Members
187 // ----------------------------------------------------------------------------
188
189 ToolDoc _toolDoc; // the tool doc for all user specified
190 // text
191 std::vector<std::string> _description; // the description which we need to
192 // separate to put it on top of the rest
193 std::vector<std::string> _usageText; // the usage lines as strings, to avoid
194 // interference with the rest of the doc
195
196 // ----------------------------------------------------------------------------
197 // Function init()
198 // ----------------------------------------------------------------------------
199
init()200 void init()
201 {
202 addOption(*this, ArgParseOption("h", "help", "Displays this help message."));
203
204 // hidden flags used for export of man pages and ctd formats
205 addOption(*this, ArgParseOption("",
206 "write-ctd",
207 "Exports the app's interface description to a .ctd file.",
208 ArgParseArgument::OUTPUT_FILE));
209 hideOption(*this, "write-ctd", true);
210
211 addOption(*this, ArgParseOption("",
212 "export-help",
213 "Export help to a format. One of {'html', 'man', 'txt'}.",
214 ArgParseArgument::STRING,
215 "FORMAT"));
216 hideOption(*this, "export-help", true);
217 setValidValues(*this, "export-help", "html man txt");
218 }
219
220 // ----------------------------------------------------------------------------
221 // Constructors
222 // ----------------------------------------------------------------------------
223
ArgumentParser()224 ArgumentParser()
225 {
226 init();
227 }
228
ArgumentParser(std::string const & _appName)229 ArgumentParser(std::string const & _appName)
230 {
231 setName(_toolDoc, _appName);
232 init();
233 }
234
235 };
236
237 // ==========================================================================
238 // Metafunctions
239 // ==========================================================================
240
241 // ==========================================================================
242 // Functions
243 // ==========================================================================
244
245 // ----------------------------------------------------------------------------
246 // Function hasOption()
247 // ----------------------------------------------------------------------------
248
249 /*!
250 * @fn ArgumentParser#hasOption
251 * @headerfile <seqan/arg_parse.h>
252 * @brief Query whether a certain option is registered in the parser.
253 *
254 * @signature bool hasOption(parser, name);
255 *
256 * @param[in] parser The ArgumentParser to query.
257 * @param[in] name The name to query for (<tt>std::string</tt>).
258 *
259 * @return bool <tt>true</tt> if there is such an option, <tt>false</tt> otherwise.
260 */
261
hasOption(ArgumentParser const & me,std::string const & name)262 inline bool hasOption(ArgumentParser const & me, std::string const & name)
263 {
264 return hasKey(me.shortNameMap, name) || hasKey(me.longNameMap, name);
265 }
266
267 // ----------------------------------------------------------------------------
268 // Function addOption()
269 // ----------------------------------------------------------------------------
270
271 /*!
272 * @fn ArgumentParser#addOption
273 * @headerfile <seqan/arg_parse.h>
274 * @brief Adds an @link ArgParseOption @endlink to an ArgumentParser.
275 *
276 * @signature void addOption(parser, option);
277 *
278 * @param[in,out] parser The ArgumentParser to add the option to.
279 * @param[in] option The ArgParseOption to add to <tt>parser</tt>.
280 */
281
_copyValidValuesToFileExt(ArgumentParser & me,std::string const & name)282 inline void _copyValidValuesToFileExt(ArgumentParser & me, std::string const & name)
283 {
284 // Copy valid values, remove leading dots.
285 ArgParseOption & option = getOption(me, name);
286 if (isInputFileArgument(option) || isOutputFileArgument(option))
287 {
288 std::string longName = option.longName.empty() ? option.shortName : option.longName;
289 longName += "-file-ext";
290 std::vector<std::string> validValues = option.validValues;
291 for (unsigned i = 0; i < length(validValues); ++i)
292 if (!validValues[i].empty() && validValues[i][0] == '.')
293 validValues[i].erase(0, 1);
294 setValidValues(me, longName, validValues);
295 }
296 }
297
addOption(ArgumentParser & me,ArgParseOption const & opt)298 inline void addOption(ArgumentParser & me, ArgParseOption const & opt)
299 {
300 // check if an option with the same identifiers was already registered
301 SEQAN_CHECK(!hasOption(me, opt.shortName), "There already is an option with the name %s!", toCString(opt.shortName));
302 SEQAN_CHECK(!hasOption(me, opt.longName), "There already is an option with the name %s!", toCString(opt.longName));
303
304 // finally append the option
305 appendValue(me.optionMap, opt);
306
307 if (!empty(opt.shortName))
308 me.shortNameMap.insert(std::make_pair(opt.shortName, length(me.optionMap) - 1));
309 if (!empty(opt.longName))
310 me.longNameMap.insert(std::make_pair(opt.longName, length(me.optionMap) - 1));
311
312 // handle the case of input and output option: add a string option --${name}-file-ext.
313 if (isInputFileArgument(opt) || isOutputFileArgument(opt))
314 {
315 std::string longName = opt.longName.empty() ? opt.shortName : opt.longName;
316 longName += "-file-ext";
317 std::string helpText = "Override file extension for --";
318 helpText += opt.longName;
319
320 // Add option, copy list argument, number of allowed values.
321 addOption(me, ArgParseOption("", longName, helpText, ArgParseOption::STRING, "EXT",
322 isListArgument(opt), numberOfAllowedValues(opt)));
323 getOption(me, longName.c_str()).tags.push_back("file-ext-override");
324 getOption(me, longName.c_str()).tags.push_back("gkn-ignore");
325 // Hide option.
326 hideOption(me, longName);
327 // Copy valid values, remove leading dots.
328 _copyValidValuesToFileExt(me, opt.longName);
329 }
330 }
331
332 // ----------------------------------------------------------------------------
333 // Function addArgument()
334 // ----------------------------------------------------------------------------
335
336 /*!
337 * @fn ArgumentParser#addArgument
338 * @headerfile <seqan/arg_parse.h>
339 * @brief Adds an @link ArgParseArgument @endlink to an ArgumentParser.
340 *
341 * @signature void addArgument(parser, arg);
342 *
343 * @param[in,out] parser The ArgumentParser to add the argument to.
344 * @param[in] arg The ArgParseArgument to add to <tt>parser</tt>.
345 */
346
_copyValidValuesToFileExt(ArgumentParser & me,unsigned no)347 inline void _copyValidValuesToFileExt(ArgumentParser & me, unsigned no)
348 {
349 // Copy valid values, remove leading dots.
350 ArgParseArgument & arg = getArgument(me, no);
351 if (isInputFileArgument(arg) || isOutputFileArgument(arg))
352 {
353 std::stringstream longNameSS;
354 longNameSS << "arg-" << (no + 1) << "-file-ext";
355 std::string longName = longNameSS.str();
356 std::vector<std::string> validValues = arg.validValues;
357 for (unsigned i = 0; i < length(validValues); ++i)
358 if (!validValues[i].empty() && validValues[i][0] == '.')
359 validValues[i].erase(0, 1);
360 setValidValues(me, longName, validValues);
361 }
362 }
363
addArgument(ArgumentParser & me,ArgParseArgument const & arg)364 inline void addArgument(ArgumentParser & me, ArgParseArgument const & arg)
365 {
366 // check previous arguments
367 // .. lists can only be last argument
368 if (!me.argumentList.empty())
369 {
370 SEQAN_CHECK(!isListArgument(me.argumentList[me.argumentList.size() - 1]),
371 "You cannot add an additional argument after a list argument.");
372 }
373
374 // check current argument
375 // .. arguments should not have default values
376 SEQAN_CHECK(arg.defaultValue.empty(), "Arguments cannot have default values.");
377 SEQAN_CHECK(arg._numberOfValues == 1, "n-Tuple of arguments are not supported.");
378
379 me.argumentList.push_back(arg);
380
381 // handle the case of input and output option: add a string option --${name}-file-ext.
382 if (isInputFileArgument(arg) || isOutputFileArgument(arg))
383 {
384 std::stringstream longNameSS;
385 longNameSS << "arg-" << me.argumentList.size() << "-file-ext";
386 std::string longName = longNameSS.str();
387 std::stringstream helpTextSS;
388 helpTextSS << "Override file extension for argument " << me.argumentList.size();
389 std::string helpText = helpTextSS.str();
390
391 // Add option, copy list argument, number of allowed values.
392 addOption(me, ArgParseOption("", longName, helpText, ArgParseOption::STRING, "EXT",
393 isListArgument(arg), numberOfAllowedValues(arg)));
394 getOption(me, longName.c_str()).tags.push_back("file-ext-override");
395 getOption(me, longName.c_str()).tags.push_back("gkn-ignore");
396 // Hide option.
397 hideOption(me, longName);
398 // Copy valid values, remove leading dots.
399 _copyValidValuesToFileExt(me, me.argumentList.size() - 1);
400 }
401 }
402
403 // ----------------------------------------------------------------------------
404 // Function _getOptionIndex()
405 // ----------------------------------------------------------------------------
406 // note that it is assumed that the option exists if this method is called
407
_getOptionIndex(ArgumentParser const & me,std::string const & name)408 inline ArgumentParser::TOptionMapSize _getOptionIndex(ArgumentParser const & me,
409 std::string const & name)
410 {
411 ArgumentParser::TOptionMapSize option_index;
412 if (me.shortNameMap.find(name) != me.shortNameMap.end())
413 {
414 option_index = me.shortNameMap.find(name)->second;
415 }
416 else
417 {
418 option_index = me.longNameMap.find(name)->second;
419 }
420 return option_index;
421 }
422
423 // ----------------------------------------------------------------------------
424 // Function getOption()
425 // ----------------------------------------------------------------------------
426
427 /*!
428 * @fn ArgumentParser#getOption
429 * @headerfile <seqan/arg_parse.h>
430 * @brief Returns a reference to the specified option.
431 *
432 * @signature TOption getOption(parser, name);
433 *
434 * @param[in] parser The parser to query.
435 * @param[in] name The short or long name of the option (<tt>std::string</tt>).
436 *
437 * @return TOption Reference to the @link ArgParseOption @endlink with the given short or long name.
438 */
439
getOption(ArgumentParser & me,std::string const & name)440 inline ArgParseOption & getOption(ArgumentParser & me, std::string const & name)
441 {
442 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
443 return me.optionMap[_getOptionIndex(me, name)];
444 }
445
getOption(ArgumentParser const & me,std::string const & name)446 inline ArgParseOption const & getOption(ArgumentParser const & me, std::string const & name)
447 {
448 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
449 return me.optionMap[_getOptionIndex(me, name)];
450 }
451
452 // ----------------------------------------------------------------------------
453 // Function setRequired()
454 // ----------------------------------------------------------------------------
455
456 /*!
457 * @fn ArgumentParser#setRequired
458 * @headerfile <seqan/arg_parse.h>
459 * @brief Sets whether or not the option with the givne name is mandatory.
460 *
461 * @signature void setRequired(parser, name[, required]).
462 *
463 * @param[in,out] parser The ArgumentParser to set the flag of.
464 * @param[in] name The short or long name of the option (<tt>std::string</tt>).
465 * @param[in] required Whether or not the option is required (<tt>bool</tt>, default to <tt>true</tt>).
466 */
467
468 inline void setRequired(ArgumentParser & me, std::string const & name, bool required = true)
469 {
470 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
471 setRequired(getOption(me, name), required);
472 }
473
474 // ----------------------------------------------------------------------------
475 // Function hideOption()
476 // ----------------------------------------------------------------------------
477
478 /*!
479 * @fn ArgumentParser#hideOption
480 * @headerfile <seqan/arg_parse.h>
481 * @brief Hides the ArgParseOption with the given name.
482 *
483 * @signature void hideOption(parser, name[, hide]).
484 *
485 * @param[in,out] parser The ArgParseOption to the the hidden flag of.
486 * @param[in] name The short or long name of the option to modify.
487 * @param[in] hide Whether or not to hide the flag (<tt>bool</tt>, defaults to <tt>true</tt>).
488 */
489
hideOption(ArgumentParser & me,std::string const & name,bool hide)490 inline void hideOption(ArgumentParser & me, std::string const & name, bool hide)
491 {
492 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
493 hideOption(getOption(me, name), hide);
494 }
495
496 // ----------------------------------------------------------------------------
497 // Function getArgument()
498 // ----------------------------------------------------------------------------
499
500 /*!
501 * @fn ArgumentParser#getArgument
502 * @headerfile <seqan/arg_parse.h>
503 * @brief Returns a reference to the given positional argument.
504 *
505 * @signature TArgument getArgument(parser, pos);
506 *
507 * @param[in] parser The ArgumentParser to query.
508 * @param[in] pos The position of the argument to return (<tt>unsigned</tt>, starting at 0).
509 *
510 * @return TArgument Reference to the @link ArgParseArgument @endlink with the given position.
511 */
512
getArgument(ArgumentParser & me,unsigned position)513 inline ArgParseArgument & getArgument(ArgumentParser & me, unsigned position)
514 {
515 SEQAN_CHECK(position < me.argumentList.size(),
516 "ArgumentParser: Only %d arguments available", me.argumentList.size());
517 return me.argumentList[position];
518 }
519
getArgument(ArgumentParser const & me,unsigned position)520 inline ArgParseArgument const & getArgument(ArgumentParser const & me, unsigned position)
521 {
522 SEQAN_CHECK(position < me.argumentList.size(),
523 "ArgumentParser: Only %d arguments available", me.argumentList.size());
524 return me.argumentList[position];
525 }
526
527 // ----------------------------------------------------------------------------
528 // Function isSet()
529 // ----------------------------------------------------------------------------
530
531 /*!
532 * @fn ArgumentParser#isSet
533 * @headerfile <seqan/arg_parse.h>
534 * @brief Query whether an option was set on the command line.
535 *
536 * @signature bool isSet(parser, name);
537 *
538 * @param[in] parser The ArgumentParser to query.
539 * @param[in] name The short or long name of the option (<tt>std::string</tt>).
540 *
541 * @return bool Whether or not the option was set on the command line or not.
542 */
543
isSet(ArgumentParser const & me,std::string const & name)544 inline bool isSet(ArgumentParser const & me, std::string const & name)
545 {
546 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
547 return isSet(getOption(me, name));
548 }
549
550 // ----------------------------------------------------------------------------
551 // Function hasDefault()
552 // ----------------------------------------------------------------------------
553
554 /*!
555 * @fn ArgumentParser#hasDefault
556 * @headerfile <seqan/arg_parse.h>
557 * @brief Query whether an option has a default value.
558 *
559 * @signature bool hasDefault(parser, name);
560 *
561 * @param[in] parser The ArgumentParser to query.
562 * @param[in] name The short or long name of the option (<tt>std::string</tt>).
563 *
564 * @return bool Whether or not the option has a default value.
565 */
566
hasDefault(ArgumentParser const & me,std::string const & name)567 inline bool hasDefault(ArgumentParser const & me, std::string const & name)
568 {
569 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
570 return hasDefault(getOption(me, name));
571 }
572
573 // ----------------------------------------------------------------------------
574 // Function _allRequiredSet()
575 // ----------------------------------------------------------------------------
576
_allRequiredSet(ArgumentParser const & me)577 inline bool _allRequiredSet(ArgumentParser const & me)
578 {
579 for (unsigned o = 0; o < length(me.optionMap); ++o)
580 if (!isSet(me.optionMap[o]) && isRequired(me.optionMap[o]))
581 return false;
582
583 return true;
584 }
585
586 // ----------------------------------------------------------------------------
587 // Function _allArgumentsSet()
588 // ----------------------------------------------------------------------------
589
_allArgumentsSet(ArgumentParser const & me)590 inline bool _allArgumentsSet(ArgumentParser const & me)
591 {
592 for (unsigned a = 0; a < me.argumentList.size(); ++a)
593 if (!isSet(me.argumentList[a]))
594 return false;
595
596 return true;
597 }
598
599 // ----------------------------------------------------------------------------
600 // Function getOptionValue()
601 // ----------------------------------------------------------------------------
602
603 /*!
604 * @fn ArgumentParser#getOptionValue
605 * @headerfile <seqan/arg_parse.h>
606 * @brief Retrieve the value of an option.
607 *
608 * @signature bool getOptionValue(dest, parser, name[, pos]);
609 *
610 * @param[in] dest The variable to write the result to (the type is a template parameter and the value type of the
611 * option must be convertible in the type of <tt>dest</tt> for the retrieval to work, also see
612 * result value).
613 * @param[in] parser The ArgumentParser to get the value from.
614 * @param[in] name The short or long name of the option (<tt>std::string</tt>).
615 * @param[in] pos Optional position for multi-value options (<tt>unsigned</tt>, defaults to 0).
616 *
617 * @return bool <tt>true</tt> if the requested option was given on the command line and could be coverted to the type of
618 * <tt>dest</tt>.
619 */
620
621 template <typename TValue>
getOptionValue(TValue & val,ArgumentParser const & me,std::string const & name,unsigned argNo)622 inline bool getOptionValue(TValue & val,
623 ArgumentParser const & me,
624 std::string const & name,
625 unsigned argNo)
626 {
627 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
628
629 if (isSet(me, name) || hasDefault(me, name))
630 return _convertArgumentValue(val,
631 getOption(me, name),
632 getArgumentValue(getOption(me, name), argNo));
633 else
634 return false;
635 }
636
637 template <typename TValue>
getOptionValue(TValue & val,ArgumentParser const & me,std::string const & name)638 inline bool getOptionValue(TValue & val,
639 ArgumentParser const & me,
640 std::string const & name)
641 {
642 return getOptionValue(val, me, name, 0);
643 }
644
645 // ----------------------------------------------------------------------------
646 // Function getOptionFileExtension()
647 // ----------------------------------------------------------------------------
648
649 /*!
650 * @fn ArgumentParser#getOptionFileExtension
651 * @headerfile <seqan/arg_parse.h>
652 * @brief Retrieve the file extension of a file option.
653 *
654 * @signature std::string getOptionFileExtension(parser, name[, pos]);
655 *
656 * @param[in] parser The ArgumentParser to get the value from.
657 * @param[in] name The short or long name of the option (<tt>std::string</tt>).
658 * @param[in] pos Optional position for multi-value options (<tt>unsigned</tt>, defaults to 0).
659 *
660 * @return std::string The extension of the option. Empty if not set or no extension.
661 *
662 * @see ArgumentParser#getArgumentFileExtension
663 *
664 * @section Overriding File Extension on the Command Line
665 *
666 * For each option with type <tt>INPUT_FILE</tt> and <tt>OUTPUT_FILE</tt>, an option with the name
667 * <tt>${name}-file-ext</tt> is automatically added to the ArgumentParser (where <tt>${name}</tt> is the name
668 * of the original option). The extension can be overridden by specifying the argument. Thus, the user of
669 * the program could give the value "file.ext" to the parameter "fname" and override the extension on the
670 * command line to "ext2" as follows:
671 *
672 * @code{.console}
673 * # program_name --fname file.ext --fname-file-ext ext2
674 * @endcode
675 */
676
677 inline std::string getOptionFileExtension(ArgumentParser const & me,
678 std::string const & name,
679 unsigned argNo = 0)
680 {
681 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
682
683 return getFileExtension(getOption(me, name), argNo);
684 }
685
686 // ----------------------------------------------------------------------------
687 // Function getOptionValueCount()
688 // ----------------------------------------------------------------------------
689
690 /*!
691 * @fn ArgumentParser#getOptionValueCount
692 * @headerfile <seqan/arg_parse.h>
693 * @brief Query number of values stored for the specified option.
694 *
695 * @signature unsigned getOptionValueCount(parser, name);
696 *
697 * @param[in] parser The ArgumentParser to query.
698 * @param[in] name The short or long name of the option (<tt>string</tt>).
699 *
700 * @return unsigned The number of values for the option with the given name.
701 */
702
getOptionValueCount(ArgumentParser const & me,std::string const & name)703 inline unsigned getOptionValueCount(ArgumentParser const & me, std::string const & name)
704 {
705 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
706 return getArgumentValues(getOption(me, name)).size();
707 }
708
709 // ----------------------------------------------------------------------------
710 // Function getArgumentValueCount()
711 // ----------------------------------------------------------------------------
712
713 /*!
714 * @fn ArgumentParser#getArgumentValueCount
715 * @headerfile <seqan/arg_parse.h>
716 * @brief Query number of values stored for the specified argument.
717 *
718 * @signature unsigned getArgumentValueCount(parser, pos);
719 *
720 * @param[in] parser The ArgumentParser to query.
721 * @param[in] name The position of the argument (<tt>unsigned</tt>, 0-based).
722 *
723 * @return unsigned The number of values for the argument with the given position.
724 */
725
getArgumentValueCount(ArgumentParser const & me,unsigned argumentPosition)726 inline unsigned getArgumentValueCount(ArgumentParser const & me, unsigned argumentPosition)
727 {
728 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
729 "Argument Parser has only %d arguments.",
730 me.argumentList.size());
731 return getArgumentValues(getArgument(me, argumentPosition)).size();
732 }
733
734 // ----------------------------------------------------------------------------
735 // Function getArgumentValue()
736 // ----------------------------------------------------------------------------
737
738 /*!
739 * @fn ArgumentParser#getArgumentValue
740 * @headerfile <seqan/arg_parse.h>
741 * @brief Retrieves the value of an argument given by its position.
742 *
743 * @signature bool getArgumentValue(dest, parser, pos[, no]);
744 *
745 * @param[in] dest The variable to write the result to (the type is a template parameter and the value type of the
746 * argument must be convertible in the type of <tt>dest</tt> for the retrieval to work, also see
747 * result value).
748 * @param[in] parser The ArgumentParser to get the value from.
749 * @param[in] pos The position of the argument to get the value of.
750 * @param[in] no Optional position for multi-value arguments (<tt>unsigned</tt>, defaults to 0).
751 *
752 * @return bool <tt>true</tt> if the retrieval was successful, <tt>false</tt> otherwise.
753 */
754
755 template <typename TValue>
getArgumentValue(TValue & value,ArgumentParser const & me,unsigned argumentPosition,unsigned argNo)756 inline bool getArgumentValue(TValue & value,
757 ArgumentParser const & me,
758 unsigned argumentPosition,
759 unsigned argNo)
760 {
761 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
762 "Argument Parser has only %d arguments.",
763 me.argumentList.size());
764 return _convertArgumentValue(value, getArgument(me, argumentPosition), getArgumentValue(getArgument(me, argumentPosition), argNo));
765 }
766
767 template <typename TValue>
getArgumentValue(TValue & value,ArgumentParser const & me,unsigned argumentPosition)768 inline bool getArgumentValue(TValue & value,
769 ArgumentParser const & me,
770 unsigned argumentPosition)
771 {
772 return getArgumentValue(value, me, argumentPosition, 0);
773 }
774
775 // ----------------------------------------------------------------------------
776 // Function getArgumentFileExtension()
777 // ----------------------------------------------------------------------------
778
779 /*!
780 * @fn ArgumentParser#getArgumentFileExtension
781 * @headerfile <seqan/arg_parse.h>
782 * @brief Retrieve the file extension of a file argument.
783 *
784 * @signature std::string argumentFileExtension(parser, pos[, argNo]);
785 *
786 * @param[in] parser The ArgumentParser to get the value from.
787 * @param[in] pos The position of the argument to query (<tt>unsigned</tt>).
788 * @param[in] argNo Optional position for multi-value options (<tt>unsigned</tt>, defaults to 0).
789 *
790 * @return std::string The extension of the argument if any.
791 *
792 * @see ArgumentParser#getOptionFileExtension
793 *
794 * @section Overriding File Extensions on the Command Line
795 *
796 * For each argument with type <tt>INPUT_FILE</tt> and <tt>OUTPUT_FILE</tt>, an option with the index
797 * <tt>arg-${idx}-file-ext</tt> is automatically added to the ArgumentParser (where <tt>${idx}</tt> is the index
798 * of the original option). The extension can be overridden by specifying the argument. Thus, the user of
799 * the program could give the value "file.ext" to the parameter "0" and override the extension on the
800 * command line to "ext2" as follows:
801 *
802 * @code{.console}
803 * # program_name file.ext --arg-0-file-ext ext2
804 * @endcode
805 */
806
807 inline std::string getArgumentFileExtension(ArgumentParser const & me,
808 unsigned argumentPosition,
809 unsigned argNo = 0)
810 {
811 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
812 "Argument Parser has only %d arguments.",
813 me.argumentList.size());
814
815
816 return getFileExtension(getArgument(me, argumentPosition), argNo);
817 }
818
819 // ----------------------------------------------------------------------------
820 // Function getOptionValues()
821 // ----------------------------------------------------------------------------
822
823 /*!
824 * @fn ArgumentParser#getOptionValues
825 * @headerfile <seqan/arg_parse.h>
826 * @brief Returns all values of an option given on the command line.
827 *
828 * @signature TVector getOptionValues(parser, name);
829 *
830 * @param[in] parser The ArgumentParser to query.
831 * @param[in] name The short or long name of the option to get (<tt>std::string</tt>).
832 *
833 * @return TVector The resulting values (<tt>std::vector<std::string></tt>).
834 */
835
getOptionValues(ArgumentParser const & me,std::string const & name)836 inline std::vector<std::string> const & getOptionValues(ArgumentParser const & me,
837 std::string const & name)
838 {
839 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
840 return getArgumentValues(getOption(me, name));
841 }
842
843 // ----------------------------------------------------------------------------
844 // Function getArgumentValues()
845 // ----------------------------------------------------------------------------
846
847 /*!
848 * @fn ArgumentParser#getArgumentValues
849 * @headerfile <seqan/arg_parse.h>
850 * @brief Returns all values of an argument given on the command line.
851 *
852 * @signature TVector getArgumentValues(parser, pos);
853 *
854 * @param[in] parser The ArgumentParser to query.
855 * @param[in] pos The position of the argument (<tt>unsigned</tt>, 0-based).
856 *
857 * @return TVector The resulting values (<tt>std::vector<std::string></tt>).
858 */
859
getArgumentValues(ArgumentParser const & me,unsigned argumentPosition)860 inline std::vector<std::string> const & getArgumentValues(ArgumentParser const & me,
861 unsigned argumentPosition)
862 {
863 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
864 "Argument Parser has only %d arguments.",
865 me.argumentList.size());
866 return getArgumentValues(getArgument(me, argumentPosition));
867 }
868
869 // ----------------------------------------------------------------------------
870 // Function setDefaultValue()
871 // ----------------------------------------------------------------------------
872
873 /*!
874 * @fn ArgumentParser#setDefaultValue
875 * @headerfile <seqan/arg_parse.h>
876 * @brief Set the default value of an option of an ArgumentParser.
877 *
878 * @signature void setDefaultValue(parser, name, v);
879 *
880 * @param[in] parser The ArgumentParser to set the default value to.
881 * @param[in] name The short or long name of the argument (<tt>std::string</tt>).
882 * @param[in] v The value to set (template parameter, must be streamable into a <tt>std::stringstream</tt>).
883 */
884
885 template <typename TValue>
setDefaultValue(ArgumentParser & me,std::string const & name,const TValue & value)886 inline void setDefaultValue(ArgumentParser & me,
887 std::string const & name,
888 const TValue & value)
889 {
890 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
891 setDefaultValue(getOption(me, name), value);
892 }
893
894 // ----------------------------------------------------------------------------
895 // Function addDefaultValue()
896 // ----------------------------------------------------------------------------
897
898 /*!
899 * @fn ArgumentParser#addDefaultValue
900 * @headerfile <seqan/arg_parse.h>
901 * @brief Add/append a value to the default values for an option in an ArgumentParser.
902 *
903 * @signature void addDefaultValue(parser, name, v);
904 *
905 * @param[in,out] parser The ArgumentParser to append the default value to.
906 * @param[in] name The short or long name of the argument (<tt>std::string</tt>).
907 * @param[in] v The value to append (template parameter, must be streamable into a <tt>std::stringstream</tt>).
908 */
909
910 template <typename TValue>
addDefaultValue(ArgumentParser & me,std::string const & name,const TValue & value)911 inline void addDefaultValue(ArgumentParser & me,
912 std::string const & name,
913 const TValue & value)
914 {
915 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
916 addDefaultValue(getOption(me, name), value);
917 }
918
919 // ----------------------------------------------------------------------------
920 // Function setMinValue()
921 // ----------------------------------------------------------------------------
922
923 /*!
924 * @fn ArgumentParser#setMinValue
925 * @headerfile <seqan/arg_parse.h>
926 * @brief Set smallest allowed value for an option or argument of an ArgumentParser.
927 *
928 * @signature void setMinValue(parser, name, v);
929 * @signature void setMinValue(parser, pos, v);
930 *
931 * @param[in,out] parser The ArgumentParser to set the minimal value for.
932 * @param[in] name The name of the option to set the minimal value for (<tt>std::string</tt>).
933 * @param[in] pos The position of the argument to set the minimal value for (<tt>unsigned</tt>, 0-based).
934 * @param[in] v The minimal value to set (<tt>std::string</tt>).
935 *
936 * @section Remarks
937 *
938 * The option/argument must have an integer or double type.
939 */
940
setMinValue(ArgumentParser & me,std::string const & name,std::string const & _minValue)941 inline void setMinValue(ArgumentParser & me,
942 std::string const & name,
943 std::string const & _minValue)
944 {
945 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
946 setMinValue(getOption(me, name), _minValue);
947 }
948
setMinValue(ArgumentParser & me,unsigned argumentPosition,std::string const & _minValue)949 inline void setMinValue(ArgumentParser & me,
950 unsigned argumentPosition,
951 std::string const & _minValue)
952 {
953 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
954 "Argument Parser has only %d arguments.",
955 me.argumentList.size());
956 setMinValue(getArgument(me, argumentPosition), _minValue);
957 }
958
959 // ----------------------------------------------------------------------------
960 // Function setMaxValue()
961 // ----------------------------------------------------------------------------
962
963 /*!
964 * @fn ArgumentParser#setMaxValue
965 * @headerfile <seqan/arg_parse.h>
966 * @brief Set largest allowed value for an option or argument of an ArgumentParser.
967 *
968 * @signature void setMaxValue(parser, name, v);
969 * @signature void setMaxValue(parser, pos, v);
970 *
971 * @param[in,out] parser The ArgumentParser to set the maximal value for.
972 * @param[in] name The name of the option to set the maximal value for (<tt>std::string</tt>).
973 * @param[in] pos The position of the argument to set the maximal value for (<tt>unsigned</tt>, 0-based).
974 * @param[in] v The maximal value to set (<tt>std::string</tt>).
975 *
976 * @section Remarks
977 *
978 * The option/argument must have an integer or double type.
979 */
980
setMaxValue(ArgumentParser & me,std::string const & name,std::string const & _maxValue)981 inline void setMaxValue(ArgumentParser & me,
982 std::string const & name,
983 std::string const & _maxValue)
984 {
985 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
986 setMaxValue(getOption(me, name), _maxValue);
987 }
988
setMaxValue(ArgumentParser & me,unsigned argumentPosition,std::string const & _minValue)989 inline void setMaxValue(ArgumentParser & me,
990 unsigned argumentPosition,
991 std::string const & _minValue)
992 {
993 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
994 "Argument Parser has only %d arguments.",
995 me.argumentList.size());
996 setMaxValue(getArgument(me, argumentPosition), _minValue);
997 }
998
999 // ----------------------------------------------------------------------------
1000 // Function setValidValues()
1001 // ----------------------------------------------------------------------------
1002
1003 /*!
1004 * @fn ArgumentParser#setValidValues
1005 * @headerfile <seqan/arg_parse.h>
1006 * @brief Set valid values for an argumetn or option of an ArgumentParser.
1007 *
1008 * @signature void setValidValues(parser, name, values);
1009 * @signature void setValidValues(parser, pos, values);
1010 *
1011 * @param[in,out] parser The ArgumentParser to set the default values to.
1012 * @param[in] name The name of the option (<tt>std::string</tt>).
1013 * @param[in] pos The position of the argument (<tt>unsigned</tt>, 0-based).
1014 * @param[in] values The values to set. Either a <tt>std::string</tt> with the values as space-separated list
1015 * or a <tt>std::vector<std::string></tt> with the values.
1016 */
1017
setValidValues(ArgumentParser & me,std::string const & name,std::vector<std::string> const & values)1018 inline void setValidValues(ArgumentParser & me,
1019 std::string const & name,
1020 std::vector<std::string> const & values)
1021 {
1022 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
1023 setValidValues(getOption(me, name), values);
1024 _copyValidValuesToFileExt(me, name);
1025 }
1026
setValidValues(ArgumentParser & me,std::string const & name,std::string const & values)1027 inline void setValidValues(ArgumentParser & me,
1028 std::string const & name,
1029 std::string const & values)
1030 {
1031 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
1032 setValidValues(getOption(me, name), values);
1033 _copyValidValuesToFileExt(me, name);
1034 }
1035
setValidValues(ArgumentParser & me,unsigned argumentPosition,std::vector<std::string> const & values)1036 inline void setValidValues(ArgumentParser & me,
1037 unsigned argumentPosition,
1038 std::vector<std::string> const & values)
1039 {
1040 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
1041 "Argument Parser has only %d arguments.",
1042 me.argumentList.size());
1043 setValidValues(getArgument(me, argumentPosition), values);
1044 _copyValidValuesToFileExt(me, argumentPosition);
1045 }
1046
setValidValues(ArgumentParser & me,unsigned argumentPosition,std::string const & values)1047 inline void setValidValues(ArgumentParser & me,
1048 unsigned argumentPosition,
1049 std::string const & values)
1050 {
1051 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
1052 "Argument Parser has only %d arguments.",
1053 me.argumentList.size());
1054 setValidValues(getArgument(me, argumentPosition), values);
1055 _copyValidValuesToFileExt(me, argumentPosition);
1056 }
1057
1058 // ----------------------------------------------------------------------------
1059 // Function setHelpText()
1060 // ----------------------------------------------------------------------------
1061
1062 /*!
1063 * @fn ArgumentParser#setHelpText
1064 * @headerfile <seqan/arg_parse.h>
1065 * @brief Set the help text of an option or argument.
1066 *
1067 * @signature void setHelpText(parser, name, text);
1068 * @signature void setHelpText(parser, pos, text);
1069 *
1070 * @param[in,out] parser The ArgumentParser object.
1071 * @param[in] name The name of the option to set the help text for (<tt>std::string</tt>).
1072 * @param[in] pos The position of the argument to set the help text for.
1073 * @param[in] text The string to use for the help text (<tt>std::string</tt>).
1074 */
1075
setHelpText(ArgumentParser & me,std::string const & name,std::string const & text)1076 inline void setHelpText(ArgumentParser & me,
1077 std::string const & name,
1078 std::string const & text)
1079 {
1080 SEQAN_CHECK(hasOption(me, name), "Unknown option: %s", toCString(name));
1081 setHelpText(getOption(me, name), text);
1082 }
1083
setHelpText(ArgumentParser & me,unsigned argumentPosition,std::string const & text)1084 inline void setHelpText(ArgumentParser & me,
1085 unsigned argumentPosition,
1086 std::string const & text)
1087 {
1088 SEQAN_CHECK(me.argumentList.size() > argumentPosition,
1089 "Argument Parser has only %d arguments.",
1090 me.argumentList.size());
1091 setHelpText(getArgument(me, argumentPosition), text);
1092 }
1093
1094 // ----------------------------------------------------------------------------
1095 // Function getFileExtensions()
1096 // ----------------------------------------------------------------------------
1097
1098 /*!
1099 * @fn ArgumentParser#getFileExtensions
1100 * @headerfile <seqan/arg_parse.h>
1101 * @brief Returns file format extension given a format tag.
1102 *
1103 * @signature TVector getFormatExtension(tag);
1104 * @signature TVector getFormatExtension(tagList);
1105 * @signature TVector getFormatExtension(tagSelector);
1106 *
1107 * @param[in] tag A single file foramt, e.g. <tt>Fastq()</tt>.
1108 * @param[in] tagList A list of file format (@link TagList @endlink).
1109 * @param[in] tagSelector A file format selector (@link TagSelector @endlink).
1110 *
1111 * @return TVector A <tt>std::vector<std::string></tt> with the allowed file format extensions.
1112 */
1113
1114 template <typename T>
1115 inline std::vector<std::string>
getFileExtensions(T const formatTag)1116 getFileExtensions(T const formatTag)
1117 {
1118 std::vector<std::string> extensions;
1119 _getFileExtensions(extensions, formatTag);
1120 return extensions;
1121 }
1122
1123
1124 } // namespace seqan
1125
1126 #endif // SEQAN_INCLUDE_ARG_PARSE_ARGUMENT_PARSER_H_
1127