Créer une application en ligne de commande avec Rust

Damien Cosset - Jun 6 - - Dev Community

Introduction

Dans cet article, nous allons construire ensemble une application en ligne de commande toute simple avec Rust. Le but du programme sera très basique. L'utilisateur nous donnera un nom de dossier et nous créerons un nouveau dossier avec ce nom. Plutôt facile non? Allons-y!

Setup

Si vous n'avez pas encore installé Rust, vous pouvez consulter la documentation officielle, il ya beaucoup d'infos utile!

Commençons par créer notre nouveau projet Rust. Pour ça, on peut lancer la commande suivante:

cargo new new_dir_cmd

Ceci va créer un nouveau dossier appelé new_dir_cmd. Bien sûr, vous pouvez remplacer ce nom par ce que vous voulez.

Si on jette un oeil à l'intérieur de notre nouveau dossier, on peut voir ceci:

Nouveau dossier Rust avec son contenu

Si on lance direct cargo run à l'intérieur de ce dossier, on va se retrouver avec notre bon vieux "Hello World!".

Cargo run Hello World

Génial, on est prêt à coder!

Créer un nouveau dossier

Première étape, on va créer un nouveau dossier. On améliorera notre programme petit à petit.

Mettons le code suivant dans notre main.rs:

use std::fs;

fn main() -> std::io::Result<()> {
    fs::create_dir_all("/Users/damiencosset/Desktop/rust/new_dir_cmd/awesome_new_dir")?;
    Ok(())
}
Enter fullscreen mode Exit fullscreen mode

On utilise le module fs qui vient du crate std. Crates ( caisses en Français ), dans le contexte de Rust, sont similaires aux packages dans d'autres languages. Si vous voulez plus d'informations sur les crates, vous pouvez consulter la documentation

On utilise la fonction create_dir_all exportée par le module. Elle prend un chemin (path) comme argument. Pour l'instant, je lui donne un nom de chemin en dur.

Enfin, cette fonction retourne un type std::io::Result. Donc, notre fonction main doit retourner ce type. On ajoute donc -> std::io::Result<()>. Après avoir créer un nouveau dossier, on renvoie simplement le Ok variant qui indique que tout est ok et qu'aucune erreur n'a été rencontré.

Note: Le caractère ? est utilisé dans Rust pour la propagation d'erreur. Si nous rencontrons une erreur pendant la création de notre dossier, nous retournerons un Err(error), Err étant le deuxième variant que peut prendre Result après Ok.

Lançons ce code et voyons ce que ça donne:

Créer un nouveau dossier en dur

Ca marche! On vient de créer notre premier nouveau dossier avec Rust!

Ajouter des arguments à notre ligne de commande

Eviddemment, ce programme n'est pas très utile. Le but est que l'utilisateur puisse donner un nom de dossier via la ligne de commande. Mettons cela en place.

Ajout du crate clap

Pour lire des arguments de notre ligne de commande, on va utiliser le crate clap. Pour consulter les crates qui ont été ajoutés à notre projet, on peut ouvrir le fichier Cargo.toml et voir ce qui se trouve après:

[dependencies]
Enter fullscreen mode Exit fullscreen mode

Tout les crates qui auront été rajoutés se trouveront ici.

Ajoutons clap avec la commande suivante:

cargo add clap --features derive

Le flag features nous permet d'utiliser des fonctionnalités optionnel du crate. Ici, on veut utilise la feature appelé derive. Pour avoir plus d'informations sur ce crate, vous pouvez consulter sa documentation. Et si nous jettons un oeil à notre Cargo.toml, nous avons à présent une nouvelle ligne:

[dependencies]
clap = { version = "4.5.4", features = ["derive"] }
Enter fullscreen mode Exit fullscreen mode

Définir nos arguments

Remplaçons notre code existant avec ceci:

use clap::Parser;
//use std::fs;

#[derive(Parser)]
struct Cli {
    directory_name: String,
}

fn main() -> std::io::Result<()> {
    let args = Cli::parse();
    println!("{}", args.directory_name);
    // fs::create_dir_all("/Users/damiencosset/Desktop/rust/new_dir_cmd/awesome_new_dir")?;
    Ok(())
}
Enter fullscreen mode Exit fullscreen mode

J'ai mis en commentaire la création de dossier pour le moment
#[derive(Parser)] indique que nous utilisons une macro personnalisée qui implémente le trait Parser. Plus simplement, un trait définit un ensemble de méthodes (ou fonctions). Ici, nous implémentons un ensemble de méthodes (ou fonctions) définit dans Parser dans notre Cli structure. Donc, notre structure Cli est capable d'appeler les méthodes implémentées, comme parse().

Avec ce code, et le pouvoir de clap, nous pouvons lire les arguments de notre ligne de commande. Lançons à nouveau notre application et donnons lui un argument:

Lancer l'application avec un argument dans notre ligne de commande

Parfait! Nous avons réussi à afficher notre argument. On peut à présent lire notre nom de dossier depuis la ligne de commande.

Récupérer le dossier actuel

Maintenant, nous avons un léger soucis. On ne va pas donner le chemin entier du dossier dans notre ligne de commande. On ne va donner que le nom du dossier que l'on souhaite créer.Donc, notre programme a besoin de savoir ou créer notre dossier. Pour garder les choses simples, nous allons prendre le dossier dans lequel nous sommes actuellement, puis y ajouter le nom du dossier que l'on vient de récupérer de la ligne de commande.

On a besoin de:

  • récupérer le chemin du dossier actuel
  • ajouter le nom du dossier à ce chemin

Pour récupérer le chemin du dossoer actuel, on peut ajouter ces 2 lignes de code:

// Import 
use std::env;

// Inside the main function
let mut path = env::current_dir()?;
Enter fullscreen mode Exit fullscreen mode

Notez que l'on utilise le mot clé mut. Cela signifie que la variable que nous venons de définir est mutable. Les variables de Rust sont par défaut immuable. En ajoutant le mot clé mut, on peut modifier notre variable pour y ajouter le nom du dossier que l'on veut créer.

En combinant tout cela, notre programme complet ressemble à ça:

use clap::Parser;
use std::env;
use std::fs;

#[derive(Parser)]
struct Cli {
    directory_name: String,
}

fn main() -> std::io::Result<()> {
    let args = Cli::parse();
    let mut path = env::current_dir()?;
    path.push(args.directory_name);
    fs::create_dir_all(path)?;
    Ok(())
}
Enter fullscreen mode Exit fullscreen mode

En utilisant push(), on peut ajouter notre nom de dossier au chemin du dossir actuel. Voyons si tout fonctionne!

Création de deux nouveaux dossiers avec notre application en ligne de commande

Wooo! Ca marche!

Et just comme ça, nous avons créé un programme très simple avec Rust qui nous permet de créer des nouveaux dossiers.

En espérant que vous avez trouvé cela intéressant!

Have fun ❤

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .