Create: Computing AgesDoc Brass
Bibliothèques

term

L'écran texte : curseur, couleurs, effacement et défilement.

Tous les ordinateurs

La bibliothèque term pilote l'écran texte de l'ordinateur. L'écran est une grille de caractères, et chaque case a sa propre couleur de texte et sa propre couleur de fond. print et write ajoutent du texte là où se trouve le curseur et passent à la ligne d'eux-mêmes, comme une machine à écrire ; term vous laisse placer le curseur n'importe où, choisir les couleurs, effacer et faire défiler. C'est l'outil des écrans d'état, des tableaux de bord, des menus et des boutons.

Les coordonnées comptent à partir de 1 : (1, 1) est le coin en haut à gauche, x est la colonne (vers la droite), y est la ligne (vers le bas).

Brass
term.clear()
term.set_cursor(1, 1)
print("Coffre de fer")
term.set_cursor(20, 1)
term.write("1234 lingots")
Écran
Coffre de fer      1234 lingots

La taille de l'écran dépend de l'ordinateur :

ordinateurcolonnes × lignescouleurs
Calculateur à tubes40 × 14aucune : un téléscripteur qui imprime sur papier
Ordinateur à transistors51 × 19aucune : phosphore vert
Mini-ordinateur51 × 19aucune : phosphore ambre
Micro-ordinateur51 × 1916 couleurs
Microcontrôleur40 × 1216 couleurs
Ordinateur moderne64 × 2416 couleurs

Tous les ordinateurs ont la bibliothèque term. Sur les plus anciens, les couleurs sont acceptées mais pas affichées (voir plus bas). Pour dessiner en pixels sous le texte, voyez gfx ; le guide Écrans et moniteurs montre comment les deux s'assemblent.

Fonctions
term.get_size()La taille de l'écran en caractères : {w = 51, h = 19} sur un Micro-ordinateur.
term.set_cursor(x, y)Place le curseur à la colonne x, ligne y.
term.get_cursor()Où se trouve le curseur : {x = ..., y = ...}, compté à partir de 1.
term.write(text)Écrit du texte au curseur, sur une seule ligne, sans passer à la ligne.
term.clear()Efface tout l'écran avec la couleur de fond du moment.
term.clear_line()Efface la ligne du curseur avec la couleur de fond du moment.
term.scroll(n)Fait monter tout le texte de l'écran de n lignes.
term.set_fg(color)Choisit la couleur du texte écrit à partir de maintenant.
term.set_bg(color)Choisit la couleur de fond des cases écrites à partir de maintenant, et de celles effacées par term.clear, term.clear_line et term.scroll.
term.colorsLa table des 16 couleurs : white (blanc) vaut 0, black (noir) vaut 15.

Curseur et taille

Le curseur est l'endroit où va le prochain caractère. print, write et term.write partent tous de là et le déplacent.

#

term.get_size()

→ table

La taille de l'écran en caractères : {w = 51, h = 19} sur un Micro-ordinateur.

Renvoie
table
w, le nombre de colonnes, et h, le nombre de lignes

Calculez les positions à partir d'elle plutôt que d'écrire des nombres à la main, et le même programme s'affiche bien sur tous les ordinateurs : un Microcontrôleur (40 colonnes), un Micro-ordinateur (51) ou un Ordinateur moderne (64).

Brass
local taille = term.get_size()
term.set_bg(term.colors.black)
term.clear()
local coins = {{1, 1}, {taille.w, 1}, {1, taille.h}, {taille.w, taille.h}}
term.set_fg(term.colors.yellow)
for _, c in ipairs(coins) do
  term.set_cursor(c[1], c[2])
  term.write("+")
