Séquences ECMA-48 CSI
Voir manuel python Affichage
LES séquences ECMA-48 permettent une spécification (couleur, endroit) de la sortie sur console et commencent par l'octet 27 "ESC". Cela permet notamment d'écrire à un endroit particulier de l'écran, effacer la console ou colorer caractères et fond. Cette fonctionnalité est d'origine avec GNU/Linux.
Pour effacer la console, par exemple:
echo -e "\x1b[2J"
ou
echo -e "\e[2J"
La documentation en Unix:
$ man console_codes
Sous Windows NT et suivant, il suffirait d'ajouter la ligne DEVICE=ANSI.SYS dans le fichier CONFIG.NT (ça n'a pas marché avec XP). On peut passer des instructions en ligne de commande avec prompt $e[2J (par exemple).
La séquence générale est ESC[#£
- ESC est l'octet 27, en python: chr(27), "\033" (octal) ou "\x1b" (hexadécimal)
- [ est la parentèse carrée ouvrante
- # symbolise ici un nombre en base décimale, plusieurs paramètres sont séparés par un point-virgule
- £ est une lettre de l'alphabet
\x1b[2J efface tout l'écran
\x1b[H place le curseur en haut à gauche
\x1b[#;#H place le curseur à un point particulier de l'écran. \x1b[1;1H place le curseur en haut à gauche
\x1b[#A déplace le curseur de # caractères vers le haut
\x1b[#B déplace le curseur de # caractères vers le bas
\x1b[#C déplace le curseur de # caractères vers la droite
\x1b[#D déplace le curseur de # caractères vers la gauche
\x1b[#f place le curseur à la ligne # , première colonne
\x1b[#L insère # lignes à la position du curseur, repousse la suite
\x1b[#M efface # lignes à la position du curseur, ramène les suivantes
\x1b[#a place le curseur à la ligne #, colonne inchangée
\x1b[#;#r définit une première et une dernière ligne pour le scroll
\x1b[s sauvegarde la position du curseur
\x1b[u replace le curseur à la position préalablement sauvegardée
\x1b[?25l cache le curseur; \x1b[?25h le rétablit
Les couleurs (très limitées) se codent \x1b[_m le souligné doit être remplacé par:
0 réinitialisation: blanc sur fond noir
1 haute intensité
3n couleur du caractère
4n couleur du fond
5 clignotement
7 inverse-video
3n: Caractère 4n: Fond 30 Gris moyen 40 Noir 31 Rouge 41 Rouge foncé 32 Vert 42 Vert foncé 33 Jaune 43 brun 34 Bleu 44 Bleu foncé 35 Magenta 45 Mauve 36 Cyan 46 Cyan foncé 37 Blanc 47 gris clair 39 Blanc gras
En python
On compose couleurs de caractère et de fond en séparant les nombres par un point virgule:
>>> print("\x1b[1;33;45m"+"Spam?"+"\x1b[0m")
Spam?
Le module ecma permet l'utilisation simple de ces codes:
paintat(ligne,colonne,texte,fond,"Chaine")
Voir Modules utilisateurs pour l'utilisation d'un module fait à la maison. Copiez le code ci-dessous dans un fichier nommé ecma.py, que vous placez par exemple dans le répertoire de votre script, ou (avec les droits de super-utilisateur) à l'adresse /usr/lib/python3.7 (ou selon votre version de python).
"""python3 ecma.py module - 2007.02.07 - www.jchr.be - GPL2 - v2.1: 2021.12.23 Enhanced printing console functions using some ECMA-48 sequences: position= line, column ; colors= foreground, background Color composition: add red=1, green=2 or blue=4. You can use number or chain: Foreground: Background: darker than foreground 0, 30 or 'grey' 0, 40 or 'black' 1, 31 or 'red' 1, 41, 'red' or 'darkred' 2, 32 or 'green' 2, 42, 'green' or 'darkgreen' 3, 33 or 'yellow' 3, 43, 'yellow' or 'brown' 4, 34 or 'blue' 4, 44, 'blue' or 'marine' 5, 35 or 'magenta' 5, 45, 'magenta' or 'purple' 6, 36 or 'cyan' 6, 46, 'cyan' or 'darkcyan' 7, 37 or 'white' 7, 47, 'white' or 'lightgrey' 9, 39 or 'bright' """ # from __future__ import print_function # uncomment only for python2 def add(txt): """Add a text at the last location, with no linefeed""" print(txt, end="", flush=True) def all(line, column, fg, bg, txt): """Prints a text at a precise location with colors - calls at(), fg(), bg()""" at(line,column) print("\x1b[%s;%sm%s" %(fgcolor(fg),bgcolor(bg),txt)) def at(line, column): """Add at location line-column ; prints without linefeed""" print("\x1b[%s;%sH" %(line, column), end="", flush=True) def bg(clr, txt): """Background color definition""" print("\x1b[%sm%s" %(bgcolor(clr),txt)) def bgcolor(bg): """Used by several functions: returns a background color""" try: if bg<10: bg+=40 return bg except: # if not a number, hoping a string: bg=bg.lower() if bg=="black": return 40 if bg=="red" or bg=="darkred": return 41 if bg=="green" or bg=="darkgreen": return 42 if bg=="brown" or "yellow": return 43 if bg=="blue" or bg=="marine": return 44 if bg=="magenta" or bg=="purple": return 45 if bg=="cyan" or bg=="darkcyan": return 46 if bg=="white" or bg=="lightgrey" or bg=="lightgray": return 47 def blink(): """Blinking mode, normal() cancels""" print("\x1b[5m", end="") def clear(): """Clears the screen""" print("\x1b[2J") def cls(): """Also clears the screen""" print("\x1b[2J") def fg(clr, txt): """Print a text with a foreground color definition""" print("\x1b[%sm%s" %(fgcolor(clr),txt)) def fgcolor(fg): """Used by several functions: returns a foreground color""" try: if fg <10: fg +=30 return fg except: # if not a color, hoping a string: bg =bg.lower() if fg=="grey" or fg=="gray": return 30 if fg=="red": return 31 if fg=="green": return 32 if fg=="yellow": return 33 if fg=="blue": return 34 if fg=="magenta": return 35 if fg=="cyan": return 36 if fg=="white": return 37 if fg=="bright": return 39 def home(txt): """Writes a chain at the 'home' position (upper left corner)""" print("\x1b[H%s" %txt) def inverse(): """Video inverse, normal() cancels""" print("\x1b[7m", end="") def new(txt): """Clears the screen and writes at the home position - same as clear + printat(1,1,chain)""" print("\x1b[2J\x1b[H%s" %txt) def normal(): """Normal video and colours, non-blinking mode""" print("\x1b[0m") def paint(fg, bg, txt): """Writes a colored string - calls fg() and bg()""" print("\x1b[%s;%sm%s" %(fgcolor(fg), bgcolor(bg), txt)) def paintfore(fg, txt): """Writes a text, choosing a colour - calls bg()""" print("\x1b[%sm%s" %(fgcolor(fg), txt)) def paintback(bg, txt): """Writes a text, choosing a background - calls bg()""" print("\x1b[%sm%s" %(bgcolor(bg), txt)) def printat(line,column,txt): """Writes a chain at a precise line/column""" print("\x1b[%s;%sH%s" %(line, column, txt))
Lorsque le fichier est importé, il est possible d'interroger l'aide:
>>> help(ecma)
>>> help(ecma.all)