Skip to content

Commit b7bdcad

Browse files
authored
YT-CPPAP-26: Split the implementation to separate header files
- Split the library implementation into multiple header files - Changed the license info in all implementation files - Changed the names of some elements to better describe their purpose
1 parent d288aff commit b7bdcad

29 files changed

+1537
-1476
lines changed

.gitmodules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[submodule "cpp-ap-demo"]
22
path = cpp-ap-demo
33
url = https://github.com/SpectraL519/cpp-ap-demo.git
4+
branch = cpp-ap-v2

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ else()
88
endif()
99

1010
project(cpp-ap
11-
VERSION 1.0
11+
VERSION 2.0.0
1212
DESCRIPTION "Command-line argument parser for C++20"
1313
HOMEPAGE_URL "https://github.com/SpectraL519/cpp-ap"
1414
LANGUAGES CXX

Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = "CPP-AP"
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = 1.2
51+
PROJECT_NUMBER = 2.0.0
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewer a

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2023-2024 Jakub Musiał and other contributors
3+
Copyright (c) 2023-2025 Jakub Musiał and other contributors
44
https://github.com/SpectraL519/cpp-ap
55

66
Permission is hereby granted, free of charge, to any person obtaining a copy

README.md

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ Command-line argument parser for C++20
1111

1212
## Overview
1313

14-
The goal of the project was to create a light, intuitive and simple to use command-line argument parser library for the `C++20` and newer standards.
15-
16-
The `CPP-AP` library does not require installing any additional tools or heavy libraries, like with `boost::program_options`. Much like with the `Doctest` framework - the only thing you need to do is copy the `argument_parser.hpp` file into the include directory of your project and you're set to go.
14+
`CPP-AP` is a lightweight and feature-rich command-line argument parsing library, designed as an alternative to `boost::program_options`. It offers a modern, intuitive interface allowing for straightforward argument configuration and parsing.
1715

1816
> [!NOTE]
1917
> [v1.0](https://github.com/SpectraL519/cpp-ap/commit/9a9e5360766b732f322ae2efe3cf5ec5f9268eef) of the library has been developed for the *Team Programming* course at the *Wrocław University of Science and Technology*.
@@ -201,35 +199,38 @@ Parameters which can be specified for both positional and optional arguments inc
201199
202200
- `action` - a function performed after reading an argument's value.
203201
Actions are represented as functions, which take the argument's value as an argument. There are two types of actions:
204-
- Void actions - `void(value_type&)`
205-
- Valued actions - `value_type(const value_type&)`
206-
207-
The default action is an empty void function.
202+
- `modify` actions | `void(value_type&)` - applied to the initialized value of an argument.
208203
209-
Actions can be used to modify a value parsed from the command-line:
204+
```c++
205+
parser.add_optional_argument<std::string>("name", "n")
206+
.action<ap::action_type::modify>([](std::string& name) { name[0] = std::toupper(name[0]); });
207+
```
210208
211-
```c++
212-
parser.add_optional_argument<double>("denominator", "d")
213-
.action<ap::void_action>([](double& value) { value = 1. / value; });
214-
```
209+
- `transform` actions | `value_type(const value_type&)` - applied to the parsed value. The returned value will be used to initialize the argument's value.
215210
216-
or en equivalent valued action:
211+
```c++
212+
std::string to_lower(std::string s) {
213+
for (auto& c : s)
214+
c = static_cast<char>(std::tolower(c));
215+
return s;
216+
}
217217
218-
```c++
219-
parser.add_optional_argument<double>("denominator", "d")
220-
.action<ap::valued_action>([](const double& value) { return 1. / value; });
221-
```
218+
parser.add_optional_argument<std::string>("key", "k")
219+
.action<ap::action_type::transform>(to_lower);
220+
```
222221
223-
Actions can also be used to perform some value checking logic, e.g. the predefined `check_file_exists` which checks if a file with a given name exists:
222+
Actions can also be used to perform some value checking logic instead of actualy modifying or transforming a value, as e.g. the predefined `check_file_exists` which verifies whether a file with a given name exists:
224223
225224
```c++
226225
parser.add_optional_argument("input", "i")
227-
.action<ap::void_action>(ap::action::check_file_exists());
226+
.action<ap::action_type::modify>(ap::action::check_file_exists());
228227
```
229228
229+
> **NOTE:** The default action is an empty `modify` action.
230+
230231
#### Optional argument specific parameters
231232
232-
- `required` - if this option is set for an argument, failure of parsing it's value will result in an error.
233+
- `required` - if this option is set for an argument and it's value is not passed in the command-line, an exception will be thrown.
233234
234235
```c++
235236
parser.add_optional_argument("output", "o").required();
@@ -293,11 +294,11 @@ The `CPP-AP` library has a few default arguments defined. To add a default argum
293294
```c++
294295
// add positional arguments - pass a std::vector of default positional arguments
295296
parser.default_positional_arguments({...});
296-
// here ... represents a list of ap::default_argument::positional values (or alternatively ap::default_posarg)
297+
// here `...` represents a list of ap::argument::default_positional values
297298
298299
// add optional arguments - pass a std::vector of default optional arguments
299300
parser.default_positional_arguments({...});
300-
// here ... represents a list of ap::default_argument::optional values (or alternatively ap::default_optarg)
301+
// here `...` represents a list of ap::argument::default_optional values
301302
```
302303
303304
The supported default arguments are:
@@ -307,7 +308,7 @@ The supported default arguments are:
307308
```c++
308309
// equivalent to:
309310
parser.add_positional_argument<std::string>("input")
310-
.action<ap::void_action>(ap::action::check_file_exists())
311+
.action<ap::action_type::modify>(ap::action::check_file_exists())
311312
.help("Input file path");
312313
```
313314
@@ -343,14 +344,14 @@ The supported default arguments are:
343344
parser.add_optional_argument("input", "i")
344345
.required()
345346
.nargs(1)
346-
.action<ap::void_action>(ap::action::check_file_exists())
347+
.action<ap::action_type::modify>(ap::action::check_file_exists())
347348
.help("Input file path");
348349
349350
// multi_input - equivalent to:
350351
parser.add_optional_argument("input", "i")
351352
.required()
352353
.nargs(ap::nargs::at_least(1))
353-
.action<ap::void_action>(ap::action::check_file_exists())
354+
.action<ap::action_type::modify>(ap::action::check_file_exists())
354355
.help("Input files paths");
355356
```
356357
@@ -402,7 +403,7 @@ int main(int argc, char* argv[]) {
402403
try {
403404
parser.parse_args(argc, argv);
404405
}
405-
catch (const ap::argument_parser_error& err) {
406+
catch (const ap::argument_parser_exception& err) {
406407
std::cerr << "[ERROR] : " << err.what() << std::endl << parser << std::endl;
407408
std::exit(EXIT_FAILURE);
408409
}
@@ -437,7 +438,7 @@ int main(int argc, char* argv[]) {
437438
438439
- Positional arguments are parsed first, in the order they were defined in and without a flag.
439440
440-
In the example above the first command-line argument must be the value for `positional_argument`:
441+
In the example above the first command-line argument must be the value for the `positional` argument:
441442
442443
```shell
443444
./power 2

include/ap/action/detail/utility.hpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2023-2025 Jakub Musiał
2+
// This file is part of the CPP-AP project (https://github.com/SpectraL519/cpp-ap).
3+
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
4+
5+
#pragma once
6+
7+
#include "ap/action/specifiers.hpp"
8+
9+
namespace ap::action::detail {
10+
11+
/**
12+
* @brief The concept is satisfied when `AS` is either a valued or void argument action
13+
* @tparam AS The action specifier type.
14+
*/
15+
template <typename AS>
16+
concept c_action_specifier = ap::detail::c_one_of<AS, action_type::transform, action_type::modify>;
17+
18+
/// @brief Template argument action callable type alias.
19+
template <c_action_specifier AS, ap::detail::c_argument_value_type T>
20+
using callable_type = typename AS::template type<T>;
21+
22+
/// @brief Template argument action callabla variant type alias.
23+
template <ap::detail::c_argument_value_type T>
24+
using action_variant_type =
25+
std::variant<callable_type<action_type::transform, T>, callable_type<action_type::modify, T>>;
26+
27+
/**
28+
* @brief Checks if an argument action variant holds a void action.
29+
* @tparam T The argument value type.
30+
* @param action The action variant.
31+
* @return True if the held action is a void action.
32+
*/
33+
template <ap::detail::c_argument_value_type T>
34+
[[nodiscard]] constexpr inline bool is_modify_action(const action_variant_type<T>& action
35+
) noexcept {
36+
return std::holds_alternative<callable_type<action_type::modify, T>>(action);
37+
}
38+
39+
} // namespace ap::action::detail
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2023-2025 Jakub Musiał
2+
// This file is part of the CPP-AP project (https://github.com/SpectraL519/cpp-ap).
3+
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
4+
5+
#pragma once
6+
7+
#include "ap/error/exceptions.hpp"
8+
#include "detail/utility.hpp"
9+
10+
#include <filesystem>
11+
12+
namespace ap::action {
13+
14+
/// @brief Returns a default argument action.
15+
template <ap::detail::c_argument_value_type T>
16+
detail::callable_type<ap::action_type::modify, T> none() noexcept {
17+
return [](T&) {};
18+
}
19+
20+
/// @brief Returns a predefined action for file name handling arguments. Checks whether a file with the given name exists.
21+
inline detail::callable_type<ap::action_type::modify, std::string> check_file_exists() noexcept {
22+
return [](std::string& file_path) {
23+
if (not std::filesystem::exists(file_path))
24+
throw argument_parser_exception(std::format("File `{}` does not exists!", file_path));
25+
};
26+
}
27+
28+
} // namespace ap::action

include/ap/action/specifiers.hpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2023-2025 Jakub Musiał
2+
// This file is part of the CPP-AP project (https://github.com/SpectraL519/cpp-ap).
3+
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
4+
5+
#pragma once
6+
7+
#include "ap/detail/concepts.hpp"
8+
9+
#include <functional>
10+
11+
namespace ap::action_type {
12+
13+
// TODO:
14+
// * on_read_action
15+
// * on_flag_action
16+
17+
/*
18+
* @brief Represents a transformating action.
19+
*
20+
* Represents an argument action which transforms the parsed value and
21+
* returns a new value with which the argument will be initialized.
22+
*/
23+
struct transform {
24+
template <ap::detail::c_argument_value_type T>
25+
using type = std::function<T(const T&)>;
26+
};
27+
28+
/*
29+
* @brief Represents a modifying action.
30+
*
31+
* Represents an argument action which modifies the value of an
32+
* already initialized argument.
33+
*
34+
* NOTE: The modify action doesn't have to actually modify the
35+
* underlying value - it can simply perform some action on it.
36+
* Example: `ap::action::check_file_exists`
37+
*/
38+
struct modify {
39+
template <ap::detail::c_argument_value_type T>
40+
using type = std::function<void(T&)>;
41+
};
42+
43+
} // namespace ap::action_type

include/ap/argument/default.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright (c) 2023-2025 Jakub Musiał
2+
// This file is part of the CPP-AP project (https://github.com/SpectraL519/cpp-ap).
3+
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
4+
5+
#pragma once
6+
7+
#include <cstdint>
8+
9+
namespace ap::argument {
10+
11+
/// @brief Enum class representing positional arguments.
12+
enum class default_positional : uint8_t { input, output };
13+
14+
/// @brief Enum class representing optional arguments.
15+
enum class default_optional : uint8_t { help, input, output, multi_input, multi_output };
16+
17+
} // namespace ap::argument

0 commit comments

Comments
 (0)