Compare commits

..

19 Commits

Author SHA1 Message Date
David Refoua
7f0cfac498 update profile.ps1's debug output 2025-11-09 04:36:41 +03:30
David Refoua
dc3b142b32 Make PowerShell profile.ps1's debug and verbose working correctly 2025-11-09 04:29:32 +03:30
David Refoua
9c3bbe9b24 Redirect Verbose and Debug stream 2025-11-09 04:06:50 +03:30
David Refoua
be44bac956 fix line endings 2025-11-09 03:59:33 +03:30
David Refoua
4fb6bed907 adjust comments 2025-11-09 03:55:06 +03:30
David Refoua
f4e68b0388 Update PowerShell test to set CMDER_DEBUG env variable inline 2025-11-09 03:48:57 +03:30
David Refoua
a824b721cb improve CI PowrShell profile test debug/verbose output 2025-11-09 03:46:29 +03:30
David Refoua
153f7310a1 Merge pull request #3042 from cmderdev/copilot/fix-and-optimize-cmder-ps1
Refactor Cmder.ps1: Apply PowerShell naming conventions and optimize code
2025-11-09 03:29:06 +03:30
David Refoua
3172771f15 Modify PowerShell test command for debug output
* Update PowerShell command to include debug preference.
* Remove un-needed `Invoke-Expression`
2025-11-09 03:24:58 +03:30
David Refoua
ef46d6465d 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
2025-11-09 03:10:20 +03:30
David Refoua
eabadf96dc fix incorrect comment 2025-11-09 02:57:19 +03:30
David Refoua
7b248bc9a3 adjust comments 2025-11-09 02:50:47 +03:30
David Refoua
2ce0146d6e adjust comments 2025-11-09 02:45:06 +03:30
copilot-swe-agent[bot]
5dfa14ccce Avoid duplicating cmd.exe prompt definition
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-11-08 22:55:15 +00:00
copilot-swe-agent[bot]
4d259ba84c Consolidate terminal conditionals and add shell integration for bash and cmd.exe
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-11-08 22:41:26 +00:00
copilot-swe-agent[bot]
bbd7507b4e Add OSC 133;D support for command exit code tracking
Co-authored-by: DRSDavidSoft <4673812+DRSDavidSoft@users.noreply.github.com>
2025-11-08 22:27:38 +00:00
copilot-swe-agent[bot]
b9246177c0 Initial plan 2025-11-08 22:24:31 +00:00
David Refoua
a8d897f633 adjust comments 2025-11-09 01:49:20 +03:30
David Refoua
304b8c7a05 simplify regex 2025-11-09 01:48:05 +03:30
8 changed files with 109 additions and 52 deletions

View File

@@ -48,7 +48,7 @@ jobs:
cmd /c vendor\init.bat /v /d /t cmd /c vendor\init.bat /v /d /t
- name: Testing PowerShell - name: Testing PowerShell
run: | run: |
PowerShell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "Invoke-Expression '. ''vendor\profile.ps1'''" PowerShell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "$env:CMDER_DEBUG='1'; . 'vendor\profile.ps1'"
- name: Testing Bash - name: Testing Bash
run: | run: |
bash vendor/cmder.sh bash vendor/cmder.sh

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).

View File

@@ -27,7 +27,7 @@
.EXAMPLE .EXAMPLE
.\build.ps1 -SourcesPath '~/custom/vendors.json' .\build.ps1 -SourcesPath '~/custom/vendors.json'
Build cmder with your own packages. See vendor/sources.json for the syntax you need to copy. Build Cmder with your own packages. See vendor/sources.json for the syntax you need to copy.
.NOTES .NOTES
AUTHORS AUTHORS
Samuel Vasko, Jack Bennett Samuel Vasko, Jack Bennett
@@ -60,7 +60,7 @@ Param(
[switch]$Compile [switch]$Compile
) )
# Get the scripts and cmder root dirs we are building in. # Get the scripts and Cmder root dirs we are building in.
$cmder_root = Resolve-Path "$PSScriptRoot\.." $cmder_root = Resolve-Path "$PSScriptRoot\.."
# Dot source util functions into this scope # Dot source util functions into this scope

View File

@@ -2,18 +2,18 @@
.Synopsis .Synopsis
Pack Cmder Pack Cmder
.DESCRIPTION .DESCRIPTION
Use this script to pack cmder into release archives Use this script to pack Cmder into release archives
You will need to make this script executable by setting your Powershell Execution Policy to Remote signed You will need to make this script executable by setting your Powershell Execution Policy to Remote signed
Then unblock the script for execution with UnblockFile .\pack.ps1 Then unblock the script for execution with UnblockFile .\pack.ps1
.EXAMPLE .EXAMPLE
.\pack.ps1 .\pack.ps1
Creates default archives for cmder Creates default archives for Cmder
.EXAMPLE .EXAMPLE
.\pack.ps1 -verbose .\pack.ps1 -verbose
Creates default archives for cmder with plenty of information Creates default archives for Cmder with plenty of information
.NOTES .NOTES
AUTHORS AUTHORS
Samuel Vasko, Jack Bennett, Martin Kemp Samuel Vasko, Jack Bennett, Martin Kemp

