Skip to content

Commit

Permalink
remove the test from visual studio 2015
Browse files Browse the repository at this point in the history
vs2015 doesn't seem to properly deal with is_assignable in the cases we care about so make a standalone version that is more direct in what we are doing

add version to appveyor and add some notes to the readme

fix a few test cases to make sure code is covered and test a few other paths

remove unneeded enum streaming operator

add some diagnostic escapes around trait code to eliminate gcc Wnarrowing warnings

work specification of the template operations

remove optional add some templates for options conversions

add the two parameter template for add_option
  • Loading branch information
phlptp committed May 26, 2019
1 parent 73aa158 commit dece416
Show file tree
Hide file tree
Showing 12 changed files with 450 additions and 155 deletions.
2 changes: 2 additions & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
version: 1.8.0.{build}

branches:
only:
- master
Expand Down
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,18 @@ While all options internally are the same type, there are several ways to add an
app.add_option(option_name, help_str="") // 🆕

app.add_option(option_name,
variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string
variable_to_bind_to, // bool, int, float, vector, 🆕 enum, or string-like, or anything with a defined conversion from a string or that takes an int, double or string in a constructor.
help_string="")

app.add_option_function<type>(option_name,
function <void(const type &value)>, // 🆕 int, bool, float, enum, vector, or string-like, or anything with a defined conversion from a string
help_string="")

app.add_complex(... // Special case: support for complex numbers
//there is a template overload which takes two template parameters the first is the type of object to assign the value to, the second is the conversion type. The conversion type should have a known way to convert from a string.
app.add_option<typename T, typename XC>(option_name,
T &output, // output must be assignable or constructible from a value of type XC
help_string="")

// Add flags
app.add_flag(option_name,
Expand Down Expand Up @@ -240,6 +244,21 @@ An option name must start with a alphabetic character, underscore, a number 🆕

The `add_option_function<type>(...` function will typically require the template parameter be given unless a `std::function` object with an exact match is passed. The type can be any type supported by the `add_option` function. The function should throw an error (`CLI::ConversionError` or `CLI::ValidationError` possibly) if the value is not valid.

The two parameter template overload can be used in cases where you want to restrict the input such as
```
double val
app.add_option<double,unsigned int>("-v",val);
```
which would first verify the input is convertible to an int before assigning it. Or using some variant type
```
using vtype=std::variant<int, double, std::string>;
vtype v1;
app.add_option<vtype,std:string>("--vs",v1);
app.add_option<vtype,int>("--vi",v1);
app.add_option<vtype,double>("--vd",v1);
```
otherwise the output would default to a string

🆕 Flag options specified through the `add_flag*` functions allow a syntax for the option names to default particular options to a false value or any other value if some flags are passed. For example:

```cpp
Expand Down Expand Up @@ -300,8 +319,8 @@ Before parsing, you can set the following options:
- `->each(void(const std::string &)>`: Run this function on each value received, as it is received. It should throw a `ValidationError` if an error is encountered.
- `->configurable(false)`: Disable this option from being in a configuration file.
`->capture_default_str()`: 🆕 Store the current value attached and display it in the help string.
`->default_function(std::string())`: 🆕 Advanced: Change the function that `capture_default_str()` uses.
`->always_capture_default()`: 🆕 Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.
- `->default_function(std::string())`: 🆕 Advanced: Change the function that `capture_default_str()` uses.
- `->always_capture_default()`: 🆕 Always run `capture_default_str()` when creating new options. Only useful on an App's `option_defaults`.


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.
Expand Down
13 changes: 8 additions & 5 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
// file LICENSE or https://github.com/CLIUtils/CLI11 for details.

#include <algorithm>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <memory>
#include <numeric>
#include <set>
#include <sstream>
#include <string>
#include <utility>
Expand Down Expand Up @@ -469,18 +467,23 @@ class App {
}

/// Add option for non-vectors (duplicate copy needed without defaulted to avoid `iostream << value`)
template <typename T, enable_if_t<!is_vector<T>::value & !std::is_const<T>::value, detail::enabler> = detail::dummy>

template <typename T,
typename XC = T,
enable_if_t<!is_vector<XC>::value && !std::is_const<XC>::value, detail::enabler> = detail::dummy>
Option *add_option(std::string option_name,
T &variable, ///< The variable to set
std::string option_description = "",
bool defaulted = false) {

auto fun = [&variable](CLI::results_t res) { return detail::lexical_cast(res[0], variable); };
auto fun = [&variable](CLI::results_t res) { // comment for spacing
return detail::lexical_assign<T, XC>(res[0], variable);
};

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->type_name(detail::type_name<XC>());

return opt;
}
Expand Down
2 changes: 0 additions & 2 deletions include/CLI/CLI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

#include "CLI/Macros.hpp"

#include "CLI/Optional.hpp"

#include "CLI/StringTools.hpp"

#include "CLI/Error.hpp"
Expand Down
97 changes: 0 additions & 97 deletions include/CLI/Optional.hpp

This file was deleted.

19 changes: 0 additions & 19 deletions include/CLI/StringTools.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@ std::ostream &operator<<(std::ostream &in, const T &item) {
return in << static_cast<typename std::underlying_type<T>::type>(item);
}

/// input streaming for enumerations
template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
std::istream &operator>>(std::istream &in, T &item) {
typename std::underlying_type<T>::type i;
in >> i;
item = static_cast<T>(i);
return in;
}
} // namespace enums

/// Export to CLI namespace
Expand All @@ -57,17 +49,6 @@ inline std::vector<std::string> split(const std::string &s, char delim) {
}
return elems;
}
/// simple utility to convert various types to a string
template <typename T> inline std::string as_string(const T &v) {
std::ostringstream s;
s << v;
return s.str();
}
// if the data type is already a string just forward it
template <typename T, typename = typename std::enable_if<std::is_constructible<std::string, T>::value>::type>
inline auto as_string(T &&v) -> decltype(std::forward<T>(v)) {
return std::forward<T>(v);
}

/// Simple function to join a string
template <typename T> std::string join(const T &v, std::string delim = ",") {
Expand Down
Loading

0 comments on commit dece416

Please sign in to comment.