diff --git a/README.md b/README.md index c45e254..661ba39 100644 --- a/README.md +++ b/README.md @@ -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 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). diff --git a/vendor/git-prompt.sh b/vendor/git-prompt.sh index a37400b..e64f906 100644 --- a/vendor/git-prompt.sh +++ b/vendor/git-prompt.sh @@ -47,9 +47,41 @@ then . ~/.config/git/git-prompt.sh fi 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 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) + + 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"'\u@\h ' # user@host 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"'λ ' # prompt: Cmder uses λ 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 MSYS2_PS1="$PS1" # for detection by MSYS2 SDK's bash.basrc diff --git a/vendor/init.bat b/vendor/init.bat index 3d82855..2eabb6e 100644 --- a/vendor/init.bat +++ b/vendor/init.bat @@ -222,6 +222,9 @@ goto :SKIP_CLINK :: Revert back to plain cmd.exe prompt without clink 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 diff --git a/vendor/profile.ps1 b/vendor/profile.ps1 index c77e81a..359c9d3 100644 --- a/vendor/profile.ps1 +++ b/vendor/profile.ps1 @@ -98,8 +98,7 @@ if (Get-Module PSReadline -ErrorAction "SilentlyContinue") { # Display an extra prompt line between the prompt and the command input Set-PSReadlineOption -ExtraPromptLineCount 1 - # Add OSC 133;C support for Windows Terminal shell integration - # This marks the start of command output (emitted when Enter is pressed) + # Invoked when Enter is pressed to submit a command if ($env:WT_SESSION) { Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { # Get the current command line @@ -110,7 +109,7 @@ if (Get-Module PSReadline -ErrorAction "SilentlyContinue") { # Accept the line first [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 [Console]::Write("$([char]0x1B)]133;C$([char]7)") } @@ -221,20 +220,25 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS $lastSUCCESS = $? $realLastExitCode = $LastExitCode - # Emit OSC 9;9 sequence for Windows Terminal directory tracking - # This enables "Duplicate Tab" and "Split Pane" to preserve the working directory - # Only active in Windows Terminal ($env:WT_SESSION) or ConEmu ($env:ConEmuPID) - $loc = $executionContext.SessionState.Path.CurrentLocation - if (($env:WT_SESSION -or $env:ConEmuPID) -and $loc.Provider.Name -eq "FileSystem") { - Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]9;9;`"$($loc.ProviderPath)`"$([char]0x1B)\" - } - - # Emit OSC 133;A sequence for Windows Terminal shell integration - # This marks the start of the prompt - # Enables features like command navigation, selection, and visual separators - # Only active in Windows Terminal ($env:WT_SESSION) - if ($env:WT_SESSION) { - Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;A$([char]7)" + # Terminal-specific escape sequences for Windows Terminal and ConEmu + if ($env:WT_SESSION -or $env:ConEmuPID) { + # Emit OSC 133;D to mark the end of command execution with exit code + if ($env:WT_SESSION) { + Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;D;$realLastExitCode$([char]7)" + } + + # Emit OSC 9;9 to enable directory tracking + # Enables "Duplicate Tab" and "Split Pane" to preserve the working directory + $loc = $executionContext.SessionState.Path.CurrentLocation + if ($loc.Provider.Name -eq "FileSystem") { + Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]9;9;`"$($loc.ProviderPath)`"$([char]0x1B)\" + } + + # 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 @@ -246,8 +250,7 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS CmderPrompt PostPrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline - # Emit OSC 133;B sequence for Windows Terminal shell integration - # This marks the start of command input (after prompt, before user types) + # Emit OSC 133;B to mark the start of command input (after prompt, before user types) if ($env:WT_SESSION) { Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;B$([char]7)" }