logo
pub fn generate_to<G, S, T>(
    gen: G,
    cmd: &mut Command,
    bin_name: S,
    out_dir: T
) -> Result<PathBuf, Error>where
    G: Generator,
    S: Into<String>,
    T: Into<OsString>,
Expand description

Generate a completions file for a specified shell at compile-time.

NOTE: to generate the file at compile time you must use a build.rs “Build Script” or a cargo-xtask

Examples

The following example generates a bash completion script via a build.rs script. In this simple example, we’ll demo a very small application with only a single subcommand and two args. Real applications could be many multiple levels deep in subcommands, and have tens or potentially hundreds of arguments.

First, it helps if we separate out our Command definition into a separate file. Whether you do this as a function, or bare Command definition is a matter of personal preference.

// src/cli.rs
pub fn build_cli() -> Command {
    Command::new("compl")
        .about("Tests completions")
        .arg(Arg::new("file")
            .help("some input file"))
        .subcommand(Command::new("test")
            .about("tests things")
            .arg(Arg::new("case")
                .long("case")
                .action(ArgAction::Set)
                .help("the case to test")))
}

In our regular code, we can simply call this build_cli() function, then call get_matches(), or any of the other normal methods directly after. For example:

// src/main.rs

mod cli;

fn main() {
    let _m = cli::build_cli().get_matches();

    // normal logic continues...
}

Next, we set up our Cargo.toml to use a build.rs build script.

build = "build.rs"

[dependencies]
clap = "*"

[build-dependencies]
clap = "*"
clap_complete = "*"

Next, we place a build.rs in our project root.

use clap_complete::{generate_to, shells::Bash};
use std::env;
use std::io::Error;

include!("src/cli.rs");

fn main() -> Result<(), Error> {
    let outdir = match env::var_os("OUT_DIR") {
        None => return Ok(()),
        Some(outdir) => outdir,
    };

    let mut cmd = build_cli();
    let path = generate_to(
        Bash,
        &mut cmd, // We need to specify what generator to use
        "myapp",  // We need to specify the bin name manually
        outdir,   // We need to specify where to write to
    )?;

    println!("cargo:warning=completion file is generated: {:?}", path);

    Ok(())
}

Now, once we compile there will be a {bin_name}.bash file in the directory. Assuming we compiled with debug mode, it would be somewhere similar to <project>/target/debug/build/myapp-<hash>/out/myapp.bash.

NOTE: Please look at the individual shells to see the name of the files generated.