Outils pour utilisateurs

Outils du site


issue58:c_c

I realize that many of our readers are students (as am I). Depending on the country, a new semester has just started, is about to start, or, in the case of Germany, is nearly over. It’s often a good idea to keep a listing (alone or in collaboration with your colleagues) of questions, and their answers, pertaining to the courses you’re taking. If you are in the habit of doing so (or are resolved to start this habit), then the following script will help make your revisions much easier. This script was written by a university professor (and FCM reader) who likes to be called “Magic Banana”. You can find it on his website: http://dcc.ufmg.br/~lcerf/en/utilities.html#trivialibre It aims to ask the questions, organized in categories, in a random order, and lets you set a fixed delay to answer each of those questions. It is named “Trivialibre” - because it was initially written to ask the questions of an eponymous game (see: http://trivialibre.humanoidz.org), which is a variation of the famous “Trivial Pursuit” for free software enthusiasts. The script is interesting in its various uses of the Shell tests, Zenity, the rather new 'shuf' command, and of 'sed'.

Je me rends compte que beaucoup de nos lecteurs sont des étudiants (comme je le suis). Selon le pays, un nouveau semestre vient de commencer, est sur le point de commencer, ou, dans le cas de l'Allemagne, est presque terminé. C'est souvent une bonne idée de garder une liste (seul ou en collaboration avec vos collègues) de questions, et leurs réponses, portant sur les cours que vous suivez.

Si vous avez l'habitude de le faire (ou si vous êtes résolu à le faire), alors le script suivant vous aidera à réviser beaucoup plus facilement. Ce script a été écrit par un professeur d'université (et lecteur du FCM) qui aime se faire appeler « Magic Banana ». Vous pouvez le trouver sur son site Internet: http://dcc.ufmg.br/~lcerf/en/utilities.html#trivialibre.

Il a pour but de poser des questions, organisées par catégorie, dans un ordre aléatoire, et vous permet de définir un délai fixe pour répondre à chacune de ces questions. Il s'appelle « Trivialibre » parce qu'il a été initialement écrit pour poser des questions d'un jeu éponyme (voir: http://trivialibre.humanoidz.org), qui est une variante, pour les amateurs de logiciels libre, du célèbre « Trivial Pursuit ». Le script est intéressant dans ses diverses utilisations des tests du shell, Zenity, de la commande assez récente « shuf » et de « sed ».

I'll briefly discuss the functionality of the script, and then explain what each command is used for (including an explanation of the uses within the script). What does it do? This shell script takes the questions from the files within the categories folder, and poses them (at random) in a zenity-formed GUI window. It displays the question, waits, and then displays the correct answer (much like flashcards work). How does it work? It uses shuf to take the files from the categories folder, shuffle the contents, and then save it in the $XDG_DATA_HOME/trivialibre folder (so that the pending questions can be recorded somewhere without losing any). Once this is taken care of, a Zenity window will then ask the user to choose a category (you can choose a specific one, or have the script choose a random one). A zenity window asks the next pending question in the chosen category. This windows contains a progress bar that reaches 100% after a delay chosen by the player (the only argument of the script), or 20secs by default. Once a category has been exhausted, it is then shuffled again and moved back into the $XDG_DATA_HOME/trivialibre folder.

Je vais discuter brièvement de la fonctionnalité du script et ensuite expliquer pourquoi chaque commande est utilisée (y compris une explication des usages dans le script).

Que fait-il ?

Ce script shell prend les questions dans des fichiers du dossier des catégories et les pose (au hasard) dans une fenêtre GUI formée par Zenity. Il affiche la question, attend, puis affiche la bonne réponse (un peu comme le font les flashcards).

Comment ça marche?

Il utilise shuf pour prendre les fichiers du dossier catégories, mélange le contenu, puis l'enregistre dans le dossier $XDG_DATA_HOME/trivialibre (de sorte que les questions en suspens peuvent être enregistrées quelque part sans en perdre).

Une fois cela fait, une fenêtre Zenity demande alors à l'utilisateur de choisir une catégorie (vous pouvez en choisir une en particulier, ou laisser le script en choisir une au hasard).

