Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ else()
endif()

project(cpp-ap
VERSION 3.0.0.5
VERSION 3.0.0.6
DESCRIPTION "Command-line argument parser for C++20"
HOMEPAGE_URL "https://github.com/SpectraL519/cpp-ap"
LANGUAGES CXX
Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ PROJECT_NAME = CPP-AP
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 3.0.0.5
PROJECT_NUMBER = 3.0.0.6

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module(
name = "cpp-ap",
version = "3.0.0.5",
version = "3.0.0.6",
)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ Command-line argument parser for C++20
- [The Parser Class](/docs/tutorial.md#the-parser-class)
- [Adding Arguments](/docs/tutorial.md#adding-arguments)
- [Argument Parameters](/docs/tutorial.md#argument-parameters)
- [Common Parameters](/docs/tutorial.md##common-parameters)
- [Parameters Specific for Optional Arguments](/docs/tutorial.md##parameters-specific-for-optional-arguments)
- [Common Parameters](/docs/tutorial.md#common-parameters)
Comment thread
SpectraL519 marked this conversation as resolved.
Outdated
- [Parameters Specific for Optional Arguments](/docs/tutorial.md#parameters-specific-for-optional-arguments)
- [Default Arguments](/docs/tutorial.md#default-arguments)
- [Parsing Arguments](/docs/tutorial.md#parsing-arguments)
- [Basic Argument Parsing Rules](/docs/tutorial.md#basic-argument-parsing-rules)
Expand Down
76 changes: 66 additions & 10 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@
- [Adding Arguments](#adding-arguments)
- [Argument Parameters](#argument-parameters)
- [Common Parameters](#common-parameters)
- [help](#1-help---the-arguments-description-which-will-be-printed-when-printing-the-parser-class-instance)
- [hidden](#2-hidden---if-this-option-is-set-for-an-argument-then-it-will-not-be-included-in-the-program-description)
- [required](#3-required---if-this-option-is-set-for-an-argument-and-its-value-is-not-passed-in-the-command-line-an-exception-will-be-thrown)
- [bypass required](#4-bypass_required---if-this-option-is-set-for-an-argument-the-required-option-for-other-arguments-will-be-discarded-if-the-bypassing-argument-is-used-in-the-command-line)
- [nargs](#5-nargs---sets-the-allowed-number-of-values-to-be-parsed-for-an-argument)
- [greedy](#6-greedy---if-this-option-is-set-the-argument-will-consume-all-command-line-values-until-its-upper-nargs-bound-is-reached)
- [choices](#7-choices---a-list-of-valid-argument-values)
- [value actions](#8-value-actions---functions-that-are-called-after-parsing-an-arguments-value)
- [default values](#9-default_values---a-list-of-values-which-will-be-used-if-no-values-for-an-argument-have-been-parsed)
- [Parameters Specific for Optional Arguments](#parameters-specific-for-optional-arguments)
- [on-flag actions](#1-on-flag-actions---functions-that-are-called-immediately-after-parsing-an-arguments-flag)
- [implicit values](#2-implicit_values---a-list-of-values-which-will-be-set-for-an-argument-if-only-its-flag-but-no-values-are-parsed-from-the-command-line)
- [Predefined Parameter Values](#predefined-parameter-values)
- [Default Arguments](#default-arguments)
- [Parsing Arguments](#parsing-arguments)
Expand Down Expand Up @@ -189,9 +200,10 @@ parser.add_<positional/optional>_argument<value_type>("argument", "a");
>
> - If the argument's value type is `ap::none_type`, the argument will not accept any values and therefore no value-related parameters can be set for such argument. This includes:
> - [nargs](#5-nargs---sets-the-allowed-number-of-values-to-be-parsed-for-an-argument-this-can-be-set-as-a)
> - [choices](#6-choices---a-list-of-valid-argument-values)
> - [value actions](#7-value-actions---function-performed-after-parsing-an-arguments-value)
> - [default_values](#8-default_values---a-list-of-values-which-will-be-used-if-no-values-for-an-argument-have-been-parsed)
> - [greedy](#6-greedy---if-this-option-is-set-the-argument-will-consume-all-command-line-values-until-its-upper-nargs-bound-is-reached)
> - [choices](#7-choices---a-list-of-valid-argument-values)
> - [value actions](#8-value-actions---functions-that-are-called-after-parsing-an-arguments-value)
> - [default_values](#9-default_values---a-list-of-values-which-will-be-used-if-no-values-for-an-argument-have-been-parsed)
> - [implicit_values](#2-implicit_values---a-list-of-values-which-will-be-set-for-an-argument-if-only-its-flag-but-no-values-are-parsed-from-the-command-line)

You can also add boolean flags:
Expand Down Expand Up @@ -343,8 +355,8 @@ Command Result

> [!NOTE]
>
> - Both positional and optional arguments have the `bypass_required` option disabled.
> - The default value of the value parameter of the `bypass_required(bool)` function is `true` for both positional and optional arguments.
> - Both all arguments have the `bypass_required` option disabled.
> - The default value of the value parameter of the `argument::bypass_required(bool)` method is `true` for all arguments.

> [!WARNING]
>
Expand Down Expand Up @@ -377,7 +389,9 @@ os << data << std::endl;

<br />

#### 5. `nargs` - Sets the allowed number of values to be parsed for an argument. This can be set as a:
#### 5. `nargs` - Sets the allowed number of values to be parsed for an argument.

The `nargs` parameter can be set as:

- Specific number:

Expand Down Expand Up @@ -416,7 +430,49 @@ os << data << std::endl;

<br />

#### 6. `choices` - A list of valid argument values.
#### 6. `greedy` - If this option is set, the argument will consume ALL command-line values until it's upper nargs bound is reached.

> [!NOTE]
>
> - By default the `greedy` option is disabled for all arguments.
> - The default value of the parameter of the `argument::greedy(bool)` method is true for all arguments.

> [!TIP]
>
> - Enabling the `greedy` option for an argument only makes sense for arguments with string-like value types.
> - If no explicit `nargs` bound is set for a greedy argument, once it starts being parsed, it will consume all remaining command-line arguments.

Consider a simple example:

```cpp
ap::argument_parser parser;
parser.program_name("run-script")
.default_arguments(ap::default_argument::o_help);

parser.add_positional_argument("script")
.help("The name of the script to run");
parser.add_optional_argument("args")
.greedy()
.help("Set the execution option");

parser.try_parse_args(argc, argv);

// Application logic here
std::cout << "Executing: " << parser.value("script") << " " << ap::util::join(parser.values("args")) << std::endl;
```

Here the program execution should look something like this:

```txt
> ./run-script remove-comments --args module.py -v --type py
Executing: remove-comments module.py -v --type py
```

Notice that even though the `-v` and `--type` command-line arguments have flag prefixes and are not defined in the program, they are not treated as unknown arguments (and therefore no exception is thrown) because the `--args` argument is marked as `greedy` and it consumes these command-line arguments as its values.

<br />

#### 7. `choices` - A list of valid argument values.

```cpp
parser.add_optional_argument<char>("method", "m").choices('a', 'b', 'c');
Expand All @@ -433,7 +489,7 @@ parser.add_optional_argument<char>("method", "m").choices('a', 'b', 'c');

<br />

#### 7. Value actions - Function performed after parsing an argument's value.
#### 8. value actions - Functions that are called after parsing an argument's value.
Actions are represented as functions, which take the argument's value as an argument. The available action types are:

- `observe` actions | `void(const value_type&)` - applied to the parsed value. No value is returned - this action type is used to perform some logic on the parsed value without modifying it.
Expand Down Expand Up @@ -478,7 +534,7 @@ Actions are represented as functions, which take the argument's value as an argu

<br />

#### 8. `default_values` - A list of values which will be used if no values for an argument have been parsed
#### 9. `default_values` - A list of values which will be used if no values for an argument have been parsed

> [!WARNING]
>
Expand Down Expand Up @@ -541,7 +597,7 @@ Command Result

Apart from the common parameters listed above, for optional arguments you can also specify the following parameters:

#### 1. On-flag actions - For optional arguments, apart from value actions, you can specify on-flag actions which are executed immediately after parsing an argument's flag.
#### 1. on-flag actions - Functions that are called immediately after parsing an argument's flag.

```cpp
void print_debug_info() noexcept {
Expand Down
32 changes: 24 additions & 8 deletions include/ap/argument.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ class argument : public detail::argument_base {
return not this->_required and this->_bypass_required;
}

/// @return `true` if the argument is greedy, `false` otherwise.
[[nodiscard]] bool is_greedy() const noexcept override {
return this->_greedy;
}

// attribute setters

/**
Expand Down Expand Up @@ -171,6 +176,18 @@ class argument : public detail::argument_base {
return *this;
}

/**
* @brief Set the `greedy` attribute of the argument.
* @param g The attribute value.
* @return Reference to the argument instance.
Comment thread
SpectraL519 marked this conversation as resolved.
*/
argument& greedy(const bool g = true) noexcept
requires(not util::c_is_none<value_type>)
{
this->_greedy = g;
return *this;
}

/**
* @brief Set the nargs range for the argument.
* @param range The attribute value.
Expand All @@ -193,8 +210,7 @@ class argument : public detail::argument_base {
argument& nargs(const count_type n) noexcept
requires(not util::c_is_none<value_type>)
{
this->_nargs_range = nargs::range(n);
return *this;
return this->nargs(nargs::range(n));
}

/**
Expand All @@ -207,8 +223,7 @@ class argument : public detail::argument_base {
argument& nargs(const count_type lower, const count_type upper) noexcept
requires(not util::c_is_none<value_type>)
{
this->_nargs_range = nargs::range(lower, upper);
return *this;
return this->nargs(nargs::range(lower, upper));
}

/**
Expand Down Expand Up @@ -671,7 +686,7 @@ class argument : public detail::argument_base {
// attributes
const ap::detail::argument_name _name; ///< The argument's name.
std::optional<std::string> _help_msg; ///< The argument's help message.
nargs::range _nargs_range; ///< The argument's nargs range attribute.
nargs::range _nargs_range; ///< The argument's nargs range attribute value.
[[no_unique_address]] value_arg_specific_type<std::vector<std::any>>
_default_values; ///< The argument's default value list.
[[no_unique_address]] value_arg_specific_type<optional_specific_type<std::vector<std::any>>>
Expand All @@ -683,9 +698,10 @@ class argument : public detail::argument_base {
[[no_unique_address]] value_arg_specific_type<std::vector<value_action_type>>
_value_actions; ///< The argument's value actions collection.

bool _required : 1; ///< The argument's `required` attribute.
bool _bypass_required : 1 = false; ///< The argument's `bypass_required` attribute.
bool _hidden : 1 = false; ///< The argument's `hidden` attribute.
bool _required : 1; ///< The argument's `required` attribute value.
bool _bypass_required : 1 = false; ///< The argument's `bypass_required` attribute value.
bool _greedy : 1 = false; ///< The argument's `greedy` attribute value.
bool _hidden : 1 = false; ///< The argument's `hidden` attribute value.

// parsing result
[[no_unique_address]] optional_specific_type<std::size_t>
Expand Down
Loading