共用方式為


教學課程:在 Windows 終端機的相同目錄中開啟索引標籤或窗格

一般而言,「新索引標籤」和「分割窗格」動作一律會在該設定檔的任何 startingDirectory 中開啟新的索引標籤/窗格。 不過,在其他平台上,新的索引標籤通常會自動使用目前索引標籤的工作目錄,作為新索引標籤的起始目錄。這讓使用者可以迅速在單一目錄中多工處理。

可惜的是,在 Windows 上很難判斷程序目前的工作目錄 (「CWD」) 是什麼。 即使我們能夠查閱,也並非所有應用程式都會在瀏覽時實際設定其 CWD。 需要注意的是,Windows PowerShell 不會在您 cd 檔案系統時變更其 CWD! 自動複製 PowerShell 的 CWD 幾乎總是會出錯。

所幸,還有一種因應措施。 應用程式可以發出特殊的逸出序列(特別是“OSC 9;9 吋格式)手動告訴終端機 CWD 應該是什麼。

在本教學課程中,您會了解如何:

  • 設定殼層以告知終端機其目前的工作目錄
  • 使用 duplicateTab 動作以開啟具有相同 CWD 的索引標籤
  • 使用 splitPane 動作以開啟具有相同 CWD 的窗格
  • 使用索引標籤操作功能表開啟具有相同 CWD 的索引標籤或窗格

設定殼層

若要告知終端機 CWD 是什麼,您需要修改殼層,以在瀏覽 OS 時發出逸出序列。 所幸大部分殼層都有機制可設定「提示」,會在每個命令之後執行。 這是新增這類輸出的最佳位置。

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.exepwsh.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
}

搭配 posh-git 的 PowerShell

如果您使用的是 posh-git,您的提示會已經經過修改。 在此情況下,建議您只將必要的輸出新增至已修改的提示。 下列範例是 ConEmu 文件 範例稍經修改的版本:

function prompt
{
  $loc = Get-Location

  $prompt = & $GitPromptScriptBlock

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

  $prompt
}

搭配 Starship 的 PowerShell

如果您使用的是 Starship,您的提示會已經經過修改。 在此情況下,建議您只將必要的輸出新增至已修改的提示。

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

WSL

Windows 子系統 Linux 發行版本主要使用 BASH 作為命令列殼層。

bash

將以下這一行新增至 .bash_profile 設定檔結尾:

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

PROMPT_COMMAND 變數會讓 bash 知道顯示提示前要執行的命令。 printf 語句是用於附加序列,以使用終端機設定工作目錄。 $(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 "$PWD") 位元會叫用 wslpath 可執行檔,以將目前的目錄轉換成其類似 Windows 的路徑。 使用 precmd_functions+= 可以確保我們將 keep_current_path 函式附加至已為此攔截定義的任何現有函式。

Fish

如果您使用的是 Fish 殼層,請將下列幾行新增至位於 ~/.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

每當目前的路徑變更,可確認目前的工作階段已由 Windows 終端機開啟 (驗證 $WT_SESSION) 並傳送作業系統命令 (OSC 9;9;),就會呼叫此函式,且目前路徑相當於 Windows 路徑 (wslpath -w)。

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`"'

注意

這裡找不到您最愛的殼層嗎? 如果您已經找到解答,歡迎開啟 PR,為慣用的殼層貢獻解決方案!

使用動作複製路徑

設定殼層來告知終端機目前目錄是什麼之後,開啟具有該路徑的新索引標籤或窗格就很簡單了。

使用 duplicateTab 開啟新的索引標籤

若要開啟與目前使用中的終端機具有相同路徑 (和設定檔) 的新索引標籤,請使用 [複製索引標籤] 動作。 這預設會系結至 Ctrl+Shift+D,如下所示:

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

(如需詳細資訊,請參閱 duplicateTab)。

使用 splitPane 開啟新窗格

若要開啟與目前使用中的終端機具有相同路徑 (和設定檔) 的新窗格,請使用 [複製窗格] 動作。 根據預設,這沒有建立繫結。 此動作最簡單的形式為:

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

(如需詳細資訊,請參閱 splitPane)。

使用功能表複製路徑

上述動作也可在索引標籤操作功能表的 [複製索引標籤] 和 [分割窗格] 項目下找到。

影像 duplicate-tab-same-cwd影像分割窗格-same-cwd