Outils pour utilisateurs

Outils du site


issue180:python

A few weeks ago, I was chatting with a new user on the PAGE Discord forum, comparing our careers in programming and how things had changed. I told him how, back in the late 1980s, I worked on a project to create windows and forms for Turbo Pascal and Modula-2. Back then, everything was pretty much done in 80×24 character terminals. Today, the word “TUI” is very popular and means “Textual User Interface”, and there are many popular Python libraries to make things easier to “Pretty up” the console applications. Most of them use the curses Python library in one form or fashion. I looked at many of the available packages and while most of them did a good job, they were very complicated, and, if I’m completely honest, way more flash than substance. I went back through the articles that I wrote in the past and found the two articles that I wrote for Full Circle back in 2010 on Curses, so I thought I’d revisit them.

Il y a quelques semaines, je discutais avec un nouvel utilisateur sur le forum Discord de PAGE, comparant nos carrières dans la programmation et la façon dont les choses avaient changé. Je lui ai raconté comment, à la fin des années 1980, j'avais travaillé sur un projet de création de fenêtres et de formulaires pour Turbo Pascal et Modula-2. À l'époque, tout se faisait à peu près dans des terminaux de 80×24 caractères.

Aujourd'hui, le mot « TUI » est très populaire et signifie « Textual User Interface », et il existe de nombreuses bibliothèques Python populaires pour faciliter l'« enjolivement » des applications console. La plupart d'entre elles utilisent la bibliothèque Python curses sous une forme ou une autre. J'ai examiné un grand nombre de paquets disponibles et, bien que la plupart d'entre eux fassent du bon travail, ils étaient très compliqués et, pour être tout à fait honnête, avec beaucoup de bling bling plutôt que de substance.

Je suis retourné dans les articles que j'ai écrits dans le passé et j'ai trouvé les deux articles que j'ai écrits sur Curses pour le Full Circle en 2010, alors j'ai pensé les revisiter.

Back to Curses Python for Windows doesn’t include the curses module, but there are libraries that can basically do the same thing. Since we are Linux based here, we don’t have to worry. So let’s get started. The initial demo program I wrote is still a good starting point for “modern” discussions of curses. Let’s take a quick look at the code (top right). You can see that there are almost as many commented lines as there are actual lines of code. When we run this code we see the image below. Pretty boring but there are important concepts presented here. To use curses, you must first import the library, then you need to create a virtual screen. import curses myscreen = curses.initscr()

Retour à Curses

Python pour Windows n'inclut pas le module Curses, mais il existe des bibliothèques qui peuvent faire la même chose. Puisque nous sommes sous Linux ici, nous n'avons pas à nous en inquiéter. Alors commençons.

Le programme de démonstration initial que j'ai écrit est toujours un bon point de départ pour les discussions « modernes » sur curses. Jetons un rapide coup d'œil au code (en haut à droite).

Vous pouvez voir qu'il y a presque autant de lignes commentées qu'il y a de lignes de code réelles.

Lorsque nous exécutons ce code, nous voyons l'image ci-dessous.

Plutôt ennuyeux, mais il y a des concepts importants présentés ici.

Pour utiliser curses, vous devez d'abord importer la bibliothèque, puis vous devez créer un écran virtuel.

import curses

myscreen = curses.initscr()

Next, we draw a border around the screen and add a line of text starting at row 12, column 25. The refresh() method actually shows what has been done to the screen. To see the new TUI screen, you MUST call the refresh() method. myscreen.border(0) myscreen.addstr(12, 25, “See Curses, See Curses Run!”) myscreen.refresh() The program then waits for the user to press a key (any key in this case), then we reset the terminal back to the way it was before we started by calling the endwin() method. myscreen.getch() curses.endwin() Nothing big, nothing special. Just a quick and dirty demo. So let’s try to do something better.

Ensuite, nous dessinons une bordure autour de l'écran et ajoutons une ligne de texte à partir de la ligne 12, colonne 25. La méthode refresh() montre vraiment ce qui a été fait. Pour voir le nouvel écran de l'interface utilisateur, vous DEVEZ appeler la méthode refresh().

myscreen.border(0)

myscreen.addstr(12, 25, “See Curses, See Curses Run !”)

myscreen.refresh()

Le programme attend ensuite que l'utilisateur appuie sur une touche (n'importe quelle touche dans ce cas), puis nous remettons le terminal dans l'état où il était avant de commencer en appelant la méthode endwin().

myscreen.getch()

curses.endwin()

Rien de grand, rien de spécial. Juste une démo rapide et sale. Essayons donc de faire quelque chose de mieux.

This time, we’ll create a demo program showing how to centre a line in the terminal and show all of the various attributes that can be set to provide different effects. First off, we need to import the curses library. import curses Next (below) we’ll create a function that will determine the length of a string and return a value for the horizontal position (x position) so the string will be centered in the terminal window. Now we can get curses initialized and get the number of rows and columns of the terminal. This allows us to use the program in any size terminal that you can use. Notice the line right after the initscr() line. This allows us to use colors in our strings. If you don’t set this, colors won’t work, and all the documentation on curses says that this call should be made “as soon after the initialization as possible”. We also get the number of rows and columns and place them into global variables so we can use the num_cols variable in the centre function. screen = curses.initscr() curses.start_color() global num_rows, num_cols num_rows, num_cols = screen.getmaxyx()

