1
0
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:
Henry Schreiner 2017-09-01 16:51:09 -04:00 committed by GitHub
parent b88f1f2ac7
commit 54114d0948
11 changed files with 97 additions and 96 deletions

17
.ci/check_style.sh Executable file
View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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; }
///@}

View File

@ -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;

View File

@ -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);
}

View File

@ -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 {