Clap est une bibliothèque permettant de gérer les arguments en ligne de commande pour les programmes écrits en rust.

Une bibliothèque supplémentaire, clap_complete permet de générer le code nécessaire à l’autocomplétion pour les interpréteurs comme bash ou zsh.

Cet article porte sur le peu de code nécessaire à le faire fonctionnner.

Configuration

S’il est bien nécessaire d’avoir clap dans les dépendances de l’application, il n’est pas utile d’ajouter clap_complete. Et pour cause, c’est lors de la compilation de l’application et non au run time que les codes pour l’autocomplétion sont générés. Les dépendances sont donc les suivantes:

[dependencies]
clap = { version = "3", features = ["derive"] }

[build-dependencies]
clap = { version = "3", features = ["derive"] }
clap_complete = { version = "3" }

Build script

Cargo, le gestionnaire de paquet Rust dispose d’une fonctionnalité appellée build scripts. Si un projet contient à sa racine un ficher build.rs, cargo va tenter de le compiler et l’exécuter avant de poursuivre avec le reste du code.

J’ai pour habitude de mettre les options de mes programmes dans un fichier éponyme src/options.rs contenant une struct Options publique. Les options en question importent peu, mais il faut que cette convention de nommage et d’emplacement soient respectée pour que le code suivant fonctionne:

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

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

fn main() -> Result<(), Error> {
    println!("cargo:rerun-if-changed=src/options.rs");

    if let Ok(directory) = env::var("CARGO_MANIFEST_DIR").as_ref() {
        let command = &mut Options::command();
        let name = &command.get_name().to_string();

        println!(
            "cargo:info=Generated {:?}",
            generate_to(Bash, command, name, directory)?
        );

        println!(
            "cargo:info=Generated {:?}",
            generate_to(Zsh, command, name, directory)?
        );
    }
    Ok(())
}

Le build.rs précédent va, à la compilation, inclure src/options.rs et donc disposer de la struct Options. Si ce fichier d’option a changé depuis la dernière compilation du projet, le build script va générer un fichier pour Bash et un pour Zsh. La liste des interpréteurs possibles est accessible ici.