mirror of
https://github.com/CLIUtils/CLI11.git
synced 2025-04-29 12:13:52 +00:00
Travis improvements and updates (#28)
* Adding check for style * Adding reformats * Fix syntax error in travis * Support clang-format 3.9 * Adding clang-tidy check
This commit is contained in:
parent
b88f1f2ac7
commit
54114d0948
17
.ci/check_style.sh
Executable file
17
.ci/check_style.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env sh
|
||||
set -evx
|
||||
|
||||
clang-format --version
|
||||
|
||||
git ls-files -- '*.cpp' '*.hpp' | xargs clang-format -i -style=file
|
||||
|
||||
git diff --exit-code --color
|
||||
|
||||
mkdir build || true
|
||||
cd build
|
||||
CXX_FLAGS="-Werror -Wall -Wextra -pedantic -std=c++11" cmake .. -DCLANG_TIDY_FIX=ON
|
||||
cmake --build .
|
||||
|
||||
git diff --exit-code --color
|
||||
|
||||
set +evx
|
@ -9,6 +9,8 @@ if [ "$CXX" = "g++" ] ; then
|
||||
else
|
||||
ln -s `which clang-$COMPILER` clang
|
||||
ln -s `which clang++-$COMPILER` clang++
|
||||
ln -s `which clang-format-$COMPILER` clang-format
|
||||
ln -s `which clang-tidy-$COMPILER` clang-tidy
|
||||
fi
|
||||
|
||||
export PATH="${DEPS_DIR}/extrabin":$PATH
|
||||
|
@ -6,3 +6,5 @@ cd build
|
||||
cmake .. -DCLI_SINGLE_FILE_TESTS=ON -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build . -- -j2
|
||||
ctest --output-on-failure
|
||||
|
||||
set +evx
|
||||
|
37
.travis.yml
37
.travis.yml
@ -13,9 +13,16 @@ matrix:
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.5
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- clang-3.9
|
||||
- clang-format-3.9
|
||||
- clang-tidy-3.9
|
||||
env:
|
||||
- COMPILER=3.9
|
||||
- CHECK_STYLE=yes
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
env:
|
||||
@ -37,8 +44,6 @@ matrix:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.7
|
||||
env:
|
||||
@ -48,19 +53,21 @@ matrix:
|
||||
install:
|
||||
- python -c 'import sys; print(sys.version_info[:])'
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd $TRAVIS_BUILD_DIR && . .ci/prepare_altern.sh
|
||||
; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] ; then cd $TRAVIS_BUILD_DIR && . .ci/build_cmake.sh
|
||||
; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] ; then cd $TRAVIS_BUILD_DIR && . .ci/build_doxygen.sh
|
||||
; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd $TRAVIS_BUILD_DIR && . .ci/prepare_altern.sh ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] ; then cd $TRAVIS_BUILD_DIR && . .ci/build_cmake.sh ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" ] ; then cd $TRAVIS_BUILD_DIR && . .ci/build_doxygen.sh ; fi
|
||||
- if [ -n "$COVERALLS" ] ; then cd $TRAVIS_BUILD_DIR && . .ci/build_lcov.sh ; fi
|
||||
- cd "${DEPS_DIR}"
|
||||
- if [ "$(python -c 'import sys; print(sys.version_info[0])')" = "2" ] ; then pip
|
||||
install --user pathlib; fi
|
||||
- if [ "$(python -c 'import sys; print(sys.version_info[0])')" = "2" ] ; then pip install --user pathlib ; fi
|
||||
script:
|
||||
- cd "${TRAVIS_BUILD_DIR}"
|
||||
- .ci/travis.sh
|
||||
- |
|
||||
if [ -n "$CHECK_STYLE" ]
|
||||
then
|
||||
.ci/check_style.sh
|
||||
else
|
||||
.ci/travis.sh
|
||||
fi
|
||||
after_success:
|
||||
- if [ -n "$COVERALLS" ] ; then cd $TRAVIS_BUILD_DIR && .ci/run_codecov.sh ; fi
|
||||
- echo "${TRAVIS_BRANCH}"
|
||||
@ -68,7 +75,7 @@ after_success:
|
||||
- |
|
||||
if [ "${TRAVIS_BRANCH}" == "master" ] && [ "${TRAVIS_PULL_REQUEST}" == "false" ] && [ -n "$DEPLOY_MAT" ]
|
||||
then
|
||||
echo "Updating docs" && cd $TRAVIS_BUILD_DIR && .ci/build_docs.sh
|
||||
echo "Updating docs" && cd $TRAVIS_BUILD_DIR && .ci/build_docs.sh
|
||||
fi
|
||||
deploy:
|
||||
provider: releases
|
||||
|
@ -1,12 +1,8 @@
|
||||
#include <CLI/CLI.hpp>
|
||||
|
||||
enum Level : std::int32_t {
|
||||
High,
|
||||
Medium,
|
||||
Low
|
||||
};
|
||||
enum Level : std::int32_t { High, Medium, Low };
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int main(int argc, char **argv) {
|
||||
CLI::App app;
|
||||
|
||||
Level level;
|
||||
@ -15,9 +11,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch (CLI::Error const& e) {
|
||||
} catch(CLI::Error const &e) {
|
||||
app.exit(e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,7 @@ int main(int argc, char **argv) {
|
||||
app.prefix_command();
|
||||
|
||||
std::vector<int> vals;
|
||||
app.add_option("--vals,-v", vals)
|
||||
->expected(1);
|
||||
app.add_option("--vals,-v", vals)->expected(1);
|
||||
|
||||
std::vector<std::string> more_comms;
|
||||
try {
|
||||
@ -19,7 +18,7 @@ int main(int argc, char **argv) {
|
||||
std::cout << "Prefix:";
|
||||
for(int v : vals)
|
||||
std::cout << v << ":";
|
||||
|
||||
|
||||
std::cout << std::endl << "Remaining commands: ";
|
||||
|
||||
// Perfer to loop over from beginning, not "pop" order
|
||||
|
@ -59,7 +59,7 @@ class App {
|
||||
|
||||
/// If true, return immediatly on an unrecognised option (implies allow_extras)
|
||||
bool prefix_command_{false};
|
||||
|
||||
|
||||
/// This is a function that runs when complete. Great for subcommands. Can throw.
|
||||
std::function<void()> callback_;
|
||||
|
||||
@ -160,7 +160,7 @@ class App {
|
||||
prefix_command_ = allow;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/// Ignore case. Subcommand inherit value.
|
||||
App *ignore_case(bool value = true) {
|
||||
ignore_case_ = value;
|
||||
@ -225,8 +225,6 @@ class App {
|
||||
} else
|
||||
throw OptionAlreadyAdded(myopt.get_name());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Add option for non-vectors (duplicate copy needed without defaulted to avoid `iostream << value`)
|
||||
template <typename T, enable_if_t<!is_vector<T>::value, detail::enabler> = detail::dummy>
|
||||
@ -251,13 +249,13 @@ class App {
|
||||
T &variable, ///< The variable to set
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res) {
|
||||
if(res.size() != 1)
|
||||
return false;
|
||||
return detail::lexical_cast(res[0], variable);
|
||||
};
|
||||
|
||||
|
||||
Option *opt = add_option(name, fun, description, defaulted);
|
||||
opt->set_custom_option(detail::type_name<T>());
|
||||
if(defaulted) {
|
||||
@ -267,13 +265,13 @@ class App {
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add option for vectors (no default)
|
||||
template <typename T>
|
||||
Option *add_option(std::string name,
|
||||
std::vector<T> &variable, ///< The variable vector to set
|
||||
std::string description = "") {
|
||||
|
||||
|
||||
CLI::callback_t fun = [&variable](CLI::results_t res) {
|
||||
bool retval = true;
|
||||
variable.clear();
|
||||
@ -283,12 +281,12 @@ class App {
|
||||
}
|
||||
return (!variable.empty()) && retval;
|
||||
};
|
||||
|
||||
|
||||
Option *opt = add_option(name, fun, description, false);
|
||||
opt->set_custom_option(detail::type_name<T>(), -1, true);
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add option for vectors
|
||||
template <typename T>
|
||||
Option *add_option(std::string name,
|
||||
@ -386,7 +384,7 @@ class App {
|
||||
opt->set_custom_option(typeval);
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add set of options
|
||||
template <typename T>
|
||||
Option *add_set(std::string name,
|
||||
@ -394,7 +392,7 @@ class App {
|
||||
std::set<T> options, ///< The set of posibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
|
||||
CLI::callback_t fun = [&member, options](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
return false;
|
||||
@ -404,7 +402,7 @@ class App {
|
||||
return false;
|
||||
return std::find(std::begin(options), std::end(options), member) != std::end(options);
|
||||
};
|
||||
|
||||
|
||||
Option *opt = add_option(name, fun, description, defaulted);
|
||||
std::string typeval = detail::type_name<T>();
|
||||
typeval += " in {" + detail::join(options) + "}";
|
||||
@ -443,17 +441,17 @@ class App {
|
||||
std::string typeval = detail::type_name<std::string>();
|
||||
typeval += " in {" + detail::join(options) + "}";
|
||||
opt->set_custom_option(typeval);
|
||||
|
||||
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/// Add set of options, string only, ignore case
|
||||
Option *add_set_ignore_case(std::string name,
|
||||
std::string &member, ///< The selected member of the set
|
||||
std::set<std::string> options, ///< The set of posibilities
|
||||
std::string description,
|
||||
bool defaulted) {
|
||||
|
||||
|
||||
CLI::callback_t fun = [&member, options](CLI::results_t res) {
|
||||
if(res.size() != 1) {
|
||||
return false;
|
||||
@ -469,7 +467,7 @@ class App {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Option *opt = add_option(name, fun, description, defaulted);
|
||||
std::string typeval = detail::type_name<std::string>();
|
||||
typeval += " in {" + detail::join(options) + "}";
|
||||
@ -912,19 +910,19 @@ class App {
|
||||
char *buffer = nullptr;
|
||||
std::string ename_string;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
// Windows version
|
||||
size_t sz = 0;
|
||||
if(_dupenv_s(&buffer, &sz, opt->envname_.c_str()) == 0 && buffer != nullptr) {
|
||||
ename_string = std::string(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
// This also works on Windows, but gives a warning
|
||||
buffer = std::getenv(opt->envname_.c_str());
|
||||
if(buffer != nullptr)
|
||||
ename_string = std::string(buffer);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(!ename_string.empty()) {
|
||||
opt->add_result(ename_string);
|
||||
@ -1068,10 +1066,8 @@ class App {
|
||||
size_t _count_remaining_required_positionals() const {
|
||||
size_t retval = 0;
|
||||
for(const Option_p &opt : options_)
|
||||
if(opt->get_positional()
|
||||
&& opt->get_required()
|
||||
&& opt->get_expected() > 0
|
||||
&& static_cast<int>(opt->count()) < opt->get_expected())
|
||||
if(opt->get_positional() && opt->get_required() && opt->get_expected() > 0 &&
|
||||
static_cast<int>(opt->count()) < opt->get_expected())
|
||||
retval = static_cast<size_t>(opt->get_expected()) - opt->count();
|
||||
|
||||
return retval;
|
||||
@ -1098,7 +1094,7 @@ class App {
|
||||
else {
|
||||
args.pop_back();
|
||||
missing()->emplace_back(detail::Classifer::NONE, positional);
|
||||
|
||||
|
||||
if(prefix_command_) {
|
||||
while(!args.empty()) {
|
||||
missing()->emplace_back(detail::Classifer::NONE, args.back());
|
||||
@ -1106,7 +1102,6 @@ class App {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Parse a subcommand, modify args and continue
|
||||
|
@ -433,9 +433,8 @@ class Option {
|
||||
/// Set the default value string representation
|
||||
void set_default_val(std::string val) { defaultval_ = val; }
|
||||
|
||||
|
||||
/// Set the type name displayed on this option
|
||||
void set_type_name(std::string val) {typeval_ = val;}
|
||||
void set_type_name(std::string val) { typeval_ = val; }
|
||||
|
||||
///@}
|
||||
|
||||
|
@ -75,9 +75,8 @@ constexpr const char *type_name() {
|
||||
// Lexical cast
|
||||
|
||||
/// Integers / enums
|
||||
template <typename T, enable_if_t<std::is_integral<T>::value
|
||||
|| std::is_enum<T>::value
|
||||
, detail::enabler> = detail::dummy>
|
||||
template <typename T,
|
||||
enable_if_t<std::is_integral<T>::value || std::is_enum<T>::value, detail::enabler> = detail::dummy>
|
||||
bool lexical_cast(std::string input, T &output) {
|
||||
try {
|
||||
output = static_cast<T>(std::stoll(input));
|
||||
@ -103,11 +102,9 @@ bool lexical_cast(std::string input, T &output) {
|
||||
}
|
||||
|
||||
/// String and similar
|
||||
template <
|
||||
typename T,
|
||||
enable_if_t<!std::is_floating_point<T>::value
|
||||
&& !std::is_integral<T>::value
|
||||
&& !std::is_enum<T>::value, detail::enabler> = detail::dummy>
|
||||
template <typename T,
|
||||
enable_if_t<!std::is_floating_point<T>::value && !std::is_integral<T>::value && !std::is_enum<T>::value,
|
||||
detail::enabler> = detail::dummy>
|
||||
bool lexical_cast(std::string input, T &output) {
|
||||
output = input;
|
||||
return true;
|
||||
|
@ -204,34 +204,25 @@ TEST_F(TApp, DefaultOpts) {
|
||||
}
|
||||
|
||||
TEST_F(TApp, EnumTest) {
|
||||
enum Level : std::int32_t {
|
||||
High,
|
||||
Medium,
|
||||
Low
|
||||
};
|
||||
enum Level : std::int32_t { High, Medium, Low };
|
||||
Level level = Level::Low;
|
||||
app.add_option("--level", level);
|
||||
|
||||
|
||||
args = {"--level", "1"};
|
||||
run();
|
||||
EXPECT_EQ(level, Level::Medium);
|
||||
}
|
||||
|
||||
TEST_F(TApp, NewEnumTest) {
|
||||
enum class Level2 : std::int32_t {
|
||||
High,
|
||||
Medium,
|
||||
Low
|
||||
};
|
||||
enum class Level2 : std::int32_t { High, Medium, Low };
|
||||
Level2 level = Level2::Low;
|
||||
app.add_option("--level", level);
|
||||
|
||||
|
||||
args = {"--level", "1"};
|
||||
run();
|
||||
EXPECT_EQ(level, Level2::Medium);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, RequiredFlags) {
|
||||
app.add_flag("-a")->required();
|
||||
app.add_flag("-b")->mandatory(); // Alternate term
|
||||
@ -440,7 +431,6 @@ TEST_F(TApp, InSetWithDefault) {
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, InCaselessSetWithDefault) {
|
||||
|
||||
std::string choice = "one";
|
||||
@ -532,7 +522,6 @@ TEST_F(TApp, VectorFixedString) {
|
||||
EXPECT_EQ(answer, strvec);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TApp, VectorDefaultedFixedString) {
|
||||
std::vector<std::string> strvec{"one"};
|
||||
std::vector<std::string> answer{"mystring", "mystring2", "mystring3"};
|
||||
@ -895,40 +884,40 @@ TEST_F(TApp, CheckSubcomFail) {
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, OptionWithDefaults) {
|
||||
int someint=2;
|
||||
int someint = 2;
|
||||
app.add_option("-a", someint, "", true);
|
||||
|
||||
|
||||
args = {"-a1", "-a2"};
|
||||
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, SetWithDefaults) {
|
||||
int someint=2;
|
||||
app.add_set("-a", someint, {1,2,3,4}, "", true);
|
||||
|
||||
int someint = 2;
|
||||
app.add_set("-a", someint, {1, 2, 3, 4}, "", true);
|
||||
|
||||
args = {"-a1", "-a2"};
|
||||
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, SetWithDefaultsConversion) {
|
||||
int someint=2;
|
||||
app.add_set("-a", someint, {1,2,3,4}, "", true);
|
||||
|
||||
int someint = 2;
|
||||
app.add_set("-a", someint, {1, 2, 3, 4}, "", true);
|
||||
|
||||
args = {"-a", "hi"};
|
||||
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
||||
// Added to test defaults on dual method
|
||||
TEST_F(TApp, SetWithDefaultsIC) {
|
||||
std::string someint="ho";
|
||||
std::string someint = "ho";
|
||||
app.add_set_ignore_case("-a", someint, {"Hi", "Ho"}, "", true);
|
||||
|
||||
|
||||
args = {"-aHi", "-aHo"};
|
||||
|
||||
|
||||
EXPECT_THROW(run(), CLI::ConversionError);
|
||||
}
|
||||
|
@ -307,16 +307,15 @@ TEST_F(TApp, BadSubcomSearch) {
|
||||
}
|
||||
|
||||
TEST_F(TApp, PrefixProgram) {
|
||||
|
||||
|
||||
app.prefix_command();
|
||||
|
||||
|
||||
app.add_flag("--simple");
|
||||
|
||||
|
||||
args = {"--simple", "other", "--simple", "--mine"};
|
||||
auto ret_args = run();
|
||||
|
||||
|
||||
EXPECT_EQ(ret_args, std::vector<std::string>({"--mine", "--simple", "other"}));
|
||||
|
||||
}
|
||||
|
||||
struct SubcommandProgram : public TApp {
|
||||
|
Loading…
x
Reference in New Issue
Block a user