diff --git a/.clang-format b/.clang-format index 666a2ba7..caaefd2d 100644 --- a/.clang-format +++ b/.clang-format @@ -19,7 +19,7 @@ BasedOnStyle: LLVM # AlwaysBreakTemplateDeclarations: false BinPackArguments: false BinPackParameters: false -# BraceWrapping: +# BraceWrapping: # AfterClass: false # AfterControlStatement: false # AfterEnum: false @@ -69,7 +69,7 @@ IndentWidth: 4 # PenaltyReturnTypeOnItsOwnLine: 60 # PointerAlignment: Right # ReflowComments: true -SortIncludes: false +SortIncludes: true # SpaceAfterCStyleCast: false # SpaceAfterTemplateKeyword: true # SpaceBeforeAssignmentOperators: true diff --git a/azure-pipelines.yml b/azure-pipelines.yml index d5ac217b..0c894b89 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,7 +15,24 @@ variables: jobs: -- job: ClangFormatTidy +- job: Formatting + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.7' + architecture: 'x64' + - script: python -m pip install pre-commit + displayName: Install pre-commit + - script: pre-commit run --all + displayName: Run pre-commit + - script: git diff --exit-code + displayName: Display format changes + condition: always() + + +- job: ClangTidy variables: CXX_FLAGS: "-Werror -Wcast-align -Wfloat-equal -Wimplicit-atomic-properties -Wmissing-declarations -Woverlength-strings -Wshadow -Wstrict-selector-match -Wundeclared-selector -Wunreachable-code -std=c++11" cli11.options: -DCLANG_TIDY_FIX=ON @@ -26,8 +43,6 @@ jobs: vmImage: 'ubuntu-16.04' container: silkeh/clang:5 steps: - - script: scripts/check_style.sh - displayName: Check format - template: .ci/azure-cmake.yml - template: .ci/azure-build.yml - script: git diff --exit-code --color diff --git a/book/chapters/config.md b/book/chapters/config.md index d83278a2..85c5b187 100644 --- a/book/chapters/config.md +++ b/book/chapters/config.md @@ -44,10 +44,10 @@ std::vector from_config(std::istream &input) const; The `CLI::ConfigItem`s that you return are simple structures with a name, a vector of parents, and a vector of results. A optionally customizable `to_flag` method on the formatter lets you change what happens when a ConfigItem turns into a flag. -Finally, set your new class as new config formatter: +Finally, set your new class as new config formatter: ```cpp app.config_formatter(std::make_shared()); ``` -See [`examples/json.cpp`](https://github.com/CLIUtils/CLI11/blob/master/examples/json.cpp) for a complete JSON config example. +See [`examples/json.cpp`](https://github.com/CLIUtils/CLI11/blob/master/examples/json.cpp) for a complete JSON config example. diff --git a/book/chapters/flags.md b/book/chapters/flags.md index ef68b860..abab3067 100644 --- a/book/chapters/flags.md +++ b/book/chapters/flags.md @@ -73,7 +73,7 @@ The values would be used like this: [include:"usage"](../code/flags.cpp) -[Source code](https://gitlab.com/CLIUtils/CLI11Tutorial/blob/master/code/flags.cpp) +[Source code](https://gitlab.com/CLIUtils/CLI11Tutorial/blob/master/code/flags.cpp) If you compile and run: diff --git a/book/chapters/formatting.md b/book/chapters/formatting.md index 8c854f6b..2af98fae 100644 --- a/book/chapters/formatting.md +++ b/book/chapters/formatting.md @@ -51,7 +51,7 @@ This is a normal printout, with `<>` indicating the methods used to produce each ... - + ``` @@ -61,10 +61,10 @@ This is a normal printout, with `<>` indicating the methods used to produce each The `make_groups` print the group name then call `make_option(o)` on the options listed in that group. The normal printout for an option looks like this: ``` - make_option_opts(o) - ┌───┴────┐ - -n,--name (REQUIRED) This is a description -└────┬────┘ └──────────┬──────────┘ + make_option_opts(o) + ┌───┴────┐ + -n,--name (REQUIRED) This is a description +└────┬────┘ └──────────┬──────────┘ make_option_name(o,p) make_option_desc(o) ``` diff --git a/book/chapters/installation.md b/book/chapters/installation.md index 4efdfa1b..22870740 100644 --- a/book/chapters/installation.md +++ b/book/chapters/installation.md @@ -1,4 +1,4 @@ -# Installation +# Installation ## Single file edition @@ -50,7 +50,7 @@ root:build # cmake .. root:build # make Scanning dependencies ... root:build # make test -[warning]Running tests... +[warning]Running tests... Test project /CLI11/build Start 1: HelpersTest 1/10 Test #1: HelpersTest ...................... Passed 0.01 sec diff --git a/book/chapters/options.md b/book/chapters/options.md index 52483157..11295980 100644 --- a/book/chapters/options.md +++ b/book/chapters/options.md @@ -20,7 +20,7 @@ You can use any C++ int-like type, not just `int`. CLI11 understands the followi | Type | CLI11 | |-------------|-------| -| int-like | Integer conversion up to 64-bit, can be unsigned | +| int-like | Integer conversion up to 64-bit, can be unsigned | | float-like | Floating point conversions | | string-like | Anything else that can be shifted into a StringStream | | vector-like | A vector of the above three types (see below) | @@ -54,7 +54,7 @@ If you use a vector instead of a plain option, you can accept more than one valu |-------------------|-----------------| | `--vec 1 --vec 2` | `--vec 1 2` | -The original version did allow the option system to access information on the grouping of options received, but was removed for simplicity. +The original version did allow the option system to access information on the grouping of options received, but was removed for simplicity. An example of setting up a vector option: diff --git a/book/chapters/toolkits.md b/book/chapters/toolkits.md index c03de232..3b8e93a1 100644 --- a/book/chapters/toolkits.md +++ b/book/chapters/toolkits.md @@ -27,4 +27,4 @@ You can call anything you would like to configure in the constructor, like `opti # Virtual functions provided -You are given a few virtual functions that you can change (only on the main App). `pre_callback` runs right before the callbacks run, letting you print out custom messages at the top of your app. +You are given a few virtual functions that you can change (only on the main App). `pre_callback` runs right before the callbacks run, letting you print out custom messages at the top of your app. diff --git a/cmake/CodeCoverage.cmake b/cmake/CodeCoverage.cmake index a1b7b860..5c3d41c9 100644 --- a/cmake/CodeCoverage.cmake +++ b/cmake/CodeCoverage.cmake @@ -170,7 +170,7 @@ function(SETUP_TARGET_FOR_COVERAGE) DEPENDS ${Coverage_DEPENDENCIES} COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." ) - + # Show where to find the lcov info report add_custom_command(TARGET ${Coverage_NAME} POST_BUILD COMMAND ; diff --git a/conanfile.py b/conanfile.py index 13fc77ac..54c1d5ad 100644 --- a/conanfile.py +++ b/conanfile.py @@ -2,6 +2,7 @@ from conans import ConanFile, CMake from conans.tools import load import re + def get_version(): try: content = load("include/CLI/Version.hpp") @@ -10,6 +11,7 @@ def get_version(): except Exception: return None + class CLI11Conan(ConanFile): name = "CLI11" version = get_version() @@ -21,9 +23,17 @@ class CLI11Conan(ConanFile): license = "BSD-3-Clause" settings = "os", "compiler", "arch", "build_type" - exports_sources = "LICENSE", "README.md", "include/*", "extern/*", "cmake/*", "CMakeLists.txt", "tests/*" + exports_sources = ( + "LICENSE", + "README.md", + "include/*", + "extern/*", + "cmake/*", + "CMakeLists.txt", + "tests/*", + ) - def build(self): # this is not building a library, just tests + def build(self): # this is not building a library, just tests cmake = CMake(self) cmake.definitions["CLI11_EXAMPLES"] = "OFF" cmake.definitions["CLI11_SINGLE_FILE"] = "OFF" diff --git a/include/CLI/Validators.hpp b/include/CLI/Validators.hpp index b4586ed1..5f684237 100644 --- a/include/CLI/Validators.hpp +++ b/include/CLI/Validators.hpp @@ -474,9 +474,10 @@ template std::string generate_set(const T &set) { using element_t = typename detail::element_type::type; using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair std::string out(1, '{'); - out.append(detail::join(detail::smart_deref(set), - [](const iteration_type_t &v) { return detail::pair_adaptor::first(v); }, - ",")); + out.append(detail::join( + detail::smart_deref(set), + [](const iteration_type_t &v) { return detail::pair_adaptor::first(v); }, + ",")); out.push_back('}'); return out; } @@ -486,17 +487,18 @@ template std::string generate_map(const T &map, bool key_only = fal using element_t = typename detail::element_type::type; using iteration_type_t = typename detail::pair_adaptor::value_type; // the type of the object pair std::string out(1, '{'); - out.append(detail::join(detail::smart_deref(map), - [key_only](const iteration_type_t &v) { - std::string res{detail::to_string(detail::pair_adaptor::first(v))}; + out.append(detail::join( + detail::smart_deref(map), + [key_only](const iteration_type_t &v) { + std::string res{detail::to_string(detail::pair_adaptor::first(v))}; - if(!key_only) { - res.append("->"); - res += detail::to_string(detail::pair_adaptor::second(v)); - } - return res; - }, - ",")); + if(!key_only) { + res.append("->"); + res += detail::to_string(detail::pair_adaptor::second(v)); + } + return res; + }, + ",")); out.push_back('}'); return out; } @@ -657,9 +659,10 @@ class IsMember : public Validator { /// You can pass in as many filter functions as you like, they nest (string only currently) template IsMember(T &&set, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&... other) - : IsMember(std::forward(set), - [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, - other...) {} + : IsMember( + std::forward(set), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} }; /// definition of the default transformation object @@ -717,9 +720,10 @@ class Transformer : public Validator { /// You can pass in as many filter functions as you like, they nest template Transformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&... other) - : Transformer(std::forward(mapping), - [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, - other...) {} + : Transformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} }; /// translate named items to other or a value set @@ -793,9 +797,10 @@ class CheckedTransformer : public Validator { /// You can pass in as many filter functions as you like, they nest template CheckedTransformer(T &&mapping, filter_fn_t filter_fn_1, filter_fn_t filter_fn_2, Args &&... other) - : CheckedTransformer(std::forward(mapping), - [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, - other...) {} + : CheckedTransformer( + std::forward(mapping), + [filter_fn_1, filter_fn_2](std::string a) { return filter_fn_2(filter_fn_1(a)); }, + other...) {} }; /// Helper function to allow ignore_case to be passed to IsMember or Transform diff --git a/scripts/ExtractVersion.py b/scripts/ExtractVersion.py index 42d82cd2..adfd18d4 100755 --- a/scripts/ExtractVersion.py +++ b/scripts/ExtractVersion.py @@ -3,15 +3,15 @@ import os import re -base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) -config_h = os.path.join(base_path, 'include', 'CLI', 'Version.hpp') -data = {'MAJOR': 0, 'MINOR': 0, 'PATCH': 0} -reg = re.compile(r'^\s*#define\s+CLI11_VERSION_([A-Z]+)\s+([0-9]+).*$') +base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +config_h = os.path.join(base_path, "include", "CLI", "Version.hpp") +data = {"MAJOR": 0, "MINOR": 0, "PATCH": 0} +reg = re.compile(r"^\s*#define\s+CLI11_VERSION_([A-Z]+)\s+([0-9]+).*$") -with open(config_h, 'r') as fp: - for l in fp: - m = reg.match(l) - if m: - data[m.group(1)] = int(m.group(2)) +with open(config_h, "r") as fp: + for l in fp: + m = reg.match(l) + if m: + data[m.group(1)] = int(m.group(2)) -print('{}.{}.{}'.format(data['MAJOR'], data['MINOR'], data['PATCH'])) +print("{}.{}.{}".format(data["MAJOR"], data["MINOR"], data["PATCH"])) diff --git a/scripts/MakeSingleHeader.py b/scripts/MakeSingleHeader.py index ab16799d..1163485a 100755 --- a/scripts/MakeSingleHeader.py +++ b/scripts/MakeSingleHeader.py @@ -24,11 +24,13 @@ CLI11:verbatim # The tag [^\n]* # Up to end of line $ # End of a line """ -verbatim_all = re.compile(verbatim_tag_str + "(.*)" + verbatim_tag_str, - re.MULTILINE | re.DOTALL | re.VERBOSE) +verbatim_all = re.compile( + verbatim_tag_str + "(.*)" + verbatim_tag_str, re.MULTILINE | re.DOTALL | re.VERBOSE +) DIR = os.path.dirname(os.path.abspath(__file__)) + class HeaderFile(object): TAG = "Unknown git revision" LICENSE = "// BSD 3 clause" @@ -43,7 +45,7 @@ class HeaderFile(object): self.__class__.VERSION = version.groups()[0] # add self.verbatim - if 'CLI11:verbatim' in inner: + if "CLI11:verbatim" in inner: self.verbatim = ["\n\n// Verbatim copy from {0}:".format(inc)] self.verbatim += verbatim_all.findall(inner) inner = verbatim_all.sub("", inner) @@ -52,7 +54,7 @@ class HeaderFile(object): self.headers = set(includes_system.findall(inner)) - self.body = '\n// From {0}:\n\n'.format(inc) + inner[inner.find('namespace'):] + self.body = "\n// From {0}:\n\n".format(inc) + inner[inner.find("namespace") :] self.namespace = None @@ -65,11 +67,11 @@ class HeaderFile(object): @property def header_str(self): - return '\n'.join('#include <'+h+'>' for h in sorted(self.headers)) + return "\n".join("#include <" + h + ">" for h in sorted(self.headers)) @property def verbatim_str(self): - return '\n'.join(self.verbatim) + return "\n".join(self.verbatim) def insert_namespace(self, namespace): self.namespace = namespace @@ -79,7 +81,7 @@ class HeaderFile(object): self.body = self.body.replace(before, after) def __str__(self): - result = '''\ + result = """\ #pragma once // CLI11: Version {self.VERSION} @@ -96,21 +98,27 @@ class HeaderFile(object): // Standard combined includes: {self.header_str} -'''.format(self=self) +""".format( + self=self + ) if self.namespace: - result += '\nnamespace ' + self.namespace + ' {\n\n' - result += '{self.verbatim_str}\n{self.body}\n'.format(self=self) + result += "\nnamespace " + self.namespace + " {\n\n" + result += "{self.verbatim_str}\n{self.body}\n".format(self=self) if self.namespace: - result += '} // namespace ' + self.namespace + '\n\n' + result += "} // namespace " + self.namespace + "\n\n" return result -def MakeHeader(output, main_header, include_dir = '../include', namespace=None, macro=None): +def MakeHeader( + output, main_header, include_dir="../include", namespace=None, macro=None +): # Set tag if possible to class variable try: - proc = Popen(['git', 'describe', '--tags', '--always'], cwd=str(DIR), stdout=PIPE) + proc = Popen( + ["git", "describe", "--tags", "--always"], cwd=str(DIR), stdout=PIPE + ) out, _ = proc.communicate() except OSError: pass @@ -120,10 +128,10 @@ def MakeHeader(output, main_header, include_dir = '../include', namespace=None, base_dir = os.path.abspath(os.path.join(DIR, include_dir)) main_header = os.path.join(base_dir, main_header) - licence_file = os.path.abspath(os.path.join(DIR, '../LICENSE')) + licence_file = os.path.abspath(os.path.join(DIR, "../LICENSE")) with open(licence_file) as f: - HeaderFile.LICENSE = ''.join('// ' + line for line in f) + HeaderFile.LICENSE = "".join("// " + line for line in f) with open(main_header) as f: header = f.read() @@ -134,7 +142,7 @@ def MakeHeader(output, main_header, include_dir = '../include', namespace=None, single_header = reduce(add, headers) if macro is not None: - before = 'CLI11_' + before = "CLI11_" print("Converting macros", before, "->", macro) single_header.macro_replacement(before, macro) @@ -142,19 +150,25 @@ def MakeHeader(output, main_header, include_dir = '../include', namespace=None, print("Adding namespace", namespace) single_header.insert_namespace(namespace) - with open(output, 'w') as f: + with open(output, "w") as f: f.write(str(single_header)) print("Created", output) -if __name__ == '__main__': - parser = ArgumentParser(usage='Convert source to single header include. Can optionally add namespace and search-replace replacements (for macros).') + +if __name__ == "__main__": + parser = ArgumentParser( + usage="Convert source to single header include. Can optionally add namespace and search-replace replacements (for macros)." + ) parser.add_argument("output", help="Single header file output") - parser.add_argument("--main", default='CLI/CLI.hpp', help="The main include file that defines the other files") - parser.add_argument("--include", default='../include', help="The include directory") + parser.add_argument( + "--main", + default="CLI/CLI.hpp", + help="The main include file that defines the other files", + ) + parser.add_argument("--include", default="../include", help="The include directory") parser.add_argument("--namespace", help="Add an optional namespace") parser.add_argument("--macro", help="Replaces CLI11_ with NEW_PREFIX_") args = parser.parse_args() MakeHeader(args.output, args.main, args.include, args.namespace, args.macro) - diff --git a/scripts/UpdateDownloadProj.py b/scripts/UpdateDownloadProj.py index c35743b6..e20797f4 100755 --- a/scripts/UpdateDownloadProj.py +++ b/scripts/UpdateDownloadProj.py @@ -5,20 +5,25 @@ from __future__ import print_function, division from plumbum import local, cli, FG from plumbum.cmd import curl -FILES = [ 'https://raw.githubusercontent.com/Crascit/DownloadProject/master/DownloadProject.cmake', - 'https://raw.githubusercontent.com/Crascit/DownloadProject/master/DownloadProject.CMakeLists.cmake.in'] +FILES = [ + "https://raw.githubusercontent.com/Crascit/DownloadProject/master/DownloadProject.cmake", + "https://raw.githubusercontent.com/Crascit/DownloadProject/master/DownloadProject.CMakeLists.cmake.in", +] DIR = local.path(__file__).dirname + def download_file(path): - name = path.split('/')[-1] + name = path.split("/")[-1] (curl[path] > name) & FG + class UpdateDownloadProj(cli.Application): def main(self): - with local.cwd(DIR / '../cmake'): + with local.cwd(DIR / "../cmake"): for f in FILES: download_file(f) + if __name__ == "__main__": UpdateDownloadProj() diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 0202a8a8..91b91ddd 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -1,6 +1,7 @@ from conans import ConanFile, CMake import os + class HelloTestConan(ConanFile): settings = "os", "compiler", "build_type", "arch" generators = "cmake" diff --git a/tests/OptionalTest.cpp b/tests/OptionalTest.cpp index 32c29d30..2710061d 100644 --- a/tests/OptionalTest.cpp +++ b/tests/OptionalTest.cpp @@ -162,7 +162,8 @@ TEST_F(TApp, BoostOptionalEnumTest) { TEST_F(TApp, BoostOptionalVector) { boost::optional> opt; - app.add_option_function>("-v,--vec", [&opt](const std::vector &v) { opt = v; }, "some vector") + app.add_option_function>( + "-v,--vec", [&opt](const std::vector &v) { opt = v; }, "some vector") ->expected(3); run(); EXPECT_FALSE(opt);