<details><summary><tt>examples/simple_dynamic.rs</tt></summary>
```no_run
//! Simple dynamic completion example
#![allow(dead_code)]
use bpaf::*;
fn crates(input: &String) -> Vec<(&'static str, Option<&'static str>)> {
let crates = [
(
"cargo-hackerman",
"Workspace hack management and package/feature query",
),
("cargo-prebuilt", "Download prebuilt crate binaries"),
("cargo-show-asm", "Display generated assembly"),
(
"cargo-supply-chain",
"Gather author, contributor, publisher data on crates",
),
("chezmoi_modify_manager", "Chezmoi addon to patch ini files"),
("xvf", "Easy archive extraction"),
("newdoc", "Generate pre-populated module files"),
(
"nust64",
"Tools for compiling a Rust project into an N64 ROM",
),
("uggo", "CLI tool to query builds from u.gg"),
];
crates
.iter()
.filter(|p| p.0.starts_with(input))
.map(|name| (name.0, Some(name.1)))
.collect::<Vec<_>>()
}
#[derive(Debug, Clone, Copy, Bpaf)]
/// Format for generated report
#[bpaf(fallback(Format::Text))]
enum Format {
/// Generate report in JSON format
Json,
/// Generate report in XML format
Xml,
/// Generate report in plaintext format
Text,
}
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct Options {
/// Select crate for analysis
#[bpaf(long("crate"), argument("NAME"), complete(crates))]
name: String,
/// Include dependencies into report
dependencies: bool,
#[bpaf(external)]
format: Format,
/// Upload report to a url
#[bpaf(positional("URL"))]
upload: Option<String>,
}
fn main() {
println!("{:?}", options().run());
}
```
</details>
<details><summary>Output</summary>
Let's consider a simple application that performs crate analysis
Application generates help message as usual
<div class='bpaf-doc'>
$ app --help<br>
<p><b>Usage</b>: <tt><b>app</b></tt> <tt><b>--crate</b></tt>=<tt><i>NAME</i></tt> [<tt><b>--dependencies</b></tt>] [<tt><b>--json</b></tt> | <tt><b>--xml</b></tt> | <tt><b>--text</b></tt>] [<tt><i>URL</i></tt>]</p><p><div>
<b>Format for generated report</b></div><dl><dt><tt><b> --json</b></tt></dt>
<dd>Generate report in JSON format</dd>
<dt><tt><b> --xml</b></tt></dt>
<dd>Generate report in XML format</dd>
<dt><tt><b> --text</b></tt></dt>
<dd>Generate report in plaintext format</dd>
</dl>
</p><p><div>
<b>Available positional items:</b></div><dl><dt><tt><i>URL</i></tt></dt>
<dd>Upload report to a url</dd>
</dl>
</p><p><div>
<b>Available options:</b></div><dl><dt><tt><b> --crate</b></tt>=<tt><i>NAME</i></tt></dt>
<dd>Select crate for analysis</dd>
<dt><tt><b> --dependencies</b></tt></dt>
<dd>Include dependencies into report</dd>
<dt><tt><b>-h</b></tt>, <tt><b>--help</b></tt></dt>
<dd>Prints help information</dd>
</dl>
</p>
<style>
div.bpaf-doc {
padding: 14px;
background-color:var(--code-block-background-color);
font-family: "Source Code Pro", monospace;
margin-bottom: 0.75em;
}
div.bpaf-doc dt { margin-left: 1em; }
div.bpaf-doc dd { margin-left: 3em; }
div.bpaf-doc dl { margin-top: 0; padding-left: 1em; }
div.bpaf-doc { padding-left: 1em; }
</style>
</div>
Shell (zsh in this case) with help of completion system can request possible items to type
along with some description
<pre>
% simple_dynamic \t
% simple_dynamic
--crate=NAME -- Select crate for analysis
--dependencies -- Include dependencies into report
URL: Upload report to a url
Format for generated report
--json -- Generate report in JSON format
--xml -- Generate report in XML format
--text -- Generate report in plaintext format
</pre>
When user provides enough input to identify a possible item - shell substitutes it and allows
to perform more completions
<pre>
% simple_dynamic --j\t
% simple_dynamic --json
</pre>
Since all output format keys are mutually exclusive - with `--json` already present on a
command line `--xml` and `--text` won't show up
<pre>
% simple_dynamic --json \t
% simple_dynamic --json
--crate=NAME -- Select crate for analysis
--dependencies -- Include dependencies into report
URL: Upload report to a url
</pre>
With dynamic completion it is easy to provide shell with more details. For example one of the
options your application can take can be a crate name from reverse dependencies. Using
`complete` method you can tell `bpaf` what values your parser expects and `bpaf` would
communicate this to shell. In this example possible completions are generated by `crates`
function from a static list, but you can use any other source. `bpaf` would only call `crates`
function when trying to complete a crate name.
<pre>
% simple_dynamic --json --crate \t
% simple_dynamic --json --crate
NAME: Select crate for analysis
cargo-hackerman -- Workspace hack management and package/feature query
cargo-prebuilt -- Download prebuilt crate binaries
cargo-show-asm -- Display generated assembly
cargo-supply-chain -- Gather author, contributor, publisher data on crates
chezmoi_modify_manager -- Chezmoi addon to patch ini files
xvf -- Easy archive extraction
newdoc -- Generate pre-populated module files
nust64 -- Tools for compiling a Rust project into an N64 ROM
uggo -- CLI tool to query builds from u.gg
</pre>
As usual completion system uses input to filter on possible variants
<pre>
% simple_dynamic --json --crate cargo-\t
% simple_dynamic --json --crate cargo-
cargo-hackerman -- Workspace hack management and package/feature query
cargo-prebuilt -- Download prebuilt crate binaries
cargo-show-asm -- Display generated assembly
cargo-supply-chain -- Gather author, contributor, publisher data on crates
</pre>
And as soon as there's enough to identify input in a unique way - shell would substitute it.
<pre>
% simple_dynamic --json --crate cargo-ha\t
% simple_dynamic --json --crate cargo-hackerman
</pre>
Outside of generating completion info - `complete` annotation does not affect the results
<div class='bpaf-doc'>
$ app --json --crate cargo-hackerman<br>
Options { name: "cargo-hackerman", dependencies: false, format: Json, upload: None }
</div>
</details>