From ab1dc0f68454982cb0d7d65872235bab25514d3e Mon Sep 17 00:00:00 2001 From: Jarryd Beck Date: Mon, 22 Aug 2022 07:35:58 +1000 Subject: [PATCH 1/5] Update copyright notice Fixes #361 --- include/cxxopts.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index 2895890..76dcc1a 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2014, 2015, 2016, 2017 Jarryd Beck +Copyright (c) 2014-2022 Jarryd Beck Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From f7cf84bd56b47728e4674f316d274b3d82a1cfb3 Mon Sep 17 00:00:00 2001 From: 66maer <505670805@qq.com> Date: Thu, 8 Sep 2022 05:33:31 +0800 Subject: [PATCH 2/5] Fix std::isblank assertion error in Visual Studio Chinese Debug (#365) --- include/cxxopts.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index 76dcc1a..ee02c57 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -2090,12 +2090,12 @@ format_description { appendNewLine = false; - if (std::isblank(*previous)) + if (std::isblank(*previous, std::locale::classic())) { lastSpace = current; } - if (!std::isblank(*current)) + if (!std::isblank(*current, std::locale::classic())) { onlyWhiteSpace = false; } From 82ac0838864fba7b65e464ade1fd53e400af1e63 Mon Sep 17 00:00:00 2001 From: Stefan Hillmich Date: Sun, 11 Sep 2022 23:02:26 +0200 Subject: [PATCH 3/5] Added missing #include (#368) --- include/cxxopts.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index ee02c57..b411bcc 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -33,6 +33,7 @@ THE SOFTWARE. #include #include #include +#include #include #include #include From d046fe0ad6acab5dbe0dcbc9457cad8fada8b288 Mon Sep 17 00:00:00 2001 From: Stefan Hillmich Date: Sun, 25 Sep 2022 22:57:05 +0200 Subject: [PATCH 4/5] Extend CI and small fixes (#370) * Extend CI to support Windows and MacOS. * Minor fixes to types. --- .github/workflows/cmake.yml | 81 ++++++++++++++++++++++++------------- include/cxxopts.hpp | 65 ++++++++++++++--------------- 2 files changed, 84 insertions(+), 62 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 3589fcb..a2a9063 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -2,43 +2,70 @@ name: CMake on: push: - branches: [ master ] + branches: [ master, main ] pull_request: - branches: [ master ] + branches: [ master, main ] workflow_dispatch: env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) BUILD_TYPE: Release -jobs: - build: - # The CMake configure and build commands are platform agnostic and should work equally - # well on Windows or Mac. You can convert this to a matrix build if you need - # cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ${{matrix.os}} +defaults: + run: + shell: bash + +jobs: + build-ubuntu: strategy: matrix: - os: [ubuntu-18.04] - compiler: [g++-7, g++-9, g++-10, clang++] - + os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ] + compiler: [ g++-9, g++-10, clang++ ] + include: + - os: ubuntu-18.04 + compiler: g++-7 + name: Build and Test on Ubuntu + runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - name: Configure CMake + run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_CXX_COMPILER=${{matrix.compiler}} + - name: Build + run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE + - name: Test + working-directory: ${{github.workspace}}/build/test + run: ctest -C $BUILD_TYPE --output-on-failure - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=${{matrix.compiler}} + build-macos: + name: Build and Test on MacOS + strategy: + matrix: + os: [ macos-11, macos-12 ] + runs-on: ${{matrix.os}} + steps: + - uses: actions/checkout@v3 + - name: Configure CMake + run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + - name: Show compile commands + run: cat build/compile_commands.json + - name: Build + run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE + - name: Test + working-directory: ${{github.workspace}}/build/test + shell: bash + run: ctest -C $BUILD_TYPE --output-on-failure - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Test - working-directory: ${{github.workspace}}/build - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C ${{env.BUILD_TYPE}} - + build-windows: + name: Build and Test on Windows + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + - uses: ilammy/msvc-dev-cmd@v1 + - name: Configure CMake + run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -T "ClangCl" + - name: Build + run: cmake --build "${{github.workspace}}/build" --config $BUILD_TYPE + - name: Test + working-directory: ${{github.workspace}}/build/test + run: cd $BUILD_TYPE && ./link_test && ./options_test diff --git a/include/cxxopts.hpp b/include/cxxopts.hpp index b411bcc..4ed4892 100644 --- a/include/cxxopts.hpp +++ b/include/cxxopts.hpp @@ -27,13 +27,10 @@ THE SOFTWARE. #ifndef CXXOPTS_HPP_INCLUDED #define CXXOPTS_HPP_INCLUDED -#include -#include #include #include #include -#include -#include +#include #include #include #include @@ -196,9 +193,9 @@ stringAppend(String&s, String a) inline String& -stringAppend(String& s, size_t n, UChar32 c) +stringAppend(String& s, std::size_t n, UChar32 c) { - for (size_t i = 0; i != n; ++i) + for (std::size_t i = 0; i != n; ++i) { s.append(c); } @@ -220,7 +217,7 @@ stringAppend(String& s, Iterator begin, Iterator end) } inline -size_t +std::size_t stringLength(const String& s) { return s.length(); @@ -278,7 +275,7 @@ toLocalString(T&& t) } inline -size_t +std::size_t stringLength(const String& s) { return s.length(); @@ -293,7 +290,7 @@ stringAppend(String&s, const String& a) inline String& -stringAppend(String& s, size_t n, char c) +stringAppend(String& s, std::size_t n, char c) { return s.append(n, c); } @@ -682,7 +679,7 @@ inline OptionNames split_option_names(const std::string &text) "abcdefghijklmnopqrstuvwxyz" "0123456789" "_-"; - if (!std::isalnum(text[token_start_pos]) || + if (!std::isalnum(text[token_start_pos], std::locale::classic()) || text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) { throw_or_mimic(text); } @@ -701,11 +698,11 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched) if (strncmp(pdata, "--", 2) == 0) { pdata += 2; - if (isalnum(*pdata)) + if (isalnum(*pdata, std::locale::classic())) { argu_desc.arg_name.push_back(*pdata); pdata += 1; - while (isalnum(*pdata) || *pdata == '-' || *pdata == '_') + while (isalnum(*pdata, std::locale::classic()) || *pdata == '-' || *pdata == '_') { argu_desc.arg_name.push_back(*pdata); pdata += 1; @@ -733,7 +730,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched) { pdata += 1; argu_desc.grouping = true; - while (isalnum(*pdata)) + while (isalnum(*pdata, std::locale::classic())) { argu_desc.arg_name.push_back(*pdata); pdata += 1; @@ -1356,7 +1353,7 @@ class OptionDetails return m_long; } - size_t + std::size_t hash() const { return m_hash; @@ -1369,7 +1366,7 @@ class OptionDetails std::shared_ptr m_value{}; int m_count; - size_t m_hash{}; + std::size_t m_hash{}; }; struct HelpOptionDetails @@ -1430,7 +1427,7 @@ CXXOPTS_IGNORE_WARNING("-Wnull-dereference") #endif CXXOPTS_NODISCARD - size_t + std::size_t count() const noexcept { return m_count; @@ -1475,7 +1472,7 @@ CXXOPTS_DIAGNOSTIC_POP // Holding this pointer is safe, since OptionValue's only exist in key-value pairs, // where the key has the string we point to. std::shared_ptr m_value{}; - size_t m_count = 0; + std::size_t m_count = 0; bool m_default = false; }; @@ -1516,8 +1513,8 @@ class KeyValue std::string m_value; }; -using ParsedHashMap = std::unordered_map; -using NameHashMap = std::unordered_map; +using ParsedHashMap = std::unordered_map; +using NameHashMap = std::unordered_map; class ParseResult { @@ -1611,7 +1608,7 @@ class ParseResult return Iterator(this, true); } - size_t + std::size_t count(const std::string& o) const { auto iter = m_keys.find(o); @@ -1821,7 +1818,7 @@ class Options } Options& - set_width(size_t width) + set_width(std::size_t width) { m_width = width; return *this; @@ -1939,7 +1936,7 @@ class Options std::string m_positional_help{}; bool m_show_positional; bool m_allow_unrecognised; - size_t m_width; + std::size_t m_width; bool m_tab_expansion; std::shared_ptr m_options; @@ -1975,8 +1972,8 @@ class OptionAdder }; namespace { -constexpr size_t OPTION_LONGEST = 30; -constexpr size_t OPTION_DESC_GAP = 2; +constexpr std::size_t OPTION_LONGEST = 30; +constexpr std::size_t OPTION_DESC_GAP = 2; String format_option @@ -2028,8 +2025,8 @@ String format_description ( const HelpOptionDetails& o, - size_t start, - size_t allowed, + std::size_t start, + std::size_t allowed, bool tab_expansion ) { @@ -2052,7 +2049,7 @@ format_description if (tab_expansion) { String desc2; - auto size = size_t{ 0 }; + auto size = std::size_t{ 0 }; for (auto c = std::begin(desc); c != std::end(desc); ++c) { if (*c == '\n') @@ -2082,7 +2079,7 @@ format_description auto startLine = current; auto lastSpace = current; - auto size = size_t{}; + auto size = std::size_t{}; bool appendNewLine; bool onlyWhiteSpace = true; @@ -2090,13 +2087,11 @@ format_description while (current != std::end(desc)) { appendNewLine = false; - - if (std::isblank(*previous, std::locale::classic())) + if (*previous == ' ' || *previous == '\t') { lastSpace = current; } - - if (!std::isblank(*current, std::locale::classic())) + if (*current != ' ' && *current != '\t') { onlyWhiteSpace = false; } @@ -2622,7 +2617,7 @@ Options::help_one_group(const std::string& g) const OptionHelp format; - size_t longest = 0; + std::size_t longest = 0; String result; @@ -2647,7 +2642,7 @@ Options::help_one_group(const std::string& g) const longest = (std::min)(longest, OPTION_LONGEST); //widest allowed description -- min 10 chars for helptext/line - size_t allowed = 10; + std::size_t allowed = 10; if (m_width > allowed + longest + OPTION_DESC_GAP) { allowed = m_width - longest - OPTION_DESC_GAP; @@ -2694,7 +2689,7 @@ Options::generate_group_help const std::vector& print_groups ) const { - for (size_t i = 0; i != print_groups.size(); ++i) + for (std::size_t i = 0; i != print_groups.size(); ++i) { const String& group_help_text = help_one_group(print_groups[i]); if (empty(group_help_text)) From 2123115f71f05846ec786d46ae34fc9666d2e165 Mon Sep 17 00:00:00 2001 From: jarro2783 Date: Mon, 26 Sep 2022 06:59:38 +1000 Subject: [PATCH 5/5] Improve positional help description. Minor change to the positional option description in README. --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c5cb132..de69e5a 100644 --- a/README.md +++ b/README.md @@ -139,10 +139,13 @@ options.add_options() ("server", "The server to execute on", cxxopts::value()) ("filenames", "The filename(s) to process", cxxopts::value>()); -options.parse_positional({"script", "server", "filenames"}) +options.parse_positional({"script", "server", "filenames"}); + +// Parse options the usual way +options.parse(argc, argv); ``` -Then parsing a set of arguments like: +For example, parsing the following arguments: ~~~ my_script.py my_server.com file1.txt file2.txt file3.txt ~~~