0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ghostty + SSH + Vimで `Ctrl-[` がundoとして働くのは何故か

0
Posted at

GhosttyからSSH接続した先でVimを使ってテキスト編集していると、

  • 挿入モードで文字入力して
  • ノーマルモードに戻ることを期待してCtrl-[ 押下すると
  • 挿入した文字列がすべて取り消される

問題に遭遇しました。
これが生じる環境は限られています。

  • クライアント: macOS + Ghostty
  • 接続方法: ssh で計算機Aに接続
    • なお、計算機Aは相当古い
  • エディタ: Vim
    • 計算機Aにインストールされていて、バージョンが古い

異なる計算機に接続したり、接続方法を変更すると、この問題を生じません。

クライアント 接続先 Ctrl-[ の挙動
Ghostty(macOS) 計算機B Esc と同じ
macOS標準Terminal 計算機A Esc と同じ
MobaXterm(Windows) 計算機A Esc と同じ

Ghosttyと計算機Aの組み合わせ(だけ)が、期待した動作をしません。

送信されるキー列を確認する

この振る舞いを理解するために、Ctrl-[ がどのように扱われるかを調べます。

cat -v

を実行して、Ctrl-[ を押下すると、キー入力が(非表示文字を含めて)表示されます(Ctrl-C で終了)。
例えば、macOS標準Terminalでは、次のように表示されます。

^[

一方Ghosttyでは、次のように表示されます。

^[[91;5u

これは「拡張(エスケープ)シーケンス」(後述)と呼ばれるものです。

なお、どちらのターミナルでも Esc^[ です。

Vimからも確認します。Vimを起動して、

:echo getchar()

として、一文字タイプすると、そのASCIIコードが表示されます。Esc27 です。
ところが問題が生じる環境では、Ctrl-[ を押下すると、以下のように表示されました。

Already at oldest change

拡張シーケンスとは: Ctrl-[Esc を区別する

【参考】Comprehensive keyboard handling in terminals

Ghosttyは、 Ctrl-[ を従来の Esc 文字ではなく、拡張シーケンスとして送信しています。それが、

^[[91;5u

です。Esc 相当の ^[ の後ろに、 [91;5u が続きます。

従来の端末(例えば、macOS標準Terminal)では、EscCtrl-[ を区別しません。その上で動作するアプリケーション(ここではVim)は、 EscCtrl-[ を区別できません。どちらを使っても効果は同じです。
TabCtrl-i の関係も同様です。

拡張シーケンスは、これらを区別するために用意されました。Ghosttyは Ctrl-[Esc と区別するために、拡張シーケンスを送信する場合があります。

^[[91;5u の意味

^[[91;5u は、Ctrl-[ を表すCSI u 形式のキーシーケンスです。(CSI: Control Sequence Introducer)

ESC [ 91 ; 5 u

各部分の意味は次の通りです。

部分 意味
ESC [ CSIの開始
91 [ のASCII/Unicodeコードポイント(10進数)
5 Ctrl修飾キー
u CSI u 形式の終端

すなわち、

CSI 91;5u = Ctrl+[

です。

拡張シーケンス非対応のVimの動作を考察する

(新しい Vim は、拡張シーケンスに対応しています。)

Ghosttyから送信される

ESC [ 91 ; 5 u

は、拡張シーケンスに対応していない場合、以下のように解釈されます。

  • ESC: ノーマルモードに移行
  • [ 9 1 ;: 解釈に失敗(効力なし)
  • 5: カウンタ
  • u: undo

すなわち、ノーマルモードに移行して、5回 undoされます。冒頭で述べた例では文字入力はなかったことになり(undo 1回分)、さらにその前の4回分の操作が(あれば)取り消されます。

対処法: GhosttyでCtrl-[の拡張シーケンスを使わない

最も手軽な対処は、Ghostty側で拡張シーケンスを使わずに、 Ctrl-[Esc 文字として送ることです。
~/.config/ghostty/config に以下を追加します。設定を反映するためには、Ghosttyの再起動が必要です。

keybind = ctrl+[=text:\x1b

(16進数 1b は、10進数の 27 です; Esc のASCIIコード。)

まとめ

拡張シーケンスが策定されていて、Ghosttyはこれを積極的に実装しています。古い環境へのsshでは、拡張シーケンスが意図しない動作を引き起こすことがあります。

現時点では、Ctrl-[Esc と区別するメリットは乏しいので、 Ctrl-[text:\x1b に割り当てることにします。

同様に、Ctrl-iTab として利用する場合は、以下の設定も追加します。

keybind = ctrl+i=text:\x09

Ctrl-i を表すCSI u 形式のキーシーケンスは ^[[105;5u です。

部分 意味
ESC [ CSIの開始
105 i のASCII/Unicodeコードポイント(10進数)
5 Ctrl修飾キー
u CSI u 形式の終端
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?