mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-05-09 16:13:54 +00:00
Customize text between option name and description (#497)
* Added an option to change the text between definition and description * Added test and readme * Update Option.hpp Fixed shadowing issue * style: fix formatting Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
This commit is contained in:
parent
b21f2e1bbe
commit
11141525ac
@ -351,6 +351,7 @@ Before parsing, you can set the following options:
|
|||||||
- `->always_capture_default()`: Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.
|
- `->always_capture_default()`: Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.
|
||||||
- `default_str(string)`: Set the default string directly. This string will also be used as a default value if no arguments are passed and the value is requested.
|
- `default_str(string)`: Set the default string directly. This string will also be used as a default value if no arguments are passed and the value is requested.
|
||||||
- `default_val(value)`: 🆕 Generate the default string from a value and validate that the value is also valid. For options that assign directly to a value type the value in that type is also updated. Value must be convertible to a string(one of known types or have a stream operator).
|
- `default_val(value)`: 🆕 Generate the default string from a value and validate that the value is also valid. For options that assign directly to a value type the value in that type is also updated. Value must be convertible to a string(one of known types or have a stream operator).
|
||||||
|
- `->option_text(string)`: Sets the text between the option name and description.
|
||||||
|
|
||||||
|
|
||||||
These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. The `each` function takes any function that has the signature `void(const std::string&)`; it should throw a `ValidationError` when validation fails. The help message will have the name of the parent option prepended. Since `each`, `check` and `transform` use the same underlying mechanism, you can chain as many as you want, and they will be executed in order. Operations added through `transform` are executed first in reverse order of addition, and `check` and `each` are run following the transform functions in order of addition. If you just want to see the unconverted values, use `.results()` to get the `std::vector<std::string>` of results.
|
These options return the `Option` pointer, so you can chain them together, and even skip storing the pointer entirely. The `each` function takes any function that has the signature `void(const std::string&)`; it should throw a `ValidationError` when validation fails. The help message will have the name of the parent option prepended. Since `each`, `check` and `transform` use the same underlying mechanism, you can chain as many as you want, and they will be executed in order. Operations added through `transform` are executed first in reverse order of addition, and `check` and `each` are run following the transform functions in order of addition. If you just want to see the unconverted values, use `.results()` to get the `std::vector<std::string>` of results.
|
||||||
|
@ -236,30 +236,34 @@ inline std::string Formatter::make_option_name(const Option *opt, bool is_positi
|
|||||||
inline std::string Formatter::make_option_opts(const Option *opt) const {
|
inline std::string Formatter::make_option_opts(const Option *opt) const {
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
|
|
||||||
if(opt->get_type_size() != 0) {
|
if(!opt->get_option_text().empty()) {
|
||||||
if(!opt->get_type_name().empty())
|
out << " " << opt->get_option_text();
|
||||||
out << " " << get_label(opt->get_type_name());
|
} else {
|
||||||
if(!opt->get_default_str().empty())
|
if(opt->get_type_size() != 0) {
|
||||||
out << "=" << opt->get_default_str();
|
if(!opt->get_type_name().empty())
|
||||||
if(opt->get_expected_max() == detail::expected_max_vector_size)
|
out << " " << get_label(opt->get_type_name());
|
||||||
out << " ...";
|
if(!opt->get_default_str().empty())
|
||||||
else if(opt->get_expected_min() > 1)
|
out << "=" << opt->get_default_str();
|
||||||
out << " x " << opt->get_expected();
|
if(opt->get_expected_max() == detail::expected_max_vector_size)
|
||||||
|
out << " ...";
|
||||||
|
else if(opt->get_expected_min() > 1)
|
||||||
|
out << " x " << opt->get_expected();
|
||||||
|
|
||||||
if(opt->get_required())
|
if(opt->get_required())
|
||||||
out << " " << get_label("REQUIRED");
|
out << " " << get_label("REQUIRED");
|
||||||
}
|
}
|
||||||
if(!opt->get_envname().empty())
|
if(!opt->get_envname().empty())
|
||||||
out << " (" << get_label("Env") << ":" << opt->get_envname() << ")";
|
out << " (" << get_label("Env") << ":" << opt->get_envname() << ")";
|
||||||
if(!opt->get_needs().empty()) {
|
if(!opt->get_needs().empty()) {
|
||||||
out << " " << get_label("Needs") << ":";
|
out << " " << get_label("Needs") << ":";
|
||||||
for(const Option *op : opt->get_needs())
|
for(const Option *op : opt->get_needs())
|
||||||
out << " " << op->get_name();
|
out << " " << op->get_name();
|
||||||
}
|
}
|
||||||
if(!opt->get_excludes().empty()) {
|
if(!opt->get_excludes().empty()) {
|
||||||
out << " " << get_label("Excludes") << ":";
|
out << " " << get_label("Excludes") << ":";
|
||||||
for(const Option *op : opt->get_excludes())
|
for(const Option *op : opt->get_excludes())
|
||||||
out << " " << op->get_name();
|
out << " " << op->get_name();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
@ -264,6 +264,9 @@ class Option : public OptionBase<Option> {
|
|||||||
/// A human readable default value, either manually set, captured, or captured by default
|
/// A human readable default value, either manually set, captured, or captured by default
|
||||||
std::string default_str_{};
|
std::string default_str_{};
|
||||||
|
|
||||||
|
/// If given, replace the text that describes the option type and usage in the help text
|
||||||
|
std::string option_text_{};
|
||||||
|
|
||||||
/// A human readable type value, set when App creates this
|
/// A human readable type value, set when App creates this
|
||||||
///
|
///
|
||||||
/// This is a lambda function so "types" can be dynamic, such as when a set prints its contents.
|
/// This is a lambda function so "types" can be dynamic, such as when a set prints its contents.
|
||||||
@ -736,6 +739,13 @@ class Option : public OptionBase<Option> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Option *option_text(std::string text) {
|
||||||
|
option_text_ = std::move(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &get_option_text() const { return option_text_; }
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
/// @name Help tools
|
/// @name Help tools
|
||||||
///@{
|
///@{
|
||||||
|
@ -89,6 +89,25 @@ TEST(Formatter, OptCustomizeSimple) {
|
|||||||
" --opt INT (MUST HAVE) Something\n\n");
|
" --opt INT (MUST HAVE) Something\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Formatter, OptCustomizeOptionText) {
|
||||||
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
|
app.get_formatter()->column_width(25);
|
||||||
|
|
||||||
|
int v{0};
|
||||||
|
app.add_option("--opt", v, "Something")->option_text("(ARG)");
|
||||||
|
|
||||||
|
std::string help = app.help();
|
||||||
|
|
||||||
|
EXPECT_THAT(help, HasSubstr("(ARG)"));
|
||||||
|
EXPECT_EQ(help,
|
||||||
|
"My prog\n"
|
||||||
|
"Usage: [OPTIONS]\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -h,--help Print this help message and exit\n"
|
||||||
|
" --opt (ARG) Something\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Formatter, FalseFlagExample) {
|
TEST(Formatter, FalseFlagExample) {
|
||||||
CLI::App app{"My prog"};
|
CLI::App app{"My prog"};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user