Skip to content

Commit

Permalink
Merge pull request #1652 from smehringer/argument_parser_misc
Browse files Browse the repository at this point in the history
[FEATURE] Adding information only to the advanced help pages is now possible.
  • Loading branch information
smehringer authored Mar 25, 2020
2 parents 7a360e2 + 3ca197e commit d374879
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 118 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ Note that 3.1.0 will be the first API stable release and interfaces in this rele

## New features

#### Argument Parser

* The following functions accept a `seqan3::argument_parser::option_spec::ADVANCED` to control what is
displayed on the (advanced) help page:
* `seqan3::argument_parser::add_section`
* `seqan3::argument_parser::add_subsection`
* `seqan3::argument_parser::add_line`
* `seqan3::argument_parser::add_list_item`
Note that other `seqan3::argument_parser::option_spec`s like `REQUIRED` are ignored.

#### I/O

* The `seqan3::format_fasta` accepts the file extenstion `.fas` as a valid extension for the FASTA format
Expand Down
31 changes: 19 additions & 12 deletions include/seqan3/argument_parser/argument_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class argument_parser
char const short_id,
std::string const & long_id,
std::string const & desc,
option_spec const & spec = option_spec::DEFAULT,
option_spec const spec = option_spec::DEFAULT,
validator_type validator = validator_type{}) // copy to bind rvalues
{
if (sub_parser != nullptr)
Expand All @@ -262,7 +262,7 @@ class argument_parser
char const short_id,
std::string const & long_id,
std::string const & desc,
option_spec const & spec = option_spec::DEFAULT)
option_spec const spec = option_spec::DEFAULT)
{
verify_identifiers(short_id, long_id);
// copy variables into the lambda because the calls are pushed to a stack
Expand Down Expand Up @@ -420,38 +420,45 @@ class argument_parser

/*!\brief Adds an help page section to the seqan3::argument_parser.
* \param[in] title The title of the section.
* \param[in] spec Whether to always display this section title (seqan3::option_spec::DEFAULT), only when showing
* the advanced help page (seqan3::option_spec::ADVANCED) or never (seqan3::option_spec::HIDDEN).
* \details This only affects the help page and other output formats.
*/
void add_section(std::string const & title)
void add_section(std::string const & title, option_spec const spec = option_spec::DEFAULT)
{
std::visit([&] (auto & f) { f.add_section(title); }, format);
std::visit([&] (auto & f) { f.add_section(title, spec); }, format);
}

/*!\brief Adds an help page subsection to the seqan3::argument_parser.
* \param[in] title The title of the subsection.
* \param[in] spec Whether to always display this subsection title (seqan3::option_spec::DEFAULT), only when showing
* the advanced help page (seqan3::option_spec::ADVANCED) or never (seqan3::option_spec::HIDDEN).
* \details This only affects the help page and other output formats.
*/
void add_subsection(std::string const & title)
void add_subsection(std::string const & title, option_spec const spec = option_spec::DEFAULT)
{
std::visit([&] (auto & f) { f.add_subsection(title); }, format);
std::visit([&] (auto & f) { f.add_subsection(title, spec); }, format);
}

/*!\brief Adds an help page text line to the seqan3::argument_parser.
* \param[in] text The text to print.
* \param[in] line_is_paragraph Whether to insert as paragraph
* or just a line (Default: false).
* \param[in] is_paragraph Whether to insert as paragraph or just a line (Default: false).
* \param[in] spec Whether to always display this line (seqan3::option_spec::DEFAULT), only when showing
* the advanced help page (seqan3::option_spec::ADVANCED) or never (seqan3::option_spec::HIDDEN).
* \details
* If the line is not a paragraph (false), only one line break is appended, otherwise two line breaks are appended.
* This only affects the help page and other output formats.
*/
void add_line(std::string const & text, bool line_is_paragraph = false)
void add_line(std::string const & text, bool is_paragraph = false, option_spec const spec = option_spec::DEFAULT)
{
std::visit([&] (auto & f) { f.add_line(text, line_is_paragraph); }, format);
std::visit([&] (auto & f) { f.add_line(text, is_paragraph, spec); }, format);
}

/*!\brief Adds an help page list item (key-value) to the seqan3::argument_parser.
* \param[in] key The key of the key-value pair of the list item.
* \param[in] desc The value of the key-value pair of the list item.
* \param[in] spec Whether to always display this list item (seqan3::option_spec::DEFAULT), only when showing
* the advanced help page (seqan3::option_spec::ADVANCED) or never (seqan3::option_spec::HIDDEN).
*
* \details
*
Expand All @@ -465,9 +472,9 @@ class argument_parser
* Super important integer for age.
*```
*/
void add_list_item(std::string const & key, std::string const & desc)
void add_list_item(std::string const & key, std::string const & desc, option_spec const spec = option_spec::DEFAULT)
{
std::visit([&] (auto & f) { f.add_list_item(key, desc); }, format);
std::visit([&] (auto & f) { f.add_list_item(key, desc, spec); }, format);
}
//!\}

Expand Down
111 changes: 42 additions & 69 deletions include/seqan3/argument_parser/detail/format_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,68 +223,38 @@ class format_help_base : public format_base

public:
/*!\brief Adds a seqan3::print_list_item call to be evaluated later on.
*
* \tparam option_type The type of variable in which to store the given command line argument.
* \tparam validator_type The type of validator applied to the value after parsing.
*
* \param[out] value The variable in which to store the given command line argument.
* \param[in] short_id The short identifier for the option (e.g. 'i').
* \param[in] long_id The long identifier for the option (e.g. "integer").
* \param[in] desc The description of the option.
* \param[in] spec Advanced option specification, see seqan3::option_spec.
* \param[in] validator The validator applied to the value after parsing (callable).
* \copydetails seqan3::argument_parser::add_option
*/
template <typename option_type, typename validator_type>
void add_option(option_type & value,
char const short_id,
std::string const & long_id,
std::string const & desc,
option_spec const & spec,
option_spec const spec,
validator_type && validator)
{
std::string msg = validator.get_help_page_message();

parser_set_up_calls.push_back([this, &value, short_id, long_id, desc, spec, msg] ()
{
if (!(spec & option_spec::HIDDEN) && (!(spec & option_spec::ADVANCED) || show_advanced_options))
derived_t().print_list_item(prep_id_for_help(short_id, long_id) +
" " + option_type_and_list_info(value),
desc +
((spec & option_spec::REQUIRED)
? std::string{" "}
: detail::to_string(" Default: ", value, ". ")) +
msg);
});
std::string id = prep_id_for_help(short_id, long_id) + " " + option_type_and_list_info(value);
std::string info{desc};
info += ((spec & option_spec::REQUIRED) ? std::string{" "} : detail::to_string(" Default: ", value, ". "));
info += validator.get_help_page_message();
store_help_page_element([this, id, info] () { derived_t().print_list_item(id, info); }, spec);
}

/*!\brief Adds a seqan3::print_list_item call to be evaluated later on.
*
* \param[in] short_id The short identifier for the flag (e.g. 'i').
* \param[in] long_id The long identifier for the flag (e.g. "integer").
* \param[in] desc The description of the flag.
* \param[in] spec Advanced flag specification, see seqan3::option_spec.
* \copydetails seqan3::argument_parser::add_flag
*/
void add_flag(bool & /*value*/,
void add_flag(bool & SEQAN3_DOXYGEN_ONLY(value),
char const short_id,
std::string const & long_id,
std::string const & desc,
option_spec const & spec)
option_spec const spec)
{
parser_set_up_calls.push_back([this, short_id, long_id, desc, spec] ()
{
if (!(spec & option_spec::HIDDEN) && (!(spec & option_spec::ADVANCED) || show_advanced_options))
derived_t().print_list_item(prep_id_for_help(short_id, long_id), desc);
});
std::string id = prep_id_for_help(short_id, long_id);
store_help_page_element([this, id, desc] () { derived_t().print_list_item(id, desc); }, spec);
}

/*!\brief Adds a seqan3::print_list_item call to be evaluated later on.
*
* \tparam option_type The type of variable in which to store the given command line argument.
* \tparam validator_type The type of validator applied to the value after parsing.
*
* \param[out] value The variable in which to store the given command line argument.
* \param[in] desc The description of the positional option.
* \param[in] validator The validator applied to the value after parsing (callable).
* \copydetails seqan3::argument_parser::add_positional_option
*/
template <typename option_type, typename validator_type>
void add_positional_option(option_type & value,
Expand Down Expand Up @@ -371,49 +341,35 @@ class format_help_base : public format_base
}

/*!\brief Adds a print_section call to parser_set_up_calls.
* \param[in] title The title of the section of the help page.
* \copydetails seqan3::argument_parser::add_section
*/
void add_section(std::string const & title)
void add_section(std::string const & title, option_spec const spec)
{
parser_set_up_calls.push_back([this, title] ()
{
derived_t().print_section(title);
});
store_help_page_element([this, title] () { derived_t().print_section(title); }, spec);
}

/*!\brief Adds a print_subsection call to parser_set_up_calls.
* \param[in] title The title of the subsection of the help page.
* \copydetails seqan3::argument_parser::add_subsection
*/
void add_subsection(std::string const & title)
void add_subsection(std::string const & title, option_spec const spec)
{
parser_set_up_calls.push_back([this, title] ()
{
derived_t().print_subsection(title);
});
store_help_page_element([this, title] () { derived_t().print_subsection(title); }, spec);
}

/*!\brief Adds a print_line call to parser_set_up_calls.
* \param[in] text The line text to be printed to the help page.
* \param[in] line_is_paragraph True if you want a new line at the end.
* \copydetails seqan3::argument_parser::add_line
*/
void add_line(std::string const & text, bool line_is_paragraph)
void add_line(std::string const & text, bool is_paragraph, option_spec const spec)
{
parser_set_up_calls.push_back([this, text, line_is_paragraph] ()
{
derived_t().print_line(text, line_is_paragraph);
});
store_help_page_element([this, text, is_paragraph] () { derived_t().print_line(text, is_paragraph); }, spec);
}

/*!\brief Adds a seqan3::print_list_item call to parser_set_up_calls.
* \param[in] key The key of the key-value pair list item.
* \param[in] desc The key of the key-value pair list item.
* \copydetails seqan3::argument_parser::add_list_item
*/
void add_list_item(std::string const & key, std::string const & desc)
void add_list_item(std::string const & key, std::string const & desc, option_spec const spec)
{
parser_set_up_calls.push_back([this, key, desc] ()
{
derived_t().print_list_item(key, desc);
});
store_help_page_element([this, key, desc] () { derived_t().print_list_item(key, desc); }, spec);
}

/*!\brief Stores all meta information about the application
Expand Down Expand Up @@ -473,6 +429,23 @@ class format_help_base : public format_base
std::vector<std::string> command_names{};
//!\brief Whether to show advanced options or not.
bool show_advanced_options{true};

private:
/*!\brief Adds a function object to parser_set_up_calls **if** the annotation in `spec` does not prevent it.
* \param[in] printer The invokable that, if added to `parser_set_up_calls`, prints information to the help page.
* \param[in] spec The option specification deciding whether to add the information to the help page.
*
* \details
*
* If `spec` equals `seqan3::option_spec::HIDDEN`, the information is never added to the help page.
* If `spec` equals `seqan3::option_spec::ADVANCED`, the information is only added to the help page if
* the advanced help page has been queried on the command line (`show_advanced_options == true`).
*/
void store_help_page_element(std::function<void()> printer, option_spec const spec)
{
if (!(spec & option_spec::HIDDEN) && (!(spec & option_spec::ADVANCED) || show_advanced_options))
parser_set_up_calls.push_back(std::move(printer));
}
};

} // namespace seqan3::detail
48 changes: 13 additions & 35 deletions include/seqan3/argument_parser/detail/format_parse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,24 +71,14 @@ class format_parse : public format_base
//!\}

