usage/spec/unknown_flags.rs
1use serde::Serialize;
2
3/// What to do with a token that looks like a flag but names no declared flag.
4///
5/// The default is [`UnknownFlags::Value`], which is where this parser parts
6/// company with clap, argparse, commander, oclif v2+, and POSIX `getopt` — all of
7/// which reject the token. The reason is that those parse *their own* argv, where
8/// a dash-word can only be a flag or a typo, while a usage spec is also used to
9/// parse things whose flags it does not own:
10///
11/// - a shell script run through `usage exec`, forwarding options to a tool it wraps
12/// - a task's arguments, where the task script is the authority on what it accepts
13/// - a completion, asked about a command line that is still being typed
14///
15/// In all three, a dash-word the spec has not heard of is far more likely to be
16/// data in transit than a mistake, and rejecting it would break the wrapper for
17/// everyone who did not enumerate the flags of the program behind it.
18///
19/// The cost is real and worth stating: a misspelled `--hekp` becomes an argument
20/// instead of an error, and whether it does depends on whether a positional is
21/// free to take it. A CLI that owns all of its flags — as opposed to forwarding
22/// them — should say [`UnknownFlags::Error`] and get the stricter reading.
23#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Serialize)]
24#[serde(rename_all = "snake_case")]
25pub enum UnknownFlags {
26 /// Offer the token to the positional arguments, like any other word. If none
27 /// can take it, it is an unexpected argument — the same error an extra word
28 /// would produce.
29 #[default]
30 Value,
31 /// Reject the token. A CLI whose flags are all its own gets typo detection
32 /// this way, at the price of needing `--` to pass a value that begins with a
33 /// dash.
34 Error,
35}
36
37impl_string_enum!(UnknownFlags {
38 UnknownFlags::Value => "value",
39 UnknownFlags::Error => "error",
40});
41
42impl UnknownFlags {
43 pub fn as_str(&self) -> &'static str {
44 match self {
45 UnknownFlags::Value => "value",
46 UnknownFlags::Error => "error",
47 }
48 }
49}
50
51/// The values a spec may use, for error messages.
52pub(crate) const UNKNOWN_FLAGS_VALUES: &str = "value, error";