终端Shell集成

Visual Studio Code 能够与常见的 shell 集成,使终端能够更好地理解 shell 内部实际发生的情况。这些额外的信息启用了一些有用的功能,例如 工作目录检测 和命令检测,装饰,以及 导航

支持的shell:

  • Linux/macOS: bash, fish, pwsh, zsh
  • Windows: 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)"

将以下内容添加到您的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文件中。在bash中运行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)"

可移植性与性能

上述的shell集成安装是跨平台的,并且如果code$PATH中,则与任何安装类型兼容。然而,这种推荐的方法会启动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集成功能之一是可以获取在终端内运行的命令的退出代码。利用这些信息,在行的左侧添加装饰以指示命令是否成功或失败。这些装饰也会出现在滚动条中相对较新的概览标尺中,就像在编辑器中一样。

蓝色圆圈出现在成功命令旁边,带有红色叉号的红色圆圈出现在失败命令旁边。圆圈的颜色出现在滚动条中

装饰物可以进行交互,以提供一些上下文操作,例如重新运行命令:

点击成功的命令装饰会显示一个包含以下项目的上下文菜单:复制输出、复制输出为HTML、重新运行命令以及这是如何工作的?

命令和概览标尺装饰可以通过terminal.integrated.shellIntegration.decorationsEnabled设置进行配置。

命令导航

通过shell集成检测到的命令会输入到命令导航功能中(Ctrl/Cmd+上Ctrl/Cmd+下),以提供更可靠的命令位置。此功能允许在命令之间快速导航并选择其输出。要从当前位置选择到命令,您还可以按住Shift,按下Shift+Ctrl/Cmd+上Shift+Ctrl/Cmd+下

命令指南

命令指南是一个在悬停时显示在命令及其输出旁边的栏。这有助于更快地识别命令,并且也是验证shell集成是否正常工作的一种方式。

终端截图,突出显示左侧的命令指南垂直条,以指示命令的边界。

您可以通过使用颜色主题来自定义命令指南的颜色。要切换命令指南,请配置terminal.integrated.shellIntegration.showCommandGuide设置。

粘性滚动

粘性滚动功能会将部分显示的命令“粘”在终端顶部,使得查看输出属于哪个命令变得更加容易。点击粘性滚动组件将滚动到终端缓冲区中命令的位置。

粘性滚动将在终端视口顶部显示命令

这可以通过terminal.integrated.stickyScroll.enabled设置来启用。

快速修复

VS Code 扫描命令的输出,并提供一个快速修复操作,这些操作很可能是用户接下来想要执行的操作。

运行 'git push --set-upstream' 将显示一个灯泡,打开下拉菜单,其中包含在 github.com 上打开新 PR 的选项

以下是一些内置的快速修复:

  • 当检测到某个端口已被监听时,建议终止该进程并重新运行之前的命令。
  • git push由于未设置上游而失败时,建议设置上游后进行推送。
  • git子命令因类似命令错误而失败时,建议使用类似的命令。
  • git push导致建议创建GitHub PR时,建议打开链接。
  • Generalcmd-not-found PowerShell反馈提供程序触发时,建议每个建议。

快速修复功能还支持无障碍信号,以便在快速修复可用时提供额外的反馈。

运行最近的命令

终端:运行最近的命令命令在快速选择中显示来自各种来源的历史记录,提供类似于 shell 的反向搜索功能(Ctrl+R)。这些来源包括当前会话的历史记录、此 shell 类型的先前会话历史记录以及常见的 shell 历史记录文件。

"运行最近命令"命令显示一个快速选择,其中包含之前运行的命令,可以像转到文件命令一样进行过滤

命令的其他一些功能:

  • 默认情况下,搜索模式为“连续搜索”,意味着搜索词必须完全匹配。搜索输入框右侧的按钮允许切换到模糊搜索。
  • 在当前会话部分,Quick Pick 的右侧有一个剪贴板图标,点击它将在编辑器中打开命令输出。
  • 快速选择右侧的固定操作可以将命令固定到列表的顶部。
  • 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"
}

转到最近的目录

