Merge pull request #3043 from cmderdev/copilot/add-osc-133-d-exit-code

Add OSC 133 shell integration support across PowerShell, Bash, and CMD.exe
This commit is contained in:
David Refoua
2025-11-09 03:10:20 +03:30
committed by GitHub
4 changed files with 63 additions and 20 deletions

View File

@@ -354,7 +354,7 @@ However, Cmder can in fact run in a variety of other terminal emulators, and eve
⚠ *Note:* Cmder includes built-in support for Windows Terminal directory tracking via OSC 9;9 sequences. This enables "Duplicate Tab" and "Split Pane" features to preserve the current working directory for both `cmd.exe` and PowerShell sessions. ⚠ *Note:* Cmder includes built-in support for Windows Terminal directory tracking via OSC 9;9 sequences. This enables "Duplicate Tab" and "Split Pane" features to preserve the current working directory for both `cmd.exe` and PowerShell sessions.
⚠ *Note:* Cmder also includes built-in support for [Windows Terminal shell integration](https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration) via OSC 133 sequences (A, B, C) for PowerShell sessions. This enables features like command navigation (jump between commands), command selection, visual command separators, and improved command history management in Windows Terminal. ⚠ *Note:* Cmder also includes built-in support for [Windows Terminal shell integration](https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration) via OSC 133 sequences (A, B, C, D) for PowerShell sessions. This enables features like command navigation (jump between commands), command selection, visual command separators, command exit code tracking, and improved command history management in Windows Terminal.
For instructions on how to integrate Cmder with your IDE, please read our [Wiki section](https://github.com/cmderdev/cmder/wiki#cmder-integration). For instructions on how to integrate Cmder with your IDE, please read our [Wiki section](https://github.com/cmderdev/cmder/wiki#cmder-integration).

37
vendor/git-prompt.sh vendored
View File

@@ -47,9 +47,41 @@ then
. ~/.config/git/git-prompt.sh . ~/.config/git/git-prompt.sh
fi fi
else else
# Setup OSC 133 shell integration for Windows Terminal
if [ -n "$WT_SESSION" ]; then
__cmder_prompt_command() {
local exit_code=$?
# Emit OSC 133;D to mark the end of command execution with exit code
printf '\e]133;D;%s\a' "$exit_code"
return $exit_code
}
__cmder_preexec() {
# Emit OSC 133;C to mark the start of command execution
printf '\e]133;C\a'
}
# Append to PROMPT_COMMAND to emit sequences just before each prompt
if [ -z "$PROMPT_COMMAND" ]; then
PROMPT_COMMAND="__cmder_prompt_command"
else
PROMPT_COMMAND="__cmder_prompt_command;$PROMPT_COMMAND"
fi
# Use DEBUG trap to emit OSC 133;C before command execution
trap '__cmder_preexec' DEBUG
fi
# Source: github.com/git-for-windows/build-extra/blob/main/git-extra/git-prompt.sh # Source: github.com/git-for-windows/build-extra/blob/main/git-extra/git-prompt.sh
PS1='\[\033]0;${TITLEPREFIX:+$TITLEPREFIX:}${PWD//[^[:ascii:]]/?}\007\]' # set window title to TITLEPREFIX (if set) and current working directory PS1='\[\033]0;${TITLEPREFIX:+$TITLEPREFIX:}${PWD//[^[:ascii:]]/?}\007\]' # set window title to TITLEPREFIX (if set) and current working directory
# PS1="$PS1"'\n' # new line (disabled) # PS1="$PS1"'\n' # new line (disabled)
if [ -n "$WT_SESSION" ]; then
# Emit OSC 133;A to mark the start of prompt
PS1="$PS1"'\e]133;A\a'
fi
PS1="$PS1"'\[\033[32m\]' # change to green and bold PS1="$PS1"'\[\033[32m\]' # change to green and bold
PS1="$PS1"'\u@\h ' # user@host<space> PS1="$PS1"'\u@\h ' # user@host<space>
PS1="$PS1${MSYSTEM:+\[\033[35m\]$MSYSTEM }" # show MSYSTEM in purple (if set) PS1="$PS1${MSYSTEM:+\[\033[35m\]$MSYSTEM }" # show MSYSTEM in purple (if set)
@@ -80,6 +112,11 @@ else
PS1="$PS1"'\[\033[30;1m\]' # change color to grey in bold PS1="$PS1"'\[\033[30;1m\]' # change color to grey in bold
PS1="$PS1"'λ ' # prompt: Cmder uses λ PS1="$PS1"'λ ' # prompt: Cmder uses λ
PS1="$PS1"'\[\033[0m\]' # reset color PS1="$PS1"'\[\033[0m\]' # reset color
if [ -n "$WT_SESSION" ]; then
# Emit OSC 133;B to mark the end of prompt
PS1="$PS1"'\[\e]133;B\a\]'
fi
fi fi
MSYS2_PS1="$PS1" # for detection by MSYS2 SDK's bash.basrc MSYS2_PS1="$PS1" # for detection by MSYS2 SDK's bash.basrc

3
vendor/init.bat vendored
View File

@@ -222,6 +222,9 @@ goto :SKIP_CLINK
:: Revert back to plain cmd.exe prompt without clink :: Revert back to plain cmd.exe prompt without clink
prompt $E[1;32;49m$P$S$_$E[1;30;49mλ$S$E[0m prompt $E[1;32;49m$P$S$_$E[1;30;49mλ$S$E[0m
:: Add Windows Terminal shell integration support (OSC 133 sequences)
if defined WT_SESSION (prompt $e]133;D$e\$e]133;A$e\$e]9;9;$P$e\%PROMPT%$e]133;B$e\)
chcp %cp%>nul chcp %cp%>nul

41
vendor/profile.ps1 vendored
View File

@@ -98,8 +98,7 @@ if (Get-Module PSReadline -ErrorAction "SilentlyContinue") {
# Display an extra prompt line between the prompt and the command input # Display an extra prompt line between the prompt and the command input
Set-PSReadlineOption -ExtraPromptLineCount 1 Set-PSReadlineOption -ExtraPromptLineCount 1
# Add OSC 133;C support for Windows Terminal shell integration # Invoked when Enter is pressed to submit a command
# This marks the start of command output (emitted when Enter is pressed)
if ($env:WT_SESSION) { if ($env:WT_SESSION) {
Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { Set-PSReadLineKeyHandler -Key Enter -ScriptBlock {
# Get the current command line # Get the current command line
@@ -110,7 +109,7 @@ if (Get-Module PSReadline -ErrorAction "SilentlyContinue") {
# Accept the line first # Accept the line first
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
# Emit OSC 133;C sequence to mark start of command output # Emit OSC 133;C to mark start of command output
# This is written directly to the console after the command is accepted # This is written directly to the console after the command is accepted
[Console]::Write("$([char]0x1B)]133;C$([char]7)") [Console]::Write("$([char]0x1B)]133;C$([char]7)")
} }
@@ -221,20 +220,25 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS
$lastSUCCESS = $? $lastSUCCESS = $?
$realLastExitCode = $LastExitCode $realLastExitCode = $LastExitCode
# Emit OSC 9;9 sequence for Windows Terminal directory tracking # Terminal-specific escape sequences for Windows Terminal and ConEmu
# This enables "Duplicate Tab" and "Split Pane" to preserve the working directory if ($env:WT_SESSION -or $env:ConEmuPID) {
# Only active in Windows Terminal ($env:WT_SESSION) or ConEmu ($env:ConEmuPID) # Emit OSC 133;D to mark the end of command execution with exit code
$loc = $executionContext.SessionState.Path.CurrentLocation if ($env:WT_SESSION) {
if (($env:WT_SESSION -or $env:ConEmuPID) -and $loc.Provider.Name -eq "FileSystem") { Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;D;$realLastExitCode$([char]7)"
Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]9;9;`"$($loc.ProviderPath)`"$([char]0x1B)\" }
}
# Emit OSC 9;9 to enable directory tracking
# Emit OSC 133;A sequence for Windows Terminal shell integration # Enables "Duplicate Tab" and "Split Pane" to preserve the working directory
# This marks the start of the prompt $loc = $executionContext.SessionState.Path.CurrentLocation
# Enables features like command navigation, selection, and visual separators if ($loc.Provider.Name -eq "FileSystem") {
# Only active in Windows Terminal ($env:WT_SESSION) Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]9;9;`"$($loc.ProviderPath)`"$([char]0x1B)\"
if ($env:WT_SESSION) { }
Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;A$([char]7)"
# Emit OSC 133;A to mark the start of the prompt
# Enables features like command navigation, selection, and visual separators
if ($env:WT_SESSION) {
Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;A$([char]7)"
}
} }
$host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf $host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf
@@ -246,8 +250,7 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS
CmderPrompt CmderPrompt
PostPrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline PostPrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline
# Emit OSC 133;B sequence for Windows Terminal shell integration # Emit OSC 133;B to mark the start of command input (after prompt, before user types)
# This marks the start of command input (after prompt, before user types)
if ($env:WT_SESSION) { if ($env:WT_SESSION) {
Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;B$([char]7)" Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;B$([char]7)"
} }