diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index dce6066..c62644a 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -6,27 +6,32 @@ on: jobs: build: - name: Build examples + name: Build and run tests runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - - name: Prepare - shell: bash + - name: Prepare env run: | sudo bash ./scripts/env/install_clang17_toolchain.sh continue-on-error: false - - name: Build - shell: bash + - name: Prepare env: CC: clang-17 CXX: clang++-17 run: | - cd example cmake -B build -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_COMPILER=clang-17 - cd build - make + continue-on-error: false + + - name: Build test executable + run: | + cd build && make + continue-on-error: false + + - name: Run tests + run: | + .build/test/run_tests continue-on-error: false diff --git a/.github/workflows/gpp.yaml b/.github/workflows/gpp.yaml index d561f21..67097f4 100644 --- a/.github/workflows/gpp.yaml +++ b/.github/workflows/gpp.yaml @@ -6,21 +6,27 @@ on: jobs: build: - name: Build examples + name: Build and run tests runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - - name: Build - shell: bash + - name: Prepare env: CC: gcc-11 CXX: g++-11 run: | - cd example cmake -B build -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_C_COMPILER=gcc-11 - cd build - make + continue-on-error: false + + - name: Build test executable + run: | + cd build && make + continue-on-error: false + + - name: Run tests + run: | + .build/test/run_tests continue-on-error: false diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml deleted file mode 100644 index 1c1b277..0000000 --- a/.github/workflows/test.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: test -on: - push: - branches: - - '*' - -jobs: - build_and_test: - name: Build and Test - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Prepare - env: - CC: gcc-11 - CXX: g++-11 - run: | - cmake -B build -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_C_COMPILER=gcc-11 - continue-on-error: false - - - name: Build test executable - run: | - cd build && make - continue-on-error: false - - - name: Run tests - run: | - ./build/test/run_test - continue-on-error: false diff --git a/README.md b/README.md index 1b35e09..4afbdcc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ Command-line argument parser for C++20 [![g++](https://github.com/SpectraL519/cpp-ap/actions/workflows/gpp.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/g++) [![clang++](https://github.com/SpectraL519/cpp-ap/actions/workflows/clang.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/clang++) -[![test](https://github.com/SpectraL519/cpp-ap/actions/workflows/test.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/test) [![format](https://github.com/SpectraL519/cpp-ap/actions/workflows/format.yaml/badge.svg)](https://github.com/SpectraL519/cpp-ap/actions/workflows/format)
@@ -467,35 +466,7 @@ int main(int argc, char* argv[]) { ## Examples -If you wish to test the parser functionality with some real examples then follow these steps: - -Open your terminal in the project's example directory: -```shell -cd /example -``` - -The examples' source files are in the `/example/source` directory. - -> [!NOTE] -> Each source file is a sepparate example. - -Building the examples: - -```shell -cmake -B build -cd build -make -``` - -or - -```shell -mkdir build && cd build -cmake .. -make -``` - -The compiled binaries will appear in the `/example/build/bin` directory. +The library usage examples / demo projects can be found in the [cpp-ap-demo](https://github.com/SpectraL519/cpp-ap-demo) repository.

@@ -538,8 +509,8 @@ Run the tests: ./run_tests -ts="" ``` - > [!NOTE] - > Test suites in the project have the same names as the files they're in. +> [!NOTE] +> Test suites in the project have the same names as the files they're in.
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt deleted file mode 100644 index 7db437b..0000000 --- a/example/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# Minimum CMake version required to build the project -cmake_minimum_required(VERSION 3.12) - -# Project -project(cpp-ap-examples) - -# Structure -set(SOURCE_DIR "source") -set(INCLUDE_DIRS "include" "../include") -set(BINARY_DIR "bin") -set(EXECUTABLE_DIR "bin") - -# Source files -file(GLOB_RECURSE SOURCES "${SOURCE_DIR}/*.cpp") - -# Include dirs -include_directories(${INCLUDE_DIRS}) - -# Default compiler options -set(DEFAULT_CXX_FLAGS "-Wall -Wextra -Wcast-align -Wconversion -Wunreachable-code -Wuninitialized -pedantic -g -O3") - -# Set compiler options -if(NOT DEFINED CMAKE_CXX_FLAGS) - set(CMAKE_CXX_FLAGS ${DEFAULT_CXX_FLAGS} CACHE STRING "Default C++ compile flags" FORCE) -endif() - -# Executables -foreach(source_file ${SOURCES}) - # get file name without extensions - get_filename_component(executable_name ${source_file} NAME_WE) - - add_executable(${executable_name} ${source_file}) - # Target properties - set_target_properties(${executable_name} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY "${BINARY_DIR}" - CXX_STANDARD 20 - CXX_STANDARD_REQUIRED YES - CXX_EXTENSIONS NO - ) - target_compile_options(${executable_name} PRIVATE ${CMAKE_CXX_FLAGS}) -endforeach() - -# Executable path -set(EXECUTABLE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${EXECUTABLE_DIR}") - -# Symbolic links -foreach(config ${CMAKE_CONFIGURATION_TYPES}) - file(CREATE_LINK "${BINARY_DIR}/test" "${EXECUTABLE_PATH}/test_${config}" SYMBOLIC) -endforeach(config) diff --git a/example/source/convert_numbers.cpp b/example/source/convert_numbers.cpp deleted file mode 100644 index 21ee5c9..0000000 --- a/example/source/convert_numbers.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include - -#include -#include - -int main(int argc, char* argv[]) { - ap::argument_parser parser; - parser.program_name("convert numbers") - .program_description("shows the correct way of using dthe choices parameter") - .default_optional_arguments({ ap::default_argument::optional::help }); - - parser.add_optional_argument("number", "n").nargs(ap::nargs::any()).help("positive integer value"); - parser.add_optional_argument("base", "b") - .required() - .default_value("dec") - .choices({ "bin", "dec", "hex" }) - .help("output number format base"); - - try { - parser.parse_args(argc, argv); - } - catch (const ap::argument_parser_error& err) { - std::cerr << "[ERROR] : " << err.what() << std::endl << parser << std::endl; - std::exit(EXIT_FAILURE); - } - - if (parser.value("help")) { - std::cout << parser << std::endl; - std::exit(EXIT_SUCCESS); - } - - const auto numbers = parser.values("number"); - const auto base = parser.value("base"); - - if (base == "bin") { - constexpr std::size_t nbits = sizeof(std::size_t) * 8; - for (const auto n : numbers) - std::cout << std::bitset(n) << std::endl; - } - else if (base == "dec") { - for (const auto n : numbers) - std::cout << n << std::endl; - } - else { - std::cout << std::hex; - for (const auto n : numbers) - std::cout << n << std::endl; - } - - return 0; -} diff --git a/example/source/merge_files.cpp b/example/source/merge_files.cpp deleted file mode 100644 index eed1c2a..0000000 --- a/example/source/merge_files.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include - -#include -#include -#include - -int main(int argc, char* argv[]) { - ap::argument_parser parser; - parser.program_name("merge files") - .program_description("shows the correct way of using default arguments") - .default_optional_arguments( - { ap::default_argument::optional::help, - ap::default_argument::optional::multi_input, - ap::default_argument::optional::output } - ); - - try { - parser.parse_args(argc, argv); - } - catch (const ap::argument_parser_error& err) { - std::cerr << "[ERROR] : " << err.what() << std::endl << parser << std::endl; - std::exit(EXIT_FAILURE); - } - - if (parser.value("help")) { - std::cout << parser << std::endl; - std::exit(EXIT_SUCCESS); - } - - const auto input_file_name_list = parser.values("input"); - const auto output_file_name = parser.value("output"); - - std::ofstream output_file(output_file_name); - if (not output_file.is_open()) - throw std::runtime_error("Cannot open file: " + output_file_name); - - for (const auto& input_file_name : input_file_name_list) { - std::ifstream input_file(input_file_name); - std::stringstream buff; - buff << input_file.rdbuf(); - output_file << buff.str(); - } - - return 0; -} diff --git a/example/source/power.cpp b/example/source/power.cpp deleted file mode 100644 index 2cc3499..0000000 --- a/example/source/power.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include - -#include -#include - -int main(int argc, char* argv[]) { - // create the parser class instance - ap::argument_parser parser; - parser.program_name("power calculator").program_description("calculates the value of an expression: base & exponent"); - - // add arguments - parser.add_positional_argument("base").help("the exponentation base value"); - parser.add_optional_argument("exponent", "e").nargs(ap::nargs::any()).help("the exponent value"); - - parser.default_optional_arguments({ ap::default_argument::optional::help }); - - // parse command-line arguments - try { - parser.parse_args(argc, argv); - } - catch (const ap::argument_parser_error& err) { - std::cerr << "[ERROR] : " << err.what() << std::endl << parser << std::endl; - std::exit(EXIT_FAILURE); - } - - // check for the help argument presence - if (parser.has_value("help")) { - std::cout << parser << std::endl; - std::exit(EXIT_SUCCESS); - } - - // check if any values for the `exponent` argument have been parsed - if (not parser.has_value("exponent")) { - std::cout << "no exponent values given" << std::endl; - std::exit(EXIT_SUCCESS); - } - - const double base = parser.value("base"); - const std::vector exponent_values = parser.values("exponent"); - - for (const int exponent : exponent_values) { - std::cout << base << " ^ " << exponent << " = " << std::pow(base, exponent) << std::endl; - } - - return 0; -} diff --git a/example/source/verbosity.cpp b/example/source/verbosity.cpp deleted file mode 100644 index c100a0e..0000000 --- a/example/source/verbosity.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include - -#include -#include - -namespace { - -enum class verbosity_level : uint16_t { low, mid, high }; - -std::istream& operator>>(std::istream& input, verbosity_level& v) { - uint16_t value; - input >> value; - - // Map the integer input to the corresponding enum value - switch (value) { - case 0u: - v = verbosity_level::low; - break; - - case 1u: - v = verbosity_level::mid; - break; - - case 2u: - v = verbosity_level::high; - break; - - default: - std::cerr << "[ERROR] : Invalid verbosity_level value - " << value << std::endl; - std::exit(EXIT_FAILURE); - } - - return input; -} - -void print_msg(const verbosity_level verbosity) { - switch (verbosity) { - case verbosity_level::low: - break; - - case verbosity_level::mid: - std::cout << "msg" << std::endl; - break; - - case verbosity_level::high: - std::cout << "this is a really verbose message" << std::endl; - break; - } -} - -} // namespace - -int main(int argc, char* argv[]) { - ap::argument_parser parser; - parser.program_name("verbosity level") - .program_description("shows the correct way of using enums as a parser argument type") - .default_optional_arguments({ ap::default_argument::optional::help }); - - parser.add_optional_argument("verbosity_level", "v") - .default_value(verbosity_level::low) - .implicit_value(verbosity_level::mid) - .nargs(1); - - try { - parser.parse_args(argc, argv); - } - catch (const ap::argument_parser_error& err) { - std::cerr << "[ERROR] : " << err.what() << std::endl << parser << std::endl; - std::exit(EXIT_FAILURE); - } - - if (parser.value("help")) { - std::cout << parser << std::endl; - std::exit(EXIT_SUCCESS); - } - - print_msg(parser.value("verbosity_level")); - - return 0; -}