In letzter Zeit habe ich mich gefragt, wie die Benutzeroberfläche von Vim funktioniert. Wenn Sie es starten, nimmt es das gesamte Terminalfenster ein, anstatt nur Text auszudrucken und Sie möglicherweise aufzufordern, etwas einzugeben, und wenn es fertig ist, eine weitere Befehlszeile darunter auszudrucken.
Wie funktioniert das, nur aus Neugier?
Antwort1
Das Terminalfenster ist lediglich eine Emulation eines "Dumb Terminal – Wikipedia", das nichts anderes kann, als Zeichenfolgen anzuzeigen, üblicherweise 24 Zeilen mit je 80 ASCII-Zeichen, wobei neue Zeichen nur am Ende der letzten Zeile hinzugefügt werden. (Denken Sie an eine Schreibmaschine.)
Die Terminals wurden nach und nach „intelligenter“ und ermöglichten es beispielsweise, den Cursor an eine bestimmte Stelle zu bewegen, Zeilen einzufügen, das nächste Zeichen in Farbe anzuzeigen usw.
Aber jeder Hersteller hat es auf seine eigene Weise gemacht, und es gab keinen einheitlichen Standard, sodass jedes Programm das Wissen über die spezifische Hardware, mit der es verwendet wurde, in sich trug. (Ich erinnere mich, dass mir auf einer Messe Anfang der 1980er Jahre ein Datenbankschnittstellenprogramm gezeigt wurde. Der Moderator gab eine Liste von etwa einem Dutzend gängiger Terminaltypen, mit denen es umgehen konnte, und sagte, dass sie ihm für nur $X beibringen könnten, mit jedem anderen Typ umzugehen, den wir in unserer Firma hatten.)
Inzwischen hatte BSD dieTermcap – WikipediaBibliothek für ihr UNIX-System. Sie spezifizierte eine textbasierte Datenbank, die eine Reihe von Standardfunktionen für jeden Terminaltyp definierte, und stellte eine C-Bibliothek bereit, die diese Datenbank verwendete, um das entsprechende Format der Zeichenfolge zu bestimmen, die basierend auf der Umgebungsvariable an das Terminal gesendet werden sollte TERM
. Natürlich unterstützten nicht alle Terminals alle Funktionen, aber das war in Ordnung, da Programme nur die verfügbaren Funktionen verwenden konnten (wenn ein Terminal beispielsweise keine direkte Adressierung hatte, musste es sich möglicherweise eine Zeile nach oben/unten und eine Position nach links/rechts bewegen).
termcap.small · freebsd/freebsd · GitHubzeigt einen Beispiel-Termcap-Eintrag für ein VT100-Terminal:
vt100|dec-vt100|vt100-am|vt100am|dec vt100:\
:do=2\E[B:co#80:li#24:cl=50\E[H\E[J:sf=2*\ED:\
:le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
:ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:\
:is=\E>\E[?1;3;4;5l\E[?7;8h\E[1;24r\E[24;1H:\
:if=/usr/share/tabset/vt100:nw=2\EE:ho=\E[H:\
:as=2\E(0:ae=2\E(B:\
:ac=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||:\
:rs=\E>\E[?1;3;4;5l\E[?7;8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=\177:\
:k0=\EOy:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\EOt:\
:k6=\EOu:k7=\EOv:k8=\EOl:k9=\EOw:k;=\EOx:@8=\EOM:\
:K1=\EOq:K2=\EOr:K3=\EOs:K4=\EOp:K5=\EOn:pt:sr=2*\EM:xn:\
:sc=2\E7:rc=2\E8:cs=5\E[%i%d;%dr:UP=2\E[%dA:DO=2\E[%dB:RI=2\E[%dC:\
:LE=2\E[%dD:ct=2\E[3g:st=2\EH:ta=^I:ms:bl=^G:cr=^M:eo:it#8:\
:RA=\E[?7l:SA=\E[?7h:po=\E[5i:pf=\E[4i:
SpäterFlüche – WikipediaDie Bibliothek wurde entwickelt, um den Prozess zu vereinfachen. Sie bietet Funktionen zum Generieren der entsprechenden Codes mit angegebenen Werten. Jedes Programm könnte einfach etwas wie sagen tgoto(capabilities, column, row)
, und die Bibliothek würde den Terminaltyp in der TERM
Umgebungsvariable finden, die Funktionen für diesen bestimmten Typ in der Termcap-Datenbank nachschlagen und eine Zeichenfolge mit den entsprechenden Terminalbefehlen zum Bewegen des Cursors an die angegebene Position generieren.
termcap(3) - OpenBSD-Handbuchseitenzeigt Deklarationen einiger Libcurses-Funktionen:
#include <curses.h>
#include <term.h>
extern char PC;
extern char * UP;
extern char * BC;
extern short ospeed;
int tgetent(char *bp, const char *name);
int tgetflag(char *id);
int tgetnum(char *id);
char *tgetstr(char *id, char **area);
char *tgoto(const char *cap, int col, int row);
int tputs(const char *str, int affcnt, int (*putc)(int));
Programme wievi - Wikipedia, verwendete diese Bibliotheken, um einen Editor bereitzustellen, der auf jedem Terminal mit adressierbarem Bildschirm funktionierte. Für einen neuen Terminaltyp musste nur der Termcap-Eintrag definiert werden, und er funktionierte automatisch und sofort mit vi
jedem anderen Programm, das auf dieser Bibliothek basierte.
Schließlich termcap
wurde es durch eine verbesserte Version namens ersetzt terminfo
und curses
durch eine neue Version ersetzt ncurses
, aber die zugrunde liegenden Prinzipien blieben dieselben.
Beachten Sie, dass dies alles von der Fähigkeit von UNIX abhängt, ein über die Tastatur eingegebenes Zeichen zu lesenohneautomatisch auf dem Terminal angezeigt. Viele Betriebssysteme konnten das damals nicht. Manche akzeptierten die Eingabe vom Terminal erst, wenn eine ganze Zeile (oder sogar ein ganzer Bildschirm) eingegeben wurde.
Antwort2
Programme mit einer vollbildlichen textuellen Benutzeroberfläche (TUI) auf Unix-ähnlichen Betriebssystemen verwenden eine Cursorpositionierungsbibliothek namens curses
.
Diese Bibliothek verwendete ursprünglich eine Terminalfunktionen-Datenbank namens , termcap
die später durch ein System namens ersetzt wurde terminfo
.
TUI-Apps, die in einem GUI-Desktop angezeigt werden, nutzen Signale zur Größenanpassung des Fensters wiesigwinch