examples/simple_dynamic.rs

```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());
}

```


Output

Let's consider a simple application that performs crate analysis

Application generates help message as usual

$ app --help

Usage: app --crate=NAME [--dependencies] [--json | --xml | --text] [URL]

Format for generated report

    --json

Generate report in JSON format

    --xml

Generate report in XML format

    --text

Generate report in plaintext format

Available positional items:

URL

Upload report to a url

Available options:

    --crate=NAME

Select crate for analysis

    --dependencies

Include dependencies into report

-h, --help

Prints help information

Shell (zsh in this case) with help of completion system can request possible items to type
along with some description

% 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

When user provides enough input to identify a possible item - shell substitutes it and allows
to perform more completions

% simple_dynamic --j\t
% simple_dynamic --json

Since all output format keys are mutually exclusive - with `--json` already present on a
command line `--xml` and `--text` won't show up

% simple_dynamic --json \t
% simple_dynamic --json
--crate=NAME             -- Select crate for analysis
--dependencies           -- Include dependencies into report
URL: Upload report to a url

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.

% 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

As usual completion system uses input to filter on possible variants

% 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

And as soon as there's enough to identify input in a unique way - shell would substitute it.

% simple_dynamic --json --crate cargo-ha\t
% simple_dynamic --json --crate cargo-hackerman

Outside of generating completion info - `complete` annotation does not affect the results

$ app --json --crate cargo-hackerman
Options { name: "cargo-hackerman", dependencies: false, format: Json, upload: None }

