Terminal
Die Terminal
-Komponente bietet einen interaktiven Terminalemulator, der sich ähnlich wie eine traditionelle Systemkonsole verhält. Sie ermöglicht Anwendungen, eine textbasierte Benutzeroberfläche anzuzeigen und zu manipulieren, behandelt Textausgaben, empfängt Benutzereingaben, interpretiert Steuersequenzen und verwaltet Bildschirmpuffer.
Dieser Terminal wurde entwickelt, um eine zuverlässige Leistung über eine Vielzahl von Anwendungsfällen hinweg zu bieten, wie z. B. beim Erstellen von Remote-Zugriffstools, Text-Dashboards, eingebetteten Befehlszeilen oder interaktiven Debug-Konsolen.
Um die Terminal
-Komponente in Ihrer App zu verwenden, stellen Sie sicher, dass Sie die folgende Abhängigkeit in Ihrer pom.xml einfügen.
<dependency>
<groupId>com.webforj</groupId>
<artifactId>webforj-terminal</artifactId>
</dependency>
Code anzeigen
- Java
Wie es funktioniert
Der Terminal verwaltet ein Raster von Textzellen, verarbeitet eingehende Zeichendatenströme und reagiert auf Benutzeraktionen wie Tippen oder Textauswahl. Er interpretiert automatisch Steuerzeichen und Escape-Sequenzen für die Cursorbewegung, Farbänderungen und das Löschen des Bildschirms.
Die grundlegenden Verhaltensweisen umfassen:
- Dateninput: Daten in den Terminal zu schreiben, aktualisiert den Bildschirm und verarbeitet sowohl Text- als auch Steuersequenzen.
- Datenoutput: Erfasst Benutzereingaben und gibt sie als strukturierte Ereignisse aus.
- Bildschirmverwaltung: Hält einen blätterbaren Verlaufsbuffer und den aktuellen Bildschirmstatus.
- Cursorverwaltung: Verfolgt die Cursorposition für Texteingaben und Reaktionen auf Steuersequenzen.
Der Terminal ist zustandsbehaftet, was bedeutet, dass er mehrbyte Zeichen korrekt rekonstruieren kann und die Kontinuität über fragmentierte Eingaben hinweg aufrechterhält.
Daten an den Terminal senden
Daten werden an den Terminal mit den Methoden write
und writeln
gesendet:
write(Object data)
: Sendet Daten in den Terminalstrom.writeln(Object data)
: Sendet Daten gefolgt von einem Zeilenumbruch.
Der Terminal verarbeitet alle eingehenden Daten als UTF-16-Strings. Er verarbeitet automatisch mehrbyte Zeichen, selbst wenn die Eingaben in fragmentierten Stücken ankommen.
Beispiel
terminal.write("echo Hello World\n");
terminal.writeln("Bereit.");
Sie können auch einen Callback angeben, der einmal ausgeführt wird, wenn das Datenpaket verarbeitet wurde:
terminal.write("Lange Befehlsausgabe", e -> {
System.out.println("Daten verarbeitet.");
});
Benutzereingaben empfangen
Der Terminal erfasst benutzergenerierte Eingaben über zwei Ereignisse:
- Datenereignis (
onData
): Tritt auf, wenn Texteingaben erfolgen, und sendet Unicode-Zeichen. - Tastenevent (
onKey
): Tritt bei jedem Tastendruck auf und enthält Informationen über Tastencodes und Modifikatoren wie Ctrl oder Alt.
Diese Ereignisse können verwendet werden, um Benutzereingaben an einen Backend zu übermitteln, UI-Elemente zu aktualisieren oder benutzerdefinierte Aktionen auszulösen.
Beispiel
terminal.onData(event -> {
String userInput = event.getValue();
backend.send(userInput);
});
terminal.onKey(event -> {
if (event.isControlKey() && "C".equals(event.getKey())) {
backend.send("SIGINT");
}
});
Alle Benutzereingaben, die vom Terminal erfasst werden (wie z. B. von onData
-Ereignissen), werden als UTF-16-Strings ausgegeben.
Wenn Ihr Backend eine andere Kodierung erwartet (z. B. UTF-8-Bytes), müssen Sie die Daten manuell umkodieren.
Verarbeitung großer Datenströme
Da der Terminal nicht sofort unbegrenzte Eingaben rendern kann, verwaltet er einen internen Eingabepuffer. Wenn dieser Puffer zu groß wird (Standardgröße etwa 50MB
), können neue eingehende Daten verworfen werden, um die Systemleistung zu schützen.
Um schnellere Datenquellen richtig zu verwalten, sollten Sie Flusskontrolle implementieren.
Beispiel für grundlegende Flusskontrolle
Pausieren Sie Ihr Backend, bis der Terminal ein Datenpaket verarbeitet hat:
pty.onData(chunk -> {
pty.pause();
terminal.write(chunk, result -> {
pty.resume();
});
});
Beispiel für Flusskontrolle mit Wasserzeichen
Für eine effizientere Kontrolle verwenden Sie Hoch-/Niedrigwasserzeichen:
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();
}
});
Code anzeigen
- Java
Anpassung
Terminaloptionen
Die Klasse TerminalOptions
ermöglicht es Ihnen, das Verhalten zu konfigurieren:
- Cursorblinken.
- Schriftarteinstellungen (Familie, Größe, Gewicht).
- Größe des Rücklaufpuffers.
- Zeilenhöhe und Buchstabenabstand.
- Barrierefreiheitseinstellungen (Bildschirmlesermodus).
Beispiel:
TerminalOptions options = new TerminalOptions()
.setCursorBlink(true)
.setFontFamily("Courier New, monospace")
.setFontSize(13)
.setScrollback(5000);
terminal.setOptions(options);
Terminalthema
Sie können den Terminal mithilfe von TerminalTheme
gestalten, das definiert:
- Hintergrund- und Vordergrundfarben.
- Standard-
ANSI
-Farbenpalette. - Cursor- und Auswahlhintergrundfarben.
Beispiel:
TerminalTheme theme = new TerminalTheme();
theme.setBackground("#1e1e1e");
theme.setForeground("#cccccc");
terminal.setTheme(theme);
Code anzeigen
- Java
Unterstützte Sequenzen
Der Terminal unterstützt eine breite Palette von standardmäßigen Steuersequenzen, die für die Cursorbewegung, Bildschirmaktualisierungen und Textformatierungen verwendet werden.
Erkannte Gruppen:
C0
-Steuercodes (einzelne Byte 7-Bit-Befehle,\x00
,\x1F
, wie Rücktaste und Zeilenumbruch)C1
-Steuercodes (einzelne Byte 8-Bit-Befehle,\x80
,\x9F
)ESC
-Sequenzen (beginnt mitESC
(\x1B
), wie speichern/wiederherstellen des Cursors, Bildschirmausrichtung)CSI
-Sequenzen (Control Sequence Introducer,ESC [
oderCSI (\x9B)
, für Operationen wie Scrollen, Löschen und Styling)DCS
-Sequenzen (Device Control Strings,ESC P
oderDCS (\x90)
)OSC
-Sequenzen (Betriebssystembefehle,ESC ]
oderOSC (\x9D)
, zum Setzen des Fenstertitels, Hyperlinks und Farben)
Einige exotische Sequenztypen wie APC
, PM
und SOS
werden erkannt, aber stillschweigend ignoriert.
Benutzerdefinierte Sequenzen können bei Bedarf durch Integrationen unterstützt werden.