共用方式為


Shell 整合

從終端機 1.15 預覽版起,Windows 終端機已開始實驗性地支援一些「殼層整合」功能。 這些功能可讓命令列更易於使用。 在先前的版本,我們會啟用殼層來告訴終端機目前的工作目錄是什麼。 現在,我們新增了更多序列的支援,允許殼層以語意方式將終端機輸出的部分描述為「提示」、「命令」或「輸出」。 殼層也可以告訴終端機命令是成功或失敗。

這是我們在終端機 1.18 版推出之部份殼層整合功能的指南。 我們計畫未來在這些功能上建置更多功能,因此我們想要取得一些其他關於各位如何使用這些功能的意見反應。

注意:從終端機 1.21 起,標記現在是穩定的功能。 在 1.21 之前,僅針對終端機的預覽組建啟用標記。 如果您使用 1.21 之前的終端機版本,則 showMarksOnScrollbar 此設定名為 experimental.showMarksOnScrollbar,且 autoMarkPrompts 已命名為 experimental.autoMarkPrompts

這是如何運作的?

殼層整合的運作方式是讓殼層 (或任何命令列應用程式) 將特殊的「逸出序列」寫入終端機。 這些逸出序列不會列印到終端機,而是會提供終端機可用來深入了解應用程式內部狀況的中繼資料。 經由將這些序列貼入殼層的提示,您可以讓殼層持續提供只有殼層知道的終端機資訊。

針對下列序列:

  • OSC 是字串 "\x1b]" - 亦即逸出字元,後面接續的是 ]
  • ST 是「字串結束字元」,可以是 \x1b\ (ESC 字元,後面接續的是 \) 或 \x7 (BEL 字元)
  • 空白字元僅供說明之用。
  • <> 中的字串是應由一些其他值取代的參數。

從終端機 v1.18 起,相關的受支援殼層整合序列如下:

  • OSC 133 ; A ST ("FTCS_PROMPT") - 提示的開頭。
  • OSC 133 ; B ST ("FTCS_COMMAND_START") - 命令列的開頭 (讀取:提示的結尾)。
  • OSC 133 ; C ST ("FTCS_COMMAND_EXECUTED") - 命令輸出的開頭 / 命令列的結尾。
  • OSC 133 ; D ; <ExitCode> ST ("FTCS_COMMAND_FINISHED") - 命令的結尾。 ExitCode 如果提供ExitCode,終端機會將 0 視為「成功」,並將任何其他項目視為錯誤。 若省略,終端機僅會保留預設色彩的標記。

如何啟用殼層整合標記

支援這些功能需要仰賴殼層與終端機之間的合作。 您必須啟用終端機中的設定,以及修改殼層的提示,才能使用這些新功能。

若要在終端機中啟用這些功能,建議您將下列內容新增至您的設定:

"profiles":
{
    "defaults":
    {
        // Enable marks on the scrollbar
        "showMarksOnScrollbar": true,

        // Needed for both pwsh, CMD and bash shell integration
        "autoMarkPrompts": true,

        // Add support for a right-click context menu
        // You can also just bind the `showContextMenu` action
        "experimental.rightClickContextMenu": true,
    },
}
"actions":
[
    // Scroll between prompts
    { "keys": "ctrl+up",   "command": { "action": "scrollToMark", "direction": "previous" }, },
    { "keys": "ctrl+down", "command": { "action": "scrollToMark", "direction": "next" }, },

    // Add the ability to select a whole command (or its output)
    { "command": { "action": "selectOutput", "direction": "prev" }, },
    { "command": { "action": "selectOutput", "direction": "next" }, },

    { "command": { "action": "selectCommand", "direction": "prev" }, },
    { "command": { "action": "selectCommand", "direction": "next" }, },
]

在殼層中啟用這些標記的方式會因殼層而異。 以下是 CMD、PowerShell 和 Zsh 的教學課程。

PowerShell (pwsh.exe)

如果您之前從未變更過 PowerShell 提示字元,建議您應該先查看 about_Prompts

我們需要編輯您的 prompt,以確保終端機得知 CWD,並以適當的標記標示提示。 PowerShell 也讓我們可以在序列中包含 133;D 上一個命令的錯誤碼,以讓終端機在命令成功或失敗時自動著色標記。

請將下列內容新增至您的 PowerShell 設定檔

$Global:__LastHistoryId = -1

function Global:__Terminal-Get-LastExitCode {
  if ($? -eq $True) {
    return 0
  }
  $LastHistoryEntry = $(Get-History -Count 1)
  $IsPowerShellError = $Error[0].InvocationInfo.HistoryId -eq $LastHistoryEntry.Id
  if ($IsPowerShellError) {
    return -1
  }
  return $LastExitCode
}

