Terminal
Le composant Terminal est un émulateur de terminal interactif qui se comporte comme une console système traditionnelle. Il gère les sorties texte, les entrées utilisateur, les séquences de contrôle et les tampons d'écran, ce qui le rend adapté à la construction d'outils d'accès à distance, de tableaux de bord textuels, de shells de commande intégrés ou de consoles de débogage.
Création d'un terminal
Pour utiliser le composant Terminal dans votre application, assurez-vous d'inclure la dépendance suivante dans votre pom.xml.
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-terminal</artifactId>
</dependency>
L'exemple suivant construit un shell de commande interactif avec des commandes tapées, une navigation dans l'historique et une sortie personnalisée.
Afficher le code
- TerminalView.java
- TerminalCommand.java
- ClearCommand.java
- DateCommand.java
- HelpCommand.java
- MsgCommand.java
- ConfirmCommand.java
- TimeCommand.java
- terminal-view.css
Comment ça fonctionne
Le terminal gère une grille de cellules textuelles, traite les flux de caractères entrants et réagit aux actions de l'utilisateur comme la frappe ou la sélection de texte. Il interprète automatiquement les caractères de contrôle et les séquences d'échappement pour le mouvement du curseur, les changements de couleur et le nettoyage de l'écran.
Les comportements principaux incluent :
- Entrée de données : L'écriture de données dans le terminal met à jour l'écran, gérant à la fois le texte et les séquences de contrôle.
- Sortie de données : Capture les frappes de l'utilisateur et les émet sous forme d'événements structurés.
- Gestion de l'écran : Maintient un tampon d'historique déroulant et l'état actuel de l'écran.
- Gestion du curseur : Suit la position du curseur pour l'entrée de texte et les réponses aux séquences de contrôle.
Le terminal est avec état, ce qui signifie qu'il reconstruit correctement les caractères multioctets et maintient la continuité à travers des entrées fragmentées.
Envoi de données au terminal
Les données sont envoyées au terminal à l'aide des méthodes write et writeln :
write(Object data): Envoie des données dans le flux du terminal.writeln(Object data): Envoie des données suivies d'une nouvelle ligne.
Le terminal traite toutes les données entrantes sous forme de chaînes UTF-16. Il gère automatiquement les caractères multioctets, même lorsque l'entrée arrive en morceaux fragmentés.
Exemple
terminal.write("echo Bonjour le monde\n");
terminal.writeln("Prêt.");
Vous pouvez également attacher un rappel qui s'exécute une fois que le morceau de données a été traité :
terminal.write("Sortie de commande longue", e -> {
System.out.println("Données traitées.");
});
Réception de l'entrée utilisateur
Le terminal capture l'entrée générée par l'utilisateur à travers deux événements :
- Événement de données (
onData) : Se déclenche lors de l'entrée de texte, envoyant des caractères Unicode. - Événement de clé (
onKey) : Se déclenche pour chaque pression de touche, y compris des informations sur les codes de touche et les modificateurs comme Ctrl ou Alt.
Ces événements peuvent être utilisés pour relayer l'entrée utilisateur à un backend, mettre à jour des éléments d'interface utilisateur ou déclencher des actions personnalisées.
Exemple
terminal.onData(event -> {
String userInput = event.getValue();
backend.send(userInput);
});
terminal.onKey(event -> {
if (event.isControlKey() && "C".equals(event.getKey())) {
backend.send("SIGINT");
}
});
Toutes les entrées utilisateur capturées par le terminal (comme celles provenant des événements onData) sont émises sous forme de chaînes UTF-16.
Si votre backend attend un encodage différent (comme des octets UTF-8), vous devez transcoder manuellement les données.
Gestion de grands flux de données
Comme le terminal ne peut pas rendre instantanément des entrées illimitées, il maintient un tampon d'entrée interne. Si ce tampon devient trop grand (environ 50 Mo par défaut), de nouvelles données entrantes peuvent être perdues pour protéger les performances du système.
Pour gérer correctement des sources de données rapides, vous devez implémenter un contrôle de flux.
Exemple de contrôle de flux de base
Pauze votre backend jusqu'à ce que le terminal termine le traitement d'un morceau :
pty.onData(chunk -> {
pty.pause();
terminal.write(chunk, result -> {
pty.resume();
});
});
Exemple de contrôle de flux de watermark
Pour un contrôle plus efficace, utilisez des points de repère haut/bas :
int HIGH_WATERMARK = 100_000;
int LOW_WATERMARK = 10_000;
int bufferedBytes = 0;
pty.onData(chunk -> {
bufferedBytes += chunk.length;
terminal.write(chunk, e -> {
bufferedBytes -= chunk.length;
if (bufferedBytes < LOW_WATERMARK) {
pty.resume();
}
});
if (bufferedBytes > HIGH_WATERMARK) {
pty.pause();
}
});
Afficher le code
- ServerLogsView.java
Personnalisation
Options du terminal
La classe TerminalOptions vous permet de configurer le comportement :
- Clignotement du curseur.
- Paramètres de police (famille, taille, poids).
- Taille du tampon de défilement.
- Hauteur de ligne et espacement des lettres.
- Paramètres d'accessibilité (mode lecteur d'écran).
Exemple :
TerminalOptions options = new TerminalOptions()
.setCursorBlink(true)
.setFontFamily("Courier New, monospace")
.setFontSize(13)
.setScrollback(5000);
terminal.setOptions(options);
Thème du terminal
Vous pouvez styliser le terminal à l'aide de TerminalTheme, qui définit :
- Couleurs de fond et de premier plan.
- Palette de couleurs
ANSIstandard. - Couleurs de fond du curseur et de la s élection.
Exemple :
TerminalTheme theme = new TerminalTheme();
theme.setBackground("#1e1e1e");
theme.setForeground("#cccccc");
terminal.setTheme(theme);
Afficher le code
- TerminalThemePickerView.java
Séquences prises en charge
Le terminal prend en charge une large gamme de séquences de contrôle standard utilisées pour le mouvement du curseur, les mises à jour de l'écran et le formatage du texte.
Groupes reconnus :
- Codes de contrôle
C0(commandes 7 bits à un octet,\x00,\x1F, comme retour arrière et retour à la ligne) - Codes de contrôle
C1(commandes à un octet,\x80,\x9F) - Séquences
ESC(commençant parESC(\x1B), comme sauvegarde/restauration du curseur, alignement de l'écran) - Séquences
CSI(Introducer de Séquence de Contrôle,ESC [ouCSI (\x9B), pour des opérations comme le défilement, l'effacement et le style) - Séquences
DCS(Chaînes de Contrôle d'Appareil,ESC PouDCS (\x90)) - Séquences
OSC(Commandes du Système d'Exploitation,ESC ]ouOSC (\x9D), pour définir le titre de la fenêtre, des hyperliens et des couleurs)
Certaines séquences exotiques comme APC, PM, et SOS sont reconnues mais silencieusement ignorées.
Des séquences personnalisées peuvent être prises en charge par le biais d'intégrations si nécessaire.