1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-04-29 20:23:55 +00:00

Add documentation for positionals_at_end documentation clarification on some of the validators (#223)

Add a flag that specifies that positional options can only occur as the last arguments of a command line.  Will generate an ExtrasError if all positional arguments are not captured, regardless of the state of allow_extras.
This commit is contained in:
Philip Top 2019-02-12 00:43:41 -08:00 committed by Henry Schreiner
parent f19b052974
commit 3d7de7d25c
4 changed files with 42 additions and 3 deletions

View File

@ -240,7 +240,7 @@ passed result will contain false or -1 if result is a signed integer type, or 0
alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`; this is equivalent to the previous alternative form of the syntax is more explicit: `"--flag,--no-flag{false}"`; this is equivalent to the previous
example. This also works for short form options `"-f,!-n"` or `"-f,-n{false}"` If `int_or_bool` is a boolean value the example. This also works for short form options `"-f,!-n"` or `"-f,-n{false}"` If `int_or_bool` is a boolean value the
default behavior is to take the last value given, while if `int_or_bool` is an integer type the behavior will be to sum default behavior is to take the last value given, while if `int_or_bool` is an integer type the behavior will be to sum
all the given arguments and return the result. This can be modifed if needed by changing the `multi_option_policy` on all the given arguments and return the result. This can be modified if needed by changing the `multi_option_policy` on
each flag (this is not inherited). each flag (this is not inherited).
On a C++14 compiler, you can pass a callback function directly to `.add_flag`, while in C++11 mode you'll need to use `.add_flag_function` if you want a callback function. The function will be given the number of times the flag was passed. You can throw a relevant `CLI::ParseError` to signal a failure. On a C++14 compiler, you can pass a callback function directly to `.add_flag`, while in C++11 mode you'll need to use `.add_flag_function` if you want a callback function. The function will be given the number of times the flag was passed. You can throw a relevant `CLI::ParseError` to signal a failure.
@ -276,6 +276,8 @@ Before parsing, you can set the following options:
- `->check(CLI::ExistingPath)`: Requires that the path (file or directory) exists. - `->check(CLI::ExistingPath)`: Requires that the path (file or directory) exists.
- `->check(CLI::NonexistentPath)`: Requires that the path does not exist. - `->check(CLI::NonexistentPath)`: Requires that the path does not exist.
- `->check(CLI::Range(min,max))`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0. - `->check(CLI::Range(min,max))`: Requires that the option be between min and max (make sure to use floating point if needed). Min defaults to 0.
- `->check(CLI::PositiveNumber)`: Requires the number be greater or equal to 0
- `->check(CLI::ValidIPV4)`: Requires that the option be a valid IPv4 string e.g. `'255.255.255.255'`, `'10.1.1.7'`
- `->transform(std::string(std::string))`: Converts the input string into the output string, in-place in the parsed options. - `->transform(std::string(std::string))`: Converts the input string into the output string, in-place in the parsed options.
- `->each(void(std::string)>`: Run this function on each value received, as it is received. - `->each(void(std::string)>`: Run this function on each value received, as it is received.
- `->configurable(false)`: Disable this option from being in a configuration file. - `->configurable(false)`: Disable this option from being in a configuration file.
@ -357,6 +359,7 @@ There are several options that are supported on the main app and subcommands. Th
- `.name(name)`: Add or change the name. - `.name(name)`: Add or change the name.
- `.callback(void() function)`: Set the callback that runs at the end of parsing. The options have already run at this point. - `.callback(void() function)`: Set the callback that runs at the end of parsing. The options have already run at this point.
- `.allow_extras()`: Do not throw an error if extra arguments are left over. - `.allow_extras()`: Do not throw an error if extra arguments are left over.
- `.positionals_at_end()`: Specify that positional arguments occur as the last arguments and throw an error if an unexpected positional is encountered.
- `.prefix_command()`: Like `allow_extras`, but stop immediately on the first unrecognized item. It is ideal for allowing your app or subcommand to be a "prefix" to calling another app. - `.prefix_command()`: Like `allow_extras`, but stop immediately on the first unrecognized item. It is ideal for allowing your app or subcommand to be a "prefix" to calling another app.
- `.footer(message)`: Set text to appear at the bottom of the help string. - `.footer(message)`: Set text to appear at the bottom of the help string.
- `.set_help_flag(name, message)`: Set the help flag name and message, returns a pointer to the created option. - `.set_help_flag(name, message)`: Set the help flag name and message, returns a pointer to the created option.

View File

@ -156,6 +156,8 @@ class App {
false false
#endif #endif
}; };
/// specify that positional arguments come at the end of the argument sequence not inheritable
bool positionals_at_end_{false};
/// A pointer to the parent if this is a subcommand /// A pointer to the parent if this is a subcommand
App *parent_{nullptr}; App *parent_{nullptr};
@ -289,6 +291,12 @@ class App {
return this; return this;
} }
/// specify that the positional arguments are only at the end of the sequence
App *positionals_at_end(bool value = true) {
positionals_at_end_ = value;
return this;
}
/// Ignore underscore. Subcommands inherit value. /// Ignore underscore. Subcommands inherit value.
App *ignore_underscore(bool value = true) { App *ignore_underscore(bool value = true) {
ignore_underscore_ = value; ignore_underscore_ = value;
@ -1575,6 +1583,9 @@ class App {
/// Check the status of the allow windows style options /// Check the status of the allow windows style options
bool get_allow_windows_style_options() const { return allow_windows_style_options_; } bool get_allow_windows_style_options() const { return allow_windows_style_options_; }
/// Check the status of the allow windows style options
bool get_positionals_at_end() const { return positionals_at_end_; }
/// Get the group of this subcommand /// Get the group of this subcommand
const std::string &get_group() const { return group_; } const std::string &get_group() const { return group_; }
@ -2018,6 +2029,9 @@ class App {
case detail::Classifier::NONE: case detail::Classifier::NONE:
// Probably a positional or something for a parent (sub)command // Probably a positional or something for a parent (sub)command
_parse_positional(args); _parse_positional(args);
if(positionals_at_end_) {
positional_only = true;
}
} }
} }
@ -2063,6 +2077,9 @@ class App {
if(parent_ != nullptr && fallthrough_) if(parent_ != nullptr && fallthrough_)
return parent_->_parse_positional(args); return parent_->_parse_positional(args);
else { else {
if(positionals_at_end_) {
throw CLI::ExtrasError(args);
}
args.pop_back(); args.pop_back();
missing_.emplace_back(detail::Classifier::NONE, positional); missing_.emplace_back(detail::Classifier::NONE, positional);

View File

@ -176,7 +176,7 @@ struct IPV4Validator : public Validator {
} }
}; };
/// Validate the argument is a number and equal greater then 0 /// Validate the argument is a number and greater than or equal to 0
struct PositiveNumber : public Validator { struct PositiveNumber : public Validator {
PositiveNumber() { PositiveNumber() {
tname = "POSITIVE"; tname = "POSITIVE";
@ -186,7 +186,7 @@ struct PositiveNumber : public Validator {
return "Failed parsing number " + number_str; return "Failed parsing number " + number_str;
} }
if(number < 0) { if(number < 0) {
return "number less then 0 " + number_str; return "Number less then 0 " + number_str;
} }
return std::string(); return std::string();
}; };

View File

@ -828,6 +828,25 @@ TEST_F(TApp, PositionalNoSpace) {
EXPECT_EQ(options.at(0), "Test"); EXPECT_EQ(options.at(0), "Test");
} }
// Tests positionals at end
TEST_F(TApp, PositionalAtEnd) {
std::string options;
std::string foo;
app.add_option("-O", options);
app.add_option("foo", foo);
app.positionals_at_end();
EXPECT_TRUE(app.get_positionals_at_end());
args = {"-O", "Test", "param1"};
run();
EXPECT_EQ(options, "Test");
EXPECT_EQ(foo, "param1");
args = {"param2", "-O", "Test"};
EXPECT_THROW(run(), CLI::ExtrasError);
}
TEST_F(TApp, PositionalNoSpaceLong) { TEST_F(TApp, PositionalNoSpaceLong) {
std::vector<std::string> options; std::vector<std::string> options;
std::string foo, bar; std::string foo, bar;