function prompt {

  # First, emit a mark for the _end_ of the previous command.

  $gle = $(__Terminal-Get-LastExitCode);
  $LastHistoryEntry = $(Get-History -Count 1)
  # Skip finishing the command if the first command has not yet started
  if ($Global:__LastHistoryId -ne -1) {
    if ($LastHistoryEntry.Id -eq $Global:__LastHistoryId) {
      # Don't provide a command line or exit code if there was no history entry (eg. ctrl+c, enter on no command)
      $out += "`e]133;D`a"
    } else {
      $out += "`e]133;D;$gle`a"
    }
  }


  $loc = $($executionContext.SessionState.Path.CurrentLocation);

  # Prompt started
  $out += "`e]133;A$([char]07)";

  # CWD
  $out += "`e]9;9;`"$loc`"$([char]07)";

  # (your prompt here)
  $out += "PWSH $loc$('>' * ($nestedPromptLevel + 1)) ";

  # Prompt ended, Command started
  $out += "`e]133;B$([char]07)";

  $Global:__LastHistoryId = $LastHistoryEntry.Id

  return $out
}

哦, 我的 Posh 設定

使用 oh-my-posh? 您會想要稍微修改上述內容,以隱藏原始的提示,然後將它新增回殼層整合逸出序列的中間。

# initialize oh-my-posh at the top of your profile.ps1
oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\gruvbox.omp.json" | Invoke-Expression
# then stash away the prompt() that oh-my-posh sets
$Global:__OriginalPrompt = $function:Prompt

function Global:__Terminal-Get-LastExitCode {
  if ($? -eq $True) { return 0 }
  $LastHistoryEntry = $(Get-History -Count 1)
  $IsPowerShellError = $Error[0].InvocationInfo.HistoryId -eq $LastHistoryEntry.Id
  if ($IsPowerShellError) { return -1 }
  return $LastExitCode
}

function prompt {
  $gle = $(__Terminal-Get-LastExitCode);
  $LastHistoryEntry = $(Get-History -Count 1)
  if ($Global:__LastHistoryId -ne -1) {
    if ($LastHistoryEntry.Id -eq $Global:__LastHistoryId) {
      $out += "`e]133;D`a"
    } else {
      $out += "`e]133;D;$gle`a"
    }
  }
  $loc = $($executionContext.SessionState.Path.CurrentLocation);
  $out += "`e]133;A$([char]07)";
  $out += "`e]9;9;`"$loc`"$([char]07)";
  
  $out += $Global:__OriginalPrompt.Invoke(); # <-- This line adds the original prompt back

  $out += "`e]133;B$([char]07)";
  $Global:__LastHistoryId = $LastHistoryEntry.Id
  return $out
}

命令提示字元

命令提示字元會從 PROMPT 環境變數提供提示。 CMD.exe讀取 $eESC 字元。 可惜的是,CMD.exe 無法在提示字元中取得上一個命令的傳回碼,因此我們無法在 CMD 提示字元中提供成功/錯誤資訊。

您可以執行下列命令來變更目前 CMD.exe 執行個體的提示:

PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\

或者,您可以從命令列設定所有未來工作階段的變數:

setx PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\$P$G$e]133;B$e\

這些範例假設您目前的 PROMPT 只是 $P$G。 您可以改為選擇以類似下列的方式包裝目前的提示:

PROMPT $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\

Bash

您可以將下列內容新增至 結尾 ~/.bashrc ,以在bash 中啟用殼層整合:

PS1="\[\033]133;D;\007\]\[\033]133;A;\007\]$PS1\[\033]133;B;\007\]"

這會以必要的序列包裝現有的 $PS1 ,以啟用殼層整合。

注意:這裡找不到您最愛的殼層嗎? 如果您弄清楚,請放心 地為慣用的殼層提供解決方案!

殼層整合功能

在相同的工作目錄中開啟新的索引標籤

在相同的工作目錄中開啟新的索引標籤

顯示捲軸中每個命令的標記

顯示捲軸中每個命令的標記

在命令間自動跳躍

這會使用 scrollToMark 上述定義的動作。

在命令間自動跳躍

選取命令的整個輸出

在此gif中 selectOutput ,我們使用系結至的動作來 ctrl+g 選取命令的整個輸出。 選取命令的整個輸出

下列會 experimental.rightClickContextMenu 使用 設定,在終端機中啟用以滑鼠右鍵按下操作功能表。 啟用該和殼層整合之後,您可以以滑鼠右鍵按下命令,以選取整個命令或其輸出。

使用滑鼠右鍵操作功能選取命令

最近的命令建議

啟用殼層整合后,可以將建議UI設定為也顯示您最近的命令。

顯示其中最近命令的建議UI

您可以使用下列動作來開啟此選單:

{
    "command": { "action": "showSuggestions", "source": "recentCommands", "useCommandline": true },
},

(如需詳細資訊,請參閱 建議檔案

其他資源