View File

@@ -172,13 +172,13 @@ function Register-Cmder() {
# Text for the context menu item. # Text for the context menu item.
$MenuText = "Cmder Here" $MenuText = "Cmder Here"
, # Defaults to the current cmder directory when run from cmder. , # Defaults to the current Cmder directory when run from Cmder.
$PathToExe = (Join-Path $env:CMDER_ROOT "cmder.exe") $PathToExe = (Join-Path $env:CMDER_ROOT "cmder.exe")
, # Commands the context menu will execute. , # Commands the context menu will execute.
$Command = "%V" $Command = "%V"
, # Defaults to the icons folder in the cmder package. , # Defaults to the icons folder in the Cmder package.
$icon = (Split-Path $PathToExe | Join-Path -ChildPath 'icons/cmder.ico') $icon = (Split-Path $PathToExe | Join-Path -ChildPath 'icons/cmder.ico')
) )
Begin Begin

49
vendor/git-prompt.sh vendored
View File

@@ -5,9 +5,9 @@ function getGitStatusSetting() {
# Get all git config entries for the current repository without pager # Get all git config entries for the current repository without pager
gitConfig=$(git --no-pager config -l 2>/dev/null) || return 0 # treat failure as enabled gitConfig=$(git --no-pager config -l 2>/dev/null) || return 0 # treat failure as enabled
# Check if git status for Cmder is disabled # Check if git status display for Cmder is disabled via config
if [[ $gitConfig =~ (^|$'\n')cmder\.status=false($|$'\n') ]] || \ # Matches: cmder.status=false or cmder.shstatus=false (Bash-specific)
[[ $gitConfig =~ (^|$'\n')cmder\.shstatus=false($|$'\n') ]] if [[ $gitConfig =~ (^|$'\n')cmder\.(sh)?status=false($|$'\n') ]]
then then
return 1 # disabled return 1 # disabled
fi fi
@@ -47,9 +47,41 @@ then
. ~/.config/git/git-prompt.sh . ~/.config/git/git-prompt.sh
fi fi
else else
# Taken parts from https://github.com/git-for-windows/build-extra/blob/main/git-extra/git-prompt.sh
# 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='\[\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)
@@ -70,7 +102,7 @@ else
PS1="$PS1"'\[\033[36m\]' # change color to cyan PS1="$PS1"'\[\033[36m\]' # change color to cyan
PS1="$PS1"'`__git_ps1`' # bash function PS1="$PS1"'`__git_ps1`' # bash function
else else
PS1="$PS1"'\[\033[37;1m\]' # change color to white PS1="$PS1"'\[\033[37;1m\]' # change color to white
PS1="$PS1"'`getSimpleGitBranch`' PS1="$PS1"'`getSimpleGitBranch`'
fi fi
fi fi
@@ -80,9 +112,14 @@ 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
# Evaluate all user-specific Bash completion scripts (if any) # Evaluate all user-specific Bash completion scripts (if any)
if test -z "$WINELOADERNOEXEC" if test -z "$WINELOADERNOEXEC"

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

91
vendor/profile.ps1 vendored
View File

@@ -7,15 +7,11 @@
$CMDER_INIT_START = Get-Date $CMDER_INIT_START = Get-Date
# Compatibility with PS major versions <= 2 # Determine the script root if not already set
if (!$PSScriptRoot) { if (!$PSScriptRoot) {
$PSScriptRoot = Split-Path $Script:MyInvocation.MyCommand.Path $PSScriptRoot = Split-Path $Script:MyInvocation.MyCommand.Path
} }
if ($ENV:CMDER_USER_CONFIG) {
Write-Verbose "CMDER IS ALSO USING INDIVIDUAL USER CONFIG FROM '$ENV:CMDER_USER_CONFIG'!"
}
# We do this for Powershell as Admin Sessions because CMDER_ROOT is not being set. # We do this for Powershell as Admin Sessions because CMDER_ROOT is not being set.
if (!$ENV:CMDER_ROOT) { if (!$ENV:CMDER_ROOT) {
if ($ENV:ConEmuDir) { if ($ENV:ConEmuDir) {
@@ -31,6 +27,12 @@ $ENV:CMDER_ROOT = ($ENV:CMDER_ROOT).TrimEnd("\")
# Recent PowerShell versions include PowerShellGet out of the box # Recent PowerShell versions include PowerShellGet out of the box
$moduleInstallerAvailable = [bool](Get-Command -Name 'Install-Module' -ErrorAction SilentlyContinue) $moduleInstallerAvailable = [bool](Get-Command -Name 'Install-Module' -ErrorAction SilentlyContinue)
# Enable Debug and Verbose output if CMDER_DEBUG environment variable is set to '1' or 'true'
if ($env:CMDER_DEBUG -and ($env:CMDER_DEBUG -match '^(1|true)$')) {
$DebugPreference = 'Continue'
$VerbosePreference = 'Continue'
}
# Add Cmder modules directory to the autoload path. # Add Cmder modules directory to the autoload path.
$CmderModulePath = Join-path $PSScriptRoot "psmodules/" $CmderModulePath = Join-path $PSScriptRoot "psmodules/"
@@ -43,28 +45,40 @@ if (-not $moduleInstallerAvailable -and -not $env:PSModulePath.Contains($CmderMo
$env:PSModulePath = $env:PSModulePath.Insert(0, "$CmderModulePath;") $env:PSModulePath = $env:PSModulePath.Insert(0, "$CmderModulePath;")
} }
if ($env:CMDER_USER_CONFIG) {
Write-Verbose "CMDER IS ALSO USING INDIVIDUAL USER CONFIG FROM '$ENV:CMDER_USER_CONFIG'!"
}
# Read vendored Git Version # Read vendored Git Version
$gitVersionVendor = Get-GitVersion -GitPath "$ENV:CMDER_ROOT\vendor\git-for-windows\cmd" $gitVendorPath = Join-Path $ENV:CMDER_ROOT 'vendor\git-for-windows\cmd'
Write-Debug "GIT VENDOR: ${gitVersionVendor}" $gitVersionVendor = Get-GitVersion -GitPath $gitVendorPath
if (-not [string]::IsNullOrEmpty($gitVersionVendor)) {
Write-Debug "GIT VENDOR: ${gitVersionVendor}"
} else {
Write-Debug "GIT VENDOR is not present at '$gitVendorPath'"
}
# Get user installed Git version(s) if found, and compare them with vendored version. # Get user installed Git version(s) if found, and compare them with vendored version.
foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) { foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) {
Write-Debug "GIT PATH: {$git.Path}" Write-Debug "GIT USER PATH: $($git.Path)"
$gitDir = Split-Path -Path $git.Path $gitDir = Split-Path -Path $git.Path
$gitDir = Get-GitShimPath -GitPath $gitDir $gitDir = Get-GitShimPath -GitPath $gitDir
$gitVersionUser = Get-GitVersion -GitPath $gitDir $gitVersionUser = Get-GitVersion -GitPath $gitDir
Write-Debug "GIT USER: ${gitVersionUser}" Write-Debug "GIT USER VERSION: ${gitVersionUser}"
$useGitVersion = Compare-GitVersion -UserVersion $gitVersionUser -VendorVersion $gitVersionVendor $useGitVersion = Compare-GitVersion -UserVersion $gitVersionUser -VendorVersion $gitVersionVendor
Write-Debug "Using Git Version: ${useGitVersion}" Write-Debug "Using Git Version: ${useGitVersion}"
# Use user installed Git # Use user installed Git
if ($null -eq $gitPathUser) { if ($null -eq $gitPathUser) {
Write-Debug "Detected Git from mingw bin directory"
Write-Debug "Git Dir: ${gitDir}"
if ($gitDir -match '\\mingw32\\bin' -or $gitDir -match '\\mingw64\\bin') { if ($gitDir -match '\\mingw32\\bin' -or $gitDir -match '\\mingw64\\bin') {
$gitPathUser = ($gitDir.subString(0,$gitDir.Length - 12)) $gitPathUser = $gitDir.subString(0, $gitDir.Length - 12)
} else { } else {
$gitPathUser = ($gitDir.subString(0,$gitDir.Length - 4)) $gitPathUser = $gitDir.subString(0, $gitDir.Length - 4)
} }
Write-Debug "Git Path User: ${gitDir}"
} }
if ($useGitVersion -eq $gitVersionUser) { if ($useGitVersion -eq $gitVersionUser) {
@@ -97,20 +111,19 @@ if (Get-Command -Name "vim" -ErrorAction SilentlyContinue) {
if (Get-Module PSReadline -ErrorAction "SilentlyContinue") { 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
$line = $null $line = $null
$cursor = $null $cursor = $null
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
# 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)")
} }
@@ -220,23 +233,28 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS
[ScriptBlock]$Prompt = { [ScriptBlock]$Prompt = {
$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
# 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)"
}
} }
# 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)"
}
$host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf $host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf
Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K" Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K"
if ($lastSUCCESS -or ($LastExitCode -ne 0)) { if ($lastSUCCESS -or ($LastExitCode -ne 0)) {
@@ -245,13 +263,12 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS
PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline
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)"
} }
$global:LastExitCode = $realLastExitCode $global:LastExitCode = $realLastExitCode
return " " return " "
} }