Skip to content

Commit a412cb8

Browse files
authored
Merge pull request #52 from lucocozz/develop
0.2.0
2 parents 224448b + 6242b5c commit a412cb8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1670
-357
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- Printing subcommand list on command execution that cannot be executed directly.
12+
- Support for variadic positional arguments, allowing multiple values for a single positional argument.
13+
14+
### Changed
15+
- Changed help output DEFAULT_MAX_LINE_WIDTH from 80 to 100.
16+
- Changed `ARGUS_RELEASE` into `ARGUS_DEBUG`
17+
18+
### Fixed
19+
- Disabled pedantic option on library compilation.
20+
- Defining `argus_init()` as a `static inline` function.
21+
- Fixed unexecuted validators in subcommand.
22+
23+
### Removed
24+
- Group description option.
25+
- Cleanup non essential regex patterns.
26+
27+
1028
## [0.1.0] - 2025-07-02
1129

1230
### Added

Justfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ examples:
165165
basic_usage) desc="Basic flags, string, and integer options" ;; \
166166
subcommands) desc="Git-like subcommands implementation" ;; \
167167
positional_args) desc="Handling positional arguments" ;; \
168+
variadic_positional) desc="Handling variadic positional arguments" ;; \
168169
custom_handlers) desc="Creating custom option handlers" ;; \
169170
advanced_options) desc="Dependencies, conflicts, and exclusive groups" ;; \
170171
nested_commands) desc="Complex nested subcommands (like git or docker)" ;; \

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ Consider traditional approaches for embedded systems with strict constraints, le
244244

