Merge branch 'master' into add-option-chars
This commit is contained in:
commit
e3e4b7fbd8
81
.github/workflows/cmake.yml
vendored
81
.github/workflows/cmake.yml
vendored
@ -2,43 +2,70 @@ name: CMake
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ master, main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
branches: [ master, main ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
BUILD_TYPE: Release
|
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:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-18.04]
|
os: [ ubuntu-18.04, ubuntu-20.04, ubuntu-22.04 ]
|
||||||
compiler: [g++-7, g++-9, g++-10, clang++]
|
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:
|
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
|
build-macos:
|
||||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
name: Build and Test on MacOS
|
||||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
strategy:
|
||||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=${{matrix.compiler}}
|
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-windows:
|
||||||
# Build your program with the given configuration
|
name: Build and Test on Windows
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
- name: Test
|
- uses: actions/checkout@v3
|
||||||
working-directory: ${{github.workspace}}/build
|
- uses: ilammy/msvc-dev-cmd@v1
|
||||||
# Execute tests defined by the CMake configuration.
|
- name: Configure CMake
|
||||||
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
|
run: cmake -S "${{github.workspace}}" -B "${{github.workspace}}/build" -DCMAKE_BUILD_TYPE=$BUILD_TYPE -T "ClangCl"
|
||||||
run: ctest -C ${{env.BUILD_TYPE}}
|
- 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
|
||||||
|
|||||||
@ -139,10 +139,13 @@ options.add_options()
|
|||||||
("server", "The server to execute on", cxxopts::value<std::string>())
|
("server", "The server to execute on", cxxopts::value<std::string>())
|
||||||
("filenames", "The filename(s) to process", cxxopts::value<std::vector<std::string>>());
|
("filenames", "The filename(s) to process", cxxopts::value<std::vector<std::string>>());
|
||||||
|
|
||||||
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
|
my_script.py my_server.com file1.txt file2.txt file3.txt
|
||||||
~~~
|
~~~
|
||||||
|
|||||||
@ -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
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -27,12 +27,10 @@ THE SOFTWARE.
|
|||||||
#ifndef CXXOPTS_HPP_INCLUDED
|
#ifndef CXXOPTS_HPP_INCLUDED
|
||||||
#define CXXOPTS_HPP_INCLUDED
|
#define CXXOPTS_HPP_INCLUDED
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cctype>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <list>
|
#include <initializer_list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -195,9 +193,9 @@ stringAppend(String&s, String a)
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
String&
|
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);
|
s.append(c);
|
||||||
}
|
}
|
||||||
@ -219,7 +217,7 @@ stringAppend(String& s, Iterator begin, Iterator end)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
size_t
|
std::size_t
|
||||||
stringLength(const String& s)
|
stringLength(const String& s)
|
||||||
{
|
{
|
||||||
return s.length();
|
return s.length();
|
||||||
@ -277,7 +275,7 @@ toLocalString(T&& t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
size_t
|
std::size_t
|
||||||
stringLength(const String& s)
|
stringLength(const String& s)
|
||||||
{
|
{
|
||||||
return s.length();
|
return s.length();
|
||||||
@ -292,7 +290,7 @@ stringAppend(String&s, const String& a)
|
|||||||
|
|
||||||
inline
|
inline
|
||||||
String&
|
String&
|
||||||
stringAppend(String& s, size_t n, char c)
|
stringAppend(String& s, std::size_t n, char c)
|
||||||
{
|
{
|
||||||
return s.append(n, c);
|
return s.append(n, c);
|
||||||
}
|
}
|
||||||
@ -681,7 +679,8 @@ inline OptionNames split_option_names(const std::string &text)
|
|||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
"0123456789"
|
"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) {
|
text.find_first_not_of(option_name_valid_chars, token_start_pos) < next_delimiter_pos) {
|
||||||
throw_or_mimic<exceptions::invalid_option_format>(text);
|
throw_or_mimic<exceptions::invalid_option_format>(text);
|
||||||
}
|
}
|
||||||
@ -700,11 +699,11 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched)
|
|||||||
if (strncmp(pdata, "--", 2) == 0)
|
if (strncmp(pdata, "--", 2) == 0)
|
||||||
{
|
{
|
||||||
pdata += 2;
|
pdata += 2;
|
||||||
if (isalnum(*pdata))
|
if (isalnum(*pdata, std::locale::classic()))
|
||||||
{
|
{
|
||||||
argu_desc.arg_name.push_back(*pdata);
|
argu_desc.arg_name.push_back(*pdata);
|
||||||
pdata += 1;
|
pdata += 1;
|
||||||
while (isalnum(*pdata) || *pdata == '-' || *pdata == '_')
|
while (isalnum(*pdata, std::locale::classic()) || *pdata == '-' || *pdata == '_')
|
||||||
{
|
{
|
||||||
argu_desc.arg_name.push_back(*pdata);
|
argu_desc.arg_name.push_back(*pdata);
|
||||||
pdata += 1;
|
pdata += 1;
|
||||||
@ -732,7 +731,7 @@ inline ArguDesc ParseArgument(const char *arg, bool &matched)
|
|||||||
{
|
{
|
||||||
pdata += 1;
|
pdata += 1;
|
||||||
argu_desc.grouping = true;
|
argu_desc.grouping = true;
|
||||||
while (isalnum(*pdata))
|
while (isalnum(*pdata, std::locale::classic()))
|
||||||
{
|
{
|
||||||
argu_desc.arg_name.push_back(*pdata);
|
argu_desc.arg_name.push_back(*pdata);
|
||||||
pdata += 1;
|
pdata += 1;
|
||||||
@ -1355,7 +1354,7 @@ class OptionDetails
|
|||||||
return m_long;
|
return m_long;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
hash() const
|
hash() const
|
||||||
{
|
{
|
||||||
return m_hash;
|
return m_hash;
|
||||||
@ -1368,7 +1367,7 @@ class OptionDetails
|
|||||||
std::shared_ptr<const Value> m_value{};
|
std::shared_ptr<const Value> m_value{};
|
||||||
int m_count;
|
int m_count;
|
||||||
|
|
||||||
size_t m_hash{};
|
std::size_t m_hash{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HelpOptionDetails
|
struct HelpOptionDetails
|
||||||
@ -1429,7 +1428,7 @@ CXXOPTS_IGNORE_WARNING("-Wnull-dereference")
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
CXXOPTS_NODISCARD
|
CXXOPTS_NODISCARD
|
||||||
size_t
|
std::size_t
|
||||||
count() const noexcept
|
count() const noexcept
|
||||||
{
|
{
|
||||||
return m_count;
|
return m_count;
|
||||||
@ -1474,7 +1473,7 @@ CXXOPTS_DIAGNOSTIC_POP
|
|||||||
// Holding this pointer is safe, since OptionValue's only exist in key-value pairs,
|
// Holding this pointer is safe, since OptionValue's only exist in key-value pairs,
|
||||||
// where the key has the string we point to.
|
// where the key has the string we point to.
|
||||||
std::shared_ptr<Value> m_value{};
|
std::shared_ptr<Value> m_value{};
|
||||||
size_t m_count = 0;
|
std::size_t m_count = 0;
|
||||||
bool m_default = false;
|
bool m_default = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1515,8 +1514,8 @@ class KeyValue
|
|||||||
std::string m_value;
|
std::string m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
using ParsedHashMap = std::unordered_map<size_t, OptionValue>;
|
using ParsedHashMap = std::unordered_map<std::size_t, OptionValue>;
|
||||||
using NameHashMap = std::unordered_map<std::string, size_t>;
|
using NameHashMap = std::unordered_map<std::string, std::size_t>;
|
||||||
|
|
||||||
class ParseResult
|
class ParseResult
|
||||||
{
|
{
|
||||||
@ -1610,7 +1609,7 @@ class ParseResult
|
|||||||
return Iterator(this, true);
|
return Iterator(this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
std::size_t
|
||||||
count(const std::string& o) const
|
count(const std::string& o) const
|
||||||
{
|
{
|
||||||
auto iter = m_keys.find(o);
|
auto iter = m_keys.find(o);
|
||||||
@ -1820,7 +1819,7 @@ class Options
|
|||||||
}
|
}
|
||||||
|
|
||||||
Options&
|
Options&
|
||||||
set_width(size_t width)
|
set_width(std::size_t width)
|
||||||
{
|
{
|
||||||
m_width = width;
|
m_width = width;
|
||||||
return *this;
|
return *this;
|
||||||
@ -1938,7 +1937,7 @@ class Options
|
|||||||
std::string m_positional_help{};
|
std::string m_positional_help{};
|
||||||
bool m_show_positional;
|
bool m_show_positional;
|
||||||
bool m_allow_unrecognised;
|
bool m_allow_unrecognised;
|
||||||
size_t m_width;
|
std::size_t m_width;
|
||||||
bool m_tab_expansion;
|
bool m_tab_expansion;
|
||||||
|
|
||||||
std::shared_ptr<OptionMap> m_options;
|
std::shared_ptr<OptionMap> m_options;
|
||||||
@ -1974,8 +1973,8 @@ class OptionAdder
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr size_t OPTION_LONGEST = 30;
|
constexpr std::size_t OPTION_LONGEST = 30;
|
||||||
constexpr size_t OPTION_DESC_GAP = 2;
|
constexpr std::size_t OPTION_DESC_GAP = 2;
|
||||||
|
|
||||||
String
|
String
|
||||||
format_option
|
format_option
|
||||||
@ -2027,8 +2026,8 @@ String
|
|||||||
format_description
|
format_description
|
||||||
(
|
(
|
||||||
const HelpOptionDetails& o,
|
const HelpOptionDetails& o,
|
||||||
size_t start,
|
std::size_t start,
|
||||||
size_t allowed,
|
std::size_t allowed,
|
||||||
bool tab_expansion
|
bool tab_expansion
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -2051,7 +2050,7 @@ format_description
|
|||||||
if (tab_expansion)
|
if (tab_expansion)
|
||||||
{
|
{
|
||||||
String desc2;
|
String desc2;
|
||||||
auto size = size_t{ 0 };
|
auto size = std::size_t{ 0 };
|
||||||
for (auto c = std::begin(desc); c != std::end(desc); ++c)
|
for (auto c = std::begin(desc); c != std::end(desc); ++c)
|
||||||
{
|
{
|
||||||
if (*c == '\n')
|
if (*c == '\n')
|
||||||
@ -2081,7 +2080,7 @@ format_description
|
|||||||
auto startLine = current;
|
auto startLine = current;
|
||||||
auto lastSpace = current;
|
auto lastSpace = current;
|
||||||
|
|
||||||
auto size = size_t{};
|
auto size = std::size_t{};
|
||||||
|
|
||||||
bool appendNewLine;
|
bool appendNewLine;
|
||||||
bool onlyWhiteSpace = true;
|
bool onlyWhiteSpace = true;
|
||||||
@ -2089,13 +2088,11 @@ format_description
|
|||||||
while (current != std::end(desc))
|
while (current != std::end(desc))
|
||||||
{
|
{
|
||||||
appendNewLine = false;
|
appendNewLine = false;
|
||||||
|
if (*previous == ' ' || *previous == '\t')
|
||||||
if (std::isblank(*previous))
|
|
||||||
{
|
{
|
||||||
lastSpace = current;
|
lastSpace = current;
|
||||||
}
|
}
|
||||||
|
if (*current != ' ' && *current != '\t')
|
||||||
if (!std::isblank(*current))
|
|
||||||
{
|
{
|
||||||
onlyWhiteSpace = false;
|
onlyWhiteSpace = false;
|
||||||
}
|
}
|
||||||
@ -2621,7 +2618,7 @@ Options::help_one_group(const std::string& g) const
|
|||||||
|
|
||||||
OptionHelp format;
|
OptionHelp format;
|
||||||
|
|
||||||
size_t longest = 0;
|
std::size_t longest = 0;
|
||||||
|
|
||||||
String result;
|
String result;
|
||||||
|
|
||||||
@ -2646,7 +2643,7 @@ Options::help_one_group(const std::string& g) const
|
|||||||
longest = (std::min)(longest, OPTION_LONGEST);
|
longest = (std::min)(longest, OPTION_LONGEST);
|
||||||
|
|
||||||
//widest allowed description -- min 10 chars for helptext/line
|
//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)
|
if (m_width > allowed + longest + OPTION_DESC_GAP)
|
||||||
{
|
{
|
||||||
allowed = m_width - longest - OPTION_DESC_GAP;
|
allowed = m_width - longest - OPTION_DESC_GAP;
|
||||||
@ -2693,7 +2690,7 @@ Options::generate_group_help
|
|||||||
const std::vector<std::string>& print_groups
|
const std::vector<std::string>& print_groups
|
||||||
) const
|
) 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]);
|
const String& group_help_text = help_one_group(print_groups[i]);
|
||||||
if (empty(group_help_text))
|
if (empty(group_help_text))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user