1
0
mirror of https://github.com/CLIUtils/CLI11.git synced 2025-05-03 14:03:52 +00:00

Adding a few tools to make manual validation easier

This commit is contained in:
Henry Fredrick Schreiner 2018-05-04 11:52:41 +02:00 committed by Henry Schreiner
parent f7d51f6a76
commit 88521b58f8
4 changed files with 33 additions and 11 deletions

View File

@ -26,6 +26,7 @@ Validators are now much more powerful [#118], all built in validators upgraded t
Other changes: Other changes:
* Better support for manual options with `get_option`, `set_results`, and `empty` [#119]
* Using `add_set` will now capture L-values for sets, allowing further modification [#113] * Using `add_set` will now capture L-values for sets, allowing further modification [#113]
* Internally, `type_name` is now a lambda function; for sets, this reads the set live [#116] * Internally, `type_name` is now a lambda function; for sets, this reads the set live [#116]
* Dropped duplicate way to run `get_type_name` (`get_typeval`) * Dropped duplicate way to run `get_type_name` (`get_typeval`)
@ -40,6 +41,7 @@ Other changes:
[#113]: https://github.com/CLIUtils/CLI11/issues/113 [#113]: https://github.com/CLIUtils/CLI11/issues/113
[#116]: https://github.com/CLIUtils/CLI11/pull/116 [#116]: https://github.com/CLIUtils/CLI11/pull/116
[#118]: https://github.com/CLIUtils/CLI11/pull/118 [#118]: https://github.com/CLIUtils/CLI11/pull/118
[#118]: https://github.com/CLIUtils/CLI11/pull/119
### Version 1.5.3: Compiler compatibility ### Version 1.5.3: Compiler compatibility
This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported. This version fixes older AppleClang compilers by removing the optimization for casting. The minimum version of Boost Optional supported has been clarified to be 1.58. CUDA 7.0 NVCC is now supported.

View File

@ -243,9 +243,10 @@ There are several options that are supported on the main app and subcommands. Th
* `.require_subcommand(min, max)`: Explicitly set min and max allowed subcommands. Setting `max` to 0 is unlimited. * `.require_subcommand(min, max)`: Explicitly set min and max allowed subcommands. Setting `max` to 0 is unlimited.
* `.add_subcommand(name, description="")` Add a subcommand, returns a pointer to the internally stored subcommand. * `.add_subcommand(name, description="")` Add a subcommand, returns a pointer to the internally stored subcommand.
* `.got_subcommand(App_or_name)`: Check to see if a subcommand was received on the command line. * `.got_subcommand(App_or_name)`: Check to see if a subcommand was received on the command line.
* `.get_subcommands()`: The list of subcommands given on the command line. * `.get_subcommands(filter)`: The list of subcommands given on the command line.
* `.get_parent()`: Get the parent App or nullptr if called on master App. * `.get_parent()`: Get the parent App or nullptr if called on master App.
* `.get_options()`: Get the list of all defined option pointers (useful for processing the app for custom output formats). * `.get_option(name)`: Get an option pointer by option name
* `.get_options(filter)`: Get the list of all defined option pointers (useful for processing the app for custom output formats).
* `.parse_order()`: Get the list of option pointers in the order they were parsed (including duplicates). * `.parse_order()`: Get the list of option pointers in the order they were parsed (including duplicates).
* `.formatter(fmt)`: Set a formatter, with signature `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more details. * `.formatter(fmt)`: Set a formatter, with signature `std::string(const App*, std::string, AppFormatMode)`. See Formatting for more details.
* `.get_description()`: Access the description. * `.get_description()`: Access the description.
@ -260,7 +261,7 @@ There are several options that are supported on the main app and subcommands. Th
* `.set_failure_message(func)`: Set the failure message function. Two provided: `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default). * `.set_failure_message(func)`: Set the failure message function. Two provided: `CLI::FailureMessage::help` and `CLI::FailureMessage::simple` (the default).
* `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""` will be hide the subcommand. * `.group(name)`: Set a group name, defaults to `"Subcommands"`. Setting `""` will be hide the subcommand.
> Note: if you have a fixed number of required positional options, that will match before subcommand names. > Note: if you have a fixed number of required positional options, that will match before subcommand names. `{}` is an empty filter function.
## Configuration file ## Configuration file

View File

@ -7,6 +7,7 @@
#include <deque> #include <deque>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <iterator>
#include <memory> #include <memory>
#include <numeric> #include <numeric>
#include <set> #include <set>
@ -14,17 +15,16 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <iterator>
// CLI Library includes // CLI Library includes
#include "CLI/Error.hpp" #include "CLI/Error.hpp"
#include "CLI/FormatterFwd.hpp"
#include "CLI/Ini.hpp" #include "CLI/Ini.hpp"
#include "CLI/Macros.hpp" #include "CLI/Macros.hpp"
#include "CLI/Option.hpp" #include "CLI/Option.hpp"
#include "CLI/Split.hpp" #include "CLI/Split.hpp"
#include "CLI/StringTools.hpp" #include "CLI/StringTools.hpp"
#include "CLI/TypeTools.hpp" #include "CLI/TypeTools.hpp"
#include "CLI/FormatterFwd.hpp"
namespace CLI { namespace CLI {
@ -1096,6 +1096,16 @@ class App {
return options; return options;
} }
/// Get an option by name
const Option *get_option(std::string name) const {
for(const Option_p &opt : options_) {
if(opt->check_name(name)) {
return opt.get();
}
}
throw OptionNotFound(name);
}
/// Check the status of ignore_case /// Check the status of ignore_case
bool get_ignore_case() const { return ignore_case_; } bool get_ignore_case() const { return ignore_case_; }
@ -1404,28 +1414,28 @@ class App {
if(!op->get_configurable()) if(!op->get_configurable())
throw INIError::NotConfigurable(current.fullname); throw INIError::NotConfigurable(current.fullname);
if(op->results_.empty()) { if(op->empty()) {
// Flag parsing // Flag parsing
if(op->get_type_size() == 0) { if(op->get_type_size() == 0) {
if(current.inputs.size() == 1) { if(current.inputs.size() == 1) {
std::string val = current.inputs.at(0); std::string val = current.inputs.at(0);
val = detail::to_lower(val); val = detail::to_lower(val);
if(val == "true" || val == "on" || val == "yes") if(val == "true" || val == "on" || val == "yes")
op->results_ = {""}; op->set_results({""});
else if(val == "false" || val == "off" || val == "no") else if(val == "false" || val == "off" || val == "no")
; ;
else else
try { try {
size_t ui = std::stoul(val); size_t ui = std::stoul(val);
for(size_t i = 0; i < ui; i++) for(size_t i = 0; i < ui; i++)
op->results_.emplace_back(""); op->add_result("");
} catch(const std::invalid_argument &) { } catch(const std::invalid_argument &) {
throw ConversionError::TrueFalse(current.fullname); throw ConversionError::TrueFalse(current.fullname);
} }
} else } else
throw ConversionError::TooManyInputsFlag(current.fullname); throw ConversionError::TooManyInputsFlag(current.fullname);
} else { } else {
op->results_ = current.inputs; op->set_results(current.inputs);
op->run_callback(); op->run_callback();
} }
} }

View File

@ -238,8 +238,11 @@ class Option : public OptionBase<Option> {
/// Count the total number of times an option was passed /// Count the total number of times an option was passed
size_t count() const { return results_.size(); } size_t count() const { return results_.size(); }
/// True if the option was not passed
size_t empty() const { return results_.empty(); }
/// This class is true if option is passed. /// This class is true if option is passed.
operator bool() const { return count() > 0; } operator bool() const { return !empty(); }
/// Clear the parsed results (mostly for testing) /// Clear the parsed results (mostly for testing)
void clear() { results_.clear(); } void clear() { results_.clear(); }
@ -593,12 +596,18 @@ class Option : public OptionBase<Option> {
return std::find(std::begin(lnames_), std::end(lnames_), name) != std::end(lnames_); return std::find(std::begin(lnames_), std::end(lnames_), name) != std::end(lnames_);
} }
/// Puts a result at the end, unless last_ is set, in which case it just keeps the last one /// Puts a result at the end
void add_result(std::string s) { void add_result(std::string s) {
results_.push_back(s); results_.push_back(s);
callback_run_ = false; callback_run_ = false;
} }
/// Set the results vector all at once
void set_results(std::vector<std::string> results) {
results_ = results;
callback_run_ = false;
}
/// Get a copy of the results /// Get a copy of the results
std::vector<std::string> results() const { return results_; } std::vector<std::string> results() const { return results_; }