类似于运行最近命令的功能,终端:转到最近目录命令会跟踪已访问的目录,并允许快速筛选和导航(cd)到这些目录。按住Alt可以将文本写入终端而不运行它。

此命令的默认快捷键是 ⌘G (Windows, Linux Ctrl+G),因为它的行为类似于编辑器中的转到行/列命令。可以通过 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上也模拟后者,因此由于缺乏VT编码,一些PowerShell键绑定无法使用标准方法实现,例如Ctrl+Space。Shell集成允许VS Code附加自定义键绑定,以发送特殊序列到PowerShell,然后在Shell集成脚本中处理并转发到适当的键处理程序。

当启用 shell 集成时,以下快捷键应在 PowerShell 中有效:

  • Ctrl+Space: 仅在Windows上默认为MenuComplete
  • Alt+Space: 在所有平台上默认为 SetMark
  • Shift+Enter: 在所有平台上默认为 AddLine
  • Shift+End: 在所有平台上默认为 SelectLine
  • Shift+Home: 在所有平台上默认为 SelectBackwardsLine

PowerShell 的实验性 IntelliSense

PowerShell 的实验性 IntelliSense 在输入 PowerShell 时显示完成列表,类似于编辑器的体验。在幕后,此功能由 PowerShell 会话的本机完成 API 提供支持,因此像变量这样的上下文感知完成是可用的。

PowerShell IntelliSense 显示补全选项,例如 Get-Alias、Get-ChildItem,例如在输入 Get- 时

您可以通过terminal.integrated.suggest.enabled设置启用实验性的PowerShell IntelliSense。

"terminal.integrated.suggest.enabled": true

注意: 此功能目前仅在Windows和macOS上可用。

Git 和 VS Code 自动补全

当启用实验性IntelliSense时,CLI的自动补全功能(如gitcodecode-insiders)默认开启。如果你的PowerShell配置文件已经启用了自动补全功能,你可能需要通过使用terminal.integrated.suggest.builtinCompletions设置来关闭这些功能。

增强的可访问性

Shell集成提供给VS Code的信息用于改进终端的可访问性。一些增强功能的例子包括:

  • 在可访问的缓冲区中导航检测到的命令 (⌥F2 (Windows Alt+F2, Linux Shift+Alt+F2))
  • 当命令失败时,会播放一个音频提示
  • 底层文本框同步,使得使用箭头和退格键的行为更加正确。

支持的转义序列

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 [; ] ST - 标记执行完成,可选择退出代码。

  • OSC 633 ; E ; [; - 显式设置命令行,带有可选的随机数。

    E序列允许终端可靠地获取由shell解释的确切命令行。当未指定此序列时,终端可能会回退使用A、B和C序列来获取命令,或者如果不可靠,则完全禁用检测。

    可选的nonce可用于验证序列是否来自shell集成脚本,以防止命令欺骗。当nonce验证成功时,使用命令前的一些保护措施将被移除,以改善用户体验。

    命令行可以使用\xAB格式转义ASCII字符,其中AB是字符代码的十六进制表示(不区分大小写),并使用\\转义\字符。必须转义分号(0x3b)和0x20及以下的字符,这对于换行符和分号尤为重要。

    一些示例:

    "\"  -> "\\"
    "\n" -> "\x0a"
    ";"  -> "\x3b"
    
  • OSC 633 ; P ; = ST - 在终端上设置一个属性,只有已知的属性会被处理。

    已知属性:

    • Cwd - Reports the current working directory to the terminal.
    • IsWindows - Indicates whether the terminal is using a Windows backend like winpty or conpty. This may be used to enable additional heuristics as the positioning of the shell integration sequences are not guaranteed to be correct. Valid values are True and False.

Final Term 终端集成

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 [; ] ST - 标记执行完成,可选择退出代码。

iTerm2 shell 集成

iTerm2 首创的以下序列得到支持:

  • OSC 1337 ; CurrentDir= S - 设置终端的当前工作目录,类似于 OSC 633 ; P ; 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 的启发式方法已经启动,以改进命令装饰的位置。