/*!\brief Adds an seqan3::detail::get_option call to be evaluated later on.
*
* \tparam option_type The type of variable in which to store the given command line argument.
* \tparam validator_type The type of validator applied to the value after parsing.
*
* \param[out] value The variable in which to store the given command line argument.
* \param[in] short_id The short identifier for the option (e.g. 'i').
* \param[in] long_id The long identifier for the option (e.g. "integer").
* \param[in] spec Advanced option specification, see seqan3::option_spec.
* \param[in] validator The validator applied to the value after parsing (callable).
*
* \throws seqan3::design_error
* \copydetails seqan3::argument_parser::add_option
*/
template <typename option_type, typename validator_type>
void add_option(option_type & value,
char const short_id,
std::string const & long_id,
std::string const & /*desc*/,
option_spec const & spec,
std::string const & SEQAN3_DOXYGEN_ONLY(desc),
option_spec const spec,
validator_type && validator)
{
option_calls.push_back([this, &value, short_id, long_id, spec, validator]()
Expand All @@ -98,18 +88,13 @@ class format_parse : public format_base
}

/*!\brief Adds a get_flag call to be evaluated later on.
*
* \param[out] value The variable in which to store the given command line argument.
* \param[in] short_id The short identifier for the flag (e.g. 'i').
* \param[in] long_id The long identifier for the flag (e.g. "integer").
*
* \throws seqan3::design_error
* \copydetails seqan3::argument_parser::add_flag
*/
void add_flag(bool & value,
char const short_id,
std::string const & long_id,
std::string const & /*desc*/,
option_spec const & /*spec*/)
std::string const & SEQAN3_DOXYGEN_ONLY(desc),
option_spec const & SEQAN3_DOXYGEN_ONLY(spec))
{
flag_calls.push_back([this, &value, short_id, long_id]()
{
Expand All @@ -118,18 +103,11 @@ class format_parse : public format_base
}

/*!\brief Adds a get_positional_option call to be evaluated later on.
*
* \tparam option_type The type of variable in which to store the given command line argument.
* \tparam validator_type The type of validator applied to the value after parsing.
*
* \param[out] value The variable in which to store the given command line argument.
* \param[in] validator The validator applied to the value after parsing (callable).
*
* \throws seqan3::design_error
* \copydetails seqan3::argument_parser::add_positional_option
*/
template <typename option_type, typename validator_type>
void add_positional_option(option_type & value,
std::string const & /*desc*/,
std::string const & SEQAN3_DOXYGEN_ONLY(desc),
validator_type && validator)
{
positional_option_calls.push_back([this, &value, validator]()
Expand Down Expand Up @@ -164,10 +142,10 @@ class format_parse : public format_base

// functions are not needed for command line parsing but are part of the format interface.
//!\cond
void add_section(std::string const &) {}
void add_subsection(std::string const &) {}
void add_line(std::string const &, bool) {}
void add_list_item(std::string const &, std::string const &) {}
void add_section(std::string const &, option_spec const) {}
void add_subsection(std::string const &, option_spec const) {}
void add_line(std::string const &, bool, option_spec const) {}
void add_list_item(std::string const &, std::string const &, option_spec const) {}
//!\endcond

//!\brief Checks whether `id` is empty.
Expand Down Expand Up @@ -655,7 +633,7 @@ class format_parse : public format_base
void get_option(option_type & value,
char const short_id,
std::string const & long_id,
option_spec const & spec,
option_spec const spec,
validator_type && validator)
{
bool short_id_is_set{get_option_by_id(value, short_id)};
Expand Down
Loading

0 comments on commit d374879

Please sign in to comment.