[技巧] 用 VSCode Terminal 連到遠端 Linux 但是有些組合鍵按不了?
如果你想用 VSCode Terminal 取代傳統用 PuTTY, MobaXterm 等 SSH 工具,第一個會遇到的障礙就是像是 Ctrl + K, Ctrl + E, Ctrl + V 有些組合鍵都沒辦法用。
"不能用"的原因可能有幾個:
- VSCode 傳送的 ASCII code 和 PuTTY 傳送的 ASCII code 不一樣
- VSCode 的組合鍵被 VSCode 上面的東西給搶先攔截了 (像是 Ctrl + E 會開啟 Go to file... 功能)
- 再來也有可能不是 VSCode 的問題,是 stty 或 SSH 端的程式沒設置好
按鍵傳送的 ASCII Code 和想像的不一樣
像是我們開 PuTTY 的設定 Terminal -> Keyboard 就會發現裡面有設置像是 Backspace 按下去應該會送出什麼 ASCII code:
預設是送出 127 (^?, 0x7f),但是有可能會出於各種因素設置到 Control-H (也就是 Ctrl + H, ^H, 8, 0x8)。但 VSCode 預設設定是右邊的。所以如果你習慣的設定剛好就和 VSCode 預設不一樣的話就會發現 VSCode terminal 中 backspace 按下去怎麼不是刪除文字而是會冒出一些怪怪的符號、或是一些不該有的行為。
按鍵被 VSCode 搶先攔截
就算你在 VSCode terminal 按 Ctrl + E,VSCode Go to file... 的功能就會搶先跳出來,terminal 根本沒有機會知道你按了什麼:
其他還有很多按鍵通通會觸發 VSCode 的功能。
別讓 VSCode 攔截按鍵
你可以在 settings.json 裡面用 "terminal.integrated.commandsToSkipShell" 來關閉哪些 VSCode commands 不要使用,記得在前面加上一個 "-" 字元,它自然就會把按鍵乖乖傳給 shell:
{
"terminal.integrated.commandsToSkipShell": [
"-editor.action.toggleTabFocusMode", // Ctrl + M
"-workbench.action.quickOpen", // Ctrl + E
"-workbench.action.quickOpenView", // Ctrl + Q
"-workbench.action.terminal.focusFind", // Ctrl + F
"-workbench.action.terminal.paste", // Ctrl + V
"-workbench.action.togglePanel", // Ctrl + J
]
}
這些 commands ID 不難查,你只要去 Keyboard Shortcuts 的頁面 (Ctrl + K, Ctrl + S) 先輸入例如 "Ctrl + E" 再找想關掉的 command 點右鍵就可以複製 ID 了。
Ctrl + K 因為對於 VSCode 來說比較特別,就像 Visual Studio 一樣有特殊功能,不過我們還是可以在 settings.json 裡面用這樣的設定讓你只有在 terminal 做事時乖乖傳給 shell:
{
"terminal.integrated.allowChords": false // Ctrl + K
}
但是像我還是比較喜歡直接按 Ctrl + V 把指令貼到 terminal 上,所以後來 Ctrl + V 的設定我還是把他註解掉了。
進階: 設定和 PuTTY 一樣的 ASCII Code
假設今天我們想要設置 Ctrl + Backspace 好了。
我們可以先開 PuTTY 或其他你喜歡用的 SSH program 用 showkey -a 來知道按下 Ctrl + Backspace 會傳送什麼 ASCII Code:
如果這時候開 VSCode terminal 也同樣用 showkey -a 按 Ctrl + Backspace 會發現他傳送不一樣的 ASCII code:
這時我們只要在 VSCode 按 Ctrl + Shift + P 輸入 Open Keyboard Shortcuts (JSON) 按 Enter 打開 keybindings.json,在 "text" 後面把 0x7f 改成 \u007f:
[
{
"key": "ctrl+backspace",
"command": "workbench.action.terminal.sendSequence",
"args": {
"text": "\u007f"
},
"when": "terminalFocus"
},
]
我們再回 VSCode terminal 再試一次:
看到和 PuTTY 打出一樣的 ASCII code 就對啦。
那如果你看到 showkey -a 按某個鍵就吐出兩三行的 ASCII code 怎麼辦? 那就是把很多 \u00xx 串在一起,例如像這樣:
[
{
"key": "ctrl+backspace",
"command": "workbench.action.terminal.sendSequence",
"args": {
"text": "\u001b\u007f"
},
"when": "terminalFocus"
},
{
"key": "ctrl+left",
"command": "workbench.action.terminal.sendSequence",
"args": {
"text": "\u001bb"
},
"when": "terminalFocus"
},
{
"key": "ctrl+right",
"command": "workbench.action.terminal.sendSequence",
"args": {
"text": "\u001bf"
},
"when": "terminalFocus"
}
]
如果某個 ASCII code 剛好是純英文數字的話其實也可以直接打那個字,例如 "\u001bb" 就是 "\u001b" + "b"。
我們記得要加上 "when": "terminalFocus",就是告訴 VSCode 只有在 terminal 中才會這樣做,不要影響到沒在使用 terminal 時的按鍵。
有興趣看更多細節的話可以參考我當初搜尋的文章或教學:
- https://github.com/Microsoft/vscode/issues/64972
- https://code.visualstudio.com/docs/editor/integrated-terminal#_send-text-from-a-keybinding
- https://superuser.com/questions/248517/show-keys-pressed-in-linux/921637#921637
其他 Terminal 好用的鍵盤設置
這個我是在這篇 Mastering VS Code's Terminal 看到的,按 Ctrl + Shift + M (用 maximize 來記) 就可以切換最大化/還原 terminal 視窗,尤其是 VSCode 重開後第一次連進去 tmux 按兩下 Ctrl + Shift + M 就可以刷新 render 的問題:
[
{
"key": "ctrl+shift+m",
"command": "workbench.action.toggleMaximizedPanel"
}
]
非 VSCode 的問題
像是公司就有一個 script 要給全部的 R&D 去 source,但是裡面就寫了客製化的 stty,導致我在 vim 按 Backspace 就會產生奇怪的 characters。後來就查到用 stty sane 其實就解決了,和用什麼 VSCode 還是 PuTTY 連進去沒有關係。
其他時候甚至有可能用一些 bind/bindkey 來做到一些事,所以如果上面 showkey -a 那招發現 ASCII code 都一樣卻還不是你預期的,就要檢查一下你用的 program 是不是有吃一些特殊設定。像是 tmux 就可以設定是 vim 還是 emacs mode,當初沒設定他就給我預設一個 mode 害我以為是 VSCode 的問題。
結語
因為 VSCode 重點不是用 terminal,是享受 VSCode 本身的功能,所以他設計就希望按鍵是拿去操控 GUI 的,但是他也夠 flexible 可以客製化各種按鍵的行為。
留言
發佈留言