最近、vim のユーザー インターフェイスがどのように動作するのか疑問に思っていました。vim を起動すると、単にテキストを印刷して何か入力するように要求し、入力が完了すると下に別のコマンド ラインを印刷するのではなく、ターミナル ウィンドウ全体を占有します。
単なる好奇心ですが、これはどのように機能するのでしょうか?
答え1
ターミナルウィンドウは単に「ダム端末 - Wikipedia」は、文字列を表示することしかできず、伝統的には 24 行の 80 ASCII 文字が表示され、新しい文字は最後の行の末尾にのみ追加されます (タイプライターを想像してください)。
端末は徐々に「スマート」になり、カーソルを特定の位置に移動したり、行を挿入したり、次の文字を色で表示したりする機能が追加されました。
しかし、各メーカーが独自の方法で実行しており、単一の標準は存在しなかったため、すべてのプログラムには、使用されている特定のハードウェアに関する知識が組み込まれていました。(1980 年代初頭の展示会でデータベース インターフェイス プログラムを見せられたことを覚えています。プレゼンターは、そのプログラムが操作できる一般的な端末の種類を 12 種類ほどリストし、わずか $X で、会社にある他の種類の端末も処理できるようにプログラムに教えることができると言いました。)
一方、BSDはTermcap - WikipediaUNIX システム用のライブラリです。これは、各タイプの端末の標準機能のセットを定義するテキストベースのデータベースを指定し、環境変数に基づいて端末に送信する文字列の適切な形式を決定するためにこのデータベースを使用する C ライブラリを提供しましたTERM
。もちろん、すべての端末がすべての機能をサポートしているわけではありませんが、プログラムは利用可能な機能のみを使用するように認識するので問題ありません (たとえば、端末に直接アドレス指定がない場合、1 行上/下に移動したり、1 位置左/右に移動したりする可能性があります)。
termcap.small · freebsd/freebsd · GitHubvt100 端末の 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:
その後、呪い - Wikipediaライブラリは、指定された値で適切なコードを生成する関数を提供することで、プロセスを簡素化するために開発されました。任意のプログラムで のように記述するだけ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));
プログラム、例えば6 - Wikipediaは、これらのライブラリを使用して、アドレス指定可能な画面を持つ任意の端末で動作するエディタを提供しました。新しいタイプの端末では、termcap エントリを定義するだけで、vi
そのライブラリに基づく他のプログラムと自動的に、そして即座に動作しました。
最終的に は とtermcap
呼ばれる改良版に置き換えられterminfo
、 はcurses
新しいバージョン に置き換えられましたncurses
が、基本的な原理は同じままでした。
これはすべて、キーボードから入力された文字を読み取るUNIXの機能に依存していることに注意してください。それなし自動的に端末に表示します。当時の多くのオペレーティング システムではこれができませんでした。行全体 (または画面全体) が入力されるまで、端末からの入力を受け付けないオペレーティング システムもありました。
答え2
Unix 系オペレーティング システム上のフルスクリーン テキスト ユーザー インターフェイス (TUI) を備えたプログラムは、と呼ばれるカーソル配置ライブラリを使用しますcurses
。
このライブラリは当初、 と呼ばれる端末機能データベースを使用していましたが、termcap
これは後に と呼ばれるシステムに置き換えられましたterminfo
。
GUIデスクトップでウィンドウ表示されるTUIアプリは、次のようなウィンドウサイズ変更シグナルを利用する。sigwinch