summaryrefslogtreecommitdiffstats
path: root/third_party/rust/clap/examples
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/clap/examples')
-rw-r--r--third_party/rust/clap/examples/README.md16
-rw-r--r--third_party/rust/clap/examples/cargo-example-derive.md38
-rw-r--r--third_party/rust/clap/examples/cargo-example-derive.rs20
-rw-r--r--third_party/rust/clap/examples/cargo-example.md38
-rw-r--r--third_party/rust/clap/examples/cargo-example.rs18
-rw-r--r--third_party/rust/clap/examples/demo.md17
-rw-r--r--third_party/rust/clap/examples/demo.rs22
-rw-r--r--third_party/rust/clap/examples/derive_ref/augment_args.rs27
-rw-r--r--third_party/rust/clap/examples/derive_ref/augment_subcommands.rs21
-rw-r--r--third_party/rust/clap/examples/derive_ref/flatten_hand_args.rs91
-rw-r--r--third_party/rust/clap/examples/derive_ref/hand_subcommand.rs79
-rw-r--r--third_party/rust/clap/examples/derive_ref/interop_tests.md248
-rw-r--r--third_party/rust/clap/examples/escaped-positional-derive.md60
-rw-r--r--third_party/rust/clap/examples/escaped-positional-derive.rs25
-rw-r--r--third_party/rust/clap/examples/escaped-positional.md60
-rw-r--r--third_party/rust/clap/examples/escaped-positional.rs32
-rw-r--r--third_party/rust/clap/examples/find.md45
-rw-r--r--third_party/rust/clap/examples/find.rs99
-rw-r--r--third_party/rust/clap/examples/git-derive.md159
-rw-r--r--third_party/rust/clap/examples/git-derive.rs164
-rw-r--r--third_party/rust/clap/examples/git.md157
-rw-r--r--third_party/rust/clap/examples/git.rs137
-rw-r--r--third_party/rust/clap/examples/multicall-busybox.md39
-rw-r--r--third_party/rust/clap/examples/multicall-busybox.rs47
-rw-r--r--third_party/rust/clap/examples/multicall-hostname.md10
-rw-r--r--third_party/rust/clap/examples/multicall-hostname.rs17
-rw-r--r--third_party/rust/clap/examples/pacman.md79
-rw-r--r--third_party/rust/clap/examples/pacman.rs111
-rw-r--r--third_party/rust/clap/examples/repl.rs92
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/01_quick.md35
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/01_quick.rs60
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/02_app_settings.md17
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/02_app_settings.rs18
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/02_apps.md16
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/02_apps.rs20
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/02_crate.md16
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/02_crate.rs18
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.md26
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.md21
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_02_option.md30
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_02_option.rs9
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.md30
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_03_positional.md20
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_03_positional.rs9
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.md23
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.rs15
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.md59
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.rs22
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_05_default_values.md20
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/03_05_default_values.rs18
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_01_enum.md47
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_01_enum.rs66
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_01_possible.md27
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_01_possible.rs26
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_02_parse.md29
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_02_parse.rs17
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_02_validate.md29
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_02_validate.rs36
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_03_relations.md53
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_03_relations.rs78
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_04_custom.md52
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/04_04_custom.rs84
-rw-r--r--third_party/rust/clap/examples/tutorial_builder/05_01_assert.rs25
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/01_quick.md35
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/01_quick.rs68
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/02_app_settings.md17
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/02_app_settings.rs18
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/02_apps.md16
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/02_apps.rs20
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/02_crate.md16
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/02_crate.rs17
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.md26
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.md21
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_02_option.md30
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_02_option.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.md30
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_03_positional.md20
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_03_positional.rs13
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.md23
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.rs13
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.md60
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.rs27
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_04_subcommands_alt.rs32
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_05_default_values.md20
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/03_05_default_values.rs14
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_01_enum.md47
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_01_enum.rs32
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_02_parse.md29
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_02_parse.rs15
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_02_validate.md29
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_02_validate.rs34
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_03_relations.md53
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_03_relations.rs75
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_04_custom.md52
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/04_04_custom.rs91
-rw-r--r--third_party/rust/clap/examples/tutorial_derive/05_01_assert.rs20
-rw-r--r--third_party/rust/clap/examples/typed-derive.md131
-rw-r--r--third_party/rust/clap/examples/typed-derive.rs102
104 files changed, 4383 insertions, 0 deletions
diff --git a/third_party/rust/clap/examples/README.md b/third_party/rust/clap/examples/README.md
new file mode 100644
index 0000000000..f98c370c82
--- /dev/null
+++ b/third_party/rust/clap/examples/README.md
@@ -0,0 +1,16 @@
+# Examples
+
+We try to focus our documentation on the [four types of
+documentation](https://documentation.divio.com/). Examples fit into this by
+providing:
+- [Cookbook / How-To Guides](https://docs.rs/clap/latest/clap/_cookbook/index.html)
+- Tutorials ([derive](https://docs.rs/clap/latest/clap/_derive/_tutorial/index.html), [builder](https://docs.rs/clap/latest/clap/_tutorial/index.html))
+
+This directory contains the source for the above.
+
+## Contributing
+
+New examples should fit within the above structure and support their narrative
+- Add the example to [Cargo.toml](../Cargo.toml) for any `required-features`
+- Document how the example works with a `.md` file which will be verified using [trycmd](https://docs.rs/trycmd)
+- Pull the `.rs` and `.md` file into the appropriate module doc comment to be accessible on docs.rs
diff --git a/third_party/rust/clap/examples/cargo-example-derive.md b/third_party/rust/clap/examples/cargo-example-derive.md
new file mode 100644
index 0000000000..a3dcef386f
--- /dev/null
+++ b/third_party/rust/clap/examples/cargo-example-derive.md
@@ -0,0 +1,38 @@
+For more on creating a custom subcommand, see [the cargo
+book](https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands).
+The crate [`clap-cargo`](https://github.com/crate-ci/clap-cargo) can help in
+mimicking cargo's interface.
+
+The help looks like:
+```console
+$ cargo-example-derive --help
+Usage: cargo <COMMAND>
+
+Commands:
+ example-derive A simple to use, efficient, and full-featured Command Line Argument Parser
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+
+$ cargo-example-derive example-derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: cargo example-derive [OPTIONS]
+
+Options:
+ --manifest-path <MANIFEST_PATH>
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+Then to directly invoke the command, run:
+```console
+$ cargo-example-derive example-derive
+None
+
+$ cargo-example-derive example-derive --manifest-path Cargo.toml
+Some("Cargo.toml")
+
+```
diff --git a/third_party/rust/clap/examples/cargo-example-derive.rs b/third_party/rust/clap/examples/cargo-example-derive.rs
new file mode 100644
index 0000000000..dfdd799fc1
--- /dev/null
+++ b/third_party/rust/clap/examples/cargo-example-derive.rs
@@ -0,0 +1,20 @@
+use clap::Parser;
+
+#[derive(Parser)] // requires `derive` feature
+#[command(name = "cargo")]
+#[command(bin_name = "cargo")]
+enum CargoCli {
+ ExampleDerive(ExampleDeriveArgs),
+}
+
+#[derive(clap::Args)]
+#[command(author, version, about, long_about = None)]
+struct ExampleDeriveArgs {
+ #[arg(long)]
+ manifest_path: Option<std::path::PathBuf>,
+}
+
+fn main() {
+ let CargoCli::ExampleDerive(args) = CargoCli::parse();
+ println!("{:?}", args.manifest_path);
+}
diff --git a/third_party/rust/clap/examples/cargo-example.md b/third_party/rust/clap/examples/cargo-example.md
new file mode 100644
index 0000000000..edf8ee18a3
--- /dev/null
+++ b/third_party/rust/clap/examples/cargo-example.md
@@ -0,0 +1,38 @@
+For more on creating a custom subcommand, see [the cargo
+book](https://doc.rust-lang.org/cargo/reference/external-tools.html#custom-subcommands).
+The crate [`clap-cargo`](https://github.com/crate-ci/clap-cargo) can help in
+mimicking cargo's interface.
+
+The help looks like:
+```console
+$ cargo-example --help
+Usage: cargo <COMMAND>
+
+Commands:
+ example A simple to use, efficient, and full-featured Command Line Argument Parser
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+
+$ cargo-example example --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: cargo example [OPTIONS]
+
+Options:
+ --manifest-path <PATH>
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+Then to directly invoke the command, run:
+```console
+$ cargo-example example
+None
+
+$ cargo-example example --manifest-path Cargo.toml
+Some("Cargo.toml")
+
+```
diff --git a/third_party/rust/clap/examples/cargo-example.rs b/third_party/rust/clap/examples/cargo-example.rs
new file mode 100644
index 0000000000..1173365144
--- /dev/null
+++ b/third_party/rust/clap/examples/cargo-example.rs
@@ -0,0 +1,18 @@
+fn main() {
+ let cmd = clap::Command::new("cargo")
+ .bin_name("cargo")
+ .subcommand_required(true)
+ .subcommand(
+ clap::command!("example").arg(
+ clap::arg!(--"manifest-path" <PATH>)
+ .value_parser(clap::value_parser!(std::path::PathBuf)),
+ ),
+ );
+ let matches = cmd.get_matches();
+ let matches = match matches.subcommand() {
+ Some(("example", matches)) => matches,
+ _ => unreachable!("clap should ensure we don't get here"),
+ };
+ let manifest_path = matches.get_one::<std::path::PathBuf>("manifest-path");
+ println!("{manifest_path:?}");
+}
diff --git a/third_party/rust/clap/examples/demo.md b/third_party/rust/clap/examples/demo.md
new file mode 100644
index 0000000000..772d98dca0
--- /dev/null
+++ b/third_party/rust/clap/examples/demo.md
@@ -0,0 +1,17 @@
+```console
+$ demo --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: demo[EXE] [OPTIONS] --name <NAME>
+
+Options:
+ -n, --name <NAME> Name of the person to greet
+ -c, --count <COUNT> Number of times to greet [default: 1]
+ -h, --help Print help
+ -V, --version Print version
+
+$ demo --name Me
+Hello Me!
+
+```
+*(version number and `.exe` extension on windows replaced by placeholders)*
diff --git a/third_party/rust/clap/examples/demo.rs b/third_party/rust/clap/examples/demo.rs
new file mode 100644
index 0000000000..8e4304a2e6
--- /dev/null
+++ b/third_party/rust/clap/examples/demo.rs
@@ -0,0 +1,22 @@
+use clap::Parser;
+
+/// Simple program to greet a person
+#[derive(Parser, Debug)]
+#[command(author, version, about, long_about = None)]
+struct Args {
+ /// Name of the person to greet
+ #[arg(short, long)]
+ name: String,
+
+ /// Number of times to greet
+ #[arg(short, long, default_value_t = 1)]
+ count: u8,
+}
+
+fn main() {
+ let args = Args::parse();
+
+ for _ in 0..args.count {
+ println!("Hello {}!", args.name)
+ }
+}
diff --git a/third_party/rust/clap/examples/derive_ref/augment_args.rs b/third_party/rust/clap/examples/derive_ref/augment_args.rs
new file mode 100644
index 0000000000..39d837cfaf
--- /dev/null
+++ b/third_party/rust/clap/examples/derive_ref/augment_args.rs
@@ -0,0 +1,27 @@
+use clap::{arg, Args, Command, FromArgMatches as _};
+
+#[derive(Args, Debug)]
+struct DerivedArgs {
+ #[arg(short, long)]
+ derived: bool,
+}
+
+fn main() {
+ let cli = Command::new("CLI").arg(arg!(-b - -built).action(clap::ArgAction::SetTrue));
+ // Augment built args with derived args
+ let cli = DerivedArgs::augment_args(cli);
+
+ let matches = cli.get_matches();
+ println!("Value of built: {:?}", matches.get_flag("built"));
+ println!(
+ "Value of derived via ArgMatches: {:?}",
+ matches.get_flag("derived")
+ );
+
+ // Since DerivedArgs implements FromArgMatches, we can extract it from the unstructured ArgMatches.
+ // This is the main benefit of using derived arguments.
+ let derived_matches = DerivedArgs::from_arg_matches(&matches)
+ .map_err(|err| err.exit())
+ .unwrap();
+ println!("Value of derived: {derived_matches:#?}");
+}
diff --git a/third_party/rust/clap/examples/derive_ref/augment_subcommands.rs b/third_party/rust/clap/examples/derive_ref/augment_subcommands.rs
new file mode 100644
index 0000000000..51cbe75d2a
--- /dev/null
+++ b/third_party/rust/clap/examples/derive_ref/augment_subcommands.rs
@@ -0,0 +1,21 @@
+use clap::{Command, FromArgMatches as _, Parser, Subcommand as _};
+
+#[derive(Parser, Debug)]
+enum Subcommands {
+ Derived {
+ #[arg(short, long)]
+ derived_flag: bool,
+ },
+}
+
+fn main() {
+ let cli = Command::new("Built CLI");
+ // Augment with derived subcommands
+ let cli = Subcommands::augment_subcommands(cli);
+
+ let matches = cli.get_matches();
+ let derived_subcommands = Subcommands::from_arg_matches(&matches)
+ .map_err(|err| err.exit())
+ .unwrap();
+ println!("Derived subcommands: {derived_subcommands:#?}");
+}
diff --git a/third_party/rust/clap/examples/derive_ref/flatten_hand_args.rs b/third_party/rust/clap/examples/derive_ref/flatten_hand_args.rs
new file mode 100644
index 0000000000..36aac09323
--- /dev/null
+++ b/third_party/rust/clap/examples/derive_ref/flatten_hand_args.rs
@@ -0,0 +1,91 @@
+use clap::error::Error;
+use clap::{Arg, ArgAction, ArgMatches, Args, Command, FromArgMatches, Parser};
+
+#[derive(Debug)]
+struct CliArgs {
+ foo: bool,
+ bar: bool,
+ quuz: Option<String>,
+}
+
+impl FromArgMatches for CliArgs {
+ fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
+ let mut matches = matches.clone();
+ Self::from_arg_matches_mut(&mut matches)
+ }
+ fn from_arg_matches_mut(matches: &mut ArgMatches) -> Result<Self, Error> {
+ Ok(Self {
+ foo: matches.get_flag("foo"),
+ bar: matches.get_flag("bar"),
+ quuz: matches.remove_one::<String>("quuz"),
+ })
+ }
+ fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
+ let mut matches = matches.clone();
+ self.update_from_arg_matches_mut(&mut matches)
+ }
+ fn update_from_arg_matches_mut(&mut self, matches: &mut ArgMatches) -> Result<(), Error> {
+ self.foo |= matches.get_flag("foo");
+ self.bar |= matches.get_flag("bar");
+ if let Some(quuz) = matches.remove_one::<String>("quuz") {
+ self.quuz = Some(quuz);
+ }
+ Ok(())
+ }
+}
+
+impl Args for CliArgs {
+ fn augment_args(cmd: Command) -> Command {
+ cmd.arg(
+ Arg::new("foo")
+ .short('f')
+ .long("foo")
+ .action(ArgAction::SetTrue),
+ )
+ .arg(
+ Arg::new("bar")
+ .short('b')
+ .long("bar")
+ .action(ArgAction::SetTrue),
+ )
+ .arg(
+ Arg::new("quuz")
+ .short('q')
+ .long("quuz")
+ .action(ArgAction::Set),
+ )
+ }
+ fn augment_args_for_update(cmd: Command) -> Command {
+ cmd.arg(
+ Arg::new("foo")
+ .short('f')
+ .long("foo")
+ .action(ArgAction::SetTrue),
+ )
+ .arg(
+ Arg::new("bar")
+ .short('b')
+ .long("bar")
+ .action(ArgAction::SetTrue),
+ )
+ .arg(
+ Arg::new("quuz")
+ .short('q')
+ .long("quuz")
+ .action(ArgAction::Set),
+ )
+ }
+}
+
+#[derive(Parser, Debug)]
+struct Cli {
+ #[arg(short, long)]
+ top_level: bool,
+ #[command(flatten)]
+ more_args: CliArgs,
+}
+
+fn main() {
+ let args = Cli::parse();
+ println!("{args:#?}");
+}
diff --git a/third_party/rust/clap/examples/derive_ref/hand_subcommand.rs b/third_party/rust/clap/examples/derive_ref/hand_subcommand.rs
new file mode 100644
index 0000000000..ebaa60d5d2
--- /dev/null
+++ b/third_party/rust/clap/examples/derive_ref/hand_subcommand.rs
@@ -0,0 +1,79 @@
+use clap::error::{Error, ErrorKind};
+use clap::{ArgMatches, Args as _, Command, FromArgMatches, Parser, Subcommand};
+
+#[derive(Parser, Debug)]
+struct AddArgs {
+ name: Vec<String>,
+}
+#[derive(Parser, Debug)]
+struct RemoveArgs {
+ #[arg(short, long)]
+ force: bool,
+ name: Vec<String>,
+}
+
+#[derive(Debug)]
+enum CliSub {
+ Add(AddArgs),
+ Remove(RemoveArgs),
+}
+
+impl FromArgMatches for CliSub {
+ fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
+ match matches.subcommand() {
+ Some(("add", args)) => Ok(Self::Add(AddArgs::from_arg_matches(args)?)),
+ Some(("remove", args)) => Ok(Self::Remove(RemoveArgs::from_arg_matches(args)?)),
+ Some((_, _)) => Err(Error::raw(
+ ErrorKind::InvalidSubcommand,
+ "Valid subcommands are `add` and `remove`",
+ )),
+ None => Err(Error::raw(
+ ErrorKind::MissingSubcommand,
+ "Valid subcommands are `add` and `remove`",
+ )),
+ }
+ }
+ fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
+ match matches.subcommand() {
+ Some(("add", args)) => *self = Self::Add(AddArgs::from_arg_matches(args)?),
+ Some(("remove", args)) => *self = Self::Remove(RemoveArgs::from_arg_matches(args)?),
+ Some((_, _)) => {
+ return Err(Error::raw(
+ ErrorKind::InvalidSubcommand,
+ "Valid subcommands are `add` and `remove`",
+ ))
+ }
+ None => (),
+ };
+ Ok(())
+ }
+}
+
+impl Subcommand for CliSub {
+ fn augment_subcommands(cmd: Command) -> Command {
+ cmd.subcommand(AddArgs::augment_args(Command::new("add")))
+ .subcommand(RemoveArgs::augment_args(Command::new("remove")))
+ .subcommand_required(true)
+ }
+ fn augment_subcommands_for_update(cmd: Command) -> Command {
+ cmd.subcommand(AddArgs::augment_args(Command::new("add")))
+ .subcommand(RemoveArgs::augment_args(Command::new("remove")))
+ .subcommand_required(true)
+ }
+ fn has_subcommand(name: &str) -> bool {
+ matches!(name, "add" | "remove")
+ }
+}
+
+#[derive(Parser, Debug)]
+struct Cli {
+ #[arg(short, long)]
+ top_level: bool,
+ #[command(subcommand)]
+ subcommand: CliSub,
+}
+
+fn main() {
+ let args = Cli::parse();
+ println!("{args:#?}");
+}
diff --git a/third_party/rust/clap/examples/derive_ref/interop_tests.md b/third_party/rust/clap/examples/derive_ref/interop_tests.md
new file mode 100644
index 0000000000..b29e2d52d0
--- /dev/null
+++ b/third_party/rust/clap/examples/derive_ref/interop_tests.md
@@ -0,0 +1,248 @@
+Following are tests for the interop examples in this directory.
+
+## Augment Args
+
+```console
+$ interop_augment_args
+Value of built: false
+Value of derived via ArgMatches: false
+Value of derived: DerivedArgs {
+ derived: false,
+}
+
+```
+
+```console
+$ interop_augment_args -b --derived
+Value of built: true
+Value of derived via ArgMatches: true
+Value of derived: DerivedArgs {
+ derived: true,
+}
+
+```
+
+```console
+$ interop_augment_args -d --built
+Value of built: true
+Value of derived via ArgMatches: true
+Value of derived: DerivedArgs {
+ derived: true,
+}
+
+```
+
+```console
+$ interop_augment_args --unknown
+? failed
+error: unexpected argument '--unknown' found
+
+Usage: interop_augment_args[EXE] [OPTIONS]
+
+For more information, try '--help'.
+
+```
+
+## Augment Subcommands
+
+```console
+$ interop_augment_subcommands
+? failed
+error: A subcommand is required but one was not provided.
+```
+
+```console
+$ interop_augment_subcommands derived
+Derived subcommands: Derived {
+ derived_flag: false,
+}
+
+```
+
+```console
+$ interop_augment_subcommands derived --derived-flag
+Derived subcommands: Derived {
+ derived_flag: true,
+}
+
+```
+
+```console
+$ interop_augment_subcommands derived --unknown
+? failed
+error: unexpected argument '--unknown' found
+
+Usage: interop_augment_subcommands[EXE] derived [OPTIONS]
+
+For more information, try '--help'.
+
+```
+
+```console
+$ interop_augment_subcommands unknown
+? failed
+error: unrecognized subcommand 'unknown'
+
+Usage: interop_augment_subcommands[EXE] [COMMAND]
+
+For more information, try '--help'.
+
+```
+
+## Hand-Implemented Subcommand
+
+```console
+$ interop_hand_subcommand
+? failed
+Usage: interop_hand_subcommand[EXE] [OPTIONS] <COMMAND>
+
+Commands:
+ add
+ remove
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -t, --top-level
+ -h, --help Print help
+
+```
+
+```console
+$ interop_hand_subcommand add
+Cli {
+ top_level: false,
+ subcommand: Add(
+ AddArgs {
+ name: [],
+ },
+ ),
+}
+
+```
+
+```console
+$ interop_hand_subcommand add a b c
+Cli {
+ top_level: false,
+ subcommand: Add(
+ AddArgs {
+ name: [
+ "a",
+ "b",
+ "c",
+ ],
+ },
+ ),
+}
+
+```
+
+```console
+$ interop_hand_subcommand add --unknown
+? failed
+error: unexpected argument '--unknown' found
+
+ tip: to pass '--unknown' as a value, use '-- --unknown'
+
+Usage: interop_hand_subcommand[EXE] add [NAME]...
+
+For more information, try '--help'.
+
+```
+
+```console
+$ interop_hand_subcommand remove
+Cli {
+ top_level: false,
+ subcommand: Remove(
+ RemoveArgs {
+ force: false,
+ name: [],
+ },
+ ),
+}
+
+```
+
+```console
+$ interop_hand_subcommand remove --force a b c
+Cli {
+ top_level: false,
+ subcommand: Remove(
+ RemoveArgs {
+ force: true,
+ name: [
+ "a",
+ "b",
+ "c",
+ ],
+ },
+ ),
+}
+
+```
+
+```console
+$ interop_hand_subcommand unknown
+? failed
+error: unrecognized subcommand 'unknown'
+
+Usage: interop_hand_subcommand[EXE] [OPTIONS] <COMMAND>
+
+For more information, try '--help'.
+
+```
+
+## Flatten Hand-Implemented Args
+
+```console
+$ interop_flatten_hand_args
+Cli {
+ top_level: false,
+ more_args: CliArgs {
+ foo: false,
+ bar: false,
+ quuz: None,
+ },
+}
+
+```
+
+```console
+$ interop_flatten_hand_args -f --bar
+Cli {
+ top_level: false,
+ more_args: CliArgs {
+ foo: true,
+ bar: true,
+ quuz: None,
+ },
+}
+
+```
+
+```console
+$ interop_flatten_hand_args --quuz abc
+Cli {
+ top_level: false,
+ more_args: CliArgs {
+ foo: false,
+ bar: false,
+ quuz: Some(
+ "abc",
+ ),
+ },
+}
+
+```
+
+```console
+$ interop_flatten_hand_args --unknown
+? failed
+error: unexpected argument '--unknown' found
+
+Usage: interop_flatten_hand_args[EXE] [OPTIONS]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/escaped-positional-derive.md b/third_party/rust/clap/examples/escaped-positional-derive.md
new file mode 100644
index 0000000000..82990b59f1
--- /dev/null
+++ b/third_party/rust/clap/examples/escaped-positional-derive.md
@@ -0,0 +1,60 @@
+**This requires enabling the [`derive` feature flag][crate::_features].**
+
+You can use `--` to escape further arguments.
+
+Let's see what this looks like in the help:
+```console
+$ escaped-positional-derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: escaped-positional-derive[EXE] [OPTIONS] [-- <SLOP>...]
+
+Arguments:
+ [SLOP]...
+
+Options:
+ -f
+ -p <PEAR>
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+Here is a baseline without any arguments:
+```console
+$ escaped-positional-derive
+-f used: false
+-p's value: None
+'slops' values: []
+
+```
+
+Notice that we can't pass positional arguments before `--`:
+```console
+$ escaped-positional-derive foo bar
+? failed
+error: unexpected argument 'foo' found
+
+Usage: escaped-positional-derive[EXE] [OPTIONS] [-- <SLOP>...]
+
+For more information, try '--help'.
+
+```
+
+But you can after:
+```console
+$ escaped-positional-derive -f -p=bob -- sloppy slop slop
+-f used: true
+-p's value: Some("bob")
+'slops' values: ["sloppy", "slop", "slop"]
+
+```
+
+As mentioned, the parser will directly pass everything through:
+```console
+$ escaped-positional-derive -- -f -p=bob sloppy slop slop
+-f used: false
+-p's value: None
+'slops' values: ["-f", "-p=bob", "sloppy", "slop", "slop"]
+
+```
diff --git a/third_party/rust/clap/examples/escaped-positional-derive.rs b/third_party/rust/clap/examples/escaped-positional-derive.rs
new file mode 100644
index 0000000000..719b3d6c21
--- /dev/null
+++ b/third_party/rust/clap/examples/escaped-positional-derive.rs
@@ -0,0 +1,25 @@
+use clap::Parser;
+
+#[derive(Parser)] // requires `derive` feature
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(short = 'f')]
+ eff: bool,
+
+ #[arg(short = 'p', value_name = "PEAR")]
+ pea: Option<String>,
+
+ #[arg(last = true)]
+ slop: Vec<String>,
+}
+
+fn main() {
+ let args = Cli::parse();
+
+ // This is what will happen with `myprog -f -p=bob -- sloppy slop slop`...
+ println!("-f used: {:?}", args.eff); // -f used: true
+ println!("-p's value: {:?}", args.pea); // -p's value: Some("bob")
+ println!("'slops' values: {:?}", args.slop); // 'slops' values: Some(["sloppy", "slop", "slop"])
+
+ // Continued program logic goes here...
+}
diff --git a/third_party/rust/clap/examples/escaped-positional.md b/third_party/rust/clap/examples/escaped-positional.md
new file mode 100644
index 0000000000..d94e3993c8
--- /dev/null
+++ b/third_party/rust/clap/examples/escaped-positional.md
@@ -0,0 +1,60 @@
+**This requires enabling the [`cargo` feature flag][crate::_features].**
+
+You can use `--` to escape further arguments.
+
+Let's see what this looks like in the help:
+```console
+$ escaped-positional --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: escaped-positional[EXE] [OPTIONS] [-- <SLOP>...]
+
+Arguments:
+ [SLOP]...
+
+Options:
+ -f
+ -p <PEAR>
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+Here is a baseline without any arguments:
+```console
+$ escaped-positional
+-f used: false
+-p's value: None
+'slops' values: []
+
+```
+
+Notice that we can't pass positional arguments before `--`:
+```console
+$ escaped-positional foo bar
+? failed
+error: unexpected argument 'foo' found
+
+Usage: escaped-positional[EXE] [OPTIONS] [-- <SLOP>...]
+
+For more information, try '--help'.
+
+```
+
+But you can after:
+```console
+$ escaped-positional -f -p=bob -- sloppy slop slop
+-f used: true
+-p's value: Some("bob")
+'slops' values: ["sloppy", "slop", "slop"]
+
+```
+
+As mentioned, the parser will directly pass everything through:
+```console
+$ escaped-positional -- -f -p=bob sloppy slop slop
+-f used: false
+-p's value: None
+'slops' values: ["-f", "-p=bob", "sloppy", "slop", "slop"]
+
+```
diff --git a/third_party/rust/clap/examples/escaped-positional.rs b/third_party/rust/clap/examples/escaped-positional.rs
new file mode 100644
index 0000000000..d107e47db4
--- /dev/null
+++ b/third_party/rust/clap/examples/escaped-positional.rs
@@ -0,0 +1,32 @@
+use clap::{arg, command, value_parser, ArgAction};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(arg!(eff: -f).action(ArgAction::SetTrue))
+ .arg(arg!(pea: -p <PEAR>).value_parser(value_parser!(String)))
+ .arg(
+ // Indicates that `slop` is only accessible after `--`.
+ arg!(slop: [SLOP])
+ .num_args(1..)
+ .last(true)
+ .value_parser(value_parser!(String)),
+ )
+ .get_matches();
+
+ // This is what will happen with `myprog -f -p=bob -- sloppy slop slop`...
+
+ // -f used: true
+ println!("-f used: {:?}", matches.get_flag("eff"));
+ // -p's value: Some("bob")
+ println!("-p's value: {:?}", matches.get_one::<String>("pea"));
+ // 'slops' values: Some(["sloppy", "slop", "slop"])
+ println!(
+ "'slops' values: {:?}",
+ matches
+ .get_many::<String>("slop")
+ .map(|vals| vals.collect::<Vec<_>>())
+ .unwrap_or_default()
+ );
+
+ // Continued program logic goes here...
+}
diff --git a/third_party/rust/clap/examples/find.md b/third_party/rust/clap/examples/find.md
new file mode 100644
index 0000000000..e9b1a86f89
--- /dev/null
+++ b/third_party/rust/clap/examples/find.md
@@ -0,0 +1,45 @@
+`find` is an example of position-sensitive flags
+
+```console
+$ find --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: find[EXE] [OPTIONS]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+TESTS:
+ --empty File is empty and is either a regular file or a directory
+ --name <NAME> Base of file name (the path with the leading directories removed) matches shell
+ pattern pattern
+
+OPERATORS:
+ -o, --or expr2 is not evaluate if exp1 is true
+ -a, --and Same as `expr1 expr1`
+
+$ find --empty -o --name .keep
+[
+ (
+ "empty",
+ Bool(
+ true,
+ ),
+ ),
+ (
+ "or",
+ Bool(
+ true,
+ ),
+ ),
+ (
+ "name",
+ String(
+ ".keep",
+ ),
+ ),
+]
+
+```
+
diff --git a/third_party/rust/clap/examples/find.rs b/third_party/rust/clap/examples/find.rs
new file mode 100644
index 0000000000..0b7f2c7000
--- /dev/null
+++ b/third_party/rust/clap/examples/find.rs
@@ -0,0 +1,99 @@
+use std::collections::BTreeMap;
+
+use clap::{arg, command, ArgGroup, ArgMatches, Command};
+
+fn main() {
+ let matches = cli().get_matches();
+ let values = Value::from_matches(&matches);
+ println!("{values:#?}");
+}
+
+fn cli() -> Command {
+ command!()
+ .group(ArgGroup::new("tests").multiple(true))
+ .next_help_heading("TESTS")
+ .args([
+ arg!(--empty "File is empty and is either a regular file or a directory").group("tests"),
+ arg!(--name <NAME> "Base of file name (the path with the leading directories removed) matches shell pattern pattern").group("tests"),
+ ])
+ .group(ArgGroup::new("operators").multiple(true))
+ .next_help_heading("OPERATORS")
+ .args([
+ arg!(-o - -or "expr2 is not evaluate if exp1 is true").group("operators"),
+ arg!(-a - -and "Same as `expr1 expr1`").group("operators"),
+ ])
+}
+
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Value {
+ Bool(bool),
+ String(String),
+}
+
+impl Value {
+ pub fn from_matches(matches: &ArgMatches) -> Vec<(clap::Id, Self)> {
+ let mut values = BTreeMap::new();
+ for id in matches.ids() {
+ if matches.try_get_many::<clap::Id>(id.as_str()).is_ok() {
+ // ignore groups
+ continue;
+ }
+ let value_source = matches
+ .value_source(id.as_str())
+ .expect("id came from matches");
+ if value_source != clap::parser::ValueSource::CommandLine {
+ // Any other source just gets tacked on at the end (like default values)
+ continue;
+ }
+ if Self::extract::<String>(matches, id, &mut values) {
+ continue;
+ }
+ if Self::extract::<bool>(matches, id, &mut values) {
+ continue;
+ }
+ unimplemented!("unknown type for {id}: {matches:?}");
+ }
+ values.into_values().collect::<Vec<_>>()
+ }
+
+ fn extract<T: Clone + Into<Value> + Send + Sync + 'static>(
+ matches: &ArgMatches,
+ id: &clap::Id,
+ output: &mut BTreeMap<usize, (clap::Id, Self)>,
+ ) -> bool {
+ match matches.try_get_many::<T>(id.as_str()) {
+ Ok(Some(values)) => {
+ for (value, index) in values.zip(
+ matches
+ .indices_of(id.as_str())
+ .expect("id came from matches"),
+ ) {
+ output.insert(index, (id.clone(), value.clone().into()));
+ }
+ true
+ }
+ Ok(None) => {
+ unreachable!("`ids` only reports what is present")
+ }
+ Err(clap::parser::MatchesError::UnknownArgument { .. }) => {
+ unreachable!("id came from matches")
+ }
+ Err(clap::parser::MatchesError::Downcast { .. }) => false,
+ Err(_) => {
+ unreachable!("id came from matches")
+ }
+ }
+ }
+}
+
+impl From<String> for Value {
+ fn from(other: String) -> Self {
+ Self::String(other)
+ }
+}
+
+impl From<bool> for Value {
+ fn from(other: bool) -> Self {
+ Self::Bool(other)
+ }
+}
diff --git a/third_party/rust/clap/examples/git-derive.md b/third_party/rust/clap/examples/git-derive.md
new file mode 100644
index 0000000000..57edb612e9
--- /dev/null
+++ b/third_party/rust/clap/examples/git-derive.md
@@ -0,0 +1,159 @@
+**This requires enabling the [`derive` feature flag][crate::_features].**
+
+Git is an example of several common subcommand patterns.
+
+Help:
+```console
+$ git-derive
+? failed
+A fictional versioning CLI
+
+Usage: git-derive[EXE] <COMMAND>
+
+Commands:
+ clone Clones repos
+ diff Compare two commits
+ push pushes things
+ add adds things
+ stash
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+
+$ git-derive help
+A fictional versioning CLI
+
+Usage: git-derive[EXE] <COMMAND>
+
+Commands:
+ clone Clones repos
+ diff Compare two commits
+ push pushes things
+ add adds things
+ stash
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+
+$ git-derive help add
+adds things
+
+Usage: git-derive[EXE] add <PATH>...
+
+Arguments:
+ <PATH>... Stuff to add
+
+Options:
+ -h, --help Print help
+
+```
+
+A basic argument:
+```console
+$ git-derive add
+? failed
+adds things
+
+Usage: git-derive[EXE] add <PATH>...
+
+Arguments:
+ <PATH>... Stuff to add
+
+Options:
+ -h, --help Print help
+
+$ git-derive add Cargo.toml Cargo.lock
+Adding ["Cargo.toml", "Cargo.lock"]
+
+```
+
+Default subcommand:
+```console
+$ git-derive stash -h
+Usage: git-derive[EXE] stash [OPTIONS]
+ git-derive[EXE] stash <COMMAND>
+
+Commands:
+ push
+ pop
+ apply
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -m, --message <MESSAGE>
+ -h, --help Print help
+
+$ git-derive stash push -h
+Usage: git-derive[EXE] stash push [OPTIONS]
+
+Options:
+ -m, --message <MESSAGE>
+ -h, --help Print help
+
+$ git-derive stash pop -h
+Usage: git-derive[EXE] stash pop [STASH]
+
+Arguments:
+ [STASH]
+
+Options:
+ -h, --help Print help
+
+$ git-derive stash -m "Prototype"
+Pushing StashPushArgs { message: Some("Prototype") }
+
+$ git-derive stash pop
+Popping None
+
+$ git-derive stash push -m "Prototype"
+Pushing StashPushArgs { message: Some("Prototype") }
+
+$ git-derive stash pop
+Popping None
+
+```
+
+External subcommands:
+```console
+$ git-derive custom-tool arg1 --foo bar
+Calling out to "custom-tool" with ["arg1", "--foo", "bar"]
+
+```
+
+Last argument:
+```console
+$ git-derive diff --help
+Compare two commits
+
+Usage: git-derive[EXE] diff [OPTIONS] [COMMIT] [COMMIT] [-- <PATH>]
+
+Arguments:
+ [COMMIT]
+ [COMMIT]
+ [PATH]
+
+Options:
+ --color[=<WHEN>] [default: auto] [possible values: always, auto, never]
+ -h, --help Print help
+
+$ git-derive diff
+Diffing stage..worktree (color=auto)
+
+$ git-derive diff ./src
+Diffing stage..worktree ./src (color=auto)
+
+$ git-derive diff HEAD ./src
+Diffing HEAD..worktree ./src (color=auto)
+
+$ git-derive diff HEAD~~ -- HEAD
+Diffing HEAD~~..worktree HEAD (color=auto)
+
+$ git-derive diff --color
+Diffing stage..worktree (color=always)
+
+$ git-derive diff --color=never
+Diffing stage..worktree (color=never)
+
+```
diff --git a/third_party/rust/clap/examples/git-derive.rs b/third_party/rust/clap/examples/git-derive.rs
new file mode 100644
index 0000000000..ad82e0cea7
--- /dev/null
+++ b/third_party/rust/clap/examples/git-derive.rs
@@ -0,0 +1,164 @@
+use std::ffi::OsStr;
+use std::ffi::OsString;
+use std::path::PathBuf;
+
+use clap::{Args, Parser, Subcommand, ValueEnum};
+
+/// A fictional versioning CLI
+#[derive(Debug, Parser)] // requires `derive` feature
+#[command(name = "git")]
+#[command(about = "A fictional versioning CLI", long_about = None)]
+struct Cli {
+ #[command(subcommand)]
+ command: Commands,
+}
+
+#[derive(Debug, Subcommand)]
+enum Commands {
+ /// Clones repos
+ #[command(arg_required_else_help = true)]
+ Clone {
+ /// The remote to clone
+ remote: String,
+ },
+ /// Compare two commits
+ Diff {
+ #[arg(value_name = "COMMIT")]
+ base: Option<OsString>,
+ #[arg(value_name = "COMMIT")]
+ head: Option<OsString>,
+ #[arg(last = true)]
+ path: Option<OsString>,
+ #[arg(
+ long,
+ require_equals = true,
+ value_name = "WHEN",
+ num_args = 0..=1,
+ default_value_t = ColorWhen::Auto,
+ default_missing_value = "always",
+ value_enum
+ )]
+ color: ColorWhen,
+ },
+ /// pushes things
+ #[command(arg_required_else_help = true)]
+ Push {
+ /// The remote to target
+ remote: String,
+ },
+ /// adds things
+ #[command(arg_required_else_help = true)]
+ Add {
+ /// Stuff to add
+ #[arg(required = true)]
+ path: Vec<PathBuf>,
+ },
+ Stash(StashArgs),
+ #[command(external_subcommand)]
+ External(Vec<OsString>),
+}
+
+#[derive(ValueEnum, Copy, Clone, Debug, PartialEq, Eq)]
+enum ColorWhen {
+ Always,
+ Auto,
+ Never,
+}
+
+impl std::fmt::Display for ColorWhen {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.to_possible_value()
+ .expect("no values are skipped")
+ .get_name()
+ .fmt(f)
+ }
+}
+
+#[derive(Debug, Args)]
+#[command(args_conflicts_with_subcommands = true)]
+struct StashArgs {
+ #[command(subcommand)]
+ command: Option<StashCommands>,
+
+ #[command(flatten)]
+ push: StashPushArgs,
+}
+
+#[derive(Debug, Subcommand)]
+enum StashCommands {
+ Push(StashPushArgs),
+ Pop { stash: Option<String> },
+ Apply { stash: Option<String> },
+}
+
+#[derive(Debug, Args)]
+struct StashPushArgs {
+ #[arg(short, long)]
+ message: Option<String>,
+}
+
+fn main() {
+ let args = Cli::parse();
+
+ match args.command {
+ Commands::Clone { remote } => {
+ println!("Cloning {remote}");
+ }
+ Commands::Diff {
+ mut base,
+ mut head,
+ mut path,
+ color,
+ } => {
+ if path.is_none() {
+ path = head;
+ head = None;
+ if path.is_none() {
+ path = base;
+ base = None;
+ }
+ }
+ let base = base
+ .as_deref()
+ .map(|s| s.to_str().unwrap())
+ .unwrap_or("stage");
+ let head = head
+ .as_deref()
+ .map(|s| s.to_str().unwrap())
+ .unwrap_or("worktree");
+ let path = path.as_deref().unwrap_or_else(|| OsStr::new(""));
+ println!(
+ "Diffing {}..{} {} (color={})",
+ base,
+ head,
+ path.to_string_lossy(),
+ color
+ );
+ }
+ Commands::Push { remote } => {
+ println!("Pushing to {remote}");
+ }
+ Commands::Add { path } => {
+ println!("Adding {path:?}");
+ }
+ Commands::Stash(stash) => {
+ let stash_cmd = stash.command.unwrap_or(StashCommands::Push(stash.push));
+ match stash_cmd {
+ StashCommands::Push(push) => {
+ println!("Pushing {push:?}");
+ }
+ StashCommands::Pop { stash } => {
+ println!("Popping {stash:?}");
+ }
+ StashCommands::Apply { stash } => {
+ println!("Applying {stash:?}");
+ }
+ }
+ }
+ Commands::External(args) => {
+ println!("Calling out to {:?} with {:?}", &args[0], &args[1..]);
+ }
+ }
+
+ // Continued program logic goes here...
+}
diff --git a/third_party/rust/clap/examples/git.md b/third_party/rust/clap/examples/git.md
new file mode 100644
index 0000000000..d90b2e8e05
--- /dev/null
+++ b/third_party/rust/clap/examples/git.md
@@ -0,0 +1,157 @@
+Git is an example of several common subcommand patterns.
+
+Help:
+```console
+$ git
+? failed
+A fictional versioning CLI
+
+Usage: git[EXE] <COMMAND>
+
+Commands:
+ clone Clones repos
+ diff Compare two commits
+ push pushes things
+ add adds things
+ stash
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+
+$ git help
+A fictional versioning CLI
+
+Usage: git[EXE] <COMMAND>
+
+Commands:
+ clone Clones repos
+ diff Compare two commits
+ push pushes things
+ add adds things
+ stash
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+
+$ git help add
+adds things
+
+Usage: git[EXE] add <PATH>...
+
+Arguments:
+ <PATH>... Stuff to add
+
+Options:
+ -h, --help Print help
+
+```
+
+A basic argument:
+```console
+$ git add
+? failed
+adds things
+
+Usage: git[EXE] add <PATH>...
+
+Arguments:
+ <PATH>... Stuff to add
+
+Options:
+ -h, --help Print help
+
+$ git add Cargo.toml Cargo.lock
+Adding ["Cargo.toml", "Cargo.lock"]
+
+```
+
+Default subcommand:
+```console
+$ git stash -h
+Usage: git[EXE] stash [OPTIONS]
+ git[EXE] stash <COMMAND>
+
+Commands:
+ push
+ pop
+ apply
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -m, --message <MESSAGE>
+ -h, --help Print help
+
+$ git stash push -h
+Usage: git[EXE] stash push [OPTIONS]
+
+Options:
+ -m, --message <MESSAGE>
+ -h, --help Print help
+
+$ git stash pop -h
+Usage: git[EXE] stash pop [STASH]
+
+Arguments:
+ [STASH]
+
+Options:
+ -h, --help Print help
+
+$ git stash -m "Prototype"
+Pushing Some("Prototype")
+
+$ git stash pop
+Popping None
+
+$ git stash push -m "Prototype"
+Pushing Some("Prototype")
+
+$ git stash pop
+Popping None
+
+```
+
+External subcommands:
+```console
+$ git custom-tool arg1 --foo bar
+Calling out to "custom-tool" with ["arg1", "--foo", "bar"]
+
+```
+
+Last argument:
+```console
+$ git diff --help
+Compare two commits
+
+Usage: git[EXE] diff [OPTIONS] [COMMIT] [COMMIT] [-- <PATH>]
+
+Arguments:
+ [COMMIT]
+ [COMMIT]
+ [PATH]
+
+Options:
+ --color[=<WHEN>] [default: auto] [possible values: always, auto, never]
+ -h, --help Print help
+
+$ git diff
+Diffing stage..worktree (color=auto)
+
+$ git diff ./src
+Diffing stage..worktree ./src (color=auto)
+
+$ git diff HEAD ./src
+Diffing HEAD..worktree ./src (color=auto)
+
+$ git diff HEAD~~ -- HEAD
+Diffing HEAD~~..worktree HEAD (color=auto)
+
+$ git diff --color
+Diffing stage..worktree (color=always)
+
+$ git diff --color=never
+Diffing stage..worktree (color=never)
+
+```
diff --git a/third_party/rust/clap/examples/git.rs b/third_party/rust/clap/examples/git.rs
new file mode 100644
index 0000000000..02173675f9
--- /dev/null
+++ b/third_party/rust/clap/examples/git.rs
@@ -0,0 +1,137 @@
+use std::ffi::OsString;
+use std::path::PathBuf;
+
+use clap::{arg, Command};
+
+fn cli() -> Command {
+ Command::new("git")
+ .about("A fictional versioning CLI")
+ .subcommand_required(true)
+ .arg_required_else_help(true)
+ .allow_external_subcommands(true)
+ .subcommand(
+ Command::new("clone")
+ .about("Clones repos")
+ .arg(arg!(<REMOTE> "The remote to clone"))
+ .arg_required_else_help(true),
+ )
+ .subcommand(
+ Command::new("diff")
+ .about("Compare two commits")
+ .arg(arg!(base: [COMMIT]))
+ .arg(arg!(head: [COMMIT]))
+ .arg(arg!(path: [PATH]).last(true))
+ .arg(
+ arg!(--color <WHEN>)
+ .value_parser(["always", "auto", "never"])
+ .num_args(0..=1)
+ .require_equals(true)
+ .default_value("auto")
+ .default_missing_value("always"),
+ ),
+ )
+ .subcommand(
+ Command::new("push")
+ .about("pushes things")
+ .arg(arg!(<REMOTE> "The remote to target"))
+ .arg_required_else_help(true),
+ )
+ .subcommand(
+ Command::new("add")
+ .about("adds things")
+ .arg_required_else_help(true)
+ .arg(arg!(<PATH> ... "Stuff to add").value_parser(clap::value_parser!(PathBuf))),
+ )
+ .subcommand(
+ Command::new("stash")
+ .args_conflicts_with_subcommands(true)
+ .args(push_args())
+ .subcommand(Command::new("push").args(push_args()))
+ .subcommand(Command::new("pop").arg(arg!([STASH])))
+ .subcommand(Command::new("apply").arg(arg!([STASH]))),
+ )
+}
+
+fn push_args() -> Vec<clap::Arg> {
+ vec![arg!(-m --message <MESSAGE>)]
+}
+
+fn main() {
+ let matches = cli().get_matches();
+
+ match matches.subcommand() {
+ Some(("clone", sub_matches)) => {
+ println!(
+ "Cloning {}",
+ sub_matches.get_one::<String>("REMOTE").expect("required")
+ );
+ }
+ Some(("diff", sub_matches)) => {
+ let color = sub_matches
+ .get_one::<String>("color")
+ .map(|s| s.as_str())
+ .expect("defaulted in clap");
+
+ let mut base = sub_matches.get_one::<String>("base").map(|s| s.as_str());
+ let mut head = sub_matches.get_one::<String>("head").map(|s| s.as_str());
+ let mut path = sub_matches.get_one::<String>("path").map(|s| s.as_str());
+ if path.is_none() {
+ path = head;
+ head = None;
+ if path.is_none() {
+ path = base;
+ base = None;
+ }
+ }
+ let base = base.unwrap_or("stage");
+ let head = head.unwrap_or("worktree");
+ let path = path.unwrap_or("");
+ println!("Diffing {base}..{head} {path} (color={color})");
+ }
+ Some(("push", sub_matches)) => {
+ println!(
+ "Pushing to {}",
+ sub_matches.get_one::<String>("REMOTE").expect("required")
+ );
+ }
+ Some(("add", sub_matches)) => {
+ let paths = sub_matches
+ .get_many::<PathBuf>("PATH")
+ .into_iter()
+ .flatten()
+ .collect::<Vec<_>>();
+ println!("Adding {paths:?}");
+ }
+ Some(("stash", sub_matches)) => {
+ let stash_command = sub_matches.subcommand().unwrap_or(("push", sub_matches));
+ match stash_command {
+ ("apply", sub_matches) => {
+ let stash = sub_matches.get_one::<String>("STASH");
+ println!("Applying {stash:?}");
+ }
+ ("pop", sub_matches) => {
+ let stash = sub_matches.get_one::<String>("STASH");
+ println!("Popping {stash:?}");
+ }
+ ("push", sub_matches) => {
+ let message = sub_matches.get_one::<String>("message");
+ println!("Pushing {message:?}");
+ }
+ (name, _) => {
+ unreachable!("Unsupported subcommand `{name}`")
+ }
+ }
+ }
+ Some((ext, sub_matches)) => {
+ let args = sub_matches
+ .get_many::<OsString>("")
+ .into_iter()
+ .flatten()
+ .collect::<Vec<_>>();
+ println!("Calling out to {ext:?} with {args:?}");
+ }
+ _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable!()
+ }
+
+ // Continued program logic goes here...
+}
diff --git a/third_party/rust/clap/examples/multicall-busybox.md b/third_party/rust/clap/examples/multicall-busybox.md
new file mode 100644
index 0000000000..e84b263514
--- /dev/null
+++ b/third_party/rust/clap/examples/multicall-busybox.md
@@ -0,0 +1,39 @@
+See the documentation for [`Command::multicall`][crate::Command::multicall] for rationale.
+
+This example omits every command except true and false,
+which are the most trivial to implement,
+```console
+$ busybox true
+? 0
+
+$ busybox false
+? 1
+
+```
+*Note: without the links setup, we can't demonstrate the multicall behavior*
+
+But includes the `--install` option as an example of why it can be useful
+for the main program to take arguments that aren't applet subcommands.
+```console
+$ busybox --install
+? failed
+...
+
+```
+
+Though users must pass something:
+```console
+$ busybox
+? failed
+Usage: busybox [OPTIONS] [APPLET]
+
+APPLETS:
+ true does nothing successfully
+ false does nothing unsuccessfully
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ --install <install> Install hardlinks for all subcommands in path
+ -h, --help Print help
+
+```
diff --git a/third_party/rust/clap/examples/multicall-busybox.rs b/third_party/rust/clap/examples/multicall-busybox.rs
new file mode 100644
index 0000000000..9260e1d70e
--- /dev/null
+++ b/third_party/rust/clap/examples/multicall-busybox.rs
@@ -0,0 +1,47 @@
+use std::path::PathBuf;
+use std::process::exit;
+
+use clap::{value_parser, Arg, ArgAction, Command};
+
+fn applet_commands() -> [Command; 2] {
+ [
+ Command::new("true").about("does nothing successfully"),
+ Command::new("false").about("does nothing unsuccessfully"),
+ ]
+}
+
+fn main() {
+ let cmd = Command::new(env!("CARGO_CRATE_NAME"))
+ .multicall(true)
+ .subcommand(
+ Command::new("busybox")
+ .arg_required_else_help(true)
+ .subcommand_value_name("APPLET")
+ .subcommand_help_heading("APPLETS")
+ .arg(
+ Arg::new("install")
+ .long("install")
+ .help("Install hardlinks for all subcommands in path")
+ .exclusive(true)
+ .action(ArgAction::Set)
+ .default_missing_value("/usr/local/bin")
+ .value_parser(value_parser!(PathBuf)),
+ )
+ .subcommands(applet_commands()),
+ )
+ .subcommands(applet_commands());
+
+ let matches = cmd.get_matches();
+ let mut subcommand = matches.subcommand();
+ if let Some(("busybox", cmd)) = subcommand {
+ if cmd.contains_id("install") {
+ unimplemented!("Make hardlinks to the executable here");
+ }
+ subcommand = cmd.subcommand();
+ }
+ match subcommand {
+ Some(("false", _)) => exit(1),
+ Some(("true", _)) => exit(0),
+ _ => unreachable!("parser should ensure only valid subcommand names are used"),
+ }
+}
diff --git a/third_party/rust/clap/examples/multicall-hostname.md b/third_party/rust/clap/examples/multicall-hostname.md
new file mode 100644
index 0000000000..0df1274e15
--- /dev/null
+++ b/third_party/rust/clap/examples/multicall-hostname.md
@@ -0,0 +1,10 @@
+See the documentation for [`Command::multicall`][crate::Command::multicall] for rationale.
+
+This example omits the implementation of displaying address config
+
+```console
+$ hostname
+www
+
+```
+*Note: without the links setup, we can't demonstrate the multicall behavior*
diff --git a/third_party/rust/clap/examples/multicall-hostname.rs b/third_party/rust/clap/examples/multicall-hostname.rs
new file mode 100644
index 0000000000..b57680a5c1
--- /dev/null
+++ b/third_party/rust/clap/examples/multicall-hostname.rs
@@ -0,0 +1,17 @@
+use clap::Command;
+
+fn main() {
+ let cmd = Command::new(env!("CARGO_CRATE_NAME"))
+ .multicall(true)
+ .arg_required_else_help(true)
+ .subcommand_value_name("APPLET")
+ .subcommand_help_heading("APPLETS")
+ .subcommand(Command::new("hostname").about("show hostname part of FQDN"))
+ .subcommand(Command::new("dnsdomainname").about("show domain name part of FQDN"));
+
+ match cmd.get_matches().subcommand_name() {
+ Some("hostname") => println!("www"),
+ Some("dnsdomainname") => println!("example.com"),
+ _ => unreachable!("parser should ensure only valid subcommand names are used"),
+ }
+}
diff --git a/third_party/rust/clap/examples/pacman.md b/third_party/rust/clap/examples/pacman.md
new file mode 100644
index 0000000000..b02cf8f1be
--- /dev/null
+++ b/third_party/rust/clap/examples/pacman.md
@@ -0,0 +1,79 @@
+[`pacman`](https://wiki.archlinux.org/index.php/pacman) defines subcommands via flags.
+
+Here, `-S` is a short flag subcommand:
+```console
+$ pacman -S package
+Installing package...
+
+```
+
+Here `--sync` is a long flag subcommand:
+```console
+$ pacman --sync package
+Installing package...
+
+```
+
+Now the short flag subcommand (`-S`) with a long flag:
+```console
+$ pacman -S --search name
+Searching for name...
+
+```
+
+And the various forms of short flags that work:
+```console
+$ pacman -S -s name
+Searching for name...
+
+$ pacman -Ss name
+Searching for name...
+
+```
+*(users can "stack" short subcommands with short flags or with other short flag subcommands)*
+
+In the help, this looks like:
+```console
+$ pacman -h
+package manager utility
+
+Usage: pacman[EXE] <COMMAND>
+
+Commands:
+ query, -Q, --query Query the package database.
+ sync, -S, --sync Synchronize packages.
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ pacman -S -h
+Synchronize packages.
+
+Usage: pacman[EXE] {sync|--sync|-S} [OPTIONS] [package]...
+
+Arguments:
+ [package]... packages
+
+Options:
+ -s, --search <search>... search remote repositories for matching strings
+ -i, --info view package information
+ -h, --help Print help
+
+```
+
+And errors:
+```console
+$ pacman -S -s foo -i bar
+? failed
+error: the argument '--search <search>...' cannot be used with '--info'
+
+Usage: pacman[EXE] {sync|--sync|-S} --search <search>... <package>...
+
+For more information, try '--help'.
+
+```
+
+**NOTE:** Keep in mind that subcommands, flags, and long flags are *case sensitive*: `-Q` and `-q` are different flags/subcommands. For example, you can have both `-Q` subcommand and `-q` flag, and they will be properly disambiguated.
+Let's make a quick program to illustrate.
diff --git a/third_party/rust/clap/examples/pacman.rs b/third_party/rust/clap/examples/pacman.rs
new file mode 100644
index 0000000000..7ab30db953
--- /dev/null
+++ b/third_party/rust/clap/examples/pacman.rs
@@ -0,0 +1,111 @@
+use clap::{Arg, ArgAction, Command};
+
+fn main() {
+ let matches = Command::new("pacman")
+ .about("package manager utility")
+ .version("5.2.1")
+ .subcommand_required(true)
+ .arg_required_else_help(true)
+ .author("Pacman Development Team")
+ // Query subcommand
+ //
+ // Only a few of its arguments are implemented below.
+ .subcommand(
+ Command::new("query")
+ .short_flag('Q')
+ .long_flag("query")
+ .about("Query the package database.")
+ .arg(
+ Arg::new("search")
+ .short('s')
+ .long("search")
+ .help("search locally installed packages for matching strings")
+ .conflicts_with("info")
+ .action(ArgAction::Set)
+ .num_args(1..),
+ )
+ .arg(
+ Arg::new("info")
+ .long("info")
+ .short('i')
+ .conflicts_with("search")
+ .help("view package information")
+ .action(ArgAction::Set)
+ .num_args(1..),
+ ),
+ )
+ // Sync subcommand
+ //
+ // Only a few of its arguments are implemented below.
+ .subcommand(
+ Command::new("sync")
+ .short_flag('S')
+ .long_flag("sync")
+ .about("Synchronize packages.")
+ .arg(
+ Arg::new("search")
+ .short('s')
+ .long("search")
+ .conflicts_with("info")
+ .action(ArgAction::Set)
+ .num_args(1..)
+ .help("search remote repositories for matching strings"),
+ )
+ .arg(
+ Arg::new("info")
+ .long("info")
+ .conflicts_with("search")
+ .short('i')
+ .action(ArgAction::SetTrue)
+ .help("view package information"),
+ )
+ .arg(
+ Arg::new("package")
+ .help("packages")
+ .required_unless_present("search")
+ .action(ArgAction::Set)
+ .num_args(1..),
+ ),
+ )
+ .get_matches();
+
+ match matches.subcommand() {
+ Some(("sync", sync_matches)) => {
+ if sync_matches.contains_id("search") {
+ let packages: Vec<_> = sync_matches
+ .get_many::<String>("search")
+ .expect("contains_id")
+ .map(|s| s.as_str())
+ .collect();
+ let values = packages.join(", ");
+ println!("Searching for {values}...");
+ return;
+ }
+
+ let packages: Vec<_> = sync_matches
+ .get_many::<String>("package")
+ .expect("is present")
+ .map(|s| s.as_str())
+ .collect();
+ let values = packages.join(", ");
+
+ if sync_matches.get_flag("info") {
+ println!("Retrieving info for {values}...");
+ } else {
+ println!("Installing {values}...");
+ }
+ }
+ Some(("query", query_matches)) => {
+ if let Some(packages) = query_matches.get_many::<String>("info") {
+ let comma_sep = packages.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
+ println!("Retrieving info for {comma_sep}...");
+ } else if let Some(queries) = query_matches.get_many::<String>("search") {
+ let comma_sep = queries.map(|s| s.as_str()).collect::<Vec<_>>().join(", ");
+ println!("Searching Locally for {comma_sep}...");
+ } else {
+ println!("Displaying all locally installed packages...");
+ }
+ }
+ _ => unreachable!(), // If all subcommands are defined above, anything else is unreachable
+ }
+}
diff --git a/third_party/rust/clap/examples/repl.rs b/third_party/rust/clap/examples/repl.rs
new file mode 100644
index 0000000000..d0baaed8d2
--- /dev/null
+++ b/third_party/rust/clap/examples/repl.rs
@@ -0,0 +1,92 @@
+use std::io::Write;
+
+use clap::Command;
+
+fn main() -> Result<(), String> {
+ loop {
+ let line = readline()?;
+ let line = line.trim();
+ if line.is_empty() {
+ continue;
+ }
+
+ match respond(line) {
+ Ok(quit) => {
+ if quit {
+ break;
+ }
+ }
+ Err(err) => {
+ write!(std::io::stdout(), "{err}").map_err(|e| e.to_string())?;
+ std::io::stdout().flush().map_err(|e| e.to_string())?;
+ }
+ }
+ }
+
+ Ok(())
+}
+
+fn respond(line: &str) -> Result<bool, String> {
+ let args = shlex::split(line).ok_or("error: Invalid quoting")?;
+ let matches = cli()
+ .try_get_matches_from(args)
+ .map_err(|e| e.to_string())?;
+ match matches.subcommand() {
+ Some(("ping", _matches)) => {
+ write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?;
+ std::io::stdout().flush().map_err(|e| e.to_string())?;
+ }
+ Some(("quit", _matches)) => {
+ write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?;
+ std::io::stdout().flush().map_err(|e| e.to_string())?;
+ return Ok(true);
+ }
+ Some((name, _matches)) => unimplemented!("{name}"),
+ None => unreachable!("subcommand required"),
+ }
+
+ Ok(false)
+}
+
+fn cli() -> Command {
+ // strip out usage
+ const PARSER_TEMPLATE: &str = "\
+ {all-args}
+ ";
+ // strip out name/version
+ const APPLET_TEMPLATE: &str = "\
+ {about-with-newline}\n\
+ {usage-heading}\n {usage}\n\
+ \n\
+ {all-args}{after-help}\
+ ";
+
+ Command::new("repl")
+ .multicall(true)
+ .arg_required_else_help(true)
+ .subcommand_required(true)
+ .subcommand_value_name("APPLET")
+ .subcommand_help_heading("APPLETS")
+ .help_template(PARSER_TEMPLATE)
+ .subcommand(
+ Command::new("ping")
+ .about("Get a response")
+ .help_template(APPLET_TEMPLATE),
+ )
+ .subcommand(
+ Command::new("quit")
+ .alias("exit")
+ .about("Quit the REPL")
+ .help_template(APPLET_TEMPLATE),
+ )
+}
+
+fn readline() -> Result<String, String> {
+ write!(std::io::stdout(), "$ ").map_err(|e| e.to_string())?;
+ std::io::stdout().flush().map_err(|e| e.to_string())?;
+ let mut buffer = String::new();
+ std::io::stdin()
+ .read_line(&mut buffer)
+ .map_err(|e| e.to_string())?;
+ Ok(buffer)
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/01_quick.md b/third_party/rust/clap/examples/tutorial_builder/01_quick.md
new file mode 100644
index 0000000000..bdba15cd2c
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/01_quick.md
@@ -0,0 +1,35 @@
+```console
+$ 01_quick --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 01_quick[EXE] [OPTIONS] [name] [COMMAND]
+
+Commands:
+ test does testing things
+ help Print this message or the help of the given subcommand(s)
+
+Arguments:
+ [name] Optional name to operate on
+
+Options:
+ -c, --config <FILE> Sets a custom config file
+ -d, --debug... Turn debugging information on
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+By default, the program does nothing:
+```console
+$ 01_quick
+Debug mode is off
+
+```
+
+But you can mix and match the various features
+```console
+$ 01_quick -dd test
+Debug mode is on
+Not printing testing lists...
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/01_quick.rs b/third_party/rust/clap/examples/tutorial_builder/01_quick.rs
new file mode 100644
index 0000000000..328ce55199
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/01_quick.rs
@@ -0,0 +1,60 @@
+use std::path::PathBuf;
+
+use clap::{arg, command, value_parser, ArgAction, Command};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(arg!([name] "Optional name to operate on"))
+ .arg(
+ arg!(
+ -c --config <FILE> "Sets a custom config file"
+ )
+ // We don't have syntax yet for optional options, so manually calling `required`
+ .required(false)
+ .value_parser(value_parser!(PathBuf)),
+ )
+ .arg(arg!(
+ -d --debug ... "Turn debugging information on"
+ ))
+ .subcommand(
+ Command::new("test")
+ .about("does testing things")
+ .arg(arg!(-l --list "lists test values").action(ArgAction::SetTrue)),
+ )
+ .get_matches();
+
+ // You can check the value provided by positional arguments, or option arguments
+ if let Some(name) = matches.get_one::<String>("name") {
+ println!("Value for name: {name}");
+ }
+
+ if let Some(config_path) = matches.get_one::<PathBuf>("config") {
+ println!("Value for config: {}", config_path.display());
+ }
+
+ // You can see how many times a particular flag or argument occurred
+ // Note, only flags can have multiple occurrences
+ match matches
+ .get_one::<u8>("debug")
+ .expect("Count's are defaulted")
+ {
+ 0 => println!("Debug mode is off"),
+ 1 => println!("Debug mode is kind of on"),
+ 2 => println!("Debug mode is on"),
+ _ => println!("Don't be crazy"),
+ }
+
+ // You can check for the existence of subcommands, and if found use their
+ // matches just as you would the top level cmd
+ if let Some(matches) = matches.subcommand_matches("test") {
+ // "$ myapp test" was run
+ if matches.get_flag("list") {
+ // "$ myapp test -l" was run
+ println!("Printing testing lists...");
+ } else {
+ println!("Not printing testing lists...");
+ }
+ }
+
+ // Continued program logic goes here...
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/02_app_settings.md b/third_party/rust/clap/examples/tutorial_builder/02_app_settings.md
new file mode 100644
index 0000000000..3ac9a95e78
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/02_app_settings.md
@@ -0,0 +1,17 @@
+```console
+$ 02_app_settings --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 02_app_settings[EXE] --two <VALUE> --one <VALUE>
+
+Options:
+ --two <VALUE>
+
+ --one <VALUE>
+
+ -h, --help
+ Print help
+ -V, --version
+ Print version
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/02_app_settings.rs b/third_party/rust/clap/examples/tutorial_builder/02_app_settings.rs
new file mode 100644
index 0000000000..4e30ec9a52
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/02_app_settings.rs
@@ -0,0 +1,18 @@
+use clap::{arg, command, ArgAction};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .next_line_help(true)
+ .arg(arg!(--two <VALUE>).required(true).action(ArgAction::Set))
+ .arg(arg!(--one <VALUE>).required(true).action(ArgAction::Set))
+ .get_matches();
+
+ println!(
+ "two: {:?}",
+ matches.get_one::<String>("two").expect("required")
+ );
+ println!(
+ "one: {:?}",
+ matches.get_one::<String>("one").expect("required")
+ );
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/02_apps.md b/third_party/rust/clap/examples/tutorial_builder/02_apps.md
new file mode 100644
index 0000000000..1f8b071b19
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/02_apps.md
@@ -0,0 +1,16 @@
+```console
+$ 02_apps --help
+Does awesome things
+
+Usage: 02_apps[EXE] --two <VALUE> --one <VALUE>
+
+Options:
+ --two <VALUE>
+ --one <VALUE>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 02_apps --version
+MyApp 1.0
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/02_apps.rs b/third_party/rust/clap/examples/tutorial_builder/02_apps.rs
new file mode 100644
index 0000000000..7d98e6cfe4
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/02_apps.rs
@@ -0,0 +1,20 @@
+use clap::{arg, Command};
+
+fn main() {
+ let matches = Command::new("MyApp")
+ .version("1.0")
+ .author("Kevin K. <kbknapp@gmail.com>")
+ .about("Does awesome things")
+ .arg(arg!(--two <VALUE>).required(true))
+ .arg(arg!(--one <VALUE>).required(true))
+ .get_matches();
+
+ println!(
+ "two: {:?}",
+ matches.get_one::<String>("two").expect("required")
+ );
+ println!(
+ "one: {:?}",
+ matches.get_one::<String>("one").expect("required")
+ );
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/02_crate.md b/third_party/rust/clap/examples/tutorial_builder/02_crate.md
new file mode 100644
index 0000000000..a0d21b3ece
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/02_crate.md
@@ -0,0 +1,16 @@
+```console
+$ 02_crate --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 02_crate[EXE] --two <VALUE> --one <VALUE>
+
+Options:
+ --two <VALUE>
+ --one <VALUE>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 02_crate --version
+clap [..]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/02_crate.rs b/third_party/rust/clap/examples/tutorial_builder/02_crate.rs
new file mode 100644
index 0000000000..ad6bb4713b
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/02_crate.rs
@@ -0,0 +1,18 @@
+use clap::{arg, command};
+
+fn main() {
+ // requires `cargo` feature, reading name, version, author, and description from `Cargo.toml`
+ let matches = command!()
+ .arg(arg!(--two <VALUE>).required(true))
+ .arg(arg!(--one <VALUE>).required(true))
+ .get_matches();
+
+ println!(
+ "two: {:?}",
+ matches.get_one::<String>("two").expect("required")
+ );
+ println!(
+ "one: {:?}",
+ matches.get_one::<String>("one").expect("required")
+ );
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.md b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.md
new file mode 100644
index 0000000000..feec8e0a7a
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.md
@@ -0,0 +1,26 @@
+```console
+$ 03_01_flag_bool --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_01_flag_bool[EXE] [OPTIONS]
+
+Options:
+ -v, --verbose
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_01_flag_bool
+verbose: false
+
+$ 03_01_flag_bool --verbose
+verbose: true
+
+$ 03_01_flag_bool --verbose --verbose
+? failed
+error: the argument '--verbose' cannot be used multiple times
+
+Usage: 03_01_flag_bool[EXE] [OPTIONS]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.rs b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.rs
new file mode 100644
index 0000000000..03f2f1756f
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_bool.rs
@@ -0,0 +1,14 @@
+use clap::{command, Arg, ArgAction};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ Arg::new("verbose")
+ .short('v')
+ .long("verbose")
+ .action(ArgAction::SetTrue),
+ )
+ .get_matches();
+
+ println!("verbose: {:?}", matches.get_flag("verbose"));
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.md b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.md
new file mode 100644
index 0000000000..5e964b67a7
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.md
@@ -0,0 +1,21 @@
+```console
+$ 03_01_flag_count --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_01_flag_count[EXE] [OPTIONS]
+
+Options:
+ -v, --verbose...
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_01_flag_count
+verbose: 0
+
+$ 03_01_flag_count --verbose
+verbose: 1
+
+$ 03_01_flag_count --verbose --verbose
+verbose: 2
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.rs b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.rs
new file mode 100644
index 0000000000..492f7d4c1f
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_01_flag_count.rs
@@ -0,0 +1,14 @@
+use clap::{command, Arg, ArgAction};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ Arg::new("verbose")
+ .short('v')
+ .long("verbose")
+ .action(ArgAction::Count),
+ )
+ .get_matches();
+
+ println!("verbose: {:?}", matches.get_count("verbose"));
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_02_option.md b/third_party/rust/clap/examples/tutorial_builder/03_02_option.md
new file mode 100644
index 0000000000..42b81fd426
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_02_option.md
@@ -0,0 +1,30 @@
+```console
+$ 03_02_option --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_02_option[EXE] [OPTIONS]
+
+Options:
+ -n, --name <name>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_02_option
+name: None
+
+$ 03_02_option --name bob
+name: Some("bob")
+
+$ 03_02_option --name=bob
+name: Some("bob")
+
+$ 03_02_option -n bob
+name: Some("bob")
+
+$ 03_02_option -n=bob
+name: Some("bob")
+
+$ 03_02_option -nbob
+name: Some("bob")
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_02_option.rs b/third_party/rust/clap/examples/tutorial_builder/03_02_option.rs
new file mode 100644
index 0000000000..e9ba3e41a9
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_02_option.rs
@@ -0,0 +1,9 @@
+use clap::{command, Arg};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(Arg::new("name").short('n').long("name"))
+ .get_matches();
+
+ println!("name: {:?}", matches.get_one::<String>("name"));
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.md b/third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.md
new file mode 100644
index 0000000000..659748e4de
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.md
@@ -0,0 +1,30 @@
+```console
+$ 03_02_option_mult --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_02_option_mult[EXE] [OPTIONS]
+
+Options:
+ -n, --name <name>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_02_option_mult
+name: None
+
+$ 03_02_option_mult --name bob
+name: Some("bob")
+
+$ 03_02_option_mult --name=bob
+name: Some("bob")
+
+$ 03_02_option_mult -n bob
+name: Some("bob")
+
+$ 03_02_option_mult -n=bob
+name: Some("bob")
+
+$ 03_02_option_mult -nbob
+name: Some("bob")
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.rs b/third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.rs
new file mode 100644
index 0000000000..1370477eb4
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_02_option_mult.rs
@@ -0,0 +1,14 @@
+use clap::{command, Arg, ArgAction};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ Arg::new("name")
+ .short('n')
+ .long("name")
+ .action(ArgAction::Append),
+ )
+ .get_matches();
+
+ println!("name: {:?}", matches.get_one::<String>("name"));
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_03_positional.md b/third_party/rust/clap/examples/tutorial_builder/03_03_positional.md
new file mode 100644
index 0000000000..d8d49f39b6
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_03_positional.md
@@ -0,0 +1,20 @@
+```console
+$ 03_03_positional --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_03_positional[EXE] [name]
+
+Arguments:
+ [name]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_03_positional
+name: None
+
+$ 03_03_positional bob
+name: Some("bob")
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_03_positional.rs b/third_party/rust/clap/examples/tutorial_builder/03_03_positional.rs
new file mode 100644
index 0000000000..f652d27ca5
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_03_positional.rs
@@ -0,0 +1,9 @@
+use clap::{command, Arg};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(Arg::new("name"))
+ .get_matches();
+
+ println!("name: {:?}", matches.get_one::<String>("name"));
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.md b/third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.md
new file mode 100644
index 0000000000..174ddd9f7b
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.md
@@ -0,0 +1,23 @@
+```console
+$ 03_03_positional_mult --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_03_positional_mult[EXE] [name]...
+
+Arguments:
+ [name]...
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_03_positional_mult
+names: []
+
+$ 03_03_positional_mult bob
+names: ["bob"]
+
+$ 03_03_positional_mult bob john
+names: ["bob", "john"]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.rs b/third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.rs
new file mode 100644
index 0000000000..bcd288d8dc
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_03_positional_mult.rs
@@ -0,0 +1,15 @@
+use clap::{command, Arg, ArgAction};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(Arg::new("name").action(ArgAction::Append))
+ .get_matches();
+
+ let args = matches
+ .get_many::<String>("name")
+ .unwrap_or_default()
+ .map(|v| v.as_str())
+ .collect::<Vec<_>>();
+
+ println!("names: {:?}", &args);
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.md b/third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.md
new file mode 100644
index 0000000000..a32b776855
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.md
@@ -0,0 +1,59 @@
+```console
+$ 03_04_subcommands help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_04_subcommands[EXE] <COMMAND>
+
+Commands:
+ add Adds files to myapp
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_04_subcommands help add
+Adds files to myapp
+
+Usage: 03_04_subcommands[EXE] add [NAME]
+
+Arguments:
+ [NAME]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_04_subcommands add bob
+'myapp add' was used, name is: Some("bob")
+
+```
+
+Because we set [`Command::arg_required_else_help`][crate::Command::arg_required_else_help]:
+```console
+$ 03_04_subcommands
+? failed
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_04_subcommands[EXE] <COMMAND>
+
+Commands:
+ add Adds files to myapp
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+Since we specified [`Command::propagate_version`][crate::Command::propagate_version], the `--version` flag
+is available in all subcommands:
+```console
+$ 03_04_subcommands --version
+clap [..]
+
+$ 03_04_subcommands add --version
+clap-add [..]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.rs b/third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.rs
new file mode 100644
index 0000000000..fbe23809e9
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_04_subcommands.rs
@@ -0,0 +1,22 @@
+use clap::{arg, command, Command};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .propagate_version(true)
+ .subcommand_required(true)
+ .arg_required_else_help(true)
+ .subcommand(
+ Command::new("add")
+ .about("Adds files to myapp")
+ .arg(arg!([NAME])),
+ )
+ .get_matches();
+
+ match matches.subcommand() {
+ Some(("add", sub_matches)) => println!(
+ "'myapp add' was used, name is: {:?}",
+ sub_matches.get_one::<String>("NAME")
+ ),
+ _ => unreachable!("Exhausted list of subcommands and subcommand_required prevents `None`"),
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_05_default_values.md b/third_party/rust/clap/examples/tutorial_builder/03_05_default_values.md
new file mode 100644
index 0000000000..b62a415508
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_05_default_values.md
@@ -0,0 +1,20 @@
+```console
+$ 03_05_default_values --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_05_default_values[EXE] [PORT]
+
+Arguments:
+ [PORT] [default: 2020]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_05_default_values
+port: 2020
+
+$ 03_05_default_values 22
+port: 22
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/03_05_default_values.rs b/third_party/rust/clap/examples/tutorial_builder/03_05_default_values.rs
new file mode 100644
index 0000000000..d259ee06ed
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/03_05_default_values.rs
@@ -0,0 +1,18 @@
+use clap::{arg, command, value_parser};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ arg!([PORT])
+ .value_parser(value_parser!(u16))
+ .default_value("2020"),
+ )
+ .get_matches();
+
+ println!(
+ "port: {:?}",
+ matches
+ .get_one::<u16>("PORT")
+ .expect("default ensures there is always a value")
+ );
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_01_enum.md b/third_party/rust/clap/examples/tutorial_builder/04_01_enum.md
new file mode 100644
index 0000000000..ec4c0aea1d
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_01_enum.md
@@ -0,0 +1,47 @@
+```console
+$ 04_01_enum --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_01_enum[EXE] <MODE>
+
+Arguments:
+ <MODE>
+ What mode to run the program in
+
+ Possible values:
+ - fast: Run swiftly
+ - slow: Crawl slowly but steadily
+
+Options:
+ -h, --help
+ Print help (see a summary with '-h')
+
+ -V, --version
+ Print version
+
+$ 04_01_enum -h
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_01_enum[EXE] <MODE>
+
+Arguments:
+ <MODE> What mode to run the program in [possible values: fast, slow]
+
+Options:
+ -h, --help Print help (see more with '--help')
+ -V, --version Print version
+
+$ 04_01_enum fast
+Hare
+
+$ 04_01_enum slow
+Tortoise
+
+$ 04_01_enum medium
+? failed
+error: invalid value 'medium' for '<MODE>'
+ [possible values: fast, slow]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_01_enum.rs b/third_party/rust/clap/examples/tutorial_builder/04_01_enum.rs
new file mode 100644
index 0000000000..aa9f41ce6d
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_01_enum.rs
@@ -0,0 +1,66 @@
+use clap::{arg, builder::PossibleValue, command, value_parser, ValueEnum};
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+enum Mode {
+ Fast,
+ Slow,
+}
+
+// Can also be derived with feature flag `derive`
+impl ValueEnum for Mode {
+ fn value_variants<'a>() -> &'a [Self] {
+ &[Mode::Fast, Mode::Slow]
+ }
+
+ fn to_possible_value<'a>(&self) -> Option<PossibleValue> {
+ Some(match self {
+ Mode::Fast => PossibleValue::new("fast").help("Run swiftly"),
+ Mode::Slow => PossibleValue::new("slow").help("Crawl slowly but steadily"),
+ })
+ }
+}
+
+impl std::fmt::Display for Mode {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.to_possible_value()
+ .expect("no values are skipped")
+ .get_name()
+ .fmt(f)
+ }
+}
+
+impl std::str::FromStr for Mode {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ for variant in Self::value_variants() {
+ if variant.to_possible_value().unwrap().matches(s, false) {
+ return Ok(*variant);
+ }
+ }
+ Err(format!("invalid variant: {s}"))
+ }
+}
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ arg!(<MODE>)
+ .help("What mode to run the program in")
+ .value_parser(value_parser!(Mode)),
+ )
+ .get_matches();
+
+ // Note, it's safe to call unwrap() because the arg is required
+ match matches
+ .get_one::<Mode>("MODE")
+ .expect("'MODE' is required and parsing will fail if its missing")
+ {
+ Mode::Fast => {
+ println!("Hare");
+ }
+ Mode::Slow => {
+ println!("Tortoise");
+ }
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_01_possible.md b/third_party/rust/clap/examples/tutorial_builder/04_01_possible.md
new file mode 100644
index 0000000000..fa2c835390
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_01_possible.md
@@ -0,0 +1,27 @@
+```console
+$ 04_01_possible --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_01_possible[EXE] <MODE>
+
+Arguments:
+ <MODE> What mode to run the program in [possible values: fast, slow]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_01_possible fast
+Hare
+
+$ 04_01_possible slow
+Tortoise
+
+$ 04_01_possible medium
+? failed
+error: invalid value 'medium' for '<MODE>'
+ [possible values: fast, slow]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_01_possible.rs b/third_party/rust/clap/examples/tutorial_builder/04_01_possible.rs
new file mode 100644
index 0000000000..3da7aca74b
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_01_possible.rs
@@ -0,0 +1,26 @@
+use clap::{arg, command};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ arg!(<MODE>)
+ .help("What mode to run the program in")
+ .value_parser(["fast", "slow"]),
+ )
+ .get_matches();
+
+ // Note, it's safe to call unwrap() because the arg is required
+ match matches
+ .get_one::<String>("MODE")
+ .expect("'MODE' is required and parsing will fail if its missing")
+ .as_str()
+ {
+ "fast" => {
+ println!("Hare");
+ }
+ "slow" => {
+ println!("Tortoise");
+ }
+ _ => unreachable!(),
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_02_parse.md b/third_party/rust/clap/examples/tutorial_builder/04_02_parse.md
new file mode 100644
index 0000000000..af03e95cbc
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_02_parse.md
@@ -0,0 +1,29 @@
+```console
+$ 04_02_parse --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_02_parse[EXE] <PORT>
+
+Arguments:
+ <PORT> Network port to use
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_02_parse 22
+PORT = 22
+
+$ 04_02_parse foobar
+? failed
+error: invalid value 'foobar' for '<PORT>': invalid digit found in string
+
+For more information, try '--help'.
+
+$ 04_02_parse_derive 0
+? failed
+error: invalid value '0' for '<PORT>': 0 is not in 1..=65535
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_02_parse.rs b/third_party/rust/clap/examples/tutorial_builder/04_02_parse.rs
new file mode 100644
index 0000000000..a3f79040d7
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_02_parse.rs
@@ -0,0 +1,17 @@
+use clap::{arg, command, value_parser};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ arg!(<PORT>)
+ .help("Network port to use")
+ .value_parser(value_parser!(u16).range(1..)),
+ )
+ .get_matches();
+
+ // Note, it's safe to call unwrap() because the arg is required
+ let port: u16 = *matches
+ .get_one::<u16>("PORT")
+ .expect("'PORT' is required and parsing will fail if its missing");
+ println!("PORT = {port}");
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_02_validate.md b/third_party/rust/clap/examples/tutorial_builder/04_02_validate.md
new file mode 100644
index 0000000000..949072bee5
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_02_validate.md
@@ -0,0 +1,29 @@
+```console
+$ 04_02_validate --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_02_validate[EXE] <PORT>
+
+Arguments:
+ <PORT> Network port to use
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_02_validate 22
+PORT = 22
+
+$ 04_02_validate foobar
+? failed
+error: invalid value 'foobar' for '<PORT>': `foobar` isn't a port number
+
+For more information, try '--help'.
+
+$ 04_02_validate 0
+? failed
+error: invalid value '0' for '<PORT>': port not in range 1-65535
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_02_validate.rs b/third_party/rust/clap/examples/tutorial_builder/04_02_validate.rs
new file mode 100644
index 0000000000..0ce53d6544
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_02_validate.rs
@@ -0,0 +1,36 @@
+use std::ops::RangeInclusive;
+
+use clap::{arg, command};
+
+fn main() {
+ let matches = command!() // requires `cargo` feature
+ .arg(
+ arg!(<PORT>)
+ .help("Network port to use")
+ .value_parser(port_in_range),
+ )
+ .get_matches();
+
+ // Note, it's safe to call unwrap() because the arg is required
+ let port: u16 = *matches
+ .get_one::<u16>("PORT")
+ .expect("'PORT' is required and parsing will fail if its missing");
+ println!("PORT = {port}");
+}
+
+const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
+
+fn port_in_range(s: &str) -> Result<u16, String> {
+ let port: usize = s
+ .parse()
+ .map_err(|_| format!("`{s}` isn't a port number"))?;
+ if PORT_RANGE.contains(&port) {
+ Ok(port as u16)
+ } else {
+ Err(format!(
+ "port not in range {}-{}",
+ PORT_RANGE.start(),
+ PORT_RANGE.end()
+ ))
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_03_relations.md b/third_party/rust/clap/examples/tutorial_builder/04_03_relations.md
new file mode 100644
index 0000000000..dd0c35a683
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_03_relations.md
@@ -0,0 +1,53 @@
+```console
+$ 04_03_relations --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_03_relations[EXE] [OPTIONS] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
+
+Arguments:
+ [INPUT_FILE] some regular input
+
+Options:
+ --set-ver <VER> set version manually
+ --major auto inc major
+ --minor auto inc minor
+ --patch auto inc patch
+ --spec-in <SPEC_IN> some special input argument
+ -c <CONFIG>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_03_relations
+? failed
+error: the following required arguments were not provided:
+ <--set-ver <VER>|--major|--minor|--patch>
+
+Usage: 04_03_relations[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_03_relations --major
+Version: 2.2.3
+
+$ 04_03_relations --major --minor
+? failed
+error: the argument '--major' cannot be used with '--minor'
+
+Usage: 04_03_relations[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_03_relations --major -c config.toml
+? failed
+error: the following required arguments were not provided:
+ <INPUT_FILE|--spec-in <SPEC_IN>>
+
+Usage: 04_03_relations[EXE] -c <CONFIG> <--set-ver <VER>|--major|--minor|--patch> <INPUT_FILE|--spec-in <SPEC_IN>>
+
+For more information, try '--help'.
+
+$ 04_03_relations --major -c config.toml --spec-in input.txt
+Version: 2.2.3
+Doing work using input input.txt and config config.toml
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_03_relations.rs b/third_party/rust/clap/examples/tutorial_builder/04_03_relations.rs
new file mode 100644
index 0000000000..935e7a334c
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_03_relations.rs
@@ -0,0 +1,78 @@
+use std::path::PathBuf;
+
+use clap::{arg, command, value_parser, ArgAction, ArgGroup};
+
+fn main() {
+ // Create application like normal
+ let matches = command!() // requires `cargo` feature
+ // Add the version arguments
+ .arg(arg!(--"set-ver" <VER> "set version manually"))
+ .arg(arg!(--major "auto inc major").action(ArgAction::SetTrue))
+ .arg(arg!(--minor "auto inc minor").action(ArgAction::SetTrue))
+ .arg(arg!(--patch "auto inc patch").action(ArgAction::SetTrue))
+ // Create a group, make it required, and add the above arguments
+ .group(
+ ArgGroup::new("vers")
+ .required(true)
+ .args(["set-ver", "major", "minor", "patch"]),
+ )
+ // Arguments can also be added to a group individually, these two arguments
+ // are part of the "input" group which is not required
+ .arg(
+ arg!([INPUT_FILE] "some regular input")
+ .value_parser(value_parser!(PathBuf))
+ .group("input"),
+ )
+ .arg(
+ arg!(--"spec-in" <SPEC_IN> "some special input argument")
+ .value_parser(value_parser!(PathBuf))
+ .group("input"),
+ )
+ // Now let's assume we have a -c [config] argument which requires one of
+ // (but **not** both) the "input" arguments
+ .arg(
+ arg!(config: -c <CONFIG>)
+ .value_parser(value_parser!(PathBuf))
+ .requires("input"),
+ )
+ .get_matches();
+
+ // Let's assume the old version 1.2.3
+ let mut major = 1;
+ let mut minor = 2;
+ let mut patch = 3;
+
+ // See if --set-ver was used to set the version manually
+ let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
+ ver.to_owned()
+ } else {
+ // Increment the one requested (in a real program, we'd reset the lower numbers)
+ let (maj, min, pat) = (
+ matches.get_flag("major"),
+ matches.get_flag("minor"),
+ matches.get_flag("patch"),
+ );
+ match (maj, min, pat) {
+ (true, _, _) => major += 1,
+ (_, true, _) => minor += 1,
+ (_, _, true) => patch += 1,
+ _ => unreachable!(),
+ };
+ format!("{major}.{minor}.{patch}")
+ };
+
+ println!("Version: {version}");
+
+ // Check for usage of -c
+ if matches.contains_id("config") {
+ let input = matches
+ .get_one::<PathBuf>("INPUT_FILE")
+ .unwrap_or_else(|| matches.get_one::<PathBuf>("spec-in").unwrap())
+ .display();
+ println!(
+ "Doing work using input {} and config {}",
+ input,
+ matches.get_one::<PathBuf>("config").unwrap().display()
+ );
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_04_custom.md b/third_party/rust/clap/examples/tutorial_builder/04_04_custom.md
new file mode 100644
index 0000000000..0a83eb9b8e
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_04_custom.md
@@ -0,0 +1,52 @@
+```console
+$ 04_04_custom --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
+
+Arguments:
+ [INPUT_FILE] some regular input
+
+Options:
+ --set-ver <VER> set version manually
+ --major auto inc major
+ --minor auto inc minor
+ --patch auto inc patch
+ --spec-in <SPEC_IN> some special input argument
+ -c <CONFIG>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_04_custom
+? failed
+error: Can only modify one version field
+
+Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_04_custom --major
+Version: 2.2.3
+
+$ 04_04_custom --major --minor
+? failed
+error: Can only modify one version field
+
+Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_04_custom --major -c config.toml
+? failed
+Version: 2.2.3
+error: INPUT_FILE or --spec-in is required when using --config
+
+Usage: 04_04_custom[EXE] [OPTIONS] [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_04_custom --major -c config.toml --spec-in input.txt
+Version: 2.2.3
+Doing work using input input.txt and config config.toml
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_builder/04_04_custom.rs b/third_party/rust/clap/examples/tutorial_builder/04_04_custom.rs
new file mode 100644
index 0000000000..840b3aa4f7
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/04_04_custom.rs
@@ -0,0 +1,84 @@
+use std::path::PathBuf;
+
+use clap::error::ErrorKind;
+use clap::{arg, command, value_parser, ArgAction};
+
+fn main() {
+ // Create application like normal
+ let mut cmd = command!() // requires `cargo` feature
+ // Add the version arguments
+ .arg(arg!(--"set-ver" <VER> "set version manually"))
+ .arg(arg!(--major "auto inc major").action(ArgAction::SetTrue))
+ .arg(arg!(--minor "auto inc minor").action(ArgAction::SetTrue))
+ .arg(arg!(--patch "auto inc patch").action(ArgAction::SetTrue))
+ // Arguments can also be added to a group individually, these two arguments
+ // are part of the "input" group which is not required
+ .arg(arg!([INPUT_FILE] "some regular input").value_parser(value_parser!(PathBuf)))
+ .arg(
+ arg!(--"spec-in" <SPEC_IN> "some special input argument")
+ .value_parser(value_parser!(PathBuf)),
+ )
+ // Now let's assume we have a -c [config] argument which requires one of
+ // (but **not** both) the "input" arguments
+ .arg(arg!(config: -c <CONFIG>).value_parser(value_parser!(PathBuf)));
+ let matches = cmd.get_matches_mut();
+
+ // Let's assume the old version 1.2.3
+ let mut major = 1;
+ let mut minor = 2;
+ let mut patch = 3;
+
+ // See if --set-ver was used to set the version manually
+ let version = if let Some(ver) = matches.get_one::<String>("set-ver") {
+ if matches.get_flag("major") || matches.get_flag("minor") || matches.get_flag("patch") {
+ cmd.error(
+ ErrorKind::ArgumentConflict,
+ "Can't do relative and absolute version change",
+ )
+ .exit();
+ }
+ ver.to_string()
+ } else {
+ // Increment the one requested (in a real program, we'd reset the lower numbers)
+ let (maj, min, pat) = (
+ matches.get_flag("major"),
+ matches.get_flag("minor"),
+ matches.get_flag("patch"),
+ );
+ match (maj, min, pat) {
+ (true, false, false) => major += 1,
+ (false, true, false) => minor += 1,
+ (false, false, true) => patch += 1,
+ _ => {
+ cmd.error(
+ ErrorKind::ArgumentConflict,
+ "Can only modify one version field",
+ )
+ .exit();
+ }
+ };
+ format!("{major}.{minor}.{patch}")
+ };
+
+ println!("Version: {version}");
+
+ // Check for usage of -c
+ if matches.contains_id("config") {
+ let input = matches
+ .get_one::<PathBuf>("INPUT_FILE")
+ .or_else(|| matches.get_one::<PathBuf>("spec-in"))
+ .unwrap_or_else(|| {
+ cmd.error(
+ ErrorKind::MissingRequiredArgument,
+ "INPUT_FILE or --spec-in is required when using --config",
+ )
+ .exit()
+ })
+ .display();
+ println!(
+ "Doing work using input {} and config {}",
+ input,
+ matches.get_one::<PathBuf>("config").unwrap().display()
+ );
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_builder/05_01_assert.rs b/third_party/rust/clap/examples/tutorial_builder/05_01_assert.rs
new file mode 100644
index 0000000000..b42c5762e7
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_builder/05_01_assert.rs
@@ -0,0 +1,25 @@
+use clap::{arg, command, value_parser};
+
+fn main() {
+ let matches = cmd().get_matches();
+
+ // Note, it's safe to call unwrap() because the arg is required
+ let port: usize = *matches
+ .get_one::<usize>("PORT")
+ .expect("'PORT' is required and parsing will fail if its missing");
+ println!("PORT = {port}");
+}
+
+fn cmd() -> clap::Command {
+ command!() // requires `cargo` feature
+ .arg(
+ arg!(<PORT>)
+ .help("Network port to use")
+ .value_parser(value_parser!(usize)),
+ )
+}
+
+#[test]
+fn verify_cmd() {
+ cmd().debug_assert();
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/01_quick.md b/third_party/rust/clap/examples/tutorial_derive/01_quick.md
new file mode 100644
index 0000000000..21bbfe1a65
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/01_quick.md
@@ -0,0 +1,35 @@
+```console
+$ 01_quick_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 01_quick_derive[EXE] [OPTIONS] [NAME] [COMMAND]
+
+Commands:
+ test does testing things
+ help Print this message or the help of the given subcommand(s)
+
+Arguments:
+ [NAME] Optional name to operate on
+
+Options:
+ -c, --config <FILE> Sets a custom config file
+ -d, --debug... Turn debugging information on
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+By default, the program does nothing:
+```console
+$ 01_quick_derive
+Debug mode is off
+
+```
+
+But you can mix and match the various features
+```console
+$ 01_quick_derive -dd test
+Debug mode is on
+Not printing testing lists...
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/01_quick.rs b/third_party/rust/clap/examples/tutorial_derive/01_quick.rs
new file mode 100644
index 0000000000..0edcd251f9
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/01_quick.rs
@@ -0,0 +1,68 @@
+use std::path::PathBuf;
+
+use clap::{Parser, Subcommand};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ /// Optional name to operate on
+ name: Option<String>,
+
+ /// Sets a custom config file
+ #[arg(short, long, value_name = "FILE")]
+ config: Option<PathBuf>,
+
+ /// Turn debugging information on
+ #[arg(short, long, action = clap::ArgAction::Count)]
+ debug: u8,
+
+ #[command(subcommand)]
+ command: Option<Commands>,
+}
+
+#[derive(Subcommand)]
+enum Commands {
+ /// does testing things
+ Test {
+ /// lists test values
+ #[arg(short, long)]
+ list: bool,
+ },
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ // You can check the value provided by positional arguments, or option arguments
+ if let Some(name) = cli.name.as_deref() {
+ println!("Value for name: {name}");
+ }
+
+ if let Some(config_path) = cli.config.as_deref() {
+ println!("Value for config: {}", config_path.display());
+ }
+
+ // You can see how many times a particular flag or argument occurred
+ // Note, only flags can have multiple occurrences
+ match cli.debug {
+ 0 => println!("Debug mode is off"),
+ 1 => println!("Debug mode is kind of on"),
+ 2 => println!("Debug mode is on"),
+ _ => println!("Don't be crazy"),
+ }
+
+ // You can check for the existence of subcommands, and if found use their
+ // matches just as you would the top level cmd
+ match &cli.command {
+ Some(Commands::Test { list }) => {
+ if *list {
+ println!("Printing testing lists...");
+ } else {
+ println!("Not printing testing lists...");
+ }
+ }
+ None => {}
+ }
+
+ // Continued program logic goes here...
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/02_app_settings.md b/third_party/rust/clap/examples/tutorial_derive/02_app_settings.md
new file mode 100644
index 0000000000..90da3ae19b
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/02_app_settings.md
@@ -0,0 +1,17 @@
+```console
+$ 02_app_settings_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 02_app_settings_derive[EXE] --two <TWO> --one <ONE>
+
+Options:
+ --two <TWO>
+
+ --one <ONE>
+
+ -h, --help
+ Print help
+ -V, --version
+ Print version
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/02_app_settings.rs b/third_party/rust/clap/examples/tutorial_derive/02_app_settings.rs
new file mode 100644
index 0000000000..abea13d19f
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/02_app_settings.rs
@@ -0,0 +1,18 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+#[command(next_line_help = true)]
+struct Cli {
+ #[arg(long)]
+ two: String,
+ #[arg(long)]
+ one: String,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("two: {:?}", cli.two);
+ println!("one: {:?}", cli.one);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/02_apps.md b/third_party/rust/clap/examples/tutorial_derive/02_apps.md
new file mode 100644
index 0000000000..b5ae1147fd
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/02_apps.md
@@ -0,0 +1,16 @@
+```console
+$ 02_apps_derive --help
+Does awesome things
+
+Usage: 02_apps_derive[EXE] --two <TWO> --one <ONE>
+
+Options:
+ --two <TWO>
+ --one <ONE>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 02_apps_derive --version
+MyApp 1.0
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/02_apps.rs b/third_party/rust/clap/examples/tutorial_derive/02_apps.rs
new file mode 100644
index 0000000000..75455efcee
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/02_apps.rs
@@ -0,0 +1,20 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(name = "MyApp")]
+#[command(author = "Kevin K. <kbknapp@gmail.com>")]
+#[command(version = "1.0")]
+#[command(about = "Does awesome things", long_about = None)]
+struct Cli {
+ #[arg(long)]
+ two: String,
+ #[arg(long)]
+ one: String,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("two: {:?}", cli.two);
+ println!("one: {:?}", cli.one);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/02_crate.md b/third_party/rust/clap/examples/tutorial_derive/02_crate.md
new file mode 100644
index 0000000000..3f64460640
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/02_crate.md
@@ -0,0 +1,16 @@
+```console
+$ 02_crate_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 02_crate_derive[EXE] --two <TWO> --one <ONE>
+
+Options:
+ --two <TWO>
+ --one <ONE>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 02_crate_derive --version
+clap [..]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/02_crate.rs b/third_party/rust/clap/examples/tutorial_derive/02_crate.rs
new file mode 100644
index 0000000000..33a7a4ee0f
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/02_crate.rs
@@ -0,0 +1,17 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)] // Read from `Cargo.toml`
+struct Cli {
+ #[arg(long)]
+ two: String,
+ #[arg(long)]
+ one: String,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("two: {:?}", cli.two);
+ println!("one: {:?}", cli.one);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.md b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.md
new file mode 100644
index 0000000000..976226003b
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.md
@@ -0,0 +1,26 @@
+```console
+$ 03_01_flag_bool_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_01_flag_bool_derive[EXE] [OPTIONS]
+
+Options:
+ -v, --verbose
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_01_flag_bool_derive
+verbose: false
+
+$ 03_01_flag_bool_derive --verbose
+verbose: true
+
+$ 03_01_flag_bool_derive --verbose --verbose
+? failed
+error: the argument '--verbose' cannot be used multiple times
+
+Usage: 03_01_flag_bool_derive[EXE] [OPTIONS]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.rs b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.rs
new file mode 100644
index 0000000000..4f68fc834a
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_bool.rs
@@ -0,0 +1,14 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(short, long)]
+ verbose: bool,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("verbose: {:?}", cli.verbose);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.md b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.md
new file mode 100644
index 0000000000..56ef9cafd9
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.md
@@ -0,0 +1,21 @@
+```console
+$ 03_01_flag_count_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_01_flag_count_derive[EXE] [OPTIONS]
+
+Options:
+ -v, --verbose...
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_01_flag_count_derive
+verbose: 0
+
+$ 03_01_flag_count_derive --verbose
+verbose: 1
+
+$ 03_01_flag_count_derive --verbose --verbose
+verbose: 2
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.rs b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.rs
new file mode 100644
index 0000000000..2b8a453ed2
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_01_flag_count.rs
@@ -0,0 +1,14 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(short, long, action = clap::ArgAction::Count)]
+ verbose: u8,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("verbose: {:?}", cli.verbose);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_02_option.md b/third_party/rust/clap/examples/tutorial_derive/03_02_option.md
new file mode 100644
index 0000000000..24e272aa81
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_02_option.md
@@ -0,0 +1,30 @@
+```console
+$ 03_02_option_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_02_option_derive[EXE] [OPTIONS]
+
+Options:
+ -n, --name <NAME>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_02_option_derive
+name: None
+
+$ 03_02_option_derive --name bob
+name: Some("bob")
+
+$ 03_02_option_derive --name=bob
+name: Some("bob")
+
+$ 03_02_option_derive -n bob
+name: Some("bob")
+
+$ 03_02_option_derive -n=bob
+name: Some("bob")
+
+$ 03_02_option_derive -nbob
+name: Some("bob")
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_02_option.rs b/third_party/rust/clap/examples/tutorial_derive/03_02_option.rs
new file mode 100644
index 0000000000..aad8ef10b2
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_02_option.rs
@@ -0,0 +1,14 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(short, long)]
+ name: Option<String>,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("name: {:?}", cli.name.as_deref());
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.md b/third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.md
new file mode 100644
index 0000000000..cd2fe1301f
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.md
@@ -0,0 +1,30 @@
+```console
+$ 03_02_option_mult_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_02_option_mult_derive[EXE] [OPTIONS]
+
+Options:
+ -n, --name <NAME>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_02_option_mult_derive
+name: []
+
+$ 03_02_option_mult_derive --name bob
+name: ["bob"]
+
+$ 03_02_option_mult_derive --name=bob
+name: ["bob"]
+
+$ 03_02_option_mult_derive -n bob
+name: ["bob"]
+
+$ 03_02_option_mult_derive -n=bob
+name: ["bob"]
+
+$ 03_02_option_mult_derive -nbob
+name: ["bob"]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.rs b/third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.rs
new file mode 100644
index 0000000000..1caa440aaa
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_02_option_mult.rs
@@ -0,0 +1,14 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(short, long)]
+ name: Vec<String>,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("name: {:?}", cli.name);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_03_positional.md b/third_party/rust/clap/examples/tutorial_derive/03_03_positional.md
new file mode 100644
index 0000000000..9437c246f2
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_03_positional.md
@@ -0,0 +1,20 @@
+```console
+$ 03_03_positional_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_03_positional_derive[EXE] [NAME]
+
+Arguments:
+ [NAME]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_03_positional_derive
+name: None
+
+$ 03_03_positional_derive bob
+name: Some("bob")
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_03_positional.rs b/third_party/rust/clap/examples/tutorial_derive/03_03_positional.rs
new file mode 100644
index 0000000000..cf5f4054fb
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_03_positional.rs
@@ -0,0 +1,13 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ name: Option<String>,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("name: {:?}", cli.name.as_deref());
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.md b/third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.md
new file mode 100644
index 0000000000..8f295e02ba
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.md
@@ -0,0 +1,23 @@
+```console
+$ 03_03_positional_mult_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_03_positional_mult_derive[EXE] [NAME]...
+
+Arguments:
+ [NAME]...
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_03_positional_mult_derive
+name: []
+
+$ 03_03_positional_mult_derive bob
+name: ["bob"]
+
+$ 03_03_positional_mult_derive bob john
+name: ["bob", "john"]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.rs b/third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.rs
new file mode 100644
index 0000000000..bd57a55c81
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_03_positional_mult.rs
@@ -0,0 +1,13 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ name: Vec<String>,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("name: {:?}", cli.name);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.md b/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.md
new file mode 100644
index 0000000000..4d57dfeeeb
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.md
@@ -0,0 +1,60 @@
+```console
+$ 03_04_subcommands_derive help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_04_subcommands_derive[EXE] <COMMAND>
+
+Commands:
+ add Adds files to myapp
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_04_subcommands_derive help add
+Adds files to myapp
+
+Usage: 03_04_subcommands_derive[EXE] add [NAME]
+
+Arguments:
+ [NAME]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_04_subcommands_derive add bob
+'myapp add' was used, name is: Some("bob")
+
+```
+
+When specifying commands with `command: Commands`, they are required.
+Alternatively, you could do `command: Option<Commands>` to make it optional.
+```console
+$ 03_04_subcommands_derive
+? failed
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_04_subcommands_derive[EXE] <COMMAND>
+
+Commands:
+ add Adds files to myapp
+ help Print this message or the help of the given subcommand(s)
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+```
+
+Since we specified [`#[command(propagate_version = true)]`][crate::Command::propagate_version],
+the `--version` flag is available in all subcommands:
+```console
+$ 03_04_subcommands_derive --version
+clap [..]
+
+$ 03_04_subcommands_derive add --version
+clap-add [..]
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.rs b/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.rs
new file mode 100644
index 0000000000..da7c644c70
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands.rs
@@ -0,0 +1,27 @@
+use clap::{Parser, Subcommand};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+#[command(propagate_version = true)]
+struct Cli {
+ #[command(subcommand)]
+ command: Commands,
+}
+
+#[derive(Subcommand)]
+enum Commands {
+ /// Adds files to myapp
+ Add { name: Option<String> },
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ // You can check for the existence of subcommands, and if found use their
+ // matches just as you would the top level cmd
+ match &cli.command {
+ Commands::Add { name } => {
+ println!("'myapp add' was used, name is: {name:?}")
+ }
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands_alt.rs b/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands_alt.rs
new file mode 100644
index 0000000000..80b0ec6b95
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_04_subcommands_alt.rs
@@ -0,0 +1,32 @@
+use clap::{Args, Parser, Subcommand};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+#[command(propagate_version = true)]
+struct Cli {
+ #[command(subcommand)]
+ command: Commands,
+}
+
+#[derive(Subcommand)]
+enum Commands {
+ /// Adds files to myapp
+ Add(AddArgs),
+}
+
+#[derive(Args)]
+struct AddArgs {
+ name: Option<String>,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ // You can check for the existence of subcommands, and if found use their
+ // matches just as you would the top level cmd
+ match &cli.command {
+ Commands::Add(name) => {
+ println!("'myapp add' was used, name is: {:?}", name.name)
+ }
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_05_default_values.md b/third_party/rust/clap/examples/tutorial_derive/03_05_default_values.md
new file mode 100644
index 0000000000..994cb33282
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_05_default_values.md
@@ -0,0 +1,20 @@
+```console
+$ 03_05_default_values_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 03_05_default_values_derive[EXE] [PORT]
+
+Arguments:
+ [PORT] [default: 2020]
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 03_05_default_values_derive
+port: 2020
+
+$ 03_05_default_values_derive 22
+port: 22
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/03_05_default_values.rs b/third_party/rust/clap/examples/tutorial_derive/03_05_default_values.rs
new file mode 100644
index 0000000000..bc33a931ab
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/03_05_default_values.rs
@@ -0,0 +1,14 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(default_value_t = 2020)]
+ port: u16,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("port: {:?}", cli.port);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_01_enum.md b/third_party/rust/clap/examples/tutorial_derive/04_01_enum.md
new file mode 100644
index 0000000000..89db08c96e
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_01_enum.md
@@ -0,0 +1,47 @@
+```console
+$ 04_01_enum_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_01_enum_derive[EXE] <MODE>
+
+Arguments:
+ <MODE>
+ What mode to run the program in
+
+ Possible values:
+ - fast: Run swiftly
+ - slow: Crawl slowly but steadily
+
+Options:
+ -h, --help
+ Print help (see a summary with '-h')
+
+ -V, --version
+ Print version
+
+$ 04_01_enum_derive -h
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_01_enum_derive[EXE] <MODE>
+
+Arguments:
+ <MODE> What mode to run the program in [possible values: fast, slow]
+
+Options:
+ -h, --help Print help (see more with '--help')
+ -V, --version Print version
+
+$ 04_01_enum_derive fast
+Hare
+
+$ 04_01_enum_derive slow
+Tortoise
+
+$ 04_01_enum_derive medium
+? failed
+error: invalid value 'medium' for '<MODE>'
+ [possible values: fast, slow]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_01_enum.rs b/third_party/rust/clap/examples/tutorial_derive/04_01_enum.rs
new file mode 100644
index 0000000000..41410a3bdc
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_01_enum.rs
@@ -0,0 +1,32 @@
+use clap::{Parser, ValueEnum};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ /// What mode to run the program in
+ #[arg(value_enum)]
+ mode: Mode,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
+enum Mode {
+ /// Run swiftly
+ Fast,
+ /// Crawl slowly but steadily
+ ///
+ /// This paragraph is ignored because there is no long help text for possible values.
+ Slow,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ match cli.mode {
+ Mode::Fast => {
+ println!("Hare");
+ }
+ Mode::Slow => {
+ println!("Tortoise");
+ }
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_02_parse.md b/third_party/rust/clap/examples/tutorial_derive/04_02_parse.md
new file mode 100644
index 0000000000..573b43cc79
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_02_parse.md
@@ -0,0 +1,29 @@
+```console
+$ 04_02_parse_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_02_parse_derive[EXE] <PORT>
+
+Arguments:
+ <PORT> Network port to use
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_02_parse_derive 22
+PORT = 22
+
+$ 04_02_parse_derive foobar
+? failed
+error: invalid value 'foobar' for '<PORT>': invalid digit found in string
+
+For more information, try '--help'.
+
+$ 04_02_parse_derive 0
+? failed
+error: invalid value '0' for '<PORT>': 0 is not in 1..=65535
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_02_parse.rs b/third_party/rust/clap/examples/tutorial_derive/04_02_parse.rs
new file mode 100644
index 0000000000..a40c6828b6
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_02_parse.rs
@@ -0,0 +1,15 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ /// Network port to use
+ #[arg(value_parser = clap::value_parser!(u16).range(1..))]
+ port: u16,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("PORT = {}", cli.port);
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_02_validate.md b/third_party/rust/clap/examples/tutorial_derive/04_02_validate.md
new file mode 100644
index 0000000000..f8835fdca0
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_02_validate.md
@@ -0,0 +1,29 @@
+```console
+$ 04_02_validate_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_02_validate_derive[EXE] <PORT>
+
+Arguments:
+ <PORT> Network port to use
+
+Options:
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_02_validate_derive 22
+PORT = 22
+
+$ 04_02_validate_derive foobar
+? failed
+error: invalid value 'foobar' for '<PORT>': `foobar` isn't a port number
+
+For more information, try '--help'.
+
+$ 04_02_validate_derive 0
+? failed
+error: invalid value '0' for '<PORT>': port not in range 1-65535
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_02_validate.rs b/third_party/rust/clap/examples/tutorial_derive/04_02_validate.rs
new file mode 100644
index 0000000000..3391d5b72d
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_02_validate.rs
@@ -0,0 +1,34 @@
+use std::ops::RangeInclusive;
+
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ /// Network port to use
+ #[arg(value_parser = port_in_range)]
+ port: u16,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("PORT = {}", cli.port);
+}
+
+const PORT_RANGE: RangeInclusive<usize> = 1..=65535;
+
+fn port_in_range(s: &str) -> Result<u16, String> {
+ let port: usize = s
+ .parse()
+ .map_err(|_| format!("`{s}` isn't a port number"))?;
+ if PORT_RANGE.contains(&port) {
+ Ok(port as u16)
+ } else {
+ Err(format!(
+ "port not in range {}-{}",
+ PORT_RANGE.start(),
+ PORT_RANGE.end()
+ ))
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_03_relations.md b/third_party/rust/clap/examples/tutorial_derive/04_03_relations.md
new file mode 100644
index 0000000000..6eafb9fbbd
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_03_relations.md
@@ -0,0 +1,53 @@
+```console
+$ 04_03_relations_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_03_relations_derive[EXE] [OPTIONS] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
+
+Arguments:
+ [INPUT_FILE] some regular input
+
+Options:
+ --set-ver <VER> set version manually
+ --major auto inc major
+ --minor auto inc minor
+ --patch auto inc patch
+ --spec-in <SPEC_IN> some special input argument
+ -c <CONFIG>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_03_relations_derive
+? failed
+error: the following required arguments were not provided:
+ <--set-ver <VER>|--major|--minor|--patch>
+
+Usage: 04_03_relations_derive[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_03_relations_derive --major
+Version: 2.2.3
+
+$ 04_03_relations_derive --major --minor
+? failed
+error: the argument '--major' cannot be used with '--minor'
+
+Usage: 04_03_relations_derive[EXE] <--set-ver <VER>|--major|--minor|--patch> [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_03_relations_derive --major -c config.toml
+? failed
+error: the following required arguments were not provided:
+ <INPUT_FILE|--spec-in <SPEC_IN>>
+
+Usage: 04_03_relations_derive[EXE] -c <CONFIG> <--set-ver <VER>|--major|--minor|--patch> <INPUT_FILE|--spec-in <SPEC_IN>>
+
+For more information, try '--help'.
+
+$ 04_03_relations_derive --major -c config.toml --spec-in input.txt
+Version: 2.2.3
+Doing work using input input.txt and config config.toml
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_03_relations.rs b/third_party/rust/clap/examples/tutorial_derive/04_03_relations.rs
new file mode 100644
index 0000000000..8657ebe837
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_03_relations.rs
@@ -0,0 +1,75 @@
+use clap::{Args, Parser};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[command(flatten)]
+ vers: Vers,
+
+ /// some regular input
+ #[arg(group = "input")]
+ input_file: Option<String>,
+
+ /// some special input argument
+ #[arg(long, group = "input")]
+ spec_in: Option<String>,
+
+ #[arg(short, requires = "input")]
+ config: Option<String>,
+}
+
+#[derive(Args)]
+#[group(required = true, multiple = false)]
+struct Vers {
+ /// set version manually
+ #[arg(long, value_name = "VER")]
+ set_ver: Option<String>,
+
+ /// auto inc major
+ #[arg(long)]
+ major: bool,
+
+ /// auto inc minor
+ #[arg(long)]
+ minor: bool,
+
+ /// auto inc patch
+ #[arg(long)]
+ patch: bool,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ // Let's assume the old version 1.2.3
+ let mut major = 1;
+ let mut minor = 2;
+ let mut patch = 3;
+
+ // See if --set_ver was used to set the version manually
+ let vers = &cli.vers;
+ let version = if let Some(ver) = vers.set_ver.as_deref() {
+ ver.to_string()
+ } else {
+ // Increment the one requested (in a real program, we'd reset the lower numbers)
+ let (maj, min, pat) = (vers.major, vers.minor, vers.patch);
+ match (maj, min, pat) {
+ (true, _, _) => major += 1,
+ (_, true, _) => minor += 1,
+ (_, _, true) => patch += 1,
+ _ => unreachable!(),
+ };
+ format!("{major}.{minor}.{patch}")
+ };
+
+ println!("Version: {version}");
+
+ // Check for usage of -c
+ if let Some(config) = cli.config.as_deref() {
+ let input = cli
+ .input_file
+ .as_deref()
+ .unwrap_or_else(|| cli.spec_in.as_deref().unwrap());
+ println!("Doing work using input {input} and config {config}");
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_04_custom.md b/third_party/rust/clap/examples/tutorial_derive/04_04_custom.md
new file mode 100644
index 0000000000..c601e9fb4d
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_04_custom.md
@@ -0,0 +1,52 @@
+```console
+$ 04_04_custom_derive --help
+A simple to use, efficient, and full-featured Command Line Argument Parser
+
+Usage: 04_04_custom_derive[EXE] [OPTIONS] [INPUT_FILE]
+
+Arguments:
+ [INPUT_FILE] some regular input
+
+Options:
+ --set-ver <VER> set version manually
+ --major auto inc major
+ --minor auto inc minor
+ --patch auto inc patch
+ --spec-in <SPEC_IN> some special input argument
+ -c <CONFIG>
+ -h, --help Print help
+ -V, --version Print version
+
+$ 04_04_custom_derive
+? failed
+error: Can only modify one version field
+
+Usage: clap [OPTIONS] [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_04_custom_derive --major
+Version: 2.2.3
+
+$ 04_04_custom_derive --major --minor
+? failed
+error: Can only modify one version field
+
+Usage: clap [OPTIONS] [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_04_custom_derive --major -c config.toml
+? failed
+Version: 2.2.3
+error: INPUT_FILE or --spec-in is required when using --config
+
+Usage: clap [OPTIONS] [INPUT_FILE]
+
+For more information, try '--help'.
+
+$ 04_04_custom_derive --major -c config.toml --spec-in input.txt
+Version: 2.2.3
+Doing work using input input.txt and config config.toml
+
+```
diff --git a/third_party/rust/clap/examples/tutorial_derive/04_04_custom.rs b/third_party/rust/clap/examples/tutorial_derive/04_04_custom.rs
new file mode 100644
index 0000000000..a84b5ed5fe
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/04_04_custom.rs
@@ -0,0 +1,91 @@
+use clap::error::ErrorKind;
+use clap::{CommandFactory, Parser};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ /// set version manually
+ #[arg(long, value_name = "VER")]
+ set_ver: Option<String>,
+
+ /// auto inc major
+ #[arg(long)]
+ major: bool,
+
+ /// auto inc minor
+ #[arg(long)]
+ minor: bool,
+
+ /// auto inc patch
+ #[arg(long)]
+ patch: bool,
+
+ /// some regular input
+ input_file: Option<String>,
+
+ /// some special input argument
+ #[arg(long)]
+ spec_in: Option<String>,
+
+ #[arg(short)]
+ config: Option<String>,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ // Let's assume the old version 1.2.3
+ let mut major = 1;
+ let mut minor = 2;
+ let mut patch = 3;
+
+ // See if --set-ver was used to set the version manually
+ let version = if let Some(ver) = cli.set_ver.as_deref() {
+ if cli.major || cli.minor || cli.patch {
+ let mut cmd = Cli::command();
+ cmd.error(
+ ErrorKind::ArgumentConflict,
+ "Can't do relative and absolute version change",
+ )
+ .exit();
+ }
+ ver.to_string()
+ } else {
+ // Increment the one requested (in a real program, we'd reset the lower numbers)
+ let (maj, min, pat) = (cli.major, cli.minor, cli.patch);
+ match (maj, min, pat) {
+ (true, false, false) => major += 1,
+ (false, true, false) => minor += 1,
+ (false, false, true) => patch += 1,
+ _ => {
+ let mut cmd = Cli::command();
+ cmd.error(
+ ErrorKind::ArgumentConflict,
+ "Can only modify one version field",
+ )
+ .exit();
+ }
+ };
+ format!("{major}.{minor}.{patch}")
+ };
+
+ println!("Version: {version}");
+
+ // Check for usage of -c
+ if let Some(config) = cli.config.as_deref() {
+ let input = cli
+ .input_file
+ .as_deref()
+ // 'or' is preferred to 'or_else' here since `Option::as_deref` is 'const'
+ .or(cli.spec_in.as_deref())
+ .unwrap_or_else(|| {
+ let mut cmd = Cli::command();
+ cmd.error(
+ ErrorKind::MissingRequiredArgument,
+ "INPUT_FILE or --spec-in is required when using --config",
+ )
+ .exit()
+ });
+ println!("Doing work using input {input} and config {config}");
+ }
+}
diff --git a/third_party/rust/clap/examples/tutorial_derive/05_01_assert.rs b/third_party/rust/clap/examples/tutorial_derive/05_01_assert.rs
new file mode 100644
index 0000000000..42ebda9a1e
--- /dev/null
+++ b/third_party/rust/clap/examples/tutorial_derive/05_01_assert.rs
@@ -0,0 +1,20 @@
+use clap::Parser;
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ /// Network port to use
+ port: u16,
+}
+
+fn main() {
+ let cli = Cli::parse();
+
+ println!("PORT = {}", cli.port);
+}
+
+#[test]
+fn verify_cli() {
+ use clap::CommandFactory;
+ Cli::command().debug_assert()
+}
diff --git a/third_party/rust/clap/examples/typed-derive.md b/third_party/rust/clap/examples/typed-derive.md
new file mode 100644
index 0000000000..9221a310da
--- /dev/null
+++ b/third_party/rust/clap/examples/typed-derive.md
@@ -0,0 +1,131 @@
+**This requires enabling the [`derive` feature flag][crate::_features].**
+
+Help:
+```console
+$ typed-derive --help
+Usage: typed-derive[EXE] [OPTIONS]
+
+Options:
+ -O <OPTIMIZATION> Implicitly using `std::str::FromStr`
+ -I <DIR> Allow invalid UTF-8 paths
+ --bind <BIND> Handle IP addresses
+ --sleep <SLEEP> Allow human-readable durations
+ -D <DEFINES> Hand-written parser for tuples
+ --port <PORT> Support for discrete numbers [default: 22] [possible values: 22, 80]
+ --log-level <LOG_LEVEL> Support enums from a foreign crate that don't implement `ValueEnum` [default: info] [possible values: trace, debug, info, warn, error]
+ -h, --help Print help
+
+```
+
+Optimization-level (number)
+```console
+$ typed-derive -O 1
+Args { optimization: Some(1), include: None, bind: None, sleep: None, defines: [], port: 22, log_level: Info }
+
+$ typed-derive -O plaid
+? failed
+error: invalid value 'plaid' for '-O <OPTIMIZATION>': invalid digit found in string
+
+For more information, try '--help'.
+
+```
+
+Include (path)
+```console
+$ typed-derive -I../hello
+Args { optimization: None, include: Some("../hello"), bind: None, sleep: None, defines: [], port: 22, log_level: Info }
+
+```
+
+IP Address
+```console
+$ typed-derive --bind 192.0.0.1
+Args { optimization: None, include: None, bind: Some(192.0.0.1), sleep: None, defines: [], port: 22, log_level: Info }
+
+$ typed-derive --bind localhost
+? failed
+error: invalid value 'localhost' for '--bind <BIND>': invalid IP address syntax
+
+For more information, try '--help'.
+
+```
+
+Time
+```console
+$ typed-derive --sleep 10s
+Args { optimization: None, include: None, bind: None, sleep: Some(Duration(10s)), defines: [], port: 22, log_level: Info }
+
+$ typed-derive --sleep forever
+? failed
+error: invalid value 'forever' for '--sleep <SLEEP>': expected number at 0
+
+For more information, try '--help'.
+
+```
+
+Defines (key-value pairs)
+```console
+$ typed-derive -D Foo=10 -D Alice=30
+Args { optimization: None, include: None, bind: None, sleep: None, defines: [("Foo", 10), ("Alice", 30)], port: 22, log_level: Info }
+
+$ typed-derive -D Foo
+? failed
+error: invalid value 'Foo' for '-D <DEFINES>': invalid KEY=value: no `=` found in `Foo`
+
+For more information, try '--help'.
+
+$ typed-derive -D Foo=Bar
+? failed
+error: invalid value 'Foo=Bar' for '-D <DEFINES>': invalid digit found in string
+
+For more information, try '--help'.
+
+```
+
+Discrete numbers
+```console
+$ typed-derive --port 22
+Args { optimization: None, include: None, bind: None, sleep: None, defines: [], port: 22, log_level: Info }
+
+$ typed-derive --port 80
+Args { optimization: None, include: None, bind: None, sleep: None, defines: [], port: 80, log_level: Info }
+
+$ typed-derive --port
+? failed
+error: a value is required for '--port <PORT>' but none was supplied
+ [possible values: 22, 80]
+
+For more information, try '--help'.
+
+$ typed-derive --port 3000
+? failed
+error: invalid value '3000' for '--port <PORT>'
+ [possible values: 22, 80]
+
+For more information, try '--help'.
+
+```
+
+Enums from crates that can't implement `ValueEnum`
+```console
+$ typed-derive --log-level debug
+Args { optimization: None, include: None, bind: None, sleep: None, defines: [], port: 22, log_level: Debug }
+
+$ typed-derive --log-level error
+Args { optimization: None, include: None, bind: None, sleep: None, defines: [], port: 22, log_level: Error }
+
+$ typed-derive --log-level
+? failed
+error: a value is required for '--log-level <LOG_LEVEL>' but none was supplied
+ [possible values: trace, debug, info, warn, error]
+
+For more information, try '--help'.
+
+$ typed-derive --log-level critical
+? failed
+error: invalid value 'critical' for '--log-level <LOG_LEVEL>'
+ [possible values: trace, debug, info, warn, error]
+
+For more information, try '--help'.
+
+```
diff --git a/third_party/rust/clap/examples/typed-derive.rs b/third_party/rust/clap/examples/typed-derive.rs
new file mode 100644
index 0000000000..1a36f11d5b
--- /dev/null
+++ b/third_party/rust/clap/examples/typed-derive.rs
@@ -0,0 +1,102 @@
+use clap::builder::TypedValueParser as _;
+use clap::Parser;
+use std::error::Error;
+
+#[derive(Parser, Debug)] // requires `derive` feature
+#[command(term_width = 0)] // Just to make testing across clap features easier
+struct Args {
+ /// Implicitly using `std::str::FromStr`
+ #[arg(short = 'O')]
+ optimization: Option<usize>,
+
+ /// Allow invalid UTF-8 paths
+ #[arg(short = 'I', value_name = "DIR", value_hint = clap::ValueHint::DirPath)]
+ include: Option<std::path::PathBuf>,
+
+ /// Handle IP addresses
+ #[arg(long)]
+ bind: Option<std::net::IpAddr>,
+
+ /// Allow human-readable durations
+ #[arg(long)]
+ sleep: Option<humantime::Duration>,
+
+ /// Hand-written parser for tuples
+ #[arg(short = 'D', value_parser = parse_key_val::<String, i32>)]
+ defines: Vec<(String, i32)>,
+
+ /// Support for discrete numbers
+ #[arg(
+ long,
+ default_value_t = 22,
+ value_parser = clap::builder::PossibleValuesParser::new(["22", "80"])
+ .map(|s| s.parse::<usize>().unwrap()),
+ )]
+ port: usize,
+
+ /// Support enums from a foreign crate that don't implement `ValueEnum`
+ #[arg(
+ long,
+ default_value_t = foreign_crate::LogLevel::Info,
+ value_parser = clap::builder::PossibleValuesParser::new(["trace", "debug", "info", "warn", "error"])
+ .map(|s| s.parse::<foreign_crate::LogLevel>().unwrap()),
+ )]
+ log_level: foreign_crate::LogLevel,
+}
+
+/// Parse a single key-value pair
+fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>>
+where
+ T: std::str::FromStr,
+ T::Err: Error + Send + Sync + 'static,
+ U: std::str::FromStr,
+ U::Err: Error + Send + Sync + 'static,
+{
+ let pos = s
+ .find('=')
+ .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?;
+ Ok((s[..pos].parse()?, s[pos + 1..].parse()?))
+}
+
+mod foreign_crate {
+ #[derive(Copy, Clone, PartialEq, Eq, Debug)]
+ pub enum LogLevel {
+ Trace,
+ Debug,
+ Info,
+ Warn,
+ Error,
+ }
+
+ impl std::fmt::Display for LogLevel {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let s = match self {
+ Self::Trace => "trace",
+ Self::Debug => "debug",
+ Self::Info => "info",
+ Self::Warn => "warn",
+ Self::Error => "error",
+ };
+ s.fmt(f)
+ }
+ }
+ impl std::str::FromStr for LogLevel {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "trace" => Ok(Self::Trace),
+ "debug" => Ok(Self::Debug),
+ "info" => Ok(Self::Info),
+ "warn" => Ok(Self::Warn),
+ "error" => Ok(Self::Error),
+ _ => Err(format!("Unknown log level: {s}")),
+ }
+ }
+ }
+}
+
+fn main() {
+ let args = Args::parse();
+ println!("{args:?}");
+}