Linux端末で \e[H\e[2J ANSI エスケープシーケンスを解釈するには?

Linux端末で \e[H\e[2J ANSI エスケープシーケンスを解釈するには?

StackOverflowに質問をもう一度投稿しましたが、回答がなく、賞金を追加しましたが効果がありません(ただ賞金を削除しました)。私の考えでは、ここの人々が何が起こっているのかをよりよく知ることができると思います。

私のJavaScriptライブラリのためのより良いANSIエスケープコードソルバーを開発していますが、コマンドの処理に問題がありますtopscript端末出力をファイルにダンプするコマンドを使用)。

代替画面を使用するMacOSのサンプルファイルがありますESC [ ? 1049 hlここに録音してください

問題は、コマンドのLinuxバージョンがtop代替画面のみを使用しないことです。\e[H\e[2J順序は1,1に移動して画面を消去することです。私の理解では、実際にこのコマンドの前に端末に印刷されたすべての内容を消去する必要があります。これが私がパーサー/インタープリターでやっていることです。しかし、Linux端末はそうではありません(私はXFce端末を使用しています)。何とか画面の一部を消去してページを下にスクロールします。

それで、私の質問は、\e[H\e[2JLinuxターミナルのようにレンダリングするために最上位のコマンド(シーケンス)を処理する正確なステップ(アルゴリズム)は何ですか?私の端末に表示されるセッション出力として文字列が必要です。

以下はスクリプトコマンドの出力例です。https://jcubic.pl/screen_dump_linux_top.txt

テストコードがありますコードペン:

次のコードを使用してください。

$.terminal.format($.terminal.overtyping($.terminal.from_ansi(text)));

Linuxでtopコマンドの出力を見てください。以前は、コマンドの出力は表示されません。すべてを印刷するmacOSファイルと比較します(実際の端末は、メイン画面に戻すときに代替画面を印刷しないことを知っていますが、その出力をそこに入れることにしました。おそらくトグルオプションを追加したかもしれません)。

端末エミュレータのソースコードを確認できることを知っていますが、単にこれについて尋ねるよりも時間がかかります。

答え1

\e[Hカーソルをホームページ(左上)に移動して\e[2J画面を消去します(よく見る部分ですが、後ろにスクロールする部分ではありません)。

多くの端末エミュレータでは、\e[2J画面上でよく見られる部分は単にその場で消去されます。結果は次のとおりです。いくつかの出力(seq 100テスト目的など)を生成するコマンドを実行してから実行すると、前のプログラムtop出力の先頭はスクロールバックバッファに残りますが、出力の終わりは永久に失われます。

この非論理的な動作を解決するために、一部の端末エミュレータ(Xfce端末で使用されるVTEウィジェットを含む)は動作を修正しました\e[2J。つまり、画面をスクロールバックバッファにスクロールします。 「一般領域」の結果は同じです。空の画面が表示されます。スクロールバックバッファの内容は間違いなくより意味があります。前のコマンドの出力全体が保持されます。

\e[3Jこれを行うには、これを使用してスクロールバックバッファを消去できます。これを送る後ろに \e[2Jそれ以外の場合は、1画面のデータがスクロールされます。 (これがまさにこのclearコマンドがすることです。)

それで、私の質問は、\e[H\e[2JLinuxターミナルのようにレンダリングするために最上位のコマンド(シーケンス)を処理する正確なステップ(アルゴリズム)は何ですか?

答えは次のとおりです。端末によって異なります。

答え2

しかし、Linux端末はそうではありません(私はXFce端末を使用しています)。何とか画面の一部を消去してページを下にスクロールします。

実際、echo -e "\033[H\033[2J"これはあなたが期待するものと正確に一致します。左上に移動して画面バッファの残りの部分を消去します。

下にスクロールするのは、画面バッファに端末よりも多くの行があるためです。

stty sizeどのくらいの行と列があるかを確認してください。それを変更してくださいstty rows X cols Y

答え3

私はこの問題を自分で解決したと思います。 XFce 端末のソースコードに ANSI エスケープコードに関する情報が見つかりません。 ANSIコードがどこで処理されるのかわかりません。

しかし、解決策は次のアルゴリズムです。

  1. コードがある場合は、[Hカーソル位置を保存してください。
  2. コードがあり、[2J前のコードがカーソルH位置に復元された場合。
  3. 1行前に移動し、xを0に移動します。
  4. y 場所を scroll_top として保存します。
  5. 次に、コードを書くたびに、[x;yHy[Hカーソル位置のオフセットとしてscroll_topを使用します。

これは多くの行を消去し、次の行が画面の上部に表示されるため、Linux端末よりもうまく機能します。 macOSのiTerm2には私に似たアルゴリズムがありますが、1 1の位置が端末ウィンドウの左上にあるようにウィンドウだけをスクロールします。

関連情報