让 Windows Terminal 新选项卡与窗格沿用当前目录

通常,“新建选项卡”和“拆分窗格”会使用配置文件中的 startingDirectory 作为新选项卡或窗格的起始目录。其他平台的新选项卡往往会自动沿用当前选项卡的工作目录,使用户能在一个目录里快速处理多项任务。

在 Windows 上,确定进程的当前工作目录(CWD)并不容易。即使可以查询,也不是所有应用都会在浏览目录时更新进程的 CWD。特别是 Windows PowerShell:在文件系统中执行 cd 时,它并不会相应修改进程 CWD。因此,自动复制 PowerShell 进程的 CWD 几乎总会出错。

解决办法是让应用发送特殊转义序列,具体为 OSC 9;9 格式,主动告诉 Terminal 当前工作目录。

本教程涵盖:配置 shell 上报当前目录;通过 duplicateTab 在同一目录打开选项卡;通过 splitPane 打开窗格;以及使用选项卡上下文菜单完成这些操作。

配置 shell

让 Terminal 知道当前目录,需要修改 shell,使其在浏览文件系统时输出转义序列。多数 shell 提供提示符配置机制,在每条命令之后执行,适合添加这类输出。

Windows

命令提示符:cmd.exe

cmd 使用环境变量 %PROMPT% 配置提示符。用以下命令,在现有提示符前加入用于设置 CWD 的序列:

set PROMPT=$e]9;9;$P$e\%PROMPT%

这会向提示符加入 $e]9;9;$P$e\。cmd 计算提示符时,会将 $e 替换为转义字符,将 $p 替换为当前工作目录。

该命令只对当前 cmd.exe 会话有效。若要永久保存,先执行上述命令,再运行:

setx PROMPT "%PROMPT%"

PowerShell:powershell.exe 或 pwsh.exe

如果从未修改 PowerShell 提示符,先阅读 about_Prompts。把下面内容加入 PowerShell 配置文件:

function prompt {
  $loc = $executionContext.SessionState.Path.CurrentLocation;

  $out = ""
  if ($loc.Provider.Name -eq "FileSystem") {
    $out += "$([char]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\"
  }
  $out += "PS $loc$('>' * ($nestedPromptLevel + 1)) ";
  return $out
}

PowerShell 与 posh-git

如果使用 posh-git,它已经修改了提示符。此时只需在现有提示符中加入必要输出。以下示例稍作修改自 ConEmu 文档:

function prompt
{
  $loc = Get-Location

  $prompt = & $GitPromptScriptBlock

  $prompt += "$([char]27)]133;A$([char]7)"
  if ($loc.Provider.Name -eq "FileSystem")
  {
    $prompt += "$([char]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\"
  }

  $prompt
}

PowerShell 与 Starship

如果使用 Starship,它同样已经修改提示符。只需补充所需输出:

function Invoke-Starship-PreCommand {
  $loc = $executionContext.SessionState.Path.CurrentLocation;
  $prompt = "$([char]27)]133;A$([char]7)"
  if ($loc.Provider.Name -eq "FileSystem")
  {
    $prompt += "$([char]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\"
  }
  $host.ui.Write($prompt)
}

WSL

Windows Subsystem for Linux 发行版通常使用 Bash 作为命令行 shell。

bash

在 .bash_profile 末尾加入:

PROMPT_COMMAND=${PROMPT_COMMAND:+"$PROMPT_COMMAND ; "}'printf "\e]9;9;%s\e\\" "$(wslpath -w "$PWD")"'

PROMPT_COMMAND 指定 Bash 显示提示符之前执行的命令。printf 输出设置 Terminal 工作目录的序列。$(wslpath -w "$PWD") 调用 wslpath,将当前目录转换为 Windows 路径。${PROMPT_COMMAND:+"$PROMPT_COMMAND; "} 利用 Bash 参数展开,确保在已有 PROMPT_COMMAND 后追加命令。

zsh

在 .zshrc 末尾加入:

keep_current_path() {
  printf "\e]9;9;%s\e\\" "$(wslpath -w "$PWD")"
}
precmd_functions+=(keep_current_path)

precmd_functions 钩子指定 zsh 显示提示符之前运行的命令。printf 输出当前目录序列,wslpath -w 将路径转换为 Windows 格式。precmd_functions+= 把 keep_current_path 加入已有钩子函数列表。

Fish

如果使用 Fish shell,在 ~/.config/fish/config.fish 末尾加入:

function storePathForWindowsTerminal --on-variable PWD
    if test -n "$WT_SESSION"
      printf "\e]9;9;%s\e\\" (wslpath -w "$PWD")
    end
end

每当当前目录改变时,该函数检查 $WT_SESSION,确认会话由 Windows Terminal 打开,然后使用 wslpath -w 得到 Windows 路径,发送操作系统命令序列 OSC 9;9;。

MINGW

对于 MINGW、Git Bash 和 Cygwin,修改 WSL 示例中的 PROMPT_COMMAND,将 wslpath 换成 cygpath。在 .bashrc 末尾加入:

PROMPT_COMMAND=${PROMPT_COMMAND:+"$PROMPT_COMMAND; "}'printf "\e]9;9;%s\e\\" "`cygpath -w "$PWD" -C ANSI`"'

注意:如果这里没有你使用的 shell,找到解决方法后,可以向 官方文档提交 PR。

使用操作复制路径

shell 上报当前目录后,就能方便地在该路径中打开新选项卡或窗格。

使用 duplicateTab 打开选项卡

“复制选项卡”操作会使用当前活动终端相同的路径和配置文件。默认快捷键是 Ctrl+Shift+D:

        { "command": "duplicateTab", "keys": "ctrl+shift+d" },

详见 duplicateTab。

使用 splitPane 打开窗格

“复制窗格”操作会使用当前活动终端相同的路径和配置文件。该操作默认未绑定快捷键,其最简单的形式为:

        { "command": { "action": "splitPane", "splitMode": "duplicate" } },

详见 splitPane。

使用菜单复制路径

也可以在选项卡上下文菜单的“复制选项卡”和“拆分窗格”条目下执行以上操作。

官方演示:在同一目录复制选项卡
原文演示:复制选项卡。
官方演示:在同一目录拆分窗格
原文演示:拆分窗格。

来源与许可

来源:Microsoft Learn 原文与 MicrosoftDocs/terminal 官方源码;作者 zadjii-msft,Microsoft 文档贡献者。文档按 CC BY 4.0 提供,材料按原样提供,不附保证。本版整理中文表述,按当前英文源码更新上述两处提示符序列,保留代码。命令未在本机实测。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容