Une fenêtre Zenity pose la question suivante en attente dans la catégorie choisie. Cette fenêtre contient une barre de progression qui atteint 100 % après un délai choisi par le joueur (le seul argument du script), ou 20 secondes par défaut. Une fois une catégorie épuisée, elle est ensuite à nouveau mélangée et déplacée vers le dossier $XDG_DATA_HOME/trivialibre.

Conditionals: Throughout the script, conditionals are used in order to navigate the varying branches of the file. They are used in if-statements, while-statements, and for-statements. 16. if [ -n “$1” ] This if-statement checks whether the argument $1 is NOT empty (-n stands for “not zero length”), so that the delay for the progress bar can be set to something other than the default 20secs. 23. if [ -z “$XDG_DATA_HOME” ] This is the exact opposite of line 16, where you check if $XDG_DATA_HOME is empty (-z stands for “zero length”). In this case, you then set the variable to “$HOME/.local/share” (which is the value it should be). 28. if [ ! -d $XDG_DATA_HOME/trivialibre ] This comparison checks to see if the directory doesn't exist, and then creates the folder (and all the category files it will need).

Conditions :

Tout au long du script, les conditions sont utilisées pour naviguer dans les différentes branches du dossier. Elles sont utilisées dans les instructions if, while, et for.

16. if [-n “$1”]

Cette instruction if vérifie si l'argument $1 n'est PAS vide (-n signifie « longueur non nulle »), de sorte que le délai pour la barre de progression peut être réglé sur autre chose que les 20 secondes par défaut.

23. if [-z “$XDG_DATA_HOME”]