Cette fois-ci, nous allons créer un programme de démonstration expliquant comment centrer une ligne dans le terminal, et montrer tous les différents attributs qui peuvent être définis pour fournir différents effets. Tout d'abord, nous devons importer la bibliothèque curses.

import curses

Ensuite (ci-dessous), nous allons créer une fonction qui déterminera la longueur d'une chaîne de caractères et retournera une valeur pour la position horizontale (position x) afin que la chaîne soit centrée dans la fenêtre du terminal.

Maintenant nous pouvons initialiser curses et obtenir le nombre de lignes et de colonnes du terminal. Cela nous permet de nous servir du programme avec n'importe quelle taille de terminal utilisable. Remarquez la ligne juste après la ligne initscr(). Elle nous permet d'utiliser des couleurs dans nos chaînes de caractères. Si vous ne définissez pas cela, les couleurs ne fonctionneront pas, et toute la documentation sur curses dit que cet appel doit être fait « le plus tôt possible après l'initialisation ». Nous récupérons également le nombre de lignes et de colonnes et les plaçons dans des variables globales afin de pouvoir utiliser la variable num_cols dans la fonction centre.

screen = curses.initscr()

curses.start_color() global num_rows, num_cols

num_rows, num_cols = screen.getmaxyx()

Now, here is the catch when using colors. Curses wants you to set up a foreground/background pair and assign it a number, rather than define it on the fly. This requires you to remember which number has the combination you want when you need to use it. That’s a bit of a pain, but that’s how it is. curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_WHITE) curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK) At this point, we can start placing our text within the screen object. Since we are going to centre these strings, it makes it easier to create the string, then pass it to the centre function to get the x (column) position and then use it in the addstr method. Notice that if you want to use some of the special attributes like bold or underline, you can use the bitwise OR pipe character to add them at the end of the addstr command. One of the last things we need to do is to prompt the user to press a key to end the demo, so we centre the string and place it near the bottom of the screen and make it blink. strng = “Press a key to end demo…” screen.addstr(num_rows - 3, centre(strng), strng, curses.A_BLINK) screen.refresh()

Maintenant, voici le problème de l'utilisation des couleurs. Curses veut que vous configuriez une paire avant-plan/arrière-plan et que vous lui attribuiez un numéro, plutôt que de la définir à la volée. Cela vous oblige à vous rappeler quel numéro a la combinaison que vous voulez quand vous avez besoin de l'utiliser. C'est un peu pénible, mais c'est comme ça.

curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_WHITE)

curses.init_pair(2, curses.COLOR_CYAN, curses.COLOR_BLACK)

A ce stade, nous pouvons commencer à placer notre texte dans l'objet écran. Puisque nous allons centrer ces chaînes, il est plus facile de créer la chaîne, puis de la passer à la fonction centre pour obtenir la position x (colonne) à utiliser ensuite dans la méthode addstr. Notez que si vous souhaitez utiliser certains attributs spéciaux comme le gras ou le soulignement, vous pouvez utiliser le caractère pipe OR pour les ajouter à la fin de la commande addstr.

L'une des dernières choses que nous devons faire est d'inviter l'utilisateur à appuyer sur une touche pour mettre fin à la démo. Nous centrons donc la chaîne de caractères, la plaçons près du bas de l'écran et la faisons clignoter.

strng = “Press a key to end demo…” # Appuyez sur une touche pour terminer la démo…

screen.addstr(num_rows - 3, centre(strng), strng, curses.A_BLINK)

écran.refresh()

Finally, we use the getch() function to wait with a blocking call until any keyboard character is pressed. Notice we don’t have to put a specific location for the cursor, since curses remembers the last position that was used, which is when we print the “Press a key to end demo…” line. Once the user presses a key, we release the terminal screen. c = screen.getch() curses.endwin() I have run out of time for this edition of ‘Python in the REAL world’. Ronnie was kind enough to give me extra time to get this done, since I have been having some more health issues. I wasn’t able to create the MicroThisMicroThat article for this month, so please forgive me. I hope I can get it finished for next month’s issue. The code for the two demos will be on my repository at https://github.com/gregwa1953/FCM-180

Enfin, nous utilisons la fonction getch() pour attendre avec un appel bloquant qu'un caractère du clavier soit enfoncé. Remarquez que nous n'avons pas besoin de mettre un emplacement spécifique pour le curseur, puisque curses se souvient de la dernière position qui a été utilisée, ce qui est le cas lorsque nous imprimons la ligne « Press a key to end demo… ». Une fois que l'utilisateur a appuyé sur une touche, nous libérons l'écran du terminal.

c = screen.getch()

curses.endwin()

Je suis à court de temps pour cette édition de « Python dans le monde réel ». Ronnie a eu la gentillesse de me donner du temps supplémentaire pour le faire, puisque j'ai eu d'autres problèmes de santé. Je n'ai pas été en mesure de créer l'article MicroThisMicroThat pour ce mois-ci, alors veuillez me pardonner. J'espère pouvoir le terminer pour le numéro du mois prochain.

Le code des deux démos sera sur mon dépôt à https://github.com/gregwa1953/FCM-180.

Encart de la page 32 : The next thing, we’ll demonstrate each of the various attributes you can set for a display string.

Ensuite, nous allons démontrer chacun des différents attributs que vous pouvez définir pour une chaîne d'affichage.

issue180/python.txt · Dernière modification : 2022/05/09 13:55 de andre_domenech