getargs_derive/command.rs
1/// Compile-time description of a command line interface, implemented by
2/// [`#[derive(GetArgs)]`](derive@crate::GetArgs).
3///
4/// The metadata is `&'static` and available without the `std` feature. It is what the shell
5/// completion and man page generators of the `std` feature read, and can be inspected to build
6/// other tools.
7/// See [Shell Completions and Man Pages][crate::guide::completions].
8pub trait Command {
9 /// The description of the command.
10 const COMMAND: CommandInfo;
11}
12
13/// The description of a command: its name, texts, arguments and subcommands.
14///
15/// Values are built with [`CommandInfo::new`] and the `const` builder methods, so that fields can
16/// be added without breaking existing code.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18#[non_exhaustive]
19pub struct CommandInfo {
20 /// The name of the command, as typed on the command line.
21 pub name: &'static str,
22 /// The short description, from `about` or the first paragraph of the doc comment. Empty when
23 /// not set.
24 pub about: &'static str,
25 /// The long description, from `long_about` or the full doc comment. Empty when not set.
26 pub long_about: &'static str,
27 /// The version set with `#[command(version)]`.
28 pub version: Option<&'static str>,
29 /// The arguments, flattened structs included, in field order, followed by the generated
30 /// `--help` and `--version` flags.
31 pub args: &'static [ArgInfo],
32 /// The subcommands, from a `#[command(subcommand)]` field, in variant order. Their
33 /// [`args`](Self::args) do not repeat the `global` arguments of their parents.
34 pub commands: &'static [CommandInfo],
35 /// Whether one of the [`commands`](Self::commands) must be given.
36 pub subcommand_required: bool,
37 /// The aliases of a subcommand listed in the help.
38 pub visible_aliases: &'static [&'static str],
39 /// The aliases of a subcommand hidden from the help.
40 pub aliases: &'static [&'static str],
41 /// Whether the subcommand is hidden from the help.
42 pub hidden: bool,
43}
44
45impl CommandInfo {
46 /// A command named `name`, without description, version, arguments or subcommands.
47 pub const fn new(name: &'static str) -> Self {
48 CommandInfo {
49 name,
50 about: "",
51 long_about: "",
52 version: None,
53 args: &[],
54 commands: &[],
55 subcommand_required: false,
56 visible_aliases: &[],
57 aliases: &[],
58 hidden: false,
59 }
60 }
61
62 /// Sets [`subcommand_required`](Self::subcommand_required).
63 pub const fn subcommand_required(mut self, required: bool) -> Self {
64 self.subcommand_required = required;
65 self
66 }
67
68 /// Sets [`visible_aliases`](Self::visible_aliases).
69 pub const fn visible_aliases(mut self, aliases: &'static [&'static str]) -> Self {
70 self.visible_aliases = aliases;
71 self
72 }
73
74 /// Sets [`aliases`](Self::aliases).
75 pub const fn aliases(mut self, aliases: &'static [&'static str]) -> Self {
76 self.aliases = aliases;
77 self
78 }
79
80 /// Sets [`hidden`](Self::hidden).
81 pub const fn hidden(mut self, hidden: bool) -> Self {
82 self.hidden = hidden;
83 self
84 }
85
86 /// Sets [`about`](Self::about).
87 pub const fn about(mut self, about: &'static str) -> Self {
88 self.about = about;
89 self
90 }
91
92 /// Sets [`long_about`](Self::long_about).
93 pub const fn long_about(mut self, long_about: &'static str) -> Self {
94 self.long_about = long_about;
95 self
96 }
97
98 /// Sets [`version`](Self::version).
99 pub const fn version(mut self, version: &'static str) -> Self {
100 self.version = Some(version);
101 self
102 }
103
104 /// Sets [`args`](Self::args).
105 pub const fn args(mut self, args: &'static [ArgInfo]) -> Self {
106 self.args = args;
107 self
108 }
109
110 /// Sets [`commands`](Self::commands).
111 pub const fn commands(mut self, commands: &'static [CommandInfo]) -> Self {
112 self.commands = commands;
113 self
114 }
115}
116
117/// How an argument is given on the command line.
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
119#[non_exhaustive]
120pub enum ArgKind {
121 /// A positional argument.
122 Positional,
123 /// A named option taking a value.
124 Option,
125 /// A named flag taking no value.
126 Flag,
127}
128
129/// The description of one argument.
130///
131/// Values are built with [`ArgInfo::new`] and the `const` builder methods, so that fields can be
132/// added without breaking existing code.
133#[derive(Debug, Clone, Copy, PartialEq, Eq)]
134#[non_exhaustive]
135pub struct ArgInfo {
136 /// The name of the field, or `help` and `version` for the generated flags.
137 pub id: &'static str,
138 /// How the argument is given.
139 pub kind: ArgKind,
140 /// The short name, without the leading `-`.
141 pub short: Option<char>,
142 /// The long name, without the leading `--`.
143 pub long: Option<&'static str>,
144 /// The short aliases listed in the help.
145 pub visible_short_aliases: &'static [char],
146 /// The short aliases hidden from the help.
147 pub short_aliases: &'static [char],
148 /// The long aliases listed in the help.
149 pub visible_aliases: &'static [&'static str],
150 /// The long aliases hidden from the help.
151 pub aliases: &'static [&'static str],
152 /// The name of the value, e.g. `FILE`. Empty for flags.
153 pub value_name: &'static str,
154 /// The short help. Empty when not set.
155 pub help: &'static str,
156 /// The long help. Empty when not set.
157 pub long_help: &'static str,
158 /// The accepted values, from `possible_values` or a [`ValueEnum`](crate::ValueEnum). Empty
159 /// when any value is accepted.
160 pub possible_values: &'static [&'static str],
161 /// The environment variable the argument falls back to.
162 pub env: Option<&'static str>,
163 /// Whether the argument is hidden from the help.
164 pub hidden: bool,
165 /// Whether the argument must be given.
166 pub required: bool,
167 /// Whether the argument can be given several times, e.g. a `Count` flag or a field collecting
168 /// [repeated values][crate::guide::collections]. A repeatable positional argument takes every
169 /// remaining positional argument.
170 pub multiple: bool,
171 /// Whether the positional argument is only filled after `--`.
172 pub last: bool,
173 /// Whether the option is `global`: also accepted after the subcommands of its command, and
174 /// listed in their help and completions.
175 pub global: bool,
176}
177
178impl ArgInfo {
179 /// An argument named `id`, without names, help or values.
180 pub const fn new(id: &'static str, kind: ArgKind) -> Self {
181 ArgInfo {
182 id,
183 kind,
184 short: None,
185 long: None,
186 visible_short_aliases: &[],
187 short_aliases: &[],
188 visible_aliases: &[],
189 aliases: &[],
190 value_name: "",
191 help: "",
192 long_help: "",
193 possible_values: &[],
194 env: None,
195 hidden: false,
196 required: false,
197 multiple: false,
198 last: false,
199 global: false,
200 }
201 }
202
203 /// Sets [`short`](Self::short).
204 pub const fn short(mut self, short: char) -> Self {
205 self.short = Some(short);
206 self
207 }
208
209 /// Sets [`long`](Self::long).
210 pub const fn long(mut self, long: &'static str) -> Self {
211 self.long = Some(long);
212 self
213 }
214
215 /// Sets [`visible_short_aliases`](Self::visible_short_aliases).
216 pub const fn visible_short_aliases(mut self, aliases: &'static [char]) -> Self {
217 self.visible_short_aliases = aliases;
218 self
219 }
220
221 /// Sets [`short_aliases`](Self::short_aliases).
222 pub const fn short_aliases(mut self, aliases: &'static [char]) -> Self {
223 self.short_aliases = aliases;
224 self
225 }
226
227 /// Sets [`visible_aliases`](Self::visible_aliases).
228 pub const fn visible_aliases(mut self, aliases: &'static [&'static str]) -> Self {
229 self.visible_aliases = aliases;
230 self
231 }
232
233 /// Sets [`aliases`](Self::aliases).
234 pub const fn aliases(mut self, aliases: &'static [&'static str]) -> Self {
235 self.aliases = aliases;
236 self
237 }
238
239 /// Sets [`value_name`](Self::value_name).
240 pub const fn value_name(mut self, value_name: &'static str) -> Self {
241 self.value_name = value_name;
242 self
243 }
244
245 /// Sets [`help`](Self::help).
246 pub const fn help(mut self, help: &'static str) -> Self {
247 self.help = help;
248 self
249 }
250
251 /// Sets [`long_help`](Self::long_help).
252 pub const fn long_help(mut self, long_help: &'static str) -> Self {
253 self.long_help = long_help;
254 self
255 }
256
257 /// Sets [`possible_values`](Self::possible_values).
258 pub const fn possible_values(mut self, values: &'static [&'static str]) -> Self {
259 self.possible_values = values;
260 self
261 }
262
263 /// Sets [`env`](Self::env).
264 pub const fn env(mut self, env: &'static str) -> Self {
265 self.env = Some(env);
266 self
267 }
268
269 /// Sets [`hidden`](Self::hidden).
270 pub const fn hidden(mut self, hidden: bool) -> Self {
271 self.hidden = hidden;
272 self
273 }
274
275 /// Sets [`required`](Self::required).
276 pub const fn required(mut self, required: bool) -> Self {
277 self.required = required;
278 self
279 }
280
281 /// Sets [`multiple`](Self::multiple).
282 pub const fn multiple(mut self, multiple: bool) -> Self {
283 self.multiple = multiple;
284 self
285 }
286
287 /// Sets [`last`](Self::last).
288 pub const fn last(mut self, last: bool) -> Self {
289 self.last = last;
290 self
291 }
292
293 /// Sets [`global`](Self::global).
294 pub const fn global(mut self, global: bool) -> Self {
295 self.global = global;
296 self
297 }
298
299 /// Whether the argument takes a value: options and positional arguments.
300 pub const fn takes_value(&self) -> bool {
301 matches!(self.kind, ArgKind::Positional | ArgKind::Option)
302 }
303
304 /// Whether the argument is positional.
305 pub const fn is_positional(&self) -> bool {
306 matches!(self.kind, ArgKind::Positional)
307 }
308
309 /// The long help, or the short help when there is no long help.
310 pub const fn long_or_short_help(&self) -> &'static str {
311 if self.long_help.is_empty() {
312 self.help
313 } else {
314 self.long_help
315 }
316 }
317}