Qu'est-ce que Clap et pourquoi en a-t-on besoin ?
Dans le monde de la programmation système, Rust s'est imposé comme un langage alliant les performances du C/C++ à la sécurité mémoire. Cependant, lors de la création d'utilitaires console, les développeurs sont souvent confrontés à la tâche fastidieuse d'analyse des arguments de ligne de commande. La bibliothèque Clap (Command Line Argument Parser) est le framework CLI le plus populaire et le plus fonctionnel pour Rust, qui prend en charge tout le travail de traitement des drapeaux, options et sous-commandes.
Clap permet de :
- Générer automatiquement l'aide (
--help) et la version (--version) ; - Traiter les arguments positionnels, les options nommées et les drapeaux ;
- Créer des sous-commandes imbriquées (comme dans
gitoucargo) ; - Valider les types de données et vérifier le caractère obligatoire des arguments ;
- Fonctionner avec l'autocomplétion pour les shells Bash, Zsh, Fish et PowerShell.
Grâce à la puissante macro derive et à l'API déclarative, Clap réduit la quantité de code de 5 à 10 fois par rapport à l'analyse manuelle. La bibliothèque prend en charge aussi bien les utilitaires simples que les interfaces complexes avec des dizaines d'options.
Installation de Clap dans un projet Rust
Ajoutez la dépendance dans Cargo.toml :
[dependencies]clap = { version = "4.5", features = ["derive"] }Le drapeau features = ["derive"] active la prise en charge des macros — c'est la méthode recommandée pour la plupart des projets. Pour les utilitaires minimalistes, vous pouvez utiliser uniquement l'API builder (sans derive).
Exemple 1 : Analyseur très simple avec la macro derive
Créons un utilitaire qui accepte un nom d'utilisateur et un drapeau de salutation optionnel :
use clap::Parser;
#[derive(Parser)]#[command(name = "greet")]#[command(about = "Salutation simple", long_about = None)]struct Cli { /// Nom d'utilisateur name: String,
/// Afficher la salutation en majuscules #[arg(short, long)] uppercase: bool,}
fn main() { let cli = Cli::parse();
let greeting = format!("Bonjour, {} !", cli.name); if cli.uppercase { println!("{}", greeting.to_uppercase()); } else { println!("{}", greeting); }}Exécutez le programme :
$ cargo run -- MondeBonjour, Monde !
$ cargo run -- Monde --uppercaseBONJOUR, MONDE !
$ cargo run -- --help# Aide générée automatiquementExemple 2 : Options avec types et valeurs par défaut
Clap convertit automatiquement les chaînes en types appropriés (nombres, énumérations, dates). Ajoutons une option pour spécifier le nombre de répétitions :
use clap::Parser;
#[derive(Parser)]#[command(name = "repeat")]struct Cli { /// Texte à répéter text: String,
/// Nombre de répétitions (par défaut 1) #[arg(short, long, default_value_t = 1)] count: u32,}
fn main() { let cli = Cli::parse(); for _ in 0..cli.count { println!("{}", cli.text); }}Vous pouvez maintenant exécuter :
$ cargo run -- "Rust" -c 3RustRustRustExemple 3 : Sous-commandes — comme dans Git
Créons un mini-utilitaire pour gérer les tâches (todo list) avec les commandes add, list et done :
use clap::{Parser, Subcommand};
#[derive(Parser)]#[command(name = "todo")]#[command(about = "Gestionnaire de tâches")]struct Cli { #[command(subcommand)] command: Commands,}
#[derive(Subcommand)]enum Commands { /// Ajouter une nouvelle tâche Add { /// Texte de la tâche task: String, }, /// Afficher toutes les tâches List, /// Marquer une tâche comme terminée Done { /// ID de la tâche id: u32, },}
fn main() { let cli = Cli::parse();
match &cli.comman