终端 Shell 集成
Visual Studio Code 能够与常见的 shell 集成,从而让终端能更多地了解 shell 内部实际发生的事情。这些额外信息启用了一些有用的功能,例如工作目录检测和命令检测、装饰器以及命令导航。
支持的 shell
- Linux/macOS: bash、fish、pwsh、zsh
- Windows: Git Bash、pwsh
安装
自动脚本注入
默认情况下,shell 集成脚本应在从 VS Code 启动的受支持的 shell 上自动激活。这是通过在 shell 会话启动时注入参数和/或环境变量来完成的。可以通过将 terminal.integrated.shellIntegration.enabled 设置为 false
来禁用此自动注入。
这种标准的、简便的方法不适用于某些高级用例,例如在子 shell 中、通过常规的 ssh
会话(未使用 Remote - SSH 扩展时)或对于某些复杂的 shell 设置。对于这些情况,推荐的启用 shell 集成的方法是手动安装。
注意:自动注入可能不适用于旧版本的 shell,例如,旧版本的 fish 不支持
$XDG_DATA_DIRS
环境变量,而注入正是通过这个变量工作的。你可能仍然可以通过手动安装来使其工作。
手动安装
要手动安装 shell 集成,VS Code shell 集成脚本需要在你的 shell 初始化期间运行。具体位置和方法取决于你使用的 shell 和操作系统。使用手动安装时,建议将 terminal.integrated.shellIntegration.enabled 设置为 false
,但这并非强制性要求。
提示: 当使用 Insiders 版本时,请将下面的
code
替换为code-insiders
。
bash
将以下内容添加到你的 ~/.bashrc
文件中。在 bash 中运行 code ~/.bashrc
可以在 VS Code 中打开该文件。
[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path bash)"
fish
将以下内容添加到你的 config.fish
文件中。在 fish 中运行 code $__fish_config_dir/config.fish
可以在 VS Code 中打开该文件。
string match -q "$TERM_PROGRAM" "vscode"
and . (code --locate-shell-integration-path fish)
pwsh
将以下内容添加到你的PowerShell 配置文件中。在 pwsh 中运行 code $Profile
可以在 VS Code 中打开该文件。
if ($env:TERM_PROGRAM -eq "vscode") { . "$(code --locate-shell-integration-path pwsh)" }
zsh
将以下内容添加到你的 ~/.zshrc
文件中。在 zsh 中运行 code ~/.zshrc
可以在 VS Code 中打开该文件。
[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path zsh)"
Git Bash
将以下内容添加到你的 ~/.bashrc
文件中。在 Git Bash 中运行 code ~/.bashrc
可以在 VS Code 中打开该文件。
[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path bash)"
可移植性与性能
如果 code
在 $PATH
中,上述 shell 集成安装是跨平台的,并与任何安装类型兼容。然而,这种推荐的方法会启动 Node.js 来获取脚本路径,导致 shell 启动时有轻微的延迟。为了减少这种延迟,可以通过提前解析路径并将其直接添加到你的初始化脚本中来内联上述脚本。
# Output the executable's path first:
code --locate-shell-integration-path bash
# Add the result of the above to the source statement:
[[ "$TERM_PROGRAM" == "vscode" ]] && . "/path/to/shell/integration/script.sh"
Shell 集成质量
使用 shell 集成时,它有一个与之关联的“质量”,用于声明其功能。这些质量由 shell 集成脚本的行为方式决定。
- 无 (None):没有激活 shell 集成。
- 丰富 (Rich):shell 集成已激活,且命令检测以理想方式工作。
- 基本 (Basic):shell 集成已激活,但命令检测可能不支持所有功能。例如,可以检测到命令运行的位置,但无法检测其退出状态。
要查看 shell 集成质量,请将鼠标悬停在终端选项卡上。或者,在悬停提示中选择显示详情 (Show Details)以查看更详细的信息。
命令装饰器和概览标尺
shell 集成所实现的功能之一是能够获取在终端中运行的命令的退出代码。利用这些信息,在行的左侧会添加装饰器,以指示命令是成功还是失败。这些装饰器也会像在编辑器中一样,显示在滚动条中新增的概览标尺上。
可以与装饰器进行交互,以执行一些上下文相关的操作,例如重新运行命令。
命令和概览标尺的装饰器可以通过 terminal.integrated.shellIntegration.decorationsEnabled 设置进行配置。
命令导航
由 shell 集成检测到的命令会被用于命令导航功能(Ctrl/Cmd+Up, Ctrl/Cmd+Down),从而提供更可靠的命令位置。此功能允许在命令之间快速导航并选择其输出。要从当前位置选择到命令,你还可以按住 Shift,然后按 Shift+Ctrl/Cmd+Up 和 Shift+Ctrl/Cmd+Down。
命令指南
命令指南是当鼠标悬停在一个命令及其输出上时,旁边显示的一个条形。这有助于更快地识别命令,也是验证 shell 集成是否正常工作的一种方式。
你可以使用颜色主题来自定义命令指南的颜色。要切换命令指南的显示,请配置 terminal.integrated.shellIntegration.showCommandGuide 设置。
粘性滚动
粘性滚动功能会将部分显示在终端顶部的命令“固定”住,这样可以更容易地看到输出属于哪个命令。点击粘性滚动组件将滚动到该命令在终端缓冲区中的位置。
此功能可以通过 terminal.integrated.stickyScroll.enabled 设置来启用。
快速修复
VS Code 会扫描命令的输出,并提供一个快速修复(Quick Fix)建议,其中包含用户接下来最可能想要执行的操作。
以下是一些内置的快速修复:
- 当检测到某个端口已被监听时,建议终止该进程并重新运行上一个命令。
- 当
git push
因未设置上游分支而失败时,建议设置上游分支并推送。 - 当一个
git
子命令因相似命令错误而失败时,建议使用相似的命令。 - 当
git push
结果中包含创建 GitHub PR 的建议时,建议打开该链接。 - 当 `General` 或 `cmd-not-found` PowerShell 反馈提供程序触发时,建议每个建议项。
快速修复功能还支持无障碍信号,以便在有快速修复可用时提供额外的反馈。
运行最近的命令
终端: 运行最近的命令 (Terminal: Run Recent Command) 命令会在一个快速选择框中显示来自各种来源的历史记录,提供与 shell 的反向搜索(Ctrl+R)类似的功能。这些来源包括当前会话的历史记录、此 shell 类型的先前会话历史记录以及通用的 shell 历史文件。
该命令的其他一些功能:
- 默认情况下,搜索模式是“连续搜索”,意味着搜索词必须完全匹配。搜索输入框右侧的按钮可以切换到模糊搜索。
- 在当前会话部分,快速选择框的右侧有一个剪贴板图标,点击它可以在编辑器中打开命令的输出。
- 快速选择框右侧的图钉操作可以将命令固定到列表顶部。
- 可以按住 Alt 键将文本写入终端而不运行它。
- 先前会话部分存储的历史记录数量由 terminal.integrated.shellIntegration.history 设置决定。
此命令的默认键盘快捷键是 Ctrl+Alt+R。但是,当无障碍模式开启时,快捷键会反转:Ctrl+R 运行最近的命令,而 Ctrl+Alt+R 将 Ctrl+R 发送到 shell。
当无障碍模式关闭时,可以使用以下键盘快捷键来切换这两个功能:
{
"key": "ctrl+r",
"command": "workbench.action.terminal.runRecentCommand",
"when": "terminalFocus"
},
{
"key": "ctrl+alt+r",
"command": "workbench.action.terminal.sendSequence",
"args": { "text": "\u0012"/*^R*/ },
"when": "terminalFocus"
}
转到最近的目录
与“运行最近的命令”功能类似,终端: 转到最近的目录 (Terminal: Go to Recent Directory) 命令会跟踪访问过的目录,并允许快速筛选和导航(cd
)到这些目录。可以按住 Alt 键将文本写入终端而不运行它。
此命令的默认键盘快捷键是 ⌘G (Windows、Linux 为 Ctrl+G),因为它的行为类似于编辑器中的转到行/列 (Go to Line/Column)命令。可以使用 Ctrl+Alt+G 将 Ctrl+G 发送到 shell。
当前工作目录检测
Shell 集成会告诉 VS Code shell 的当前工作目录是什么。在 Windows 上,如果不通过正则表达式检测提示符,是无法获取此信息的;而在 macOS 和 Linux 上,则需要轮询,这对性能不利。
这带来的最大功能之一是增强了终端中链接的解析。以链接 package.json
为例,当 shell 集成被禁用时激活该链接,如果工作区中有多个 package.json
文件,它会打开一个搜索快速选择框,并将 package.json
作为筛选条件。然而,当 shell 集成启用时,它会直接打开当前文件夹中的 package.json
文件,因为当前位置是已知的。这使得例如 ls
的输出能够可靠地打开正确的文件。
当前工作目录还用于在终端选项卡、“运行最近的命令”快速选择框中显示目录,以及用于 "terminal.integrated.splitCwd": "inherited"
功能。
扩展的 PowerShell 键盘快捷键
Windows 的控制台 API 允许比 Linux/macOS 终端更多的键盘快捷键。由于 VS Code 的终端即使在 Windows 上也模拟后者,因此有些 PowerShell 键盘快捷键(如 Ctrl+Space)由于缺少 VT 编码而无法通过标准方式实现。Shell 集成允许 VS Code 附加自定义键盘快捷键,以向 PowerShell 发送一个特殊序列,然后在 shell 集成脚本中处理该序列并转发给正确的按键处理程序。
启用 shell 集成后,以下键盘快捷键应在 PowerShell 中生效:
- Ctrl+Space:仅在 Windows 上默认为
MenuComplete
- Alt+Space:在所有平台上默认为
SetMark
- Shift+Enter:在所有平台上默认为
AddLine
- Shift+End:在所有平台上默认为
SelectLine
- Shift+Home:在所有平台上默认为
SelectBackwardsLine
增强的无障碍性
Shell 集成提供给 VS Code 的信息用于改善终端的无障碍性。一些增强功能的例子包括:
- 在无障碍缓冲区中通过检测到的命令进行导航(⌥F2 (Windows 为 Alt+F2, Linux 为 Shift+Alt+F2))
- 当命令失败时会播放声音提示。
- 底层的文本框同步,使得使用箭头键和退格键的行为更加正确。
智能感知 (预览)
终端中的智能感知(IntelliSense)使你能够接收文件、文件夹、命令、命令参数和选项的建议。此功能由 shell 集成 terminal.integrated.shellIntegration.enable 提供支持,并可以通过 terminal.integrated.suggest.enabled 启用。
VS Code 从 Fig 规范中获取命令,并根据 $PATH
验证每个 shell 的内置函数(适用于 pwsh
、bash
、zsh
和 fish
),以确保它们存在。在 Windows 上,你可以使用 terminal.integrated.suggest.windowsExecutableExtensions 设置来配置特定的可执行文件集。
键盘导航
默认情况下,Tab 键插入建议。一旦在列表中进行了导航,Enter 键也会同样插入建议。你可以使用 terminal.integrated.suggest.selectionMode 设置来配置此行为。
要在接受建议时既插入又在终端中运行它,请配置 terminal.integrated.suggest.runOnEnter。
智能感知可以通过 ⌃Space (Windows, Linux Ctrl+Space) 手动触发,也可以在输入时触发,后者可以通过 terminal.integrated.suggest.quickSuggestions 禁用。当输入特定字符(例如 /
)时也可以触发智能感知,这可以通过 terminal.integrated.suggest.suggestOnTriggerCharacters
进行配置。
当 shell 提供内联补全时,VS Code 会将其作为列表中的第一个补全项显示。你可以使用 terminal.integrated.suggest.inlineSuggestion 设置来进一步配置此行为。
设置 terminal.integrated.suggest.showStatusBar 控制是否在列表底部显示状态栏。该状态栏提供了解更多(⇧⌘L (Windows, Linux Ctrl+Shift+L))、插入(Tab)和配置(⇧⌘, (Windows, Linux Ctrl+Shift+,))等操作。在你初次使用智能感知功能时,了解更多操作会高亮显示,以提高可发现性。
建议控件可以显示关于建议的额外详细信息。你可以使用 ⌃Space (Windows, Linux Ctrl+Space) 切换这些详细信息的可见性。屏幕阅读器用户可以使用 ⌃⌥Space (Windows, Linux Ctrl+Alt+Space) 聚焦到详细信息控件以听取其朗读。
全局补全缓存
为了提高性能,VS Code 会为特定的 shell 积极缓存全局变量。当你对添加命令的 shell 启动逻辑进行更改,并且这些更改没有被自动检测到时,请使用终端:清除建议缓存的全局变量 (Terminal: Clear Suggest Cached Globals) 命令(terminal.integrated.suggest.clearCachedGlobals
)手动刷新缓存。
支持的转义序列
VS Code 支持几种自定义的转义序列。
VS Code 自定义序列 'OSC 633 ; ... ST'
VS Code 有一套自定义的转义序列,旨在在 VS Code 的终端中运行时启用 shell 集成功能。这些序列被内置脚本使用,但也可以被任何能够向终端发送序列的应用程序使用,例如 Julia 扩展就使用这些序列来支持 Julia REPL 中的 shell 集成。
这些序列应该会被其他终端忽略,但除非其他终端最终更广泛地采用这些序列,否则建议在写入它们之前检查 $TERM_PROGRAM
是否为 vscode
。
-
OSC 633 ; A ST
:标记提示符开始。 -
OSC 633 ; B ST
:标记提示符结束。 -
OSC 633 ; C ST
:标记预执行。 -
OSC 633 ; D [; <exitcode>] ST
:标记执行完成,并可附带一个可选的退出代码。 -
OSC 633 ; E ; <commandline> [; <nonce] ST
:显式设置命令行,并可附带一个可选的 nonce。E 序列允许终端可靠地获取由 shell 解释的确切命令行。如果未指定此序列,终端可能会退而求其次,使用 A、B 和 C 序列来获取命令,或者如果不可靠则完全禁用检测。
可选的 nonce 可用于验证序列是否来自 shell 集成脚本,以防止命令欺骗。当 nonce 验证成功时,在使用命令之前的一些保护措施将被移除,以改善用户体验。
命令行可以使用
\xAB
格式转义 ASCII 字符,其中 AB 是字符代码的十六进制表示(不区分大小写),并使用\\
转义\
字符。必须转义分号(0x3b
)和 0x20 及以下的字符,这对于换行符和分号尤为重要。一些示例
"\" -> "\\" "\n" -> "\x0a" ";" -> "\x3b"
-
OSC 633 ; P ; <Property>=<Value> ST
:在终端上设置一个属性,只有已知的属性会被处理。已知属性
Cwd
:向终端报告当前工作目录。IsWindows
:指示终端是否正在使用 Windows 后端,如 winpty 或 conpty。这可以用于启用额外的启发式方法,因为 shell 集成序列的位置不保证是正确的。有效值为True
和False
。HasRichCommandDetection
:指示终端是否具有丰富的命令检测能力。当 shell 集成脚本以 VS Code 期望的理想方式运行时,此属性设置为True
,具体来说,序列应按A, B, E, C, D
的顺序出现在预期的位置。
Final Term shell 集成
VS Code 支持 Final Term 的 shell 集成序列,这使得非 VS Code 的 shell 集成脚本也能在 VS Code 中工作。这会导致体验有所下降,因为它不像 OSC 633
那样支持那么多功能。以下是支持的具体序列:
OSC 133 ; A ST
:标记提示符开始。OSC 133 ; B ST
:标记提示符结束。OSC 133 ; C ST
:标记预执行。OSC 133 ; D [; <exitcode>] ST
:标记执行完成,并可附带一个可选的退出代码。
iTerm2 shell 集成
支持以下由 iTerm2 首创的序列:
-
OSC 1337 ; CurrentDir=<Cwd> S
:设置终端的当前工作目录,类似于OSC 633 ; P ; Cwd=<Cwd> ST
。 -
OSC 1337 ; SetMark ST
:在触发它的行的左侧添加一个标记,并在滚动条上添加一个注释。这些标记与命令导航集成,使其可以通过 ⌘↑ (Windows, Linux Ctrl+Up) 和 ⌘↓ (Windows, Linux Ctrl+Down) 轻松导航。
常见问题
自动注入在什么情况下不起作用?
有几种情况下自动注入不起作用,以下是一些常见情况:
-
$PROMPT_COMMAND
的格式不受支持,将其更改为指向单个函数是解决此问题的一个简单方法。例如:prompt() { printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}" } PROMPT_COMMAND=prompt
-
一些 shell 插件可能会在初始化时通过取消设置
$VSCODE_SHELL_INTEGRATION
来明确禁用 VS Code 的 shell 集成。
为什么在禁用该功能时命令装饰器仍然显示?
这很可能是因为你的系统上安装了另一个终端的 shell 集成,而 VS Code 能够理解它。如果你不想要任何装饰器,可以使用以下设置隐藏它们:
"terminal.integrated.shellIntegration.decorationsEnabled": never
或者,你可以从你的 shell rc/启动脚本中移除 shell 集成脚本,但你将无法使用命令感知功能,如命令导航。
为什么在 Windows 上命令装饰器会跳动?
Windows 使用一个名为 ConPTY 的模拟伪终端(pty)后端。它的工作方式与常规 pty 有些不同,因为它需要保持与 Windows 控制台 API 的兼容性。其中一个影响是,pty 以特殊方式处理渲染,导致用于识别终端缓冲区中命令的 shell 集成序列可能会错位。当命令跳动时,通常是在命令运行后,VS Code 的启发式算法启动以改善命令装饰器的位置。