C'est l'exact opposé de la ligne 16, où vous vérifiez si $XDG_DATA_HOME est vide (-z est synonyme de “longueur zéro”). Dans ce cas, vous définissez alors la variable à “$HOME/.local/share” (qui est la valeur qu'il devrait avoir).

28. if [ ! -d $XDG_DATA_HOME/trivialibre ]

Cette comparaison vérifie si le répertoire n'existe pas, puis crée le dossier (et tous les fichiers catégorie dont il aura besoin).

39. while [ -n “$categoryName” ] Here, we use the conditional we used in line 16, but in a while-statement. This means the loop will keep running until the variable is empty (which happens when the player clicks the “cancel” button). Once the variable is empty, the program effectively quits. 42. if [ “$categoryName” = 'Random!' ] This is a simple String comparison, where we check if the user has selected Random! (as a category) or not. 48. if [ ! -s “$questionList” ] Usually -s is used to check if a file exists and is not empty. Since we're negating it (the “!”), we are actually checking to see if the file is empty, i.e. if the questions within the category are exhausted. If it is, then the next step is to re-populate the file.

39. while [ -n “$categoryName” ]

Ici, nous utilisons la condition que nous avons utilisée à la ligne 16, mais dans une instruction while. Cela signifie que la boucle va continuer de tourner jusqu'à ce que la variable soit vide (ce qui arrive quand le joueur clique sur le bouton « Annuler »). Une fois que la variable est vide, le programme se ferme.

42. if [ “$categoryName” = 'Random!' ]

Il s'agit d'une simple comparaison de chaînes, où nous vérifions si l'utilisateur a choisi « Random! » (le hasard) (en tant que catégorie) ou pas.

48. if [ ! -s “$questionList” ]

Habituellement -s est utilisé pour vérifier si un fichier existe et n'est pas vide. Puisque nous prenons le contraire (le « ! »), nous vérifions en fait si le fichier est vide, c'est-à-dire si les questions relevant de la catégorie sont épuisées. Si c'est le cas, alors la prochaine étape consiste à re-remplir le fichier.

Shuf: Shuf is a program included in the coreutils package, and creates permutations (variations) of the lines within a file. It's used in the following ways in the script (the numbers before the commands are the line numbers): 33. shuf -o “$XDG_DATA_HOME/trivialibre/$category” “$category” In this instance, shuf takes the contents of the file (whose name is saved in variable “category”), creates a permutation, and then saves it in $XDG_DATA_HOME/trivialibre under the same name. This permutation is then the one used in the script. 44. `shuf -n 1 -e *` In this case, shuf displays only the first line of the permutation (“-n 1”), and accepts the arguments as the contents of the file (“-e”). This means it takes the list of categories, creates a permutation, and selects the top one. This is the function used when “Random” is chosen as a category. 50. shuf -o “$XDG_DATA_HOME/trivialibre/$categoryName” “$categoryName” This is the same as in line 33, as it is simply replenishing the exhausted category.

Shuf:

Shuf est un programme inclus dans le paquet coreutils et crée des permutations (variations) des lignes dans un fichier. Il est utilisé comme suit dans le script (les numéros avant les commandes sont les numéros de ligne) :

33. shuf -o “$XDG_DATA_HOME/trivialibre/$category” “$category”

Dans ce cas, shuf prend le contenu du fichier (dont le nom est enregistré dans la variable « category »), crée une permutation, puis l'enregistre dans $XDG_DATA_HOME/trivialibre sous le même nom. Cette permutation est alors celle qui est utilisée dans le script.

44. `shuf -n 1 -e *`

Dans ce cas, shuf affiche seulement la première ligne de la permutation (« -n 1 ») et accepte comme argument le contenu du fichier (« -e »). Cela signifie qu'il prend la liste des catégories, crée une permutation et sélectionne la première. Cette fonction est utilisée lorsque « Random » est choisi comme catégorie.

50. shuf -o “$XDG_DATA_HOME/trivialibre/$categoryName” “$categoryName”

C'est la même chose qu'à la ligne 33, car il remplit tout simplement la catégorie épuisée.

Zenity: “zenity is a program that will display GTK+ dialogs, and return (either in the return code, or on standard output) the user’s input. This allows you to present information, and ask for information from the user, from all manner of shell scripts.” (taken from the zenity manpage). 11. zenity –list –radiolist –window-icon=../token.png –height=247 –title='Trivialibre' –text='Choose a category in the list below or cancel to quit\n(the same questions will not be asked again next time).' –hide-header –column= –column= This creates a GTK window with a radio list, using the token.png file as the window icon. It also includes the window title, the text (outside of the radio button), and offers some configuration (such as geometry). The radio buttons are populated by piping the output of ls -1 through sed and then zenity. Sed is used to format the ls output so that Zenity can use it. It should be noted that Zenity expects each string to be preceded by a TRUE or FALSE, where it denotes which string is the default choice (the line marked TRUE).

Zenity :

« Zenity est un programme qui affiche des boîtes de dialogues de type GTK+ et qui retourne un code (soit par retour dans le script, soit à l'écran) dépendant de l'action de l'utilisateur. Il vous permet d'afficher des informations, de demander des saisies aux utilisateurs, etc., à partir de scripts shell. » (Extrait de la page de manuel Zenity.)

11. zenity –list –radiolist –window-icon=../token.png –height=247 –title='Trivialibre' –text='Choose a category in the list below or cancel to quit\n(the same questions will not be asked again next time).' –hide-header –column= –column=

Ceci crée une fenêtre GTK avec une liste de boutons « radio », en utilisant le fichier token.png comme icône de fenêtre. Il comprend également le titre de la fenêtre, le texte (en dehors du bouton radio) et offre quelques configurations (comme la géométrie). Les boutons radio sont labellisés en redirigeant la sortie de ls -1 à sed, puis à Zenity. Sed est utilisé pour formater la sortie ls de sorte que Zenity puisse l'utiliser. Il convient de noter que Zenity s'attend à ce que chaque chaîne soit précédée par un TRUE ou FALSE, qui désigne quelle chaîne est le choix par défaut (la ligne marquée TRUE).

51, zenity –info –window-icon=../token.png –title=“Exhaustion of the questions \”$categoryName\“” –text=“All questions in the category \”$categoryName\“ having been asked, they are reused (in a different order).” This is the window that notifies the user when a category has been completed. 60. zenity –progress –window-icon=../token.png –title=“In the category \”$categoryName\“” –text=“Question of $author:\n\n$question” In this example, zenity creates a progress bar (using a for loop to run through a percentage for the time between the question and the answer, defined earlier in the script). The percentage for the progress bar is read in through the standard input, which is adjusted every second in this script. 64. zenity –info –window-icon=../token.png –title='Answer' –text=“The answer is:\n\n$answer” Once the progress bar has reached 100% and the user has clicked on the OK button, this command is then called, providing the answer to the question. It will also be displayed if the user clicks the “cancel” button, interrupting the progress bar and displaying the answer. For a better introduction to Zenity, you can check out my article in FCM#46.

51. zenity –info –window-icon=../token.png –title=“Exhaustion of the questions \”$categoryName\“” –text=“All questions in the category \”$categoryName\“ having been asked, they are reused (in a different order).”

C'est la fenêtre qui informe l'utilisateur quand une catégorie a été complétée.

60. zenity –progress –window-icon=../token.png –title=“In the category \”$categoryName\“” –text=“Question of $author:\n\n$question”

Dans cet exemple, Zenity crée une barre de progression (en utilisant une boucle for pour parcourir un pourcentage de temps entre la question et la réponse, définie plus tôt dans le script). Le pourcentage de la barre de progression est lu à travers l'entrée standard, qui est ajusté à chaque seconde dans ce script.

64. zenity –info –window-icon=../token.png –title='Answer' –text=“The answer is:\n\n$answer”

Une fois que la barre de progression a atteint 100 % et que l'utilisateur a cliqué sur le bouton OK, cette commande est ensuite appelée, fournissant la réponse à la question. Elle sera également affichée si l'utilisateur clique sur le bouton « Annuler », interrompant la barre de progression et affichant la réponse.

Pour une meilleure introduction à Zenity, vous pouvez consulter mon article dans le FCM n° 46.

Sed: Sed is a command that allows you to use regular expressions in order to modify text that you can input. I will be writing an article on both sed and awk in the near future. 11. sed iFALSE This is used after the “ls -1” command, and inserts (hence the “i”) the word “FALSE” before every line, so that Zenity can correctly format the data into the radio list. 62. sed -i 1d “$questionList” Here, sed edits the list of questions in-place (“-i”) and simply removes the first line of the file, thereby effectively removing the question that was just asked.

Sed :

Sed est une commande qui vous permet d'utiliser des expressions régulières en vue de modifier le texte que vous pouvez entrer. Je vais écrire un article à la fois sur sed et awk dans un proche avenir.

11. sed iFALSE

Ceci est utilisé après la commande « ls -1 », et insère (d'où le «i») le mot « FALSE » (faux) devant chaque ligne, de sorte que Zenity peut formater correctement les données dans la liste des boutons radio.

62. sed -i 1d “$questionList”

Ici, sed modifie la liste des questions sur place (« -i ») et supprime tout simplement la première ligne du fichier, retirant ainsi la question qui vient d'être posée.

How do I add categories? You can add categories using LibreOffice Calc (or any other program which can create CSV (comma separated values) files). Instead of commas, a tab should be used as the separator, and nothing to separate text. Be sure to give the file the name of the category you want it to represent. I hope you've found this article interesting (and the script useful). I would like to once again thank Magic Banana for supplying the script and being extremely helpful when organizing this article. If anyone has any questions, suggestions, or requests, feel free to email me at lswest34@gmail.com. Be sure to include “C&C” or “FCM” in the title, so that I don't overlook it. Further Reading: • “Linux Shell Scripting with Bash” - Ken O. Burtch (Developer's Library) • Corresponding manpages • FCM#46 of FCM (for Zenity) • info coreutils 'test invocation' • info coreutils 'shuf' • info sed

Comment puis-je ajouter des catégories?

Vous pouvez ajouter des catégories à l'aide de LibreOffice Calc (ou tout autre programme qui peut créer des fichiers CSV (Comma Separated Values [Ndt : dont les champs sont séparés par des virgules]). Au lieu de virgules, une tabulation devrait être utilisée comme séparateur et rien d'autre pour séparer le texte. Assurez-vous de donner au fichier le nom de la catégorie que vous voulez qu'il représente.

J'espère que vous avez trouvé cet article intéressant (et le script utile). Je tiens à remercier encore une fois Magic Banana pour avoir fourni le script et avoir été extrêmement utile lors de l'organisation de cet article. Si quelqu'un a des questions, des suggestions ou demandes, n'hésitez pas à m'envoyer un e-mail à lswest34@gmail.com. N'oubliez pas d'inclure « C&C » ou « FCM » dans le titre, de sorte que je ne le manque pas.

Pour aller plus loin :

• « Linux Shell Scripting avec Bash », Ken Burtch O. (Developer's Library).

• Les pages de manuel correspondantes.

• Le FCM n° 46 (pour Zenity).

• info coreutils « test invocation ».

• info coreutils « shuf ».

• info sed.

issue58/c_c.txt · Dernière modification : 2012/03/17 10:16 de auntiee