Texte résumé par l'IA durumis
- Rust est un langage très adapté pour l'écriture de CLI, et j'ai implémenté un simple programme CLI avec des fonctions de connexion et de déconnexion à l'aide des bibliothèques clap et ratatui.
- J'ai défini diverses options et sous-commandes avec clap, et mis en place une zone de saisie interactive avec ratatui pour améliorer la commodité et la sécurité.
- En date du 18 avril 2024, j'ai présenté une méthode pratique pour écrire des programmes CLI avec Rust.
D'après mon expérience, le langage qui permet de créer les CLI les plus robustes et les plus faciles à utiliser est Rust.
En effet, grâce à ses capacités d'extension de macro exceptionnelles, il est possible de définir toutes les contraintes et vérifications au niveau de la structure tout en profitant pleinement de la puissance de son typage.
Dans cet article, nous allons créer un exemple de programme CLI simple qui permet de gérer les connexions et les déconnexions en utilisant clap et ratatui. Par la suite, nous présenterons le processus de création de base et les applications potentielles.
Configuration de base de clap
Ajoutez d'abord les quatre dépendances suivantes :
```javascript atty = { version = "0.2.14", optional = true } structopt = { version = "0.3.18", optional = true } clap = { version = "4.4.18", features = ["derive"] } serde = { version = "1", features = ["derive"] }
Les deux premières sont pour la correspondance des commandes cargo, et les deux dernières sont pour l'analyse clap.
Ajoutons maintenant le code.
Commencez par définir le type de commande de niveau supérieur, puis insérez un enum de sous-commandes.
L'enum SubCommand contiendra les commandes de connexion et de déconnexion qui seront définies prochainement.
Et une fois que la commande est initialisée comme ci-dessus, la création de la structure de base est terminée.
Le programme ainsi créé peut être exécuté via cargo run ou en l'installant avec cargo install avant de l'exécuter.
cargo install peut être utilisé pour installer une commande et l'exécuter directement.
Définir des sous-commandes
Définissons maintenant les sous-commandes une par une.
Login et Logout devraient être des sous-commandes distinctes.
J'ai créé un fichier séparé pour définir la commande login.
Dans les objets Option à l'intérieur, nous définissons ici les éléments de flag.
short spécifie si un raccourci comme -i doit être créé, et long spécifie si un texte complet comme --id doit être créé. help est bien sûr l'aide.
Pour créer ces flags en tant qu'éléments facultatifs, il faut définir le type comme Option ou ajouter l'attribut default_value.
Et on l'ajoute en tant que variante à la sous-commande de l'objet de commande du niveau supérieur.
Ensuite, c'est la commande logout. C'est plus facile.
Car il n'y a pas d'options à donner.
On l'enregistre aussi en tant que sous-commande de la commande du niveau supérieur.
Comme l'action est également ramifiée en enum au niveau du point d'entrée, il suffit de la faire correspondre par appariement de motifs.
Et quand on l'exécute, on peut voir que les sous-commandes ont été ajoutées à la liste.
L'exécution fonctionne également bien. Cela vous avertit si vous manquez un flag obligatoire.
Si vous le fournissez, cela fonctionnera correctement. Cependant, il n'effectue aucune action pour le moment.
Isoler et implémenter l'action
Ajoutons maintenant la partie implémentation. Je préfère séparer la logique par fichier dans ce genre de situation. Si tout est regroupé, le code devient trop difficile à lire et à maintenir.
J'ai créé un module d'action et un fichier pour chaque action de sous-commande.
Chaque fonction d'action prend les valeurs des options de la sous-commande en tant qu'arguments.
Et délègue l'exécution au module d'action au niveau du point d'entrée.
Ça a l'air plutôt propre, n'est-ce pas ?
Maintenant que presque tout est prêt, nous allons implémenter une logique réaliste.
Le login a été conçu pour exporter les flags reçus vers un fichier d'identification.
Le logout supprime le fichier d'identification créé.
Alors, si vous essayez de vous connecter,
Il sera créé comme vous l'avez entré, et
Si vous essayez de vous déconnecter ,
Il sera supprimé comme prévu.
Implémenter une commande interactive avec une IUT
Cependant, si vous avez un ou deux flags obligatoires, il est assez pénible de les trouver tous et de les saisir.
De plus, il se peut que l'exposition du mot de passe à l'écran pose des problèmes de sécurité.
Dans ce cas, il peut être préférable de fournir une IUT pour la commodité et la sécurité.
Nous allons implémenter une boîte de dialogue interactive avec masquage du mot de passe en utilisant ratatui, qui est un environnement IUT assez pratique pour Rust.
Ajoutez d'abord les deux dépendances suivantes :
```javascript crossterm = "0.27.0" ratatui = "0.26.0"
Et j'ai ajouté une option pour l'exécution interactive au flag Login.
Si cette option est présente, le contrôle est transféré au contexte interactif.
C'est le début.
Voici le code de base.
Cela peut paraître un peu long à première vue, mais il n'y a rien de très important.
Il ne fait que tourner en boucle sans fin et rend les éléments de texte de manière continue.
Et quand la saisie "q" est entrée, la boucle se termine et le programme s'arrête.
Si vous l'exécutez correctement,
Vous serez redirigé vers le contexte de la commande assez rapidement.
Si vous tapez "q", le programme se terminera.
Implémentons maintenant le processus de saisie.
En fait, c'est assez simple.
Définissez les étapes du processus en tant que type, et définissez le contexte de l'étape actuelle et les variables d'entrée.
Au début de chaque boucle, le texte d'instruction et l'état de la saisie actuelle sont rendus en fonction de l'étape actuelle.
Lorsque la fin est atteinte avec Done, la saisie est terminée, donc la fonction run est appelée à nouveau pour réutiliser la logique existante.
La gestion des événements est un peu plus long.
J'ai fait en sorte que la variable d'entrée puisse être modifiée ou que l'étape suivante puisse être passée en fonction de l'étape et de l'entrée.
Si la touche Backspace est enfoncée, elle est effacée, si un caractère est entré, il est ajouté. Si la touche Esc est enfoncée, le programme se termine, et si la touche Entrée est enfoncée, l'étape suivante est passée.
Essayons à nouveau.
La saisie est correcte et
Le mot de passe est également masqué correctement.
Une fois que vous avez tout saisi et appuyé sur Enter,
Le programme se terminera et la valeur saisie sera émise.
Voilà comment cela fonctionne.
Il faut un peu de bidouille, mais ce n'est pas si difficile.
Le code complet est disponible sur le lien ci-dessous.