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
//! Localization-aware parsing for `clap` command trees.
//!
//! This module connects three pieces that are otherwise easy to wire
//! inconsistently: [`clap::Parser`] implementations, [`LocalizeCmd`] command
//! metadata rewriting, and [`crate::Localizer`] error-message lookup. It keeps
//! the parse path responsible for both building a localized command tree before
//! `clap` sees the arguments and localizing any parse or `from_arg_matches`
//! error after `clap` rejects them.
//!
//! Use [`parse_localized_command`] when the caller already has a command tree
//! or needs an explicit catalogue key root via [`LocalizeCmd::with_base`]. Use
//! [`LocalizedParse`] for the common zero-configuration path where the default
//! catalogue root should come from the parser's binary name or command name.
use LocalizeCmd;
use crate::;
use ;
use OsString;
/// Parses arguments with a pre-built localized command and localizes parse
/// errors through the supplied localizer.
///
/// This is the base-agnostic primitive for applications that need to override
/// the command identifier base before parsing.
///
/// # Side effects
///
/// Parse errors are passed through [`crate::localize_clap_error_with_command`].
/// When that fallback path cannot find a translation, it emits a warn-level
/// `tracing` event with stable `identifier`, `error_kind`, and `locale` fields
/// before returning the original `clap` error.
///
/// # Errors
///
/// Returns `clap::Error` when clap rejects the input or when the parsed
/// [`ArgMatches`] cannot be converted into `P`.
///
/// # Panics
///
/// Panics when the provided command contains identifiers that cannot be
/// represented as Fluent message identifiers. This matches the
/// [`LocalizeCmd::localize`] and [`crate::message_id_for`] contract.
///
/// # Examples
///
/// ```rust
/// use clap::{CommandFactory, Parser};
/// use ortho_config::{
/// LocalizeCmd, NoOpLocalizer, parse_localized_command,
/// };
///
/// #[derive(Debug, Parser)]
/// #[command(name = "demo", bin_name = "demo")]
/// struct Cli {
/// #[arg(long)]
/// verbose: bool,
/// }
///
/// let localizer = NoOpLocalizer::new();
/// let command = Cli::command().with_base("acme.demo").localize(&localizer);
/// let (cli, matches) =
/// parse_localized_command::<Cli, _, _>(command, ["demo", "--verbose"], &localizer)?;
///
/// assert!(cli.verbose);
/// assert!(matches.get_flag("verbose"));
/// # Ok::<(), clap::Error>(())
/// ```
/// Blanket extension trait for parsing any `clap::Parser` type with localized
/// command metadata and errors.
///
/// The default implementation derives the identifier base from the command's
/// `bin_name`, falling back to the command name. Use
/// [`parse_localized_command`] with [`LocalizeCmd::with_base`] when catalogue
/// keys need a different root.
///
/// # Panics
///
/// The methods panic when the command contains identifiers that cannot be
/// represented as Fluent message identifiers. This matches the
/// [`LocalizeCmd::localize`] and [`crate::message_id_for`] contract.
///
/// # Observability
///
/// Parse errors flow through [`parse_localized_command`], so missing
/// translations emit the same warn-level `tracing` event before the original
/// `clap` error is returned.
///
/// # Examples
///
/// ```rust
/// use clap::Parser;
/// use ortho_config::{LocalizedParse, NoOpLocalizer};
///
/// #[derive(Debug, Parser)]
/// #[command(name = "demo", bin_name = "demo")]
/// struct Cli {
/// #[arg(long)]
/// verbose: bool,
/// }
///
/// let localizer = NoOpLocalizer::new();
/// let cli = Cli::try_parse_localized_from(["demo", "--verbose"], &localizer)?;
///
/// assert!(cli.verbose);
/// # Ok::<(), clap::Error>(())
/// ```