Skip to content

Commit

Permalink
defaultval -> default_str, added always_capture_default
Browse files Browse the repository at this point in the history
  • Loading branch information
henryiii committed Apr 9, 2019
1 parent 6e7535f commit bb6b63f
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 47 deletions.
4 changes: 2 additions & 2 deletions examples/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class ConfigJSON : public CLI::Config {
j[name] = opt->results();

// If the option has a default and is requested by optional argument
else if(default_also && !opt->get_defaultval().empty())
j[name] = opt->get_defaultval();
else if(default_also && !opt->get_default_str().empty())
j[name] = opt->get_default_str();

// Flag, one passed
} else if(opt->count() == 1) {
Expand Down
68 changes: 43 additions & 25 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,17 +429,33 @@ class App {
Option *add_option(std::string option_name,
callback_t option_callback,
std::string option_description = "",
bool defaulted = false) {
Option myopt{option_name, option_description, option_callback, defaulted, this};
bool defaulted = false,
std::function<std::string()> func = {}) {
Option myopt{option_name, option_description, option_callback, this};

if(std::find_if(std::begin(options_), std::end(options_), [&myopt](const Option_p &v) {
return *v == myopt;
}) == std::end(options_)) {
options_.emplace_back();
Option_p &option = options_.back();
option.reset(new Option(option_name, option_description, option_callback, defaulted, this));
option.reset(new Option(option_name, option_description, option_callback, this));

// Set the default string capture function
option->default_function(func);

// For compatibility with CLI11 1.7 and before, capture the default string here
if(defaulted)
option->capture_default_str();

// Transfer defaults to the new option
option_defaults_.copy_to(option.get());

// Don't bother to capture if we already did
if(!defaulted && option->get_always_capture_default())
option->capture_default_str();

return option.get();

} else
throw OptionAlreadyAdded(myopt.get_name());
}
Expand All @@ -451,16 +467,15 @@ class App {
std::string option_description = "",
bool defaulted = false) {

CLI::callback_t fun = [&variable](CLI::results_t res) { return detail::lexical_cast(res[0], variable); };
auto fun = [&variable](CLI::results_t res) { return detail::lexical_cast(res[0], variable); };

Option *opt = add_option(option_name, fun, option_description, defaulted);
Option *opt = add_option(option_name,
fun,
option_description,
defaulted,
[&variable]() { return std::string(CLI::detail::to_string(variable)); });
opt->type_name(detail::type_name<T>());

opt->default_function([&variable]() { return std::string(CLI::detail::to_string(variable)); });

if(defaulted)
opt->capture_default_str();

return opt;
}

Expand All @@ -470,7 +485,7 @@ class App {
const std::function<void(const T &)> &func, ///< the callback to execute
std::string option_description = "") {

CLI::callback_t fun = [func](CLI::results_t res) {
auto fun = [func](CLI::results_t res) {
T variable;
bool result = detail::lexical_cast(res[0], variable);
if(result) {
Expand All @@ -497,14 +512,14 @@ class App {
return add_option(option_name, CLI::callback_t(), option_description, false);
}

/// Add option for vectors with defaulted argument
/// Add option for vectors
template <typename T>
Option *add_option(std::string option_name,
std::vector<T> &variable, ///< The variable vector to set
std::string option_description = "",
bool defaulted = false) {

CLI::callback_t fun = [&variable](CLI::results_t res) {
auto fun = [&variable](CLI::results_t res) {
bool retval = true;
variable.clear();
variable.reserve(res.size());
Expand All @@ -516,20 +531,17 @@ class App {
return (!variable.empty()) && retval;
};

Option *opt = add_option(option_name, fun, option_description, defaulted);
opt->type_name(detail::type_name<T>())->type_size(-1);

opt->default_function([&variable]() {
auto default_function = [&variable]() {
std::vector<std::string> defaults;
defaults.resize(variable.size());
std::transform(variable.begin(), variable.end(), defaults.begin(), [](T &val) {
return std::string(CLI::detail::to_string(val));
});
return std::string("[" + detail::join(defaults) + "]");
});
};

if(defaulted)
opt->capture_default_str();
Option *opt = add_option(option_name, fun, option_description, defaulted, default_function);
opt->type_name(detail::type_name<T>())->type_size(-1);

return opt;
}
Expand Down Expand Up @@ -961,13 +973,19 @@ class App {
return worked;
};

CLI::Option *opt = add_option(option_name, std::move(fun), std::move(option_description), defaulted);
opt->type_name(label)->type_size(2);
if(defaulted) {
auto default_function = [&variable]() {
std::stringstream out;
out << variable;
opt->default_str(out.str());
}
return out.str();
};

CLI::Option *opt = add_option(option_name,
std::move(fun),
std::move(option_description),
defaulted,
default_function);

opt->type_name(label)->type_size(2);
return opt;
}

Expand Down
4 changes: 2 additions & 2 deletions include/CLI/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ ConfigINI::to_config(const App *app, bool default_also, bool write_description,
value = detail::ini_join(opt->results());

// If the option has a default and is requested by optional argument
else if(default_also && !opt->get_defaultval().empty())
value = opt->get_defaultval();
else if(default_also && !opt->get_default_str().empty())
value = opt->get_default_str();
// Flag, one passed
} else if(opt->count() == 1) {
value = "true";
Expand Down
4 changes: 2 additions & 2 deletions include/CLI/Formatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ inline std::string Formatter::make_option_opts(const Option *opt) const {
if(opt->get_type_size() != 0) {
if(!opt->get_type_name().empty())
out << " " << get_label(opt->get_type_name());
if(!opt->get_defaultval().empty())
out << "=" << opt->get_defaultval();
if(!opt->get_default_str().empty())
out << "=" << opt->get_default_str();
if(opt->get_expected() > 1)
out << " x " << opt->get_expected();
if(opt->get_expected() == -1)
Expand Down
41 changes: 25 additions & 16 deletions include/CLI/Option.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,16 @@ template <typename CRTP> class OptionBase {

/// Allow this option to be given in a configuration file
bool configurable_{true};

/// Disable overriding flag values with '=value'
bool disable_flag_override_{false};

/// Specify a delimiter character for vector arguments
char delimiter_{'\0'};

/// Automatically capture default value
bool always_capture_default_{false};

/// Policy for multiple arguments when `expected_ == 1` (can be set on bool flags, too)
MultiOptionPolicy multi_option_policy_{MultiOptionPolicy::Throw};

Expand Down Expand Up @@ -107,7 +113,12 @@ template <typename CRTP> class OptionBase {
/// The status of configurable
bool get_disable_flag_override() const { return disable_flag_override_; }

/// Get the current delimeter char
char get_delimiter() const { return delimiter_; }

/// Return true if this will automatically capture the default value for help printing
bool get_always_capture_default() const { return always_capture_default_; }

/// The status of the multi option policy
MultiOptionPolicy get_multi_option_policy() const { return multi_option_policy_; }

Expand Down Expand Up @@ -219,16 +230,14 @@ class Option : public OptionBase<Option> {
/// The description for help strings
std::string description_;

/// A human readable default value, usually only set if default is true in creation
std::string defaultval_;
/// A human readable default value, either manually set, captured, or captured by default
std::string default_str_;

/// 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.
std::function<std::string()> type_name_{[]() { return std::string(); }};

/// True if this option has a default
bool default_{false};

/// Run this function to capture a default (ignore if empty)
std::function<std::string()> default_function_;
Expand Down Expand Up @@ -280,9 +289,8 @@ class Option : public OptionBase<Option> {
Option(std::string option_name,
std::string option_description,
std::function<bool(results_t)> callback,
bool defaulted,
App *parent)
: description_(std::move(option_description)), default_(defaulted), parent_(parent),
: description_(std::move(option_description)), parent_(parent),
callback_(std::move(callback)) {
std::tie(snames_, lnames_, pname_) = detail::get_names(detail::split_names(option_name));
}
Expand All @@ -309,6 +317,7 @@ class Option : public OptionBase<Option> {

/// Set the number of expected arguments (Flags don't use this)
Option *expected(int value) {

// Break if this is a flag
if(type_size_ == 0)
throw IncorrectConstruction::SetFlag(get_name(true, true));
Expand Down Expand Up @@ -535,8 +544,12 @@ class Option : public OptionBase<Option> {
/// The set of options excluded
std::set<Option *> get_excludes() const { return excludes_; }

/// The default value (for help printing) DEPRECATED Use get_default_str() instead
CLI11_DEPRECATED("Use get_default_str() instead")
std::string get_defaultval() const { return default_str_; }

/// The default value (for help printing)
std::string get_defaultval() const { return defaultval_; }
std::string get_default_str() const { return default_str_; }

/// Get the callback function
callback_t get_callback() const { return callback_; }
Expand Down Expand Up @@ -574,9 +587,6 @@ class Option : public OptionBase<Option> {
((multi_option_policy_ != MultiOptionPolicy::Throw || (expected_ < 0 && type_size_ < 0) ? -1 : 1));
}

/// True if this has a default value
int get_default() const { return default_; }

/// True if the argument can be given directly
bool get_positional() const { return pname_.length() > 0; }

Expand Down Expand Up @@ -861,7 +871,7 @@ class Option : public OptionBase<Option> {
void results(T &output) const {
bool retval;
if(results_.empty()) {
retval = detail::lexical_cast(defaultval_, output);
retval = detail::lexical_cast(default_str_, output);
} else if(results_.size() == 1) {
retval = detail::lexical_cast(results_[0], output);
} else {
Expand Down Expand Up @@ -944,19 +954,18 @@ class Option : public OptionBase<Option> {
/// Capture the default value from the original value (if it can be captured)
Option *capture_default_str() {
if(default_function_) {
defaultval_ = default_function_();
default_ = true;
default_str_ = default_function_();
}
return this;
}

/// Set the default value string representation
/// Set the default value string representation (does not change the contained value)
Option *default_str(std::string val) {
defaultval_ = val;
default_str_ = val;
return this;
}

/// Set the default value string representation and evaluate
/// Set the default value string representation and evaluate into the bound value
Option *default_val(std::string val) {
default_str(val);
auto old_results = results_;
Expand Down

0 comments on commit bb6b63f

Please sign in to comment.