類似 vim 的命令列 GUI

類似 vim 的命令列 GUI

最近,我一直想知道vim 的用戶界面是如何工作的,當你啟動它時,它會佔據整個終端窗口,而不僅僅是打印文本,可能需要你輸入一些內容,當它完成時打印下面的另一個命令行。

只是出於好奇,這是如何運作的?

答案1

終端機視窗只是“的模擬”啞終端 - 維基百科" 除了顯示字符行外什麼也做不了,傳統上是 24 行,每行 80 個 ASCII 字符,新字符僅添加在最後一行的末尾。(想想打字機。)

終端逐漸變得“智慧”,增加了將遊標移動到特定位置、插入行、以顏色顯示下一個字元等功能。

但每個製造商都以自己的方式做到這一點,並且沒有統一的標準,因此每個程式都會內建有關其所使用的特定硬體的知識。 (我記得在20 世紀80 年代初期的一次貿易展覽會上,有人向我展示了一個資料庫介面程式。演示者列出了它知道如何使用的十幾種常見終端類型,並表示只需花費X 美元,他們就可以教它來處理我們公司的任何其他類型。

同時,BSD 開發了Termcap - 維基百科UNIX 系統的函式庫。它指定了一個基於文字的資料庫,該資料庫為每種類型的終端定義了一組標準功能,並提供了一個 C 庫,該庫使用該資料庫根據環境變數確定發送到終端的字串的適當格式TERM。當然,並非所有終端都支援所有功能,但這沒關係,程式會知道只使用那些可用的功能(例如,如果終端沒有直接尋址,它可能會向上/向下移動一行並向左移動/右一個位置)。

termcap.small · freebsd/freebsd · GitHub顯示了 vt100 終端機的範例 termcap 條目:

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:

後來,一個詛咒 - 維基百科開發庫是為了簡化過程,提供產生具有指定值的適當程式碼的函數。任何程式都可以簡單地說類似 的內容tgoto(capabilities, column, row),庫將在TERM環境變數中尋找終端類型,在termcap 資料庫中尋找該特定類型的功能,並產生一個包含適當終端命令的字串,用於將遊標移至指定的位置位置。

termcap(3) - OpenBSD 手冊頁顯示一些 libcurses 函數的宣告:

#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));

程序,例如vi - 維基百科,使用這些庫提供了一個可以在任何具有可尋址螢幕的終端上運行的編輯器。一種新型終端只需要定義其 termcap 條目,並且它會自動、即時地與vi基於該程式庫的任何其他程式一起使用。

最終termcap被一個名為 的改進版本所取代terminfo,並被curses新版本所取代ncurses,但底層原理保持不變。

請注意,這一切都依賴 UNIX 讀取從鍵盤輸入的字元的能力沒有自動將其顯示在終端機上。當時的許多作業系統都無法做到這一點。有些甚至不會接受來自終端的輸入,直到輸入整行(甚至螢幕)。

答案2

類別 Unix 作業系統上具有全螢幕文字使用者介面 (TUI) 的程式使用名為curses.

該庫最初使用名為 的終端功能資料庫,termcap後來被名為 的系統所取代terminfo

在 GUI 桌面中開啟視窗的 TUI 應用程式利用視窗大小調整訊號,例如sigwinch

相關內容