245245
📚 **[Complete Documentation](https://argus-lib.com)** - Comprehensive guides and tutorials
246246
🚀 **[Quick Start Guide](https://argus-lib.com/getting-started/quickstart)** - Get running in minutes
247-
💡 **[Examples](https://argus-lib.com/examples/simple-cli)** - Real-world usage patterns
247+
💡 **[Example](https://github.com/lucocozz/argus-git-demo)** - Git clone demonstration
248248
🔧 **[API Reference](https://argus-lib.com/api-reference/overview)** - Complete function documentation
249249

250250
## Requirements

argus.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ EXPORTS
3838
free_map_int_handler
3939
free_map_float_handler
4040
free_map_bool_handler
41+
variadic_string_handler
42+
variadic_int_handler
43+
variadic_float_handler
44+
free_variadic_string_handler
4145
range_validator
4246
length_validator
4347
count_validator

benchmarks/benchmark_release_mode.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,20 @@ ARGUS_OPTIONS(
1212
HELP_OPTION(),
1313
VERSION_OPTION(),
1414

15-
GROUP_START("Input Options", GROUP_DESC("Options related to input")),
15+
GROUP_START("Input Options"),
1616
OPTION_FLAG('v', "verbose", HELP("Enable verbose output")),
1717
OPTION_STRING('i', "input", HELP("Input file"), DEFAULT("input.txt")),
1818
OPTION_ARRAY_STRING('I', "include", HELP("Include files"), FLAGS(FLAG_SORTED | FLAG_UNIQUE)),
1919
GROUP_END(),
2020

21-
GROUP_START("Output Options", GROUP_DESC("Options related to output")),
21+
GROUP_START("Output Options"),
2222
OPTION_STRING('o', "output", HELP("Output file"), DEFAULT("output.txt")),
2323
OPTION_STRING('f', "format", HELP("Output format"),
2424
VALIDATOR(V_CHOICE_STR("text", "json", "xml", "binary"))),
2525
OPTION_FLAG('s', "silent", HELP("Suppress output"), CONFLICT("verbose")),
2626
GROUP_END(),
2727

28-
GROUP_START("Processing Options", GROUP_DESC("Options controlling processing")),
28+
GROUP_START("Processing Options"),
2929
OPTION_INT('l', "level", HELP("Processing level"),
3030
VALIDATOR(V_RANGE(1, 10)), DEFAULT(5)),
3131
OPTION_INT('j', "jobs", HELP("Number of parallel jobs"),
@@ -35,7 +35,7 @@ ARGUS_OPTIONS(
3535
OPTION_MAP_STRING('D', "define", HELP("Define variables"), FLAGS(FLAG_SORTED_KEY)),
3636
GROUP_END(),
3737

38-
GROUP_START("Advanced Options", GROUP_DESC("Advanced configuration")),
38+
GROUP_START("Advanced Options"),
3939
OPTION_FLAG('d', "debug", HELP("Enable debug mode")),
4040
OPTION_STRING('c', "config", HELP("Configuration file")),
4141
OPTION_ARRAY_INT('p', "ports", HELP("Port numbers"), FLAGS(FLAG_SORTED | FLAG_UNIQUE)),

docs/docs/api-reference/overview.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ POSITIONAL_STRING(name, ...) // String positional
7676
POSITIONAL_INT(name, ...) // Integer positional
7777
POSITIONAL_BOOL(name, ...) // Boolean positional
7878
POSITIONAL_FLOAT(name, ...) // Float positional
79+
80+
// Variadic positionals (accept multiple values)
81+
POSITIONAL_MANY_STRING(name, ...) // Variadic string positional
82+
POSITIONAL_MANY_INT(name, ...) // Variadic integer positional
83+
POSITIONAL_MANY_FLOAT(name, ...) // Variadic float positional
7984
```
8085
8186
### Structure Macros

docs/docs/api-reference/regex-patterns.md

Lines changed: 5 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,22 @@ OPTION_STRING('e', "email", HELP("Email address"),
2222
| Pattern | Validates | Example |
2323
|---------|-----------|---------|
2424
| `ARGUS_RE_IPV4` | IPv4 addresses | `192.168.1.1` |
25-
| `ARGUS_RE_IP4CIDR` | IPv4 with optional CIDR | `192.168.1.0/24` |
2625
| `ARGUS_RE_IPV6` | IPv6 addresses | `2001:db8::1` |
2726
2827
```c
2928
OPTION_STRING('i', "ip", HELP("Server IP address"),
3029
VALIDATOR(V_REGEX(ARGUS_RE_IPV4)))
3130
32-
OPTION_STRING('n', "network", HELP("Network range"),
33-
VALIDATOR(V_REGEX(ARGUS_RE_IP4CIDR)))
3431
```
3532

3633
### Network Infrastructure
3734

3835
| Pattern | Validates | Example |
3936
|---------|-----------|---------|
40-
| `ARGUS_RE_MAC` | MAC addresses | `01:23:45:67:89:AB` |
4137
| `ARGUS_RE_DOMAIN` | Domain names (FQDN) | `example.com` |
4238
| `ARGUS_RE_PORT` | Port numbers (1-65535) | `8080` |
4339

4440
```c
45-
OPTION_STRING('m', "mac", HELP("MAC address"),
46-
VALIDATOR(V_REGEX(ARGUS_RE_MAC)))
47-
4841
OPTION_STRING('d', "domain", HELP("Domain name"),
4942
VALIDATOR(V_REGEX(ARGUS_RE_DOMAIN)))
5043
```
@@ -55,7 +48,6 @@ OPTION_STRING('d', "domain", HELP("Domain name"),
5548
|---------|-----------|---------|
5649
| `ARGUS_RE_URL` | Any protocol URL | `https://example.com/path` |
5750
| `ARGUS_RE_HTTP` | HTTP(S) URLs only | `http://example.com` |
58-
| `ARGUS_RE_FILE_URL` | File URLs | `file:///path/to/file` |
5951
6052
```c
6153
OPTION_STRING('u', "url", HELP("Website URL"),
@@ -82,78 +74,44 @@ OPTION_STRING('c', "contact", HELP("Contact email (strict)"),
8274
VALIDATOR(V_REGEX(ARGUS_RE_EMAIL_STRICT)))
8375
```
8476
85-
### Phone Numbers
86-
87-
| Pattern | Validates | Example |
88-
|---------|-----------|---------|
89-
| `ARGUS_RE_PHONE_INTL` | International format | `+12345678901` |
90-
| `ARGUS_RE_PHONE_US` | US phone numbers | `123-456-7890` |
91-
| `ARGUS_RE_PHONE_EU` | European phone numbers | `+33 123456789` |
92-
93-
```c
94-
OPTION_STRING('p', "phone", HELP("Phone number"),
95-
VALIDATOR(V_REGEX(ARGUS_RE_PHONE_US)))
96-
```
9777
9878
## // Date and Time Patterns
9979
10080
| Pattern | Validates | Example |
10181
|---------|-----------|---------|
10282
| `ARGUS_RE_ISO_DATE` | ISO date (YYYY-MM-DD) | `2024-03-15` |
10383
| `ARGUS_RE_ISOTIME` | ISO datetime | `2024-03-15T14:30:00` |
104-
| `ARGUS_RE_US_DATE` | US date format | `03/15/2024` |
105-
| `ARGUS_RE_EU_DATE` | European date format | `15/03/2024` |
106-
| `ARGUS_RE_TIME24` | 24-hour time | `14:30:00` |
10784
10885
```c
10986
OPTION_STRING('d', "date", HELP("Date (YYYY-MM-DD)"),
11087
VALIDATOR(V_REGEX(ARGUS_RE_ISO_DATE)))
11188
112-
OPTION_STRING('t', "time", HELP("Time (HH:MM:SS)"),
113-
VALIDATOR(V_REGEX(ARGUS_RE_TIME24)))
89+
OPTION_STRING('t', "datetime", HELP("DateTime (ISO format)"),
90+
VALIDATOR(V_REGEX(ARGUS_RE_ISOTIME)))
11491
```
11592

116-
## // Geographic Patterns
117-
118-
| Pattern | Validates | Example |
119-
|---------|-----------|---------|
120-
| `ARGUS_RE_ZIP` | US ZIP codes | `12345` or `12345-6789` |
121-
| `ARGUS_RE_UK_POST` | UK postcodes | `SW1A 1AA` |
122-
| `ARGUS_RE_CA_POST` | Canadian postal codes | `A1A 1A1` |
123-
| `ARGUS_RE_LATITUDE` | Latitude (-90 to 90) | `40.7128` |
124-
| `ARGUS_RE_LONGITUDE` | Longitude (-180 to 180) | `-74.0060` |
125-
126-
```c
127-
OPTION_STRING('z', "zip", HELP("ZIP code"),
128-
VALIDATOR(V_REGEX(ARGUS_RE_ZIP)))
129-
130-
OPTION_STRING('l', "lat", HELP("Latitude"),
131-
VALIDATOR(V_REGEX(ARGUS_RE_LATITUDE)))
132-
```
13393

13494
## // Security Patterns
13595

13696
| Pattern | Validates | Example |
13797
|---------|-----------|---------|
13898
| `ARGUS_RE_USER` | Username (3-20 chars) | `user_123` |
13999
| `ARGUS_RE_PASSWD` | Basic password | `password123` |
140-
| `ARGUS_RE_PASSWD_STRONG` | Strong password | `Pass123!` |
141100
| `ARGUS_RE_UUID` | UUID v4 format | `550e8400-e29b-41d4-a716-446655440000` |
142101

143102
```c
144103
OPTION_STRING('u', "username", HELP("Username"),
145104
VALIDATOR(V_REGEX(ARGUS_RE_USER)))
146105

147-
OPTION_STRING('p', "password", HELP("Strong password"),
148-
VALIDATOR(V_REGEX(ARGUS_RE_PASSWD_STRONG)))
106+
OPTION_STRING('p', "password", HELP("Password"),
107+
VALIDATOR(V_REGEX(ARGUS_RE_PASSWD)))
149108
```
150109
151110
## // File System Patterns
152111
153112
| Pattern | Validates | Example |
154113
|---------|-----------|---------|
155114
| `ARGUS_RE_UNIX_PATH` | Unix absolute paths | `/path/to/file` |
156-
| `ARGUS_RE_WIN_PATH` | Windows absolute paths | `C:\folder\file` |
157115
| `ARGUS_RE_FILENAME` | Filename with extension | `document.pdf` |
158116
159117
```c
@@ -164,21 +122,7 @@ OPTION_STRING('n', "name", HELP("Filename"),
164122
VALIDATOR(V_REGEX(ARGUS_RE_FILENAME)))
165123
```
166124

167-
## // Visual and Data Patterns
168-
169-
### Colors
170-
171-
| Pattern | Validates | Example |
172-
|---------|-----------|---------|
173-
| `ARGUS_RE_HEX_COLOR` | Hex colors | `#FF0000` or `#F00` |
174-
| `ARGUS_RE_RGB` | RGB color format | `rgb(255,0,0)` |
175-
176-
```c
177-
OPTION_STRING('c', "color", HELP("Hex color"),
178-
VALIDATOR(V_REGEX(ARGUS_RE_HEX_COLOR)))
179-
```
180-
181-
### Numbers and Formats
125+
## // Numbers and Formats
182126

183127
| Pattern | Validates | Example |
184128
|---------|-----------|---------|
@@ -236,7 +180,6 @@ Each pattern includes helpful error hints:
236180

237181
- `ARGUS_RE_EMAIL`: "Enter email: [email protected]"
238182
- `ARGUS_RE_IPV4`: "Enter valid IPv4: 192.168.1.1"
239-
- `ARGUS_RE_PHONE_US`: "Enter US phone: 123-456-7890"
240183
- `ARGUS_RE_ISO_DATE`: "Enter date: YYYY-MM-DD"
241184

242185
Custom patterns should include similar hints:

docs/docs/appendices/cheat-sheet.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,14 @@ OPTION_MAP_BOOL('f', "features", HELP("Feature flags"))
5454
## // Positional Arguments
5555

5656
```c
57+
// Single positionals
5758
POSITIONAL_STRING("input", HELP("Input file"))
5859
POSITIONAL_INT("count", HELP("Count"), FLAGS(FLAG_OPTIONAL))
60+
61+
// Variadic positionals (accept multiple values)
62+
POSITIONAL_MANY_STRING("files", HELP("Files to process"))
63+
POSITIONAL_MANY_INT("numbers", HELP("Numbers to calculate"))
64+
POSITIONAL_MANY_FLOAT("values", HELP("Decimal values"))
5965
```
6066
6167
## // Option Modifiers
@@ -90,7 +96,6 @@ ARGUS_RE_EMAIL // [email protected]
9096
ARGUS_RE_IPV4 // 192.168.1.1
9197
ARGUS_RE_URL // https://example.com
9298
ARGUS_RE_ISO_DATE // 2024-03-15
93-
ARGUS_RE_PHONE_US // 123-456-7890
9499
ARGUS_RE_UUID // 550e8400-e29b-41d4-a716-446655440000
95100
```
96101

@@ -208,6 +213,9 @@ int main(int argc, char **argv)
208213
# Positional
209214
program input.txt output.txt
210215
216+
# Variadic positionals
217+
program file1.c file2.c file3.c ...
218+
211219
# Stop parsing
212220
program --option -- --not-an-option
213221
```
@@ -251,12 +259,12 @@ endpoint_t *ep = (endpoint_t*)argus_get(&argus, "endpoint").as_ptr;
251259
## // Groups
252260
253261
```c
254-
GROUP_START("Connection", GROUP_DESC("Network options")),
262+
GROUP_START("Connection"),
255263
OPTION_STRING('h', "host", HELP("Hostname")),
256264
OPTION_INT('p', "port", HELP("Port")),
257265
GROUP_END(),
258266
259-
GROUP_START("Output", GROUP_DESC("Output options")),
267+
GROUP_START("Output"),
260268
OPTION_STRING('o', "output", HELP("Output file")),
261269
OPTION_STRING('f', "format", HELP("Format")),
262270
GROUP_END(),

docs/docs/features/collections.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,75 @@ ARGUS_OPTIONS(
178178
</TabItem>
179179
</Tabs>
180180

181+
## // Variadic Positional
182+
183+
Accept multiple values for positional arguments, similar to array options but for positional parameters:
184+
185+
<Tabs>
186+
<TabItem value="variadic-types" label="Variadic Types" default>
187+
188+
```c
189+
ARGUS_OPTIONS(
190+
options,
191+
HELP_OPTION(),
192+
193+
// Multiple string values
194+
POSITIONAL_MANY_STRING("files", HELP("Input files to process"),
195+
HINT("FILE..."),
196+
FLAGS(FLAG_UNIQUE | FLAG_SORTED)),
197+
198+
// Multiple integer values
199+
POSITIONAL_MANY_INT("numbers", HELP("Numbers to process"),
200+
HINT("NUM..."),
201+
VALIDATOR(V_COUNT(1, 10))),
202+
203+
// Multiple float values
204+
POSITIONAL_MANY_FLOAT("values", HELP("Float values"),
205+
HINT("VAL...")),
206+
)
207+
```
208+
209+
**Supported types:**
210+
- `POSITIONAL_MANY_STRING` - Multiple text values
211+
- `POSITIONAL_MANY_INT` - Multiple integer values
212+
- `POSITIONAL_MANY_FLOAT` - Multiple decimal values
213+
214+
**Important restrictions:**
215+
- Only one `POSITIONAL_MANY` argument allowed per command
216+
- Must be placed after all regular positional arguments
217+
- Cannot mix with optional positional arguments
218+
- Cannot be used with subcommands at the same level
219+
220+
</TabItem>
221+
<TabItem value="variadic-usage" label="Usage Examples">
222+
223+
```bash
224+
# Process multiple files
225+
./program file1.c file2.c file3.c
226+
227+
# Process numbers
228+
./program 1 2 3 4 5
229+
230+
# No arguments (if optional)
231+
./program
232+
233+
# With other options
234+
./program --verbose file1.txt file2.txt
235+
```
236+
237+
**Key characteristics:**
238+
- Accepts zero or more values
239+
- Values are collected into an array
240+
- Supports same flags as array options (`FLAG_SORTED`, `FLAG_UNIQUE`)
241+
- Can use validation like `V_COUNT()` to enforce limits
242+
243+
**Access methods:**
244+
- Same as array collections: `argus_get().as_array`, `argus_count()`, `argus_array_it()`
245+
- See [Accessing Values](../fundamentals/accessing-values#variadic-positional) for detailed examples
246+
247+
</TabItem>
248+
</Tabs>
249+
181250
## // Accessing Collection Values
182251
183252
<Tabs>

docs/docs/features/validation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,6 @@ ARGUS_OPTIONS(
297297
- `ARGUS_RE_IPV6` - IPv6 addresses
298298
- `ARGUS_RE_URL` - URLs (any protocol)
299299
- `ARGUS_RE_ISO_DATE` - ISO dates (YYYY-MM-DD)
300-
- `ARGUS_RE_PHONE_US` - US phone numbers
301300
- `ARGUS_RE_UUID` - UUID v4 format
302301

303302
</TabItem>

0 commit comments

Comments
 (0)