end
local texte = taille.w .. " x " .. taille.h
term.set_fg(term.colors.white)
term.set_cursor(math.floor((taille.w - #texte) / 2) + 1, math.floor(taille.h / 2))
term.write(texte)
Écran
Écran

Exactement le même programme sur un Microcontrôleur, dont l'écran est plus petit :

Brass
local taille = term.get_size()
term.set_bg(term.colors.black)
term.clear()
local coins = {{1, 1}, {taille.w, 1}, {1, taille.h}, {taille.w, taille.h}}
term.set_fg(term.colors.yellow)
for _, c in ipairs(coins) do
  term.set_cursor(c[1], c[2])
  term.write("+")
end
local texte = taille.w .. " x " .. taille.h
term.set_fg(term.colors.white)
term.set_cursor(math.floor((taille.w - #texte) / 2) + 1, math.floor(taille.h / 2))
term.write(texte)
Écran
Écran

Un moniteur ne change pas cette taille : un mur de moniteurs montre la même grille, en plus grand.

Voir aussi term.set_cursor()

#

term.set_cursor(x, y)

Place le curseur à la colonne x, ligne y.

Paramètres
x number
la colonne, 1 à gauche
y number
la ligne, 1 en haut
Brass
term.clear()
term.set_cursor(5, 2)
term.write("Four 1 : allumé")
term.set_cursor(5, 3)
term.write("Four 2 : plus de charbon")
Écran
    Four 1 : allumé
    Four 2 : plus de charbon

La position doit être en nombres entiers : term.set_cursor(10.5, 1) arrête le programme avec bad argument #1 to 'set_cursor' (number has no integer representation). Quand vous calculez une position (pour centrer un texte, par exemple), arrondissez-la avec math.floor.

Une position hors de l'écran est permise, sans erreur, mais ce que vous y écrivez est perdu : les caractères qui tombent hors de l'écran ne sont tout simplement pas dessinés. Un texte qui commence près du bord droit est coupé :

Brass
term.clear()
term.set_cursor(48, 1)
term.write("Pression")
term.set_cursor(1, 2)
term.write("seul Pres est visible")
Écran
                                               Pres
seul Pres est visible

Voir aussi term.get_cursor() term.write()

#

term.get_cursor()

→ table

Où se trouve le curseur : {x = ..., y = ...}, compté à partir de 1.

Renvoie
table
x et y, la position du curseur

Pratique pour retenir un endroit et y revenir plus tard, pour mettre à jour une valeur sans redessiner le reste :

Brass
term.clear()
term.set_cursor(1, 1)
write("Fer dans le coffre : ")
local place = term.get_cursor()
print("...")
-- plus tard, quand le compte est connu :
term.set_cursor(place.x, place.y)
term.write("1234 ")
Écran
Fer dans le coffre : 1234

Après term.write, le curseur se trouve juste après le dernier caractère, même au-delà du bord droit : écrire jusqu'à la dernière colonne d'un écran de 51 colonnes laisse x à 52.

Voir aussi term.set_cursor()

Écrire

#

term.write(text)

Écrit du texte au curseur, sur une seule ligne, sans passer à la ligne.

Paramètres
text any
le texte à écrire (un nombre ou toute autre valeur est converti, comme avec tostring)

term.write est l'outil de précision de l'écran : il écrit exactement là où se trouve le curseur et ne touche à rien d'autre. Il diffère des fonctions globales write et print sur quatre points :

term.writewrite et print
au bord droitla suite du texte est coupéele texte continue sur la ligne suivante
\naffiché comme une espacepasse à la ligne
une tabulation \taffichée comme ?des espaces jusqu'au multiple de 4 colonnes suivant
en bas de l'écranne fait jamais défilerfait défiler l'écran vers le haut
Brass
term.clear()
term.set_cursor(1, 1)
term.write("Charbon :\t12\nFer :\t40")
term.set_cursor(1, 2)
write("Charbon :\t12\nFer :\t40")
Écran
Charbon :?12 Fer :?40
Charbon :   12
Fer :   40

Utilisez donc term.write pour tout ce qui est placé sur une grille (une valeur dans un cadre, un bouton, une barre d'état), et print pour un texte qui s'écoule, comme un journal. Les autres caractères de contrôle s'affichent ? avec les deux.

Le texte prend les couleurs du moment (term.set_fg, term.set_bg). Écrire coûte une instruction de plus par tranche de 16 caractères.

Voir aussi write() print() term.set_cursor()

Effacer et faire défiler

Ces trois fonctions remplissent des cases d'espaces dans la couleur de fond du moment, et aucune ne déplace le curseur.

#

term.clear()

Efface tout l'écran avec la couleur de fond du moment.

Le curseur reste où il était : un effacement est donc presque toujours suivi de term.set_cursor(1, 1).

Brass
print("ancienne ligne 1")
print("ancienne ligne 2")
term.clear()
print("après l'effacement")
local c = term.get_cursor()
print("curseur sur la ligne " .. c.y)
Écran
après l'effacement
curseur sur la ligne 4

(Le nouveau texte commence à la ligne 3, sous l'emplacement des anciennes lignes.)

Pour peindre tout l'écran, choisissez d'abord le fond :

Brass
term.set_bg(term.colors.blue)
term.clear()
term.set_cursor(3, 2)
term.set_fg(term.colors.yellow)
term.write("TOUT EN BLEU")
Écran
Écran

term.clear n'efface pas ce que gfx a dessiné : appelez gfx.clear() pour les dessins.

Voir aussi term.clear_line() gfx.clear()

#

term.clear_line()

Efface la ligne du curseur avec la couleur de fond du moment.

Deux usages courants : effacer une ligne avant d'y écrire un texte plus court, et peindre une barre de couleur en travers de l'écran.

Brass
term.set_bg(term.colors.black)
term.clear()
term.set_cursor(1, 1)
term.set_bg(term.colors.green)
term.clear_line()
term.set_fg(term.colors.black)
term.write(" Stockage OK")
term.set_cursor(1, 3)
term.set_bg(term.colors.red)
term.clear_line()
term.set_fg(term.colors.white)
term.write(" Chaudière en surchauffe")
term.set_bg(term.colors.black)
Écran
Écran

Voir aussi term.clear() term.set_cursor()

#

term.scroll(n)

Fait monter tout le texte de l'écran de n lignes.

Paramètres
n number
de combien de lignes monter le texte ; un nombre négatif le fait descendre

Les lignes du haut disparaissent, et de nouvelles lignes vides (dans la couleur de fond du moment) apparaissent en bas. Avec un n négatif, le texte descend et les lignes vides apparaissent en haut. Défiler de la hauteur de l'écran ou plus l'efface. n doit être un nombre entier.

Brass
term.clear()
term.set_cursor(1, 1)
print("ligne 1")
print("ligne 2")
print("ligne 3")
term.scroll(1)
Écran
ligne 2
ligne 3

Le curseur ne bouge pas avec le texte, et les dessins de gfx restent où ils sont (gfx.scroll les déplace). print fait défiler tout seul quand il atteint le bas ; term.scroll sert à un programme qui place lui-même ses lignes, comme un journal sous un titre fixe (voir les motifs plus bas).

Voir aussi term.clear()

Couleurs

Il y a 16 couleurs, numérotées de 0 à 15 dans l'ordre des teintures de Minecraft. Utilisez leurs noms par term.colors : term.colors.red vaut 14. La page Couleurs les montre toutes.

#

term.set_fg(color)

Choisit la couleur du texte écrit à partir de maintenant.

Paramètres
color number
une couleur de 0 à 15, comme term.colors.red

Ce qui est déjà à l'écran garde ses couleurs : seuls les caractères suivants changent.

Brass
term.set_bg(term.colors.black)
term.clear()
term.set_cursor(1, 1)
term.set_fg(term.colors.lime)
print("Réservoir d'eau : 92 %")
term.set_fg(term.colors.yellow)
print("Réservoir de lave : 35 %")
term.set_fg(term.colors.red)
print("Réservoir de carburant : 4 %, à remplir !")
term.set_fg(term.colors.white)
Écran
Écran

La couleur doit être un nombre de 0 à 15. Un nom de couleur entre guillemets est une erreur ici (contrairement à gfx, qui accepte "red") : term.set_fg("red") s'arrête avec bad argument #1 to 'set_fg' (number expected, got string), et term.set_fg(16) avec bad argument #1 to 'set_fg' (color must be 0..15). Avec un nom rangé dans une variable, écrivez term.colors[nom].

Astuce

Les couleurs restent après la fin du programme : l'invite du shell serait rouge elle aussi. Terminez vos programmes par term.set_fg(term.colors.white) et term.set_bg(term.colors.black). Le bouton Stopper (Ctrl+T) les remet à zéro, et efface l'écran.

Voir aussi term.set_bg() term.colors

#

term.set_bg(color)

Choisit la couleur de fond des cases écrites à partir de maintenant, et de celles effacées par term.clear, term.clear_line et term.scroll.

Paramètres
color number
une couleur de 0 à 15, comme term.colors.blue

Un fond coloré transforme un texte en étiquette ou en bouton. Pensez à revenir au noir ensuite :

Brass
term.set_bg(term.colors.black)
term.clear()
term.set_cursor(2, 2)
term.set_bg(term.colors.green)
term.set_fg(term.colors.white)
term.write(" OUVRIR ")
term.set_bg(term.colors.black)
term.write("  ")
term.set_bg(term.colors.red)
term.write(" FERMER ")
term.set_bg(term.colors.black)
term.set_cursor(2, 4)
term.set_fg(term.colors.light_gray)
term.write("Cliquez sur un bouton pour bouger le portail.")
Écran
Écran

Le programme buttons fait de tels boutons un panneau cliquable avec os.pull_event("click").

Voir aussi term.set_fg() term.colors

#

term.colors

→ tablevaleur

La table des 16 couleurs : white (blanc) vaut 0, black (noir) vaut 15.

Renvoie
table
les 16 noms de couleurs, chacun donnant son numéro
numéronomnuméronom
0 white (blanc)8 light_gray (gris clair)
1 orange9 cyan
2 magenta10 purple (violet)
3 light_blue (bleu clair)11 blue (bleu)
4 yellow (jaune)12 brown (marron)
5 lime (vert clair)13 green (vert)
6 pink (rose)14 red (rouge)
7 gray (gris)15 black (noir)

Les mêmes noms et numéros servent dans gfx. Les voici sur un Micro-ordinateur :

Brass
term.set_bg(term.colors.black)
term.clear()
local noms = {"white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray",
  "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"}
for i, nom in ipairs(noms) do
  local colonne = 2 + math.floor((i - 1) / 8) * 25
  local ligne = 2 + (i - 1) % 8 * 2
  term.set_cursor(colonne, ligne)
  term.set_fg(term.colors.gray)
  term.write("[")
  term.set_bg(term.colors[nom])
  term.write("    ")
  term.set_bg(term.colors.black)
  term.write("]")
  term.set_fg(term.colors.white)
  term.write(" " .. term.colors[nom] .. " " .. nom)
end
Écran
Écran

Voir aussi term.set_fg() term.set_bg() Couleurs

Moniteurs et écrans anciens

Les moniteurs. Un Moniteur cathodique ou un Moniteur LCD qui touche l'ordinateur affiche son écran : la même grille, les mêmes caractères et couleurs, agrandis pour remplir le moniteur (plusieurs moniteurs côte à côte forment un seul grand écran, jusqu'à 8 × 6 blocs). Le programme ne voit aucune différence : term.get_size donne la taille de l'écran propre de l'ordinateur. Le Moniteur cathodique garde l'aspect de l'ordinateur (vert ou ambre sur les anciens, phosphore vert pour le papier du Calculateur à tubes), le Moniteur LCD affiche toujours les couleurs. Voyez Moniteurs.

Les écrans à phosphore. L'Ordinateur à transistors (vert) et le Mini-ordinateur (ambre) ont des écrans monochromes : chaque caractère s'allume dans la couleur du phosphore, et les couleurs de fond ne s'affichent pas. term.set_fg et term.set_bg marchent quand même (sans erreur) : un programme écrit pour un écran couleur tourne sans changement, mais ses couleurs disparaissent. Voici l'exemple « OUVRIR / FERMER » ci-dessus sur un Ordinateur à transistors :

Brass
term.set_bg(term.colors.black)
term.clear()
term.set_cursor(2, 2)
term.set_bg(term.colors.green)
term.set_fg(term.colors.white)
term.write(" OUVRIR ")
term.set_bg(term.colors.black)
term.write("  ")
term.set_bg(term.colors.red)
term.write(" FERMER ")
term.set_bg(term.colors.black)
term.set_cursor(2, 4)
term.set_fg(term.colors.light_gray)
term.write("Cliquez sur un bouton pour bouger le portail.")
Écran
Écran

On ne distingue plus les boutons du texte. Sur ces écrans, montrez les choses avec des caractères : des crochets autour des boutons, > pour un choix, une barre de # pour un niveau.

Brass
term.clear()
term.set_cursor(2, 2)
term.write("[ OUVRIR ]  [ FERMER ]")
term.set_cursor(2, 4)
term.write("Eau    [##########----------]  50 %")
term.set_cursor(2, 5)
term.write("Lave   [###-----------------]  15 %")
term.set_cursor(2, 7)
term.write("> Démarrer les pompes")
term.set_cursor(2, 8)
term.write("  Arrêter les pompes")
Écran
Écran

Le téléscripteur. Le Calculateur à tubes imprime sur une feuille de papier, 40 caractères sur 14 lignes, à l'encre sombre. C'est toujours le même genre d'écran : print fait monter le papier, term.set_cursor, term.clear et term.scroll marchent comme sur les autres. Seules les couleurs ne sont pas imprimées, et le papier ne se clique pas : un clic dans la fenêtre du terminal n'envoie aucun évènement click (un moniteur relié à un Calculateur à tubes peut quand même être pressé). Il n'y a pas de gfx sur le Calculateur à tubes.

Brass
print("== RAPPORT SILICIUM ==")
print("boules tirées :      12")
print("plaquettes coupées : 72")
print("rebuts :              3")
Écran
== RAPPORT SILICIUM ==
boules tirées :      12
plaquettes coupées : 72
rebuts :              3

Motifs courants

Un titre centré. Retirez la longueur du texte de la largeur, coupez en deux, et arrondissez vers le bas :

Brass
local function centrer(y, texte)
  local taille = term.get_size()
  term.set_cursor(math.floor((taille.w - #texte) / 2) + 1, y)
  term.write(texte)
end
term.clear()
centrer(1, "CHAUFFERIE")

Une barre d'état en bas. Peignez la dernière ligne, écrivez dessus, puis remettez le curseur où il était, pour ne pas déranger les print du reste du programme :

Brass
local function etat(texte)
  local taille = term.get_size()
  local retour = term.get_cursor()
  term.set_cursor(1, taille.h)
  term.set_bg(term.colors.gray)
  term.set_fg(term.colors.white)
  term.clear_line()
  term.write(" " .. texte)
  term.set_bg(term.colors.black)
  term.set_cursor(retour.x, retour.y)
end
etat("Ligne de presses : en marche, 37 objets/min")

Redessiner une ligne sans clignotement. Un programme qui efface tout l'écran et redessine tout chaque seconde fait clignoter l'écran : sur un ordinateur lent, le dessin prend plusieurs ticks, et les joueurs le voient à moitié fait. Dessinez les parties fixes une fois, puis réécrivez seulement les valeurs qui changent. Complétez le nouveau texte avec des espaces, pour qu'une valeur plus courte efface la fin de la plus longue :

Brass
term.clear()
term.set_cursor(1, 1)
term.write("Lingots de fer :")
term.set_cursor(1, 2)
term.write("Lingots d'or :")
local function montrer(ligne, valeur)
  term.set_cursor(18, ligne)
  term.write(string.format("%-8d", valeur))  -- 8 colonnes, complétées d'espaces
end
montrer(1, 1234)
montrer(2, 56)
montrer(1, 99)  -- "1234" devient "99", pas "9934"
term.set_cursor(1, 4)  -- laissez le curseur sous l'écran dessiné
Écran
Lingots de fer : 99
Lingots d'or :   56

Un écran avec une barre de titre. Tout ensemble : une barre colorée avec un titre centré, des valeurs en deux couleurs, et une barre d'état :

Brass
local taille = term.get_size()
term.set_bg(term.colors.black)
term.clear()

local function barre(y, couleur, texte)
  term.set_cursor(1, y)
  term.set_bg(couleur)
  term.set_fg(term.colors.white)
  term.clear_line()
  term.set_cursor(math.floor((taille.w - #texte) / 2) + 1, y)
  term.write(texte)
  term.set_bg(term.colors.black)
end

local function valeur(y, libelle, quantite, unite, ok)
  term.set_cursor(3, y)
  term.set_fg(term.colors.light_gray)
  term.write(libelle)
  term.set_cursor(24, y)
  if ok then term.set_fg(term.colors.lime) else term.set_fg(term.colors.red) end
  term.write(quantite .. " " .. unite)
end

barre(1, term.colors.blue, "MOTEUR À VAPEUR - CHAUFFERIE")
valeur(3, "Chaleur chaudière", 18, "/ 18", true)
valeur(4, "Entrée d'eau", 1620, "mB/t", true)
valeur(5, "Moteurs en marche", 6, "sur 8", false)
valeur(6, "Capacité de stress", 98304, "su", true)
barre(taille.h, term.colors.gray, "mis à jour chaque seconde")
Écran
Écran

Un tableau de bord sur deux colonnes. Deux panneaux côte à côte, chacun avec son titre, pour deux parties d'une usine :

Brass
local taille = term.get_size()
local moitie = math.floor(taille.w / 2)
term.set_bg(term.colors.black)
term.clear()

local function panneau(x, titre, couleur, lignes)
  term.set_cursor(x, 1)
  term.set_bg(couleur)
  term.set_fg(term.colors.black)
  term.write(string.format(" %-" .. (moitie - 2) .. "s", titre))
  term.set_bg(term.colors.black)
  for i, ligne in ipairs(lignes) do
    term.set_cursor(x + 1, i + 2)
    term.set_fg(term.colors.white)
    term.write(ligne[1])
    term.set_cursor(x + moitie - 8, i + 2)
    term.set_fg(ligne[3])
    term.write(string.format("%6d", ligne[2]))
  end
end

panneau(1, "FONDERIE : LINGOTS", term.colors.orange, {
  {"Fer", 1234, term.colors.lime},
  {"Or", 312, term.colors.lime},
  {"Cuivre", 18, term.colors.red},
})
panneau(moitie + 1, "PRESSES : PLAQUES", term.colors.light_blue, {
  {"Fer", 640, term.colors.lime},
  {"Laiton", 96, term.colors.yellow},
  {"Or", 0, term.colors.red},
})
Écran
Écran

Un journal en couleurs sous un titre fixe. Chaque ligne porte une étiquette colorée. Quand l'écran est plein, term.scroll fait monter les lignes et le titre est redessiné en haut :

Brass
local taille = term.get_size()
local ligne = 2

local function titre()
  term.set_cursor(1, 1)
  term.set_bg(term.colors.gray)
  term.set_fg(term.colors.white)
  term.clear_line()
  term.write(" Journal du trieur")
  term.set_bg(term.colors.black)
end

local function journal(couleur, etiquette, texte)
  if ligne > taille.h then
    term.scroll(1)
    titre()
    ligne = taille.h
  end
  term.set_cursor(1, ligne)
  term.set_fg(couleur)
  term.write(etiquette)
  term.set_fg(term.colors.white)
  term.write(" " .. texte)
  ligne = ligne + 1
end

term.set_bg(term.colors.black)
term.clear()
titre()
local cargaison = {"lingots de fer", "lingots de cuivre", "pépites d'or", "andésite", "plaques de laiton"}
for i = 1, 20 do
  local objet = cargaison[(i - 1) % #cargaison + 1]
  journal(term.colors.lime, "[ OK ]", "tri : " .. (i * 7 % 50 + 14) .. " " .. objet)
  if i == 9 then
    journal(term.colors.yellow, "[WARN]", "coffre renforcé B plein à 90 %")
  end
end
journal(term.colors.red, "[FAIL]", "coffre renforcé B plein, tapis arrêté")
Écran
Écran