1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
//! Derive-first command-line parsing and configuration for Rust.
//!
//! Define your CLI and configuration with Rust types, and Argx derives parsing, help, diagnostics,
//! completions, schema discovery, and layered configuration from those definitions.
//!
//! # Installation
//!
//! ```text
//! cargo add argx
//! ```
//!
//! Derive support is enabled by default. Enable the optional `toml` feature when using TOML
//! configuration layers:
//!
//! ```text
//! cargo add argx --features toml
//! ```
//!
//! # Quick start
//!
//! ```
//! use argx::{Args, Parser, Subcommand};
//!
//! #[derive(Parser)]
//! #[argx(name = "acme")]
//! struct Cli {
//! #[argx(subcommand)]
//! command: Command,
//! }
//!
//! #[derive(Subcommand)]
//! enum Command {
//! /// Start the service.
//! Serve(Serve),
//!
//! /// Print service status.
//! Status,
//! }
//!
//! #[derive(Args)]
//! struct Serve {
//! /// Port to listen on.
//! #[argx(long, default = 8080)]
//! port: u16,
//! }
//!
//! let cli = Cli::try_parse_from(["acme", "serve", "--port", "3000"])?;
//! match cli.command {
//! Command::Serve(args) => assert_eq!(args.port, 3000),
//! Command::Status => unreachable!(),
//! }
//! # Ok::<(), argx::Error>(())
//! ```
//!
//! Rust documentation becomes CLI help, while field types define parsing. [`Parser::parse`] is the
//! ordinary process entry point. The `try_parse*` methods return [`Error`] instead of printing and
//! exiting.
//!
//! # Configuration
//!
//! `#[derive(Config)]` builds a typed configuration value from explicitly ordered layers. A
//! generated `loader()` starts empty. Applications add [`Defaults`], [`Dotenv`], [`Environment`],
//! and [`Argv`] in the precedence order they want. The optional `toml` feature adds `Toml`:
//!
//! ```
//! use argx::{Argv, Defaults};
//!
//! #[derive(Debug, argx::Config)]
//! struct Config {
//! #[argx(long, default = 4)]
//! workers: usize,
//!
//! #[argx(long)]
//! endpoint: String,
//! }
//!
//! let config = Config::loader()
//! .layer(Defaults)
//! .layer(Argv::new(["acme", "--endpoint", "http://localhost"]))
//! .resolve()?;
//!
//! assert_eq!(config.workers, 4);
//! assert_eq!(config.endpoint, "http://localhost");
//! # Ok::<(), argx::ConfigError>(())
//! ```
//!
//! Layers are applied in call order. A later layer replaces only fields it supplies. An absent
//! value never masks an earlier one. Declared field defaults are therefore not implicit:
//! they take effect only when [`Defaults`] appears in the layer stack. Non-optional fields are
//! required only after all configured layers have been resolved.
//!
//! For example, an application can define increasing precedence entirely by layer order:
//!
//! ```text
//! earlier layers later layers
//! Defaults -> Dotenv -> Toml -> Environment -> Argv
//! ```
//!
//! This order is illustrative, not built in. Omitting or reordering a layer changes the
//! application's configuration policy.
//!
//! ## Configuration attributes
//!
//! A `Config` declaration accepts `#[argx(prefix = "...")]`. The prefix maps ordinary fields to
//! environment variables by uppercasing field components and joining them with `_`. For example,
//! `#[argx(prefix = "ACME")]` maps `workers` to `ACME_WORKERS`. A flattened `server.workers`
//! field maps to `ACME_SERVER_WORKERS`. Variables without a generated or explicit mapping are
//! ignored.
//!
//! Configuration fields accept:
//!
//! | Attribute | Meaning |
//! | --- | --- |
//! | `default` | use the field type's [`std::default::Default`] implementation in a [`Defaults`] layer |
//! | `default = expression` | use a typed Rust expression in a [`Defaults`] layer |
//! | `env = "NAME"` | map the field to one exact environment variable |
//! | `flatten` | compose one direct nested `Config` across every layer |
//! | `long`, `short` | expose the field through argv using the normal named-option spelling rules |
//! | `alias`, `aliases`, `global`, `delimited`, `value_enum`, `allow_hyphen_values`, `allow_negative_numbers`, `help` | forward normal CLI metadata to the generated argv field |
//!
//! A field participates in [`Argv`] only when it has CLI metadata such as `long` or `short`.
//! Configuration-only fields need no CLI annotation. A flattened field always composes its nested
//! argv surface, but does not itself accept `default` or `env`.
//!
//! [`Dotenv`] and `Toml` read only the paths supplied to their layers; Argx performs no
//! configuration-file discovery. [`Environment`] reads the current process environment. TOML
//! interpolation can use environment values supplied by earlier environment layers.
//!
//! [`Argv::new`] expects a complete argument vector including the program name. [`Argv::current`]
//! captures the current process argv in that form.
//!
//! # Commands and composition
//!
//! Argx has three derive roles:
//!
//! - `#[derive(Parser)]` applies to a named-field or unit struct and defines the root command.
//! - `#[derive(Args)]` applies to a named-field or unit struct and defines reusable arguments.
//! - `#[derive(Subcommand)]` applies to a non-empty enum. Each variant is either a unit command or
//! contains exactly one direct `Args` payload.
//!
//! Command and variant names default to kebab-case. `#[argx(name = "...")]` replaces the canonical
//! spelling, and subcommand variants may declare hidden `alias` or `aliases` spellings.
//!
//! A field with `#[argx(subcommand)]` selects one child from a derived subcommand enum. Command
//! names are matched exactly.
//!
//! A field with `#[argx(flatten)]` composes one direct `Args` declaration into the current command.
//! Flattening does not create a new command scope: its arguments participate in the containing
//! command's parsing, validation, and help. A flatten field's Rust documentation
//! becomes a help-group heading when present.
//!
//! Named options are local to their declaring command unless marked `#[argx(global)]`. Global
//! options remain visible in descendant scopes. If an ancestor and descendant use the same
//! spelling, the nearest active command scope wins.
//!
//! # Arguments and cardinality
//!
//! A field is positional unless `long` or `short` is present. A bare `#[argx(long)]` infers the
//! kebab-case field name. A bare `#[argx(short)]` infers its first character. Explicit spellings
//! are accepted with `long = "..."` and `short = 'x'`. Named fields may add hidden long spellings
//! with `alias` or `aliases`.
//!
//! The derive recognizes these field shapes:
//!
//! | Rust shape | Binding semantics |
//! | --- | --- |
//! | named `bool` | value-less switch |
//! | `T` | exactly one required value |
//! | `Option<T>` | zero or one value |
//! | `Vec<T>` | zero or more values |
//! | `Option<Vec<T>>` | optional zero-or-more collection |
//!
//! Named collections may be repeated. Positional collections consume the remaining positional
//! values.
//!
//! Value conversion depends on the direct value type:
//!
//! - a field marked `#[argx(value_enum)]` parses through its finite [`trait@ValueEnum`] vocabulary.
//! - `String` consumes UTF-8 text.
//! - `OsString` and `PathBuf` preserve operating-system strings.
//! - other value types are converted through [`std::str::FromStr`].
//!
//! ## Finite values
//!
//! When a value has a fixed command-line vocabulary, derive [`ValueEnum`] and mark the field with
//! `#[argx(value_enum)]`. The enum then supplies the accepted values for parsing, help, and
//! completion.
//!
//! ```
//! #[derive(Debug, argx::ValueEnum)]
//! enum Output {
//! HumanReadable,
//! Json,
//! }
//!
//! #[derive(argx::Parser)]
//! struct Cli {
//! /// Output format.
//! #[argx(long, value_enum)]
//! format: Output,
//! }
//! ```
//!
//! Derived variants use Argx's normal kebab-case spelling, and parsing is exact and case-sensitive.
//! The derive also implements [`std::str::FromStr`] for ordinary Rust use.
//!
//! ## Typed defaults
//!
//! Scalar named options may declare `#[argx(default = expression)]`. The expression is evaluated as
//! the field's Rust type and is used when the option is absent.
//!
//! ## Argument relationships
//!
//! `requires` and `conflicts` express relationships between argument fields in one composed command
//! context. References use Rust field names and are validated during derivation/composition.
//!
//! `requires` makes another field mandatory when the source argument is supplied. `conflicts`
//! rejects combinations that cannot be used together. Typed defaults satisfy requirements without
//! activating conflicts.
//!
//! ```
//! #[derive(argx::Parser)]
//! struct Cli {
//! #[argx(long, requires = "token")]
//! remote: bool,
//!
//! #[argx(long)]
//! token: Option<String>,
//!
//! #[argx(long, conflicts = "remote")]
//! offline: bool,
//! }
//! ```
//!
//! # Argv grammar
//!
//! Argx accepts long options as `--name value` or `--name=value`, supports short-option bundles,
//! and treats `--` as the end of option parsing.
//!
//! Detached values that look like options are rejected by default. Use `allow_hyphen_values` for
//! arbitrary flag-like values or `allow_negative_numbers` when only negative numbers should be
//! accepted. `OsString` and `PathBuf` preserve native argument strings; text and `FromStr` values
//! require UTF-8.
//!
//! # Parser entry points
//!
//! [`Parser::parse`] and [`Parser::try_parse`] read the current process arguments. The `*_from`
//! variants accept a complete argv sequence including the program name. `parse` methods print
//! terminal actions and errors and may exit the process; `try_parse` methods return [`Error`] to
//! the caller.
//!
//! ```
//! use argx::{Error, Parser as _};
//!
//! #[derive(argx::Parser)]
//! struct Cli {
//! input: String,
//! }
//!
//! match Cli::try_parse_from(["acme", "--help"]) {
//! Err(Error::DisplayHelp { help }) => assert!(help.contains("Usage:")),
//! _ => panic!("expected the built-in help action"),
//! }
//! ```
//!
//! # Help and version
//!
//! Every command scope has built-in `-h` and `--help`. Commands with `version` or `long_version`
//! also receive `-V` and `--version`. If only one version is supplied, it is used for both forms.
//!
//! Rust documentation supplies command and argument descriptions. The first paragraph is used as
//! the short summary, level-one headings create additional help sections, and documentation on a
//! flattened field becomes that group's heading.
//!
//! `about = "..."` explicitly replaces the command's derived descriptive text. `help = "..."`
//! replaces a field's derived one-line summary. Hidden flag and subcommand aliases are accepted by
//! parsing but omitted from generated help so help presents one canonical interface.
//!
//! During parsing, help and version are represented as [`Error::DisplayHelp`] and
//! [`Error::DisplayVersion`] terminal actions. The process-oriented parsing methods print those
//! actions to stdout and exit successfully. Other parse/binding errors go to stderr and exit with
//! status 2.
//!
//! # Shell completions
//!
//! Argx generates dynamic completion adapters for Bash, Fish, Nushell, and Zsh through the
//! [`completion`] module.
//!
//! ```
//! use argx::{Parser as _, completion::Shell};
//!
//! # #[derive(argx::Parser)]
//! # #[argx(name = "acme")]
//! # struct Cli;
//! let script = Cli::render_completion(Shell::Zsh)?;
//! assert!(script.contains("#compdef acme"));
//! # Ok::<(), argx::completion::ScriptError>(())
//! ```
//!
//! [`Parser::parse`] handles completion requests automatically.
//!
//! Fields marked `#[argx(value_enum)]` complete from the same finite vocabulary used for parsing
//! and help. Hidden aliases are accepted while reconstructing command scope but are not suggested.
//! Argx does not infer choices from arbitrary [`std::str::FromStr`] implementations or provide
//! filesystem or custom value completers.
//!
//! Applications typically expose generated adapters through a `completions <shell>` command. See
//! the `completions` example for a complete integration.
//!
//! # Schema discovery
//!
//! Mark commands that participate in schema discovery with `#[argx(schema)]`. Argx exposes
//! Draft 2020-12 JSON Schema through `-S` / `--schema` in the selected command scope and through
//! the root `schema [COMMAND]...` pseudo-command.
//!
//! Structural commands expose their immediate children by default, allowing tools to walk the
//! command tree incrementally. Leaf commands expose their invocation schema and, when associated
//! with a handler, typed result and error schemas. Use `--full` to recursively expand a structural
//! command.
//!
//! Structural [`Args`] and `Subcommand` declarations use the same `#[argx(schema)]` marker.
//! Associate executable leaves with typed results and errors using `#[argx(handler = CommandType)]`
//! on a free function or `#[argx(handler = method)]` on an inherent impl.
//!
//! `#[argx(schema)]` on result and error data types delegates their JSON Schema generation to
//! Schemars. See the `schema` example for a complete structural and leaf discovery flow.
//!
//! # `#[argx(...)]` attribute reference
//!
//! Rust documentation is the preferred source for user-facing descriptions. `#[argx(...)]`
//! metadata controls command-line semantics or provides an explicit override where Rust docs are
//! not the desired CLI text.
//!
//! ## `Parser` and `Args` declarations
//!
//! Struct declarations accept `name = "..."` and `about = "..."`. `name` replaces the inferred
//! kebab-case command name. `about` replaces documentation-derived descriptive text. A `Parser`
//! declaration may additionally use `version = expression`, `long_version = expression`, and the
//! marker `schema`. If only one version expression is supplied, Argx uses it for both `-V` and
//! `--version`. `schema` enables machine-readable discovery. Structural `Args` declarations that
//! contain a subcommand field may also use `schema` to participate in that command topology.
//! Version metadata remains root-only.
//!
//! Aliases belong to selectable `Subcommand` variants. An `Args` declaration has no standalone
//! command name: flattening composes it into the current command, while a subcommand payload uses
//! the variant as the visible command.
//!
//! ## `Subcommand` variants
//!
//! The enum itself accepts the `schema` marker when it participates in machine-readable command
//! topology. Individual variants accept:
//!
//! - `name = "..."` to replace the inferred kebab-case command spelling.
//! - `about = "..."` to override documentation-derived descriptive text.
//! - `alias = "..."` for one hidden accepted command spelling.
//! - `aliases = ["...", "..."]` for multiple hidden accepted spellings.
//! - `version = expression` and `long_version = expression` for version actions local to that
//! command scope.
//!
//! Canonical names and aliases share one sibling namespace. Aliases are accepted by parsing and
//! dynamic lookup but omitted from human help.
//!
//! ## Argument fields
//!
//! Ordinary fields are positional unless `long` or `short` is present. The supported field
//! metadata is:
//!
//! | Attribute | Meaning |
//! | --- | --- |
//! | `long` / `long = "name"` | infer or explicitly set a long option spelling |
//! | `short` / `short = 'x'` | infer or explicitly set a short option spelling |
//! | `alias = "name"` | add one hidden long spelling to a named option |
//! | `aliases = ["a", "b"]` | add multiple hidden long spellings to a named option |
//! | `global` | keep a named option visible in descendant command scopes |
//! | `count` | bind the number of occurrences of a value-less flag to a `u8` field |
//! | `delimited` | split collection values on commas before conversion |
//! | `default = expression` | use a typed Rust default for a scalar value option or counted flag |
//! | `requires = "field"` | require another argument when this argument is supplied |
//! | `requires = ["a", "b"]` | require multiple arguments |
//! | `conflicts = "field"` | reject use with another argument |
//! | `conflicts = ["a", "b"]` | reject use with multiple arguments |
//! | `allow_hyphen_values` | allow arbitrary flag-like detached values for a named value option |
//! | `allow_negative_numbers` | accept negative-number values without accepting other flags |
//! | `value_enum` | use a finite [`trait@ValueEnum`] vocabulary for parsing, help, completion, and schema discovery |
//! | `help = "..."` | override the field's documentation-derived one-line help text |
//! | `flatten` | compose one direct [`Args`] field into the current command |
//! | `subcommand` | select one direct derived `Subcommand` enum |
//!
//! Long and alias spellings are written without leading dashes. `count` uses a `u8` field, and
//! `delimited` splits collection values on commas. `requires` and `conflicts` refer to Rust field
//! names, including fields contributed through `flatten`. Incompatible attribute combinations are
//! rejected during derivation.
//!
//! # Derive restrictions
//!
//! Argx rejects unsupported command shapes at compile time. `Parser` and `Args` use unit or
//! named-field structs, subcommand variants are unit variants or carry one direct `Args` payload,
//! and structural fields hold their derived types directly. Invalid layouts and incompatible
//! attributes produce compile-time diagnostics.
//!
//! # Platform support
//!
//! The supported native targets are Linux and macOS. Windows is supported through the Windows
//! Subsystem for Linux (WSL). Native Windows targets are not supported.
use ;
pub use ;
pub use Error;
// Generated absolute paths must also work when a derive is used inside this crate. Integration
// targets already receive this name through Cargo; the library target needs the self alias.
extern crate self as argx;
pub use Config;
pub use ;
pub use Toml;
pub use ;
/// Parses command-line arguments into a typed value.
///
/// Use the `parse*` methods for ordinary CLI process behavior and the `try_parse*` methods when
/// the caller owns error and process handling.
/// Parses already-separated arguments for the public parser entry points.
/// Implementation details shared with generated code.
///
/// This module is public so proc-macro expansions can name these items from downstream crates. It
/// is not part of Argx's stable user-facing API.