xtermの拡張入力 と ANSIエスケープシーケンス
ESCの表現 → ^[, \e, 0x1b, 033
xterm の formatOtherKeysオプションの変換を網羅した elisp
Ctrl-Tab → u001b[27;5;9~
Ctrl-Shift-Tab → u001b[27;6;9~
Ctrl-( → u001b[27;6;40~
Ctrl-/ → u001b[27;5;47~
Ctrl-? → u001b[63;6u
Ctrl-. → 46;5u
Ctrl-> → 62;6u
code:modifyOtherKeys.el
(define-key input-decode-map "\e[46;5u" (kbd "C-."))
(define-key input-decode-map "\e[44;5u" (kbd "C-,"))
(define-key input-decode-map "\e[60;6u" (kbd "C-<"))
(define-key input-decode-map "\e[62;6u" (kbd "C->"))
(define-key input-decode-map "\e[59;5u" (kbd "C-;"))
(define-key input-decode-map "\e[40;6u" (kbd "C-("))
(define-key input-decode-map "\e[41;6u" (kbd "C-)")) ; Emacs では認識しないようだ
(define-key input-decode-map "\e[49;5u" (kbd "C-1"))
(define-key input-decode-map "\e[39;5u" (kbd "C-'"))
(define-key input-decode-map "\e[45;5u" (kbd "C--"))
(define-key input-decode-map "\e[43;6u" (kbd "C-+"))
(define-key input-decode-map "\e[61;5u" (kbd "C-="))
(define-key input-decode-map "\e[63;6u" (kbd "C-?"))
code:settings.json
{ "command": { "action": "sendInput", "input": "\u001b[27;5;9~" }, "keys": "ctrl+tab" },
{ "command": { "action": "sendInput", "input": "\u001b[27;6;9~" }, "keys": "ctrl+shift+tab" },
{ "command": { "action": "sendInput", "input": "\u001b[27;6;40~" }, "keys": "ctrl+(" },
{ "command": { "action": "sendInput", "input": "\u001b[59;5u" }, "keys": "ctrl+;" },
{ "command": { "action": "sendInput", "input": "\u001b[58;6u" }, "keys": "ctrl+:" },
{ "command": { "action": "sendInput", "input": "\u001b[46;5u" }, "keys": "ctrl+." },
{ "command": { "action": "sendInput", "input": "\u001b[62;6u" }, "keys": "ctrl+>" },
{ "command": { "action": "sendInput", "input": "\u001b[34;6u" }, "keys": "ctrl+\"" },
{ "command": { "action": "sendInput", "input": "\u001b[39;5u" }, "keys": "ctrl+'" },
{ "command": { "action": "sendInput", "input": "\u001b[63;6u" }, "keys": "ctrl+?" },
{ "command": { "action": "sendInput", "input": "\u001b[43;6u" }, "keys": "ctrl+shift+=" },
{ "command": { "action": "sendInput", "input": "\u001b[27;5;47~" }, "keys": "ctrl+/" },
{ "command": { "action": "sendInput", "input": "\u001b[27;5;88~" }, "keys": "ctrl+shift+x" },
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
^Xとか ^I って何を意味するのか?
もし端末がAlt / Meta 押下時に ^[(Esc)を送信するとき、^[^@ は Ctrl-Alt-Space を表す
xterm の SendsEscpace の項目を参照すること
infocmp / terminfo(5) の出力をみると、機能するキーエスケープを確認できるはず
infocmp xterm | fgrep '\E[1;2H' → KHOM とか。
KHOM は shift + Home を表す
^c は Ctrl-c(大文字小文字の区別なし)を表す
^ の後に続くのはアルファベットか @[\]^_ のいずれか。
対応する制御文字の数値コードは、印刷可能な文字(文字や句読点)の数値コードから64を引いたもの
64を引く → 基数2でビットを0にすることに相当
例えば ^[ は [ のコード数(91) から 64 を引く → 91 - 64 = 27 = Escの文字コード
^? は文字127を表す
Alt(UNIXの歴史的経緯によりMetaとも呼ばれる)と印字可能文字の組み合わせは「^[ + その文字」を送信する
ほとんどのFnや矢印キーは「エスケープシーケンス」を送信している
ただし、詳細はターミナル実装と設定内容による
Shift / Ctrl / Alt (Meta) のモディファイアは数値コードで指定する
エスケープシーケンスの後に ;数値 の形式で指定する
F5 はエスケープシーケンス^[[15~を送信するので ^[[15;2~ で Shift+F5 を意味する
カーソルキーは、^[[と文字XとモディファイアMの組み合わせは ^[[1MX
^[[1;3D = Alt+Left
^[[1;5C = Ctrl+Right
^[[1;3A = Alt+Up
^[^@ = Ctrl+Alt+@ = Escape Ctrl+@
ほとんどのターミナルでは Ctrl+Space は ^@ を送信する
よって、 ^[^@ = Ctrl+Alt+Space = Escape Ctrl+Space
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Ctrl+Shift をちゃんと認識させたいが…
~/.Xresources → xlib を使うアプリケーションの共通設定ファイル
編集後に xrdb ~/.Xresources コマンドが必要
ESC の後に [ が続くと CSI という機能になる
Control Sequece Introducer
CSI のフォーマット → CSI コードポイント;モディファイア u
コードポイント → Unicodeのコードポイントを10進数で
モディファイア → 以下から選択
None Shift Alt Alt+Shift Ctrl Ctrl+Shift Ctrl+Alt Ctrl+Alt+Shift
1 2 3 4 5 6 7 8
よって C-S-x をターミナル内のアプリに送信したければ → ESC[88;5u
code:Xresources
Ctrl ~Meta Shift <Key>x :string("\033[88;5u")
以下の回答によれば、 C-S-a は ESC[65;5u で良いらしいが、xterm でしか有効ではない?
WindowsTerminal ではどうも動かない
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
簡易まとめ
ターミナルエミュレータは古のvt100というハードウェアの仕様にのっとり、Ctrl-Shiftの押下を判別する方法は基本的には無い。 上記設定後に vim なら noremap <ESC>[49;5u :!echo C<CR> Emacs なら (define-key input-decode-map "\e[63;6u" (kbd "C-?")) などの設定でTUIでもGUIっぽいショートカットキーが使えるようになるはず。