From 538662ce56a8cbf8cb6edbfd8643b090681d6e44 Mon Sep 17 00:00:00 2001 From: David Refoua Date: Sat, 8 Nov 2025 17:39:50 +0330 Subject: [PATCH 1/2] improve documentation --- README.md | 2 +- vendor/profile.ps1 | 550 +++++++++++++++++++------------------ vendor/psmodules/Cmder.ps1 | 358 ++++++++++++------------ 3 files changed, 458 insertions(+), 452 deletions(-) diff --git a/README.md b/README.md index 4eec2fe..c45e254 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 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) 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. 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/profile.ps1 b/vendor/profile.ps1 index 75dc4f2..977b8c5 100644 --- a/vendor/profile.ps1 +++ b/vendor/profile.ps1 @@ -1,272 +1,278 @@ -# Init Script for PowerShell -# Created as part of Cmder project -# NOTE: This file must be saved using UTF-8 with BOM encoding for prompt symbol to work correctly. - -# !!! THIS FILE IS OVERWRITTEN WHEN CMDER IS UPDATED -# !!! Use "%CMDER_ROOT%\config\user_profile.ps1" to add your own startup commands - -$CMDER_INIT_START = Get-Date - -# Compatibility with PS major versions <= 2 -if (!$PSScriptRoot) { - $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. -if (!$ENV:CMDER_ROOT) { - if ($ENV:ConEmuDir) { - $ENV:CMDER_ROOT = Resolve-Path($ENV:ConEmuDir + "\..\..") - } else { - $ENV:CMDER_ROOT = Resolve-Path($PSScriptRoot + "\..") - } -} - -# Remove trailing '\' -$ENV:CMDER_ROOT = ($ENV:CMDER_ROOT).TrimEnd("\") - -# Recent PowerShell versions include PowerShellGet out of the box -$moduleInstallerAvailable = [bool](Get-Command -Name 'Install-Module' -ErrorAction SilentlyContinue) - -# Add Cmder modules directory to the autoload path. -$CmderModulePath = Join-path $PSScriptRoot "psmodules/" - -$CmderFunctions = Join-Path $CmderModulePath "Cmder.ps1" -. $CmderFunctions - -if(-not $moduleInstallerAvailable -and -not $env:PSModulePath.Contains($CmderModulePath) ) { - $env:PSModulePath = $env:PSModulePath.Insert(0, "$CmderModulePath;") -} - -$gitVersionVendor = (readVersion -gitPath "$ENV:CMDER_ROOT\vendor\git-for-windows\cmd") -Write-Debug "GIT VENDOR: ${gitVersionVendor}" - -# Get user installed Git Version[s] and Compare with vendored if found. -foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) { - Write-Debug "GIT PATH: {$git.Path}" - $gitDir = Split-Path -Path $git.Path - $gitDir = isGitShim -gitPath $gitDir - $gitVersionUser = (readVersion -gitPath $gitDir) - Write-Debug "GIT USER: ${gitVersionUser}" - - $useGitVersion = compare_git_versions -userVersion $gitVersionUser -vendorVersion $gitVersionVendor - Write-Debug "Using Git Version: ${useGitVersion}" - - # Use user installed Git - if ($null -eq $gitPathUser) { - if ($gitDir -match '\\mingw32\\bin' -or $gitDir -match '\\mingw64\\bin') { - $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 12)) - } else { - $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 4)) - } - } - - if ($useGitVersion -eq $gitVersionUser) { - Write-Debug "Using Git Dir: ${gitDir}" - $ENV:GIT_INSTALL_ROOT = $gitPathUser - $ENV:GIT_INSTALL_TYPE = 'USER' - break - } -} - -# User vendored Git. -if ($null -eq $ENV:GIT_INSTALL_ROOT -and $null -ne $gitVersionVendor) { - $ENV:GIT_INSTALL_ROOT = "$ENV:CMDER_ROOT\vendor\git-for-windows" - $ENV:GIT_INSTALL_TYPE = 'VENDOR' -} - -Write-Debug "GIT_INSTALL_ROOT: ${ENV:GIT_INSTALL_ROOT}" -Write-Debug "GIT_INSTALL_TYPE: ${ENV:GIT_INSTALL_TYPE}" - -if ($null -ne $ENV:GIT_INSTALL_ROOT) { - $env:Path = Configure-Git -gitRoot "$ENV:GIT_INSTALL_ROOT" -gitType $ENV:GIT_INSTALL_TYPE -gitPathUser $gitPathUser -} - -if (Get-Command -Name "vim" -ErrorAction SilentlyContinue) { - New-Alias -name "vi" -value vim -} - -if (Get-Module PSReadline -ErrorAction "SilentlyContinue") { - 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) - if ($env:WT_SESSION) { - Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { - # Get the current command line - $line = $null - $cursor = $null - [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) - - # Accept the line first - [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() - - # Emit OSC 133;C sequence to mark start of command output - # This is written directly to the console after the command is accepted - [Console]::Write("$([char]27)]133;C$([char]7)") - } - } -} - -# Pre-assign default prompt hooks so the first run of cmder gets a working prompt. -$env:gitLoaded = $null -[ScriptBlock]$PrePrompt = {} -[ScriptBlock]$PostPrompt = {} -[ScriptBlock]$CmderPrompt = { - # Check if we're currently running under Admin privileges. - $identity = [Security.Principal.WindowsIdentity]::GetCurrent() - $principal = [Security.Principal.WindowsPrincipal] $identity - $adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator - $color = "White" - if ($principal.IsInRole($adminRole)) { $color = "Red" } - $Host.UI.RawUI.ForegroundColor = "White" - Microsoft.PowerShell.Utility\Write-Host "PS " -NoNewline -ForegroundColor $color - Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green - checkGit($pwd.ProviderPath) - Microsoft.PowerShell.Utility\Write-Host "`nλ" -NoNewLine -ForegroundColor "DarkGray" -} - -# Enhance Path -$env:Path = "$Env:CMDER_ROOT\bin;$Env:CMDER_ROOT\vendor\bin;$env:Path;$Env:CMDER_ROOT" - -# Drop *.ps1 files into "$ENV:CMDER_ROOT\config\profile.d" -# to source them at startup. -if (-not (Test-Path -PathType container "$ENV:CMDER_ROOT\config\profile.d")) { - New-Item -ItemType Directory -Path "$ENV:CMDER_ROOT\config\profile.d" -} - -Push-Location $ENV:CMDER_ROOT\config\profile.d -foreach ($x in Get-ChildItem *.psm1) { - Write-Verbose "Sourcing $x" - Import-Module $x -} -foreach ($x in Get-ChildItem *.ps1) { - Write-Verbose "Sourcing $x" - . $x -} -Pop-Location - -# Drop *.ps1 files into "$ENV:CMDER_USER_CONFIG\config\profile.d" -# to source them at startup. Requires using cmder.exe /C [cmder_user_root_path] argument -if ($ENV:CMDER_USER_CONFIG -ne "" -and (Test-Path "$ENV:CMDER_USER_CONFIG\profile.d")) { - Push-Location $ENV:CMDER_USER_CONFIG\profile.d - foreach ($x in Get-ChildItem *.psm1) { - Write-Verbose "Sourcing $x" - Import-Module $x - } - foreach ($x in Get-ChildItem *.ps1) { - Write-Verbose "Sourcing $x" - . $x - } - Pop-Location -} - -# Renaming to "config\user_profile.ps1" to "user_profile.ps1" for consistency. -if (Test-Path "$env:CMDER_ROOT\config\user-profile.ps1") { - Rename-Item "$env:CMDER_ROOT\config\user-profile.ps1" user_profile.ps1 -} - -$CmderUserProfilePath = Join-Path $env:CMDER_ROOT "config\user_profile.ps1" -if (Test-Path $CmderUserProfilePath) { - # Create this file and place your own command in there. - . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module -} - -if ($ENV:CMDER_USER_CONFIG) { - # Renaming to "$env:CMDER_USER_CONFIG\user-profile.ps1" to "user_profile.ps1" for consistency. - if (Test-Path "$env:CMDER_USER_CONFIG\user-profile.ps1") { - Rename-Item "$env:CMDER_USER_CONFIG\user-profile.ps1" user_profile.ps1 - } - - $env:Path = "$Env:CMDER_USER_CONFIG\bin;$env:Path" - - $CmderUserProfilePath = Join-Path $ENV:CMDER_USER_CONFIG "user_profile.ps1" - if (Test-Path $CmderUserProfilePath) { - . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module - } -} - -if (-not (Test-Path $CmderUserProfilePath)) { - $CmderUserProfilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($CmderUserProfilePath) - Write-Host -NoNewline "`r" - Write-Host -BackgroundColor Green -ForegroundColor Black "First Run: Creating user startup file: $CmderUserProfilePath" - Copy-Item "$env:CMDER_ROOT\vendor\user_profile.ps1.default" -Destination $CmderUserProfilePath -} - -# -# Prompt Section -# Users should modify their user_profile.ps1 as it will be safe from updates. -# - -# Only set the prompt if it is currently set to the default -# This allows users to configure the prompt in their user_profile.ps1 or config\profile.d\*.ps1 -if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionState.Path.CurrentLocation\)\$\(' -and ` - $(Get-Command prompt).Definition -match '\(\$nestedPromptLevel \+ 1\)\) ";') { - - <# - This scriptblock runs every time the prompt is returned. - Explicitly use functions from MS namespace to protect from being overridden in the user session. - Custom prompt functions are loaded in as constants to get the same behaviour - #> - [ScriptBlock]$Prompt = { - $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]27)]9;9;`"$($loc.ProviderPath)`"$([char]27)\" - } - - # 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]27)]133;A$([char]7)" - } - - $host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf - Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K" - if ($lastSUCCESS -or ($LastExitCode -ne 0)) { - Microsoft.PowerShell.Utility\Write-Host - } - PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline - 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) - if ($env:WT_SESSION) { - Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]27)]133;B$([char]7)" - } - - $global:LastExitCode = $realLastExitCode - return " " - } - - # Once Created these code blocks cannot be overwritten - # if (-not $(Get-Command PrePrompt).Options -match 'Constant') {Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant} - # if (-not $(Get-Command CmderPrompt).Options -match 'Constant') {Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant} - # if (-not $(Get-Command PostPrompt).Options -match 'Constant') {Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant} - - Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant - Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant - Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant - - # Functions can be made constant only at creation time - # ReadOnly at least requires `-force` to be overwritten - # if (!$(Get-Command Prompt).Options -match 'ReadOnly') {Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly} - Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly -} - -$CMDER_INIT_END = Get-Date - -$ElapsedTime = New-TimeSpan -Start $CMDER_INIT_START -End $CMDER_INIT_END - -Write-Verbose "Elapsed Time: $($ElapsedTime.TotalSeconds) seconds total" +# Init Script for PowerShell +# Created as part of Cmder project +# NOTE: This file must be saved using UTF-8 with BOM encoding for prompt symbol to work correctly. + +# !!! THIS FILE IS OVERWRITTEN WHEN CMDER IS UPDATED +# !!! Use "%CMDER_ROOT%\config\user_profile.ps1" to add your own startup commands + +$CMDER_INIT_START = Get-Date + +# Compatibility with PS major versions <= 2 +if (!$PSScriptRoot) { + $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. +if (!$ENV:CMDER_ROOT) { + if ($ENV:ConEmuDir) { + $ENV:CMDER_ROOT = Resolve-Path($ENV:ConEmuDir + "\..\..") + } else { + $ENV:CMDER_ROOT = Resolve-Path($PSScriptRoot + "\..") + } +} + +# Remove trailing '\' +$ENV:CMDER_ROOT = ($ENV:CMDER_ROOT).TrimEnd("\") + +# Recent PowerShell versions include PowerShellGet out of the box +$moduleInstallerAvailable = [bool](Get-Command -Name 'Install-Module' -ErrorAction SilentlyContinue) + +# Add Cmder modules directory to the autoload path. +$CmderModulePath = Join-path $PSScriptRoot "psmodules/" + +# Import Cmder functions +$CmderFunctions = Join-Path $CmderModulePath "Cmder.ps1" +. $CmderFunctions + +# Configure PSModulePath to include Cmder modules if not already present +if (-not $moduleInstallerAvailable -and -not $env:PSModulePath.Contains($CmderModulePath) ) { + $env:PSModulePath = $env:PSModulePath.Insert(0, "$CmderModulePath;") +} + +# Read vendored Git Version +$gitVersionVendor = (readGitVersion -gitPath "$ENV:CMDER_ROOT\vendor\git-for-windows\cmd") +Write-Debug "GIT VENDOR: ${gitVersionVendor}" + +# Get user installed Git version(s) if found, and compare them with vendored version. +foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) { + Write-Debug "GIT PATH: {$git.Path}" + $gitDir = Split-Path -Path $git.Path + $gitDir = isGitShim -gitPath $gitDir + $gitVersionUser = (readGitVersion -gitPath $gitDir) + Write-Debug "GIT USER: ${gitVersionUser}" + + $useGitVersion = compare_git_versions -userVersion $gitVersionUser -vendorVersion $gitVersionVendor + Write-Debug "Using Git Version: ${useGitVersion}" + + # Use user installed Git + if ($null -eq $gitPathUser) { + if ($gitDir -match '\\mingw32\\bin' -or $gitDir -match '\\mingw64\\bin') { + $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 12)) + } else { + $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 4)) + } + } + + if ($useGitVersion -eq $gitVersionUser) { + Write-Debug "Using Git Dir: ${gitDir}" + $ENV:GIT_INSTALL_ROOT = $gitPathUser + $ENV:GIT_INSTALL_TYPE = 'USER' + break + } +} + +# Use vendored Git if no user Git found or user Git is older than vendored Git +if ($null -eq $ENV:GIT_INSTALL_ROOT -and $null -ne $gitVersionVendor) { + $ENV:GIT_INSTALL_ROOT = "$ENV:CMDER_ROOT\vendor\git-for-windows" + $ENV:GIT_INSTALL_TYPE = 'VENDOR' +} + +Write-Debug "GIT_INSTALL_ROOT: ${ENV:GIT_INSTALL_ROOT}" +Write-Debug "GIT_INSTALL_TYPE: ${ENV:GIT_INSTALL_TYPE}" + +if ($null -ne $ENV:GIT_INSTALL_ROOT) { + $env:Path = Configure-Git -gitRoot "$ENV:GIT_INSTALL_ROOT" -gitType $ENV:GIT_INSTALL_TYPE -gitPathUser $gitPathUser +} + +# Create 'vi' alias for 'vim' if vim is available +if (Get-Command -Name "vim" -ErrorAction SilentlyContinue) { + New-Alias -name "vi" -value vim +} + +# PSReadline configuration +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) + if ($env:WT_SESSION) { + Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { + # Get the current command line + $line = $null + $cursor = $null + [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) + + # Accept the line first + [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() + + # Emit OSC 133;C sequence 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)") + } + } +} + +# Pre-assign default prompt hooks so the first run of Cmder gets a working prompt +$env:gitLoaded = $null +[ScriptBlock]$PrePrompt = {} +[ScriptBlock]$PostPrompt = {} +[ScriptBlock]$CmderPrompt = { + # Check if we're currently running under Admin privileges + $identity = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = [Security.Principal.WindowsPrincipal] $identity + $adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator + $color = "White" + if ($principal.IsInRole($adminRole)) { $color = "Red" } + $Host.UI.RawUI.ForegroundColor = "White" + Microsoft.PowerShell.Utility\Write-Host "PS " -NoNewline -ForegroundColor $color + Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green + checkGit($pwd.ProviderPath) + Microsoft.PowerShell.Utility\Write-Host "`nλ" -NoNewLine -ForegroundColor "DarkGray" +} + +# Enhance Path +$env:Path = "$Env:CMDER_ROOT\bin;$Env:CMDER_ROOT\vendor\bin;$env:Path;$Env:CMDER_ROOT" + +# Drop *.ps1 files into "$ENV:CMDER_ROOT\config\profile.d" +# to source them at startup. +if (-not (Test-Path -PathType container "$ENV:CMDER_ROOT\config\profile.d")) { + New-Item -ItemType Directory -Path "$ENV:CMDER_ROOT\config\profile.d" +} + +Push-Location $ENV:CMDER_ROOT\config\profile.d +foreach ($x in Get-ChildItem *.psm1) { + Write-Verbose "Sourcing $x" + Import-Module $x +} +foreach ($x in Get-ChildItem *.ps1) { + Write-Verbose "Sourcing $x" + . $x +} +Pop-Location + +# Drop *.ps1 files into "$ENV:CMDER_USER_CONFIG\config\profile.d" +# to source them at startup. Requires using cmder.exe /C [cmder_user_root_path] argument +if ($ENV:CMDER_USER_CONFIG -ne "" -and (Test-Path "$ENV:CMDER_USER_CONFIG\profile.d")) { + Push-Location $ENV:CMDER_USER_CONFIG\profile.d + foreach ($x in Get-ChildItem *.psm1) { + Write-Verbose "Sourcing $x" + Import-Module $x + } + foreach ($x in Get-ChildItem *.ps1) { + Write-Verbose "Sourcing $x" + . $x + } + Pop-Location +} + +# Renaming to "config\user_profile.ps1" to "user_profile.ps1" for consistency. +if (Test-Path "$env:CMDER_ROOT\config\user-profile.ps1") { + Rename-Item "$env:CMDER_ROOT\config\user-profile.ps1" user_profile.ps1 +} + +$CmderUserProfilePath = Join-Path $env:CMDER_ROOT "config\user_profile.ps1" +if (Test-Path $CmderUserProfilePath) { + # Create this file and place your own command in there. + . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module +} + +if ($ENV:CMDER_USER_CONFIG) { + # Renaming to "$env:CMDER_USER_CONFIG\user-profile.ps1" to "user_profile.ps1" for consistency. + if (Test-Path "$env:CMDER_USER_CONFIG\user-profile.ps1") { + Rename-Item "$env:CMDER_USER_CONFIG\user-profile.ps1" user_profile.ps1 + } + + $env:Path = "$Env:CMDER_USER_CONFIG\bin;$env:Path" + + $CmderUserProfilePath = Join-Path $ENV:CMDER_USER_CONFIG "user_profile.ps1" + if (Test-Path $CmderUserProfilePath) { + . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module + } +} + +if (-not (Test-Path $CmderUserProfilePath)) { + $CmderUserProfilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($CmderUserProfilePath) + Write-Host -NoNewline "`r" + Write-Host -BackgroundColor Green -ForegroundColor Black "First Run: Creating user startup file: $CmderUserProfilePath" + Copy-Item "$env:CMDER_ROOT\vendor\user_profile.ps1.default" -Destination $CmderUserProfilePath +} + +# +# Prompt Section +# Users should modify their user_profile.ps1 as it will be safe from updates. +# + +# Only set the prompt if it is currently set to the default +# This allows users to configure the prompt in their user_profile.ps1 or config\profile.d\*.ps1 +if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionState.Path.CurrentLocation\)\$\(' -and ` + $(Get-Command prompt).Definition -match '\(\$nestedPromptLevel \+ 1\)\) ";') { + + <# + This scriptblock runs every time the prompt is returned. + Explicitly use functions from MS namespace to protect from being overridden in the user session. + Custom prompt functions are loaded in as constants to get the same behaviour + #> + [ScriptBlock]$Prompt = { + $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)" + } + + $host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf + Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K" + if ($lastSUCCESS -or ($LastExitCode -ne 0)) { + Microsoft.PowerShell.Utility\Write-Host + } + PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline + 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) + if ($env:WT_SESSION) { + Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;B$([char]7)" + } + + $global:LastExitCode = $realLastExitCode + return " " + } + + # Once Created these code blocks cannot be overwritten + # if (-not $(Get-Command PrePrompt).Options -match 'Constant') {Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant} + # if (-not $(Get-Command CmderPrompt).Options -match 'Constant') {Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant} + # if (-not $(Get-Command PostPrompt).Options -match 'Constant') {Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant} + + Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant + Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant + Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant + + # Functions can be made constant only at creation time + # ReadOnly at least requires `-force` to be overwritten + # if (!$(Get-Command Prompt).Options -match 'ReadOnly') {Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly} + Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly +} + +$CMDER_INIT_END = Get-Date + +$ElapsedTime = New-TimeSpan -Start $CMDER_INIT_START -End $CMDER_INIT_END + +Write-Verbose "Elapsed Time: $($ElapsedTime.TotalSeconds) seconds total" diff --git a/vendor/psmodules/Cmder.ps1 b/vendor/psmodules/Cmder.ps1 index e3c48d4..79c249b 100644 --- a/vendor/psmodules/Cmder.ps1 +++ b/vendor/psmodules/Cmder.ps1 @@ -1,179 +1,179 @@ -function readVersion($gitPath) { - $gitExecutable = "${gitPath}\git.exe" - - if (-not (Test-Path "$gitExecutable")) { - return $null - } - - $gitVersion = (cmd /c "${gitExecutable}" --version) - - if ($gitVersion -match 'git version') { - ($trash1, $trash2, $gitVersion) = $gitVersion.split(' ', 3) - } else { - pause - return $null - } - - return $gitVersion.toString() -} - -function isGitShim($gitPath) { - # check if there is a shim file - if yes, read the actual executable path - # See: github.com/ScoopInstaller/Shim - - if (Test-Path "${gitPath}\git.shim") { - $shim = (get-content "${gitPath}\git.shim") - ($trash, $gitPath) = $shim.replace(' ', '').split('=') - - $gitPath = $gitPath.replace('\git.exe', '') - } - - return $gitPath.toString() -} - -function compareVersions($userVersion, $vendorVersion) { - if ($null -ne $userVersion) { - ($userMajor, $userMinor, $userPatch, $userBuild) = $userVersion.split('.', 4) - } else { - return -1 - } - - if ($null -ne $vendorVersion) { - ($vendorMajor, $vendorMinor, $vendorPatch, $vendorBuild) = $vendorVersion.split('.', 4) - } else { - return 1 - } - - if (($userMajor -eq $vendorMajor) -and ($userMinor -eq $vendorMinor) -and ($userPatch -eq $vendorPatch) -and ($userBuild -eq $vendorBuild)) { - return 1 - } - - if ($userMajor -gt $vendorMajor) { return 1 } - if ($userMajor -lt $vendorMajor) { return -1 } - - if ($userMinor -gt $vendorMinor) { return 1 } - if ($userMinor -lt $vendorMinor) { return -1 } - - if ($userPatch -gt $vendorPatch) { return 1 } - if ($userPatch -lt $vendorPatch) { return -1 } - - if ($userBuild -gt $vendorBuild) { return 1 } - if ($userBuild -lt $vendorBuild) { return -1 } - - return 0 -} - -function compare_git_versions($userVersion, $vendorVersion) { - $result = compareVersions -userVersion $userVersion -vendorVersion $vendorVersion - - Write-Debug "Compare Versions Result: ${result}" - if ($result -ge 0) { - return $userVersion - } - else { - return $vendorVersion - } -} - -function Configure-Git($gitRoot, $gitType, $gitPathUser) { - # Proposed Behavior - - # Modify the path if we are using VENDORED Git, do nothing if using USER Git. - # If User Git is installed but is older, match its path config adding paths - # in the same path positions allowing a user to configure Cmder Git path - # using locally installed Git Path Config. - if ($gitType -eq 'VENDOR') { - # If User Git is installed replace its path config with Newer Vendored Git Path - if (($null -ne $gitPathUser) -and ($gitPathUser -ne '')) { - Write-Verbose "Cmder 'profile.ps1': Replacing older user Git path '$gitPathUser' with newer vendored Git path '$gitRoot' in the system path..." - - $newPath = ($env:path -ireplace [regex]::Escape($gitPathUser), $gitRoot) - } - else { - if (-not ($env:Path -match [regex]::Escape("$gitRoot\cmd"))) { - Write-Debug "Adding $gitRoot\cmd to the path" - $newPath = $($gitRoot + "\cmd" + ";" + $env:Path) - } - - # Add "$gitRoot\mingw[32|64]\bin" to the path if exists and not done already - if ((Test-Path "$gitRoot\mingw32\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw32\bin"))) { - Write-Debug "Adding $gitRoot\mingw32\bin to the path" - $newPath = "$newPath;$gitRoot\mingw32\bin" - } - elseif ((Test-Path "$gitRoot\mingw64\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw64\bin"))) { - Write-Debug "Adding $gitRoot\mingw64\bin to the path" - $newPath = "$newPath;$gitRoot\mingw64\bin" - } - - # Add "$gitRoot\usr\bin" to the path if exists and not done already - if ((Test-Path "$gitRoot\usr\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\usr\bin"))) { - Write-Debug "Adding $gitRoot\usr\bin to the path" - $newPath = "$newPath;$gitRoot\usr\bin" - } - } - - return $newPath - } - - return $env:path -} - -function Import-Git() { - $GitModule = Get-Module -Name Posh-Git -ListAvailable - if ($GitModule | Select-Object version | Where-Object version -le ([version]"0.6.1.20160330")) { - Import-Module Posh-Git > $null - } - if ($GitModule | Select-Object version | Where-Object version -ge ([version]"1.0.0")) { - Import-Module Posh-Git > $null - $GitPromptSettings.AnsiConsole = $false - } - if (-not $GitModule) { - Write-Host -NoNewline "`r`n" - Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart Cmder." - Write-Host -NoNewline "`r$([char]0x1B)[A" - return $false - } - # Make sure we only run once by always returning true - return $true -} - -function checkGit($Path) { - if (-not (Get-Command git -ErrorAction SilentlyContinue)) { - return - } - if (-not (Test-Path -Path (Join-Path $Path '.git'))) { - $SplitPath = Split-Path $path - if ($SplitPath) { checkGit($SplitPath) } - return - } - if (getGitStatusSetting -eq $true) { - if ($null -eq $env:gitLoaded) { - $env:gitLoaded = Import-Git - } - if ($env:gitLoaded -eq $true) { - Write-VcsStatus - } - } - else { - $headContent = Get-Content (Join-Path $Path '.git/HEAD') - if ($headContent -like "ref: refs/heads/*") { - $branchName = $headContent.Substring(16) - } - else { - $branchName = "HEAD detached at $($headContent.Substring(0, 7))" - } - Write-Host " [$branchName]" -NoNewline -ForegroundColor White - } -} - -function getGitStatusSetting() { - $gitStatus = (git --no-pager config -l) | Out-String - - foreach ($line in $($gitStatus -split "`r`n")) { - if (($line -match 'cmder.status=false') -or ($line -match 'cmder.psstatus=false')) { - return $false - } - } - - return $true -} +function readGitVersion($gitPath) { + $gitExecutable = "${gitPath}\git.exe" + + if (-not (Test-Path "$gitExecutable")) { + return $null + } + + $gitVersion = (cmd /c "${gitExecutable}" --version) + + if ($gitVersion -match 'git version') { + ($trash1, $trash2, $gitVersion) = $gitVersion.split(' ', 3) + } else { + pause + return $null + } + + return $gitVersion.toString() +} + +function isGitShim($gitPath) { + # Check if there is a shim file - if yes, read the actual executable path + # See: github.com/ScoopInstaller/Shim + + if (Test-Path "${gitPath}\git.shim") { + $shim = (get-content "${gitPath}\git.shim") + ($trash, $gitPath) = $shim.replace(' ', '').split('=') + + $gitPath = $gitPath.replace('\git.exe', '') + } + + return $gitPath.toString() +} + +function compareVersions($userVersion, $vendorVersion) { + if ($null -ne $userVersion) { + ($userMajor, $userMinor, $userPatch, $userBuild) = $userVersion.split('.', 4) + } else { + return -1 + } + + if ($null -ne $vendorVersion) { + ($vendorMajor, $vendorMinor, $vendorPatch, $vendorBuild) = $vendorVersion.split('.', 4) + } else { + return 1 + } + + if (($userMajor -eq $vendorMajor) -and ($userMinor -eq $vendorMinor) -and ($userPatch -eq $vendorPatch) -and ($userBuild -eq $vendorBuild)) { + return 1 + } + + if ($userMajor -gt $vendorMajor) { return 1 } + if ($userMajor -lt $vendorMajor) { return -1 } + + if ($userMinor -gt $vendorMinor) { return 1 } + if ($userMinor -lt $vendorMinor) { return -1 } + + if ($userPatch -gt $vendorPatch) { return 1 } + if ($userPatch -lt $vendorPatch) { return -1 } + + if ($userBuild -gt $vendorBuild) { return 1 } + if ($userBuild -lt $vendorBuild) { return -1 } + + return 0 +} + +function compare_git_versions($userVersion, $vendorVersion) { + $result = compareVersions -userVersion $userVersion -vendorVersion $vendorVersion + + Write-Debug "Compare Versions Result: ${result}" + if ($result -ge 0) { + return $userVersion + } + else { + return $vendorVersion + } +} + +function Configure-Git($gitRoot, $gitType, $gitPathUser) { + # Proposed Behavior + + # Modify the path if we are using VENDORED Git, do nothing if using USER Git. + # If User Git is installed but is older, match its path config adding paths + # in the same path positions allowing a user to configure Cmder Git path + # using locally installed Git Path Config. + if ($gitType -eq 'VENDOR') { + # If User Git is installed replace its path config with Newer Vendored Git Path + if (($null -ne $gitPathUser) -and ($gitPathUser -ne '')) { + Write-Verbose "Cmder 'profile.ps1': Replacing older user Git path '$gitPathUser' with newer vendored Git path '$gitRoot' in the system path..." + + $newPath = ($env:path -ireplace [regex]::Escape($gitPathUser), $gitRoot) + } + else { + if (-not ($env:Path -match [regex]::Escape("$gitRoot\cmd"))) { + Write-Debug "Adding $gitRoot\cmd to the path" + $newPath = $($gitRoot + "\cmd" + ";" + $env:Path) + } + + # Add "$gitRoot\mingw[32|64]\bin" to the path if exists and not done already + if ((Test-Path "$gitRoot\mingw32\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw32\bin"))) { + Write-Debug "Adding $gitRoot\mingw32\bin to the path" + $newPath = "$newPath;$gitRoot\mingw32\bin" + } + elseif ((Test-Path "$gitRoot\mingw64\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw64\bin"))) { + Write-Debug "Adding $gitRoot\mingw64\bin to the path" + $newPath = "$newPath;$gitRoot\mingw64\bin" + } + + # Add "$gitRoot\usr\bin" to the path if exists and not done already + if ((Test-Path "$gitRoot\usr\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\usr\bin"))) { + Write-Debug "Adding $gitRoot\usr\bin to the path" + $newPath = "$newPath;$gitRoot\usr\bin" + } + } + + return $newPath + } + + return $env:path +} + +function Import-Git() { + $GitModule = Get-Module -Name Posh-Git -ListAvailable + if ($GitModule | Select-Object version | Where-Object version -le ([version]"0.6.1.20160330")) { + Import-Module Posh-Git > $null + } + if ($GitModule | Select-Object version | Where-Object version -ge ([version]"1.0.0")) { + Import-Module Posh-Git > $null + $GitPromptSettings.AnsiConsole = $false + } + if (-not $GitModule) { + Write-Host -NoNewline "`r`n" + Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart Cmder." + Write-Host -NoNewline "`r$([char]0x1B)[A" + return $false + } + # Make sure we only run once by always returning true + return $true +} + +function checkGit($Path) { + if (-not (Get-Command git -ErrorAction SilentlyContinue)) { + return + } + if (-not (Test-Path -Path (Join-Path $Path '.git'))) { + $SplitPath = Split-Path $path + if ($SplitPath) { checkGit($SplitPath) } + return + } + if (getGitStatusSetting -eq $true) { + if ($null -eq $env:gitLoaded) { + $env:gitLoaded = Import-Git + } + if ($env:gitLoaded -eq $true) { + Write-VcsStatus + } + } + else { + $headContent = Get-Content (Join-Path $Path '.git/HEAD') + if ($headContent -like "ref: refs/heads/*") { + $branchName = $headContent.Substring(16) + } + else { + $branchName = "HEAD detached at $($headContent.Substring(0, 7))" + } + Write-Host " [$branchName]" -NoNewline -ForegroundColor White + } +} + +function getGitStatusSetting() { + $gitStatus = (git --no-pager config -l) | Out-String + + foreach ($line in $($gitStatus -split "`r`n")) { + if (($line -match 'cmder.status=false') -or ($line -match 'cmder.psstatus=false')) { + return $false + } + } + + return $true +} From a0d085f93eaa69c22449d0217e8daf9eaea2b180 Mon Sep 17 00:00:00 2001 From: David Refoua Date: Sat, 8 Nov 2025 20:48:07 +0330 Subject: [PATCH 2/2] fix line endings --- vendor/profile.ps1 | 556 ++++++++++++++++++------------------- vendor/psmodules/Cmder.ps1 | 358 ++++++++++++------------ 2 files changed, 457 insertions(+), 457 deletions(-) diff --git a/vendor/profile.ps1 b/vendor/profile.ps1 index 977b8c5..c77e81a 100644 --- a/vendor/profile.ps1 +++ b/vendor/profile.ps1 @@ -1,278 +1,278 @@ -# Init Script for PowerShell -# Created as part of Cmder project -# NOTE: This file must be saved using UTF-8 with BOM encoding for prompt symbol to work correctly. - -# !!! THIS FILE IS OVERWRITTEN WHEN CMDER IS UPDATED -# !!! Use "%CMDER_ROOT%\config\user_profile.ps1" to add your own startup commands - -$CMDER_INIT_START = Get-Date - -# Compatibility with PS major versions <= 2 -if (!$PSScriptRoot) { - $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. -if (!$ENV:CMDER_ROOT) { - if ($ENV:ConEmuDir) { - $ENV:CMDER_ROOT = Resolve-Path($ENV:ConEmuDir + "\..\..") - } else { - $ENV:CMDER_ROOT = Resolve-Path($PSScriptRoot + "\..") - } -} - -# Remove trailing '\' -$ENV:CMDER_ROOT = ($ENV:CMDER_ROOT).TrimEnd("\") - -# Recent PowerShell versions include PowerShellGet out of the box -$moduleInstallerAvailable = [bool](Get-Command -Name 'Install-Module' -ErrorAction SilentlyContinue) - -# Add Cmder modules directory to the autoload path. -$CmderModulePath = Join-path $PSScriptRoot "psmodules/" - -# Import Cmder functions -$CmderFunctions = Join-Path $CmderModulePath "Cmder.ps1" -. $CmderFunctions - -# Configure PSModulePath to include Cmder modules if not already present -if (-not $moduleInstallerAvailable -and -not $env:PSModulePath.Contains($CmderModulePath) ) { - $env:PSModulePath = $env:PSModulePath.Insert(0, "$CmderModulePath;") -} - -# Read vendored Git Version -$gitVersionVendor = (readGitVersion -gitPath "$ENV:CMDER_ROOT\vendor\git-for-windows\cmd") -Write-Debug "GIT VENDOR: ${gitVersionVendor}" - -# Get user installed Git version(s) if found, and compare them with vendored version. -foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) { - Write-Debug "GIT PATH: {$git.Path}" - $gitDir = Split-Path -Path $git.Path - $gitDir = isGitShim -gitPath $gitDir - $gitVersionUser = (readGitVersion -gitPath $gitDir) - Write-Debug "GIT USER: ${gitVersionUser}" - - $useGitVersion = compare_git_versions -userVersion $gitVersionUser -vendorVersion $gitVersionVendor - Write-Debug "Using Git Version: ${useGitVersion}" - - # Use user installed Git - if ($null -eq $gitPathUser) { - if ($gitDir -match '\\mingw32\\bin' -or $gitDir -match '\\mingw64\\bin') { - $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 12)) - } else { - $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 4)) - } - } - - if ($useGitVersion -eq $gitVersionUser) { - Write-Debug "Using Git Dir: ${gitDir}" - $ENV:GIT_INSTALL_ROOT = $gitPathUser - $ENV:GIT_INSTALL_TYPE = 'USER' - break - } -} - -# Use vendored Git if no user Git found or user Git is older than vendored Git -if ($null -eq $ENV:GIT_INSTALL_ROOT -and $null -ne $gitVersionVendor) { - $ENV:GIT_INSTALL_ROOT = "$ENV:CMDER_ROOT\vendor\git-for-windows" - $ENV:GIT_INSTALL_TYPE = 'VENDOR' -} - -Write-Debug "GIT_INSTALL_ROOT: ${ENV:GIT_INSTALL_ROOT}" -Write-Debug "GIT_INSTALL_TYPE: ${ENV:GIT_INSTALL_TYPE}" - -if ($null -ne $ENV:GIT_INSTALL_ROOT) { - $env:Path = Configure-Git -gitRoot "$ENV:GIT_INSTALL_ROOT" -gitType $ENV:GIT_INSTALL_TYPE -gitPathUser $gitPathUser -} - -# Create 'vi' alias for 'vim' if vim is available -if (Get-Command -Name "vim" -ErrorAction SilentlyContinue) { - New-Alias -name "vi" -value vim -} - -# PSReadline configuration -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) - if ($env:WT_SESSION) { - Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { - # Get the current command line - $line = $null - $cursor = $null - [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) - - # Accept the line first - [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() - - # Emit OSC 133;C sequence 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)") - } - } -} - -# Pre-assign default prompt hooks so the first run of Cmder gets a working prompt -$env:gitLoaded = $null -[ScriptBlock]$PrePrompt = {} -[ScriptBlock]$PostPrompt = {} -[ScriptBlock]$CmderPrompt = { - # Check if we're currently running under Admin privileges - $identity = [Security.Principal.WindowsIdentity]::GetCurrent() - $principal = [Security.Principal.WindowsPrincipal] $identity - $adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator - $color = "White" - if ($principal.IsInRole($adminRole)) { $color = "Red" } - $Host.UI.RawUI.ForegroundColor = "White" - Microsoft.PowerShell.Utility\Write-Host "PS " -NoNewline -ForegroundColor $color - Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green - checkGit($pwd.ProviderPath) - Microsoft.PowerShell.Utility\Write-Host "`nλ" -NoNewLine -ForegroundColor "DarkGray" -} - -# Enhance Path -$env:Path = "$Env:CMDER_ROOT\bin;$Env:CMDER_ROOT\vendor\bin;$env:Path;$Env:CMDER_ROOT" - -# Drop *.ps1 files into "$ENV:CMDER_ROOT\config\profile.d" -# to source them at startup. -if (-not (Test-Path -PathType container "$ENV:CMDER_ROOT\config\profile.d")) { - New-Item -ItemType Directory -Path "$ENV:CMDER_ROOT\config\profile.d" -} - -Push-Location $ENV:CMDER_ROOT\config\profile.d -foreach ($x in Get-ChildItem *.psm1) { - Write-Verbose "Sourcing $x" - Import-Module $x -} -foreach ($x in Get-ChildItem *.ps1) { - Write-Verbose "Sourcing $x" - . $x -} -Pop-Location - -# Drop *.ps1 files into "$ENV:CMDER_USER_CONFIG\config\profile.d" -# to source them at startup. Requires using cmder.exe /C [cmder_user_root_path] argument -if ($ENV:CMDER_USER_CONFIG -ne "" -and (Test-Path "$ENV:CMDER_USER_CONFIG\profile.d")) { - Push-Location $ENV:CMDER_USER_CONFIG\profile.d - foreach ($x in Get-ChildItem *.psm1) { - Write-Verbose "Sourcing $x" - Import-Module $x - } - foreach ($x in Get-ChildItem *.ps1) { - Write-Verbose "Sourcing $x" - . $x - } - Pop-Location -} - -# Renaming to "config\user_profile.ps1" to "user_profile.ps1" for consistency. -if (Test-Path "$env:CMDER_ROOT\config\user-profile.ps1") { - Rename-Item "$env:CMDER_ROOT\config\user-profile.ps1" user_profile.ps1 -} - -$CmderUserProfilePath = Join-Path $env:CMDER_ROOT "config\user_profile.ps1" -if (Test-Path $CmderUserProfilePath) { - # Create this file and place your own command in there. - . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module -} - -if ($ENV:CMDER_USER_CONFIG) { - # Renaming to "$env:CMDER_USER_CONFIG\user-profile.ps1" to "user_profile.ps1" for consistency. - if (Test-Path "$env:CMDER_USER_CONFIG\user-profile.ps1") { - Rename-Item "$env:CMDER_USER_CONFIG\user-profile.ps1" user_profile.ps1 - } - - $env:Path = "$Env:CMDER_USER_CONFIG\bin;$env:Path" - - $CmderUserProfilePath = Join-Path $ENV:CMDER_USER_CONFIG "user_profile.ps1" - if (Test-Path $CmderUserProfilePath) { - . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module - } -} - -if (-not (Test-Path $CmderUserProfilePath)) { - $CmderUserProfilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($CmderUserProfilePath) - Write-Host -NoNewline "`r" - Write-Host -BackgroundColor Green -ForegroundColor Black "First Run: Creating user startup file: $CmderUserProfilePath" - Copy-Item "$env:CMDER_ROOT\vendor\user_profile.ps1.default" -Destination $CmderUserProfilePath -} - -# -# Prompt Section -# Users should modify their user_profile.ps1 as it will be safe from updates. -# - -# Only set the prompt if it is currently set to the default -# This allows users to configure the prompt in their user_profile.ps1 or config\profile.d\*.ps1 -if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionState.Path.CurrentLocation\)\$\(' -and ` - $(Get-Command prompt).Definition -match '\(\$nestedPromptLevel \+ 1\)\) ";') { - - <# - This scriptblock runs every time the prompt is returned. - Explicitly use functions from MS namespace to protect from being overridden in the user session. - Custom prompt functions are loaded in as constants to get the same behaviour - #> - [ScriptBlock]$Prompt = { - $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)" - } - - $host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf - Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K" - if ($lastSUCCESS -or ($LastExitCode -ne 0)) { - Microsoft.PowerShell.Utility\Write-Host - } - PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline - 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) - if ($env:WT_SESSION) { - Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;B$([char]7)" - } - - $global:LastExitCode = $realLastExitCode - return " " - } - - # Once Created these code blocks cannot be overwritten - # if (-not $(Get-Command PrePrompt).Options -match 'Constant') {Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant} - # if (-not $(Get-Command CmderPrompt).Options -match 'Constant') {Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant} - # if (-not $(Get-Command PostPrompt).Options -match 'Constant') {Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant} - - Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant - Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant - Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant - - # Functions can be made constant only at creation time - # ReadOnly at least requires `-force` to be overwritten - # if (!$(Get-Command Prompt).Options -match 'ReadOnly') {Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly} - Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly -} - -$CMDER_INIT_END = Get-Date - -$ElapsedTime = New-TimeSpan -Start $CMDER_INIT_START -End $CMDER_INIT_END - -Write-Verbose "Elapsed Time: $($ElapsedTime.TotalSeconds) seconds total" +# Init Script for PowerShell +# Created as part of Cmder project +# NOTE: This file must be saved using UTF-8 with BOM encoding for prompt symbol to work correctly. + +# !!! THIS FILE IS OVERWRITTEN WHEN CMDER IS UPDATED +# !!! Use "%CMDER_ROOT%\config\user_profile.ps1" to add your own startup commands + +$CMDER_INIT_START = Get-Date + +# Compatibility with PS major versions <= 2 +if (!$PSScriptRoot) { + $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. +if (!$ENV:CMDER_ROOT) { + if ($ENV:ConEmuDir) { + $ENV:CMDER_ROOT = Resolve-Path($ENV:ConEmuDir + "\..\..") + } else { + $ENV:CMDER_ROOT = Resolve-Path($PSScriptRoot + "\..") + } +} + +# Remove trailing '\' +$ENV:CMDER_ROOT = ($ENV:CMDER_ROOT).TrimEnd("\") + +# Recent PowerShell versions include PowerShellGet out of the box +$moduleInstallerAvailable = [bool](Get-Command -Name 'Install-Module' -ErrorAction SilentlyContinue) + +# Add Cmder modules directory to the autoload path. +$CmderModulePath = Join-path $PSScriptRoot "psmodules/" + +# Import Cmder functions +$CmderFunctions = Join-Path $CmderModulePath "Cmder.ps1" +. $CmderFunctions + +# Configure PSModulePath to include Cmder modules if not already present +if (-not $moduleInstallerAvailable -and -not $env:PSModulePath.Contains($CmderModulePath) ) { + $env:PSModulePath = $env:PSModulePath.Insert(0, "$CmderModulePath;") +} + +# Read vendored Git Version +$gitVersionVendor = (readGitVersion -gitPath "$ENV:CMDER_ROOT\vendor\git-for-windows\cmd") +Write-Debug "GIT VENDOR: ${gitVersionVendor}" + +# Get user installed Git version(s) if found, and compare them with vendored version. +foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) { + Write-Debug "GIT PATH: {$git.Path}" + $gitDir = Split-Path -Path $git.Path + $gitDir = isGitShim -gitPath $gitDir + $gitVersionUser = (readGitVersion -gitPath $gitDir) + Write-Debug "GIT USER: ${gitVersionUser}" + + $useGitVersion = compare_git_versions -userVersion $gitVersionUser -vendorVersion $gitVersionVendor + Write-Debug "Using Git Version: ${useGitVersion}" + + # Use user installed Git + if ($null -eq $gitPathUser) { + if ($gitDir -match '\\mingw32\\bin' -or $gitDir -match '\\mingw64\\bin') { + $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 12)) + } else { + $gitPathUser = ($gitDir.subString(0,$gitDir.Length - 4)) + } + } + + if ($useGitVersion -eq $gitVersionUser) { + Write-Debug "Using Git Dir: ${gitDir}" + $ENV:GIT_INSTALL_ROOT = $gitPathUser + $ENV:GIT_INSTALL_TYPE = 'USER' + break + } +} + +# Use vendored Git if no user Git found or user Git is older than vendored Git +if ($null -eq $ENV:GIT_INSTALL_ROOT -and $null -ne $gitVersionVendor) { + $ENV:GIT_INSTALL_ROOT = "$ENV:CMDER_ROOT\vendor\git-for-windows" + $ENV:GIT_INSTALL_TYPE = 'VENDOR' +} + +Write-Debug "GIT_INSTALL_ROOT: ${ENV:GIT_INSTALL_ROOT}" +Write-Debug "GIT_INSTALL_TYPE: ${ENV:GIT_INSTALL_TYPE}" + +if ($null -ne $ENV:GIT_INSTALL_ROOT) { + $env:Path = Configure-Git -gitRoot "$ENV:GIT_INSTALL_ROOT" -gitType $ENV:GIT_INSTALL_TYPE -gitPathUser $gitPathUser +} + +# Create 'vi' alias for 'vim' if vim is available +if (Get-Command -Name "vim" -ErrorAction SilentlyContinue) { + New-Alias -name "vi" -value vim +} + +# PSReadline configuration +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) + if ($env:WT_SESSION) { + Set-PSReadLineKeyHandler -Key Enter -ScriptBlock { + # Get the current command line + $line = $null + $cursor = $null + [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) + + # Accept the line first + [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() + + # Emit OSC 133;C sequence 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)") + } + } +} + +# Pre-assign default prompt hooks so the first run of Cmder gets a working prompt +$env:gitLoaded = $null +[ScriptBlock]$PrePrompt = {} +[ScriptBlock]$PostPrompt = {} +[ScriptBlock]$CmderPrompt = { + # Check if we're currently running under Admin privileges + $identity = [Security.Principal.WindowsIdentity]::GetCurrent() + $principal = [Security.Principal.WindowsPrincipal] $identity + $adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator + $color = "White" + if ($principal.IsInRole($adminRole)) { $color = "Red" } + $Host.UI.RawUI.ForegroundColor = "White" + Microsoft.PowerShell.Utility\Write-Host "PS " -NoNewline -ForegroundColor $color + Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green + checkGit($pwd.ProviderPath) + Microsoft.PowerShell.Utility\Write-Host "`nλ" -NoNewLine -ForegroundColor "DarkGray" +} + +# Enhance Path +$env:Path = "$Env:CMDER_ROOT\bin;$Env:CMDER_ROOT\vendor\bin;$env:Path;$Env:CMDER_ROOT" + +# Drop *.ps1 files into "$ENV:CMDER_ROOT\config\profile.d" +# to source them at startup. +if (-not (Test-Path -PathType container "$ENV:CMDER_ROOT\config\profile.d")) { + New-Item -ItemType Directory -Path "$ENV:CMDER_ROOT\config\profile.d" +} + +Push-Location $ENV:CMDER_ROOT\config\profile.d +foreach ($x in Get-ChildItem *.psm1) { + Write-Verbose "Sourcing $x" + Import-Module $x +} +foreach ($x in Get-ChildItem *.ps1) { + Write-Verbose "Sourcing $x" + . $x +} +Pop-Location + +# Drop *.ps1 files into "$ENV:CMDER_USER_CONFIG\config\profile.d" +# to source them at startup. Requires using cmder.exe /C [cmder_user_root_path] argument +if ($ENV:CMDER_USER_CONFIG -ne "" -and (Test-Path "$ENV:CMDER_USER_CONFIG\profile.d")) { + Push-Location $ENV:CMDER_USER_CONFIG\profile.d + foreach ($x in Get-ChildItem *.psm1) { + Write-Verbose "Sourcing $x" + Import-Module $x + } + foreach ($x in Get-ChildItem *.ps1) { + Write-Verbose "Sourcing $x" + . $x + } + Pop-Location +} + +# Renaming to "config\user_profile.ps1" to "user_profile.ps1" for consistency. +if (Test-Path "$env:CMDER_ROOT\config\user-profile.ps1") { + Rename-Item "$env:CMDER_ROOT\config\user-profile.ps1" user_profile.ps1 +} + +$CmderUserProfilePath = Join-Path $env:CMDER_ROOT "config\user_profile.ps1" +if (Test-Path $CmderUserProfilePath) { + # Create this file and place your own command in there. + . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module +} + +if ($ENV:CMDER_USER_CONFIG) { + # Renaming to "$env:CMDER_USER_CONFIG\user-profile.ps1" to "user_profile.ps1" for consistency. + if (Test-Path "$env:CMDER_USER_CONFIG\user-profile.ps1") { + Rename-Item "$env:CMDER_USER_CONFIG\user-profile.ps1" user_profile.ps1 + } + + $env:Path = "$Env:CMDER_USER_CONFIG\bin;$env:Path" + + $CmderUserProfilePath = Join-Path $ENV:CMDER_USER_CONFIG "user_profile.ps1" + if (Test-Path $CmderUserProfilePath) { + . "$CmderUserProfilePath" # user_profile.ps1 is not a module DO NOT USE import-module + } +} + +if (-not (Test-Path $CmderUserProfilePath)) { + $CmderUserProfilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($CmderUserProfilePath) + Write-Host -NoNewline "`r" + Write-Host -BackgroundColor Green -ForegroundColor Black "First Run: Creating user startup file: $CmderUserProfilePath" + Copy-Item "$env:CMDER_ROOT\vendor\user_profile.ps1.default" -Destination $CmderUserProfilePath +} + +# +# Prompt Section +# Users should modify their user_profile.ps1 as it will be safe from updates. +# + +# Only set the prompt if it is currently set to the default +# This allows users to configure the prompt in their user_profile.ps1 or config\profile.d\*.ps1 +if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionState.Path.CurrentLocation\)\$\(' -and ` + $(Get-Command prompt).Definition -match '\(\$nestedPromptLevel \+ 1\)\) ";') { + + <# + This scriptblock runs every time the prompt is returned. + Explicitly use functions from MS namespace to protect from being overridden in the user session. + Custom prompt functions are loaded in as constants to get the same behaviour + #> + [ScriptBlock]$Prompt = { + $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)" + } + + $host.UI.RawUI.WindowTitle = Microsoft.PowerShell.Management\Split-Path $pwd.ProviderPath -Leaf + Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K" + if ($lastSUCCESS -or ($LastExitCode -ne 0)) { + Microsoft.PowerShell.Utility\Write-Host + } + PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline + 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) + if ($env:WT_SESSION) { + Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x1B)]133;B$([char]7)" + } + + $global:LastExitCode = $realLastExitCode + return " " + } + + # Once Created these code blocks cannot be overwritten + # if (-not $(Get-Command PrePrompt).Options -match 'Constant') {Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant} + # if (-not $(Get-Command CmderPrompt).Options -match 'Constant') {Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant} + # if (-not $(Get-Command PostPrompt).Options -match 'Constant') {Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant} + + Set-Item -Path function:\PrePrompt -Value $PrePrompt -Options Constant + Set-Item -Path function:\CmderPrompt -Value $CmderPrompt -Options Constant + Set-Item -Path function:\PostPrompt -Value $PostPrompt -Options Constant + + # Functions can be made constant only at creation time + # ReadOnly at least requires `-force` to be overwritten + # if (!$(Get-Command Prompt).Options -match 'ReadOnly') {Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly} + Set-Item -Path function:\prompt -Value $Prompt -Options ReadOnly +} + +$CMDER_INIT_END = Get-Date + +$ElapsedTime = New-TimeSpan -Start $CMDER_INIT_START -End $CMDER_INIT_END + +Write-Verbose "Elapsed Time: $($ElapsedTime.TotalSeconds) seconds total" diff --git a/vendor/psmodules/Cmder.ps1 b/vendor/psmodules/Cmder.ps1 index 79c249b..a72da65 100644 --- a/vendor/psmodules/Cmder.ps1 +++ b/vendor/psmodules/Cmder.ps1 @@ -1,179 +1,179 @@ -function readGitVersion($gitPath) { - $gitExecutable = "${gitPath}\git.exe" - - if (-not (Test-Path "$gitExecutable")) { - return $null - } - - $gitVersion = (cmd /c "${gitExecutable}" --version) - - if ($gitVersion -match 'git version') { - ($trash1, $trash2, $gitVersion) = $gitVersion.split(' ', 3) - } else { - pause - return $null - } - - return $gitVersion.toString() -} - -function isGitShim($gitPath) { - # Check if there is a shim file - if yes, read the actual executable path - # See: github.com/ScoopInstaller/Shim - - if (Test-Path "${gitPath}\git.shim") { - $shim = (get-content "${gitPath}\git.shim") - ($trash, $gitPath) = $shim.replace(' ', '').split('=') - - $gitPath = $gitPath.replace('\git.exe', '') - } - - return $gitPath.toString() -} - -function compareVersions($userVersion, $vendorVersion) { - if ($null -ne $userVersion) { - ($userMajor, $userMinor, $userPatch, $userBuild) = $userVersion.split('.', 4) - } else { - return -1 - } - - if ($null -ne $vendorVersion) { - ($vendorMajor, $vendorMinor, $vendorPatch, $vendorBuild) = $vendorVersion.split('.', 4) - } else { - return 1 - } - - if (($userMajor -eq $vendorMajor) -and ($userMinor -eq $vendorMinor) -and ($userPatch -eq $vendorPatch) -and ($userBuild -eq $vendorBuild)) { - return 1 - } - - if ($userMajor -gt $vendorMajor) { return 1 } - if ($userMajor -lt $vendorMajor) { return -1 } - - if ($userMinor -gt $vendorMinor) { return 1 } - if ($userMinor -lt $vendorMinor) { return -1 } - - if ($userPatch -gt $vendorPatch) { return 1 } - if ($userPatch -lt $vendorPatch) { return -1 } - - if ($userBuild -gt $vendorBuild) { return 1 } - if ($userBuild -lt $vendorBuild) { return -1 } - - return 0 -} - -function compare_git_versions($userVersion, $vendorVersion) { - $result = compareVersions -userVersion $userVersion -vendorVersion $vendorVersion - - Write-Debug "Compare Versions Result: ${result}" - if ($result -ge 0) { - return $userVersion - } - else { - return $vendorVersion - } -} - -function Configure-Git($gitRoot, $gitType, $gitPathUser) { - # Proposed Behavior - - # Modify the path if we are using VENDORED Git, do nothing if using USER Git. - # If User Git is installed but is older, match its path config adding paths - # in the same path positions allowing a user to configure Cmder Git path - # using locally installed Git Path Config. - if ($gitType -eq 'VENDOR') { - # If User Git is installed replace its path config with Newer Vendored Git Path - if (($null -ne $gitPathUser) -and ($gitPathUser -ne '')) { - Write-Verbose "Cmder 'profile.ps1': Replacing older user Git path '$gitPathUser' with newer vendored Git path '$gitRoot' in the system path..." - - $newPath = ($env:path -ireplace [regex]::Escape($gitPathUser), $gitRoot) - } - else { - if (-not ($env:Path -match [regex]::Escape("$gitRoot\cmd"))) { - Write-Debug "Adding $gitRoot\cmd to the path" - $newPath = $($gitRoot + "\cmd" + ";" + $env:Path) - } - - # Add "$gitRoot\mingw[32|64]\bin" to the path if exists and not done already - if ((Test-Path "$gitRoot\mingw32\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw32\bin"))) { - Write-Debug "Adding $gitRoot\mingw32\bin to the path" - $newPath = "$newPath;$gitRoot\mingw32\bin" - } - elseif ((Test-Path "$gitRoot\mingw64\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw64\bin"))) { - Write-Debug "Adding $gitRoot\mingw64\bin to the path" - $newPath = "$newPath;$gitRoot\mingw64\bin" - } - - # Add "$gitRoot\usr\bin" to the path if exists and not done already - if ((Test-Path "$gitRoot\usr\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\usr\bin"))) { - Write-Debug "Adding $gitRoot\usr\bin to the path" - $newPath = "$newPath;$gitRoot\usr\bin" - } - } - - return $newPath - } - - return $env:path -} - -function Import-Git() { - $GitModule = Get-Module -Name Posh-Git -ListAvailable - if ($GitModule | Select-Object version | Where-Object version -le ([version]"0.6.1.20160330")) { - Import-Module Posh-Git > $null - } - if ($GitModule | Select-Object version | Where-Object version -ge ([version]"1.0.0")) { - Import-Module Posh-Git > $null - $GitPromptSettings.AnsiConsole = $false - } - if (-not $GitModule) { - Write-Host -NoNewline "`r`n" - Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart Cmder." - Write-Host -NoNewline "`r$([char]0x1B)[A" - return $false - } - # Make sure we only run once by always returning true - return $true -} - -function checkGit($Path) { - if (-not (Get-Command git -ErrorAction SilentlyContinue)) { - return - } - if (-not (Test-Path -Path (Join-Path $Path '.git'))) { - $SplitPath = Split-Path $path - if ($SplitPath) { checkGit($SplitPath) } - return - } - if (getGitStatusSetting -eq $true) { - if ($null -eq $env:gitLoaded) { - $env:gitLoaded = Import-Git - } - if ($env:gitLoaded -eq $true) { - Write-VcsStatus - } - } - else { - $headContent = Get-Content (Join-Path $Path '.git/HEAD') - if ($headContent -like "ref: refs/heads/*") { - $branchName = $headContent.Substring(16) - } - else { - $branchName = "HEAD detached at $($headContent.Substring(0, 7))" - } - Write-Host " [$branchName]" -NoNewline -ForegroundColor White - } -} - -function getGitStatusSetting() { - $gitStatus = (git --no-pager config -l) | Out-String - - foreach ($line in $($gitStatus -split "`r`n")) { - if (($line -match 'cmder.status=false') -or ($line -match 'cmder.psstatus=false')) { - return $false - } - } - - return $true -} +function readGitVersion($gitPath) { + $gitExecutable = "${gitPath}\git.exe" + + if (-not (Test-Path "$gitExecutable")) { + return $null + } + + $gitVersion = (cmd /c "${gitExecutable}" --version) + + if ($gitVersion -match 'git version') { + ($trash1, $trash2, $gitVersion) = $gitVersion.split(' ', 3) + } else { + pause + return $null + } + + return $gitVersion.toString() +} + +function isGitShim($gitPath) { + # Check if there is a shim file - if yes, read the actual executable path + # See: github.com/ScoopInstaller/Shim + + if (Test-Path "${gitPath}\git.shim") { + $shim = (get-content "${gitPath}\git.shim") + ($trash, $gitPath) = $shim.replace(' ', '').split('=') + + $gitPath = $gitPath.replace('\git.exe', '') + } + + return $gitPath.toString() +} + +function compareVersions($userVersion, $vendorVersion) { + if ($null -ne $userVersion) { + ($userMajor, $userMinor, $userPatch, $userBuild) = $userVersion.split('.', 4) + } else { + return -1 + } + + if ($null -ne $vendorVersion) { + ($vendorMajor, $vendorMinor, $vendorPatch, $vendorBuild) = $vendorVersion.split('.', 4) + } else { + return 1 + } + + if (($userMajor -eq $vendorMajor) -and ($userMinor -eq $vendorMinor) -and ($userPatch -eq $vendorPatch) -and ($userBuild -eq $vendorBuild)) { + return 1 + } + + if ($userMajor -gt $vendorMajor) { return 1 } + if ($userMajor -lt $vendorMajor) { return -1 } + + if ($userMinor -gt $vendorMinor) { return 1 } + if ($userMinor -lt $vendorMinor) { return -1 } + + if ($userPatch -gt $vendorPatch) { return 1 } + if ($userPatch -lt $vendorPatch) { return -1 } + + if ($userBuild -gt $vendorBuild) { return 1 } + if ($userBuild -lt $vendorBuild) { return -1 } + + return 0 +} + +function compare_git_versions($userVersion, $vendorVersion) { + $result = compareVersions -userVersion $userVersion -vendorVersion $vendorVersion + + Write-Debug "Compare Versions Result: ${result}" + if ($result -ge 0) { + return $userVersion + } + else { + return $vendorVersion + } +} + +function Configure-Git($gitRoot, $gitType, $gitPathUser) { + # Proposed Behavior + + # Modify the path if we are using VENDORED Git, do nothing if using USER Git. + # If User Git is installed but is older, match its path config adding paths + # in the same path positions allowing a user to configure Cmder Git path + # using locally installed Git Path Config. + if ($gitType -eq 'VENDOR') { + # If User Git is installed replace its path config with Newer Vendored Git Path + if (($null -ne $gitPathUser) -and ($gitPathUser -ne '')) { + Write-Verbose "Cmder 'profile.ps1': Replacing older user Git path '$gitPathUser' with newer vendored Git path '$gitRoot' in the system path..." + + $newPath = ($env:path -ireplace [regex]::Escape($gitPathUser), $gitRoot) + } + else { + if (-not ($env:Path -match [regex]::Escape("$gitRoot\cmd"))) { + Write-Debug "Adding $gitRoot\cmd to the path" + $newPath = $($gitRoot + "\cmd" + ";" + $env:Path) + } + + # Add "$gitRoot\mingw[32|64]\bin" to the path if exists and not done already + if ((Test-Path "$gitRoot\mingw32\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw32\bin"))) { + Write-Debug "Adding $gitRoot\mingw32\bin to the path" + $newPath = "$newPath;$gitRoot\mingw32\bin" + } + elseif ((Test-Path "$gitRoot\mingw64\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\mingw64\bin"))) { + Write-Debug "Adding $gitRoot\mingw64\bin to the path" + $newPath = "$newPath;$gitRoot\mingw64\bin" + } + + # Add "$gitRoot\usr\bin" to the path if exists and not done already + if ((Test-Path "$gitRoot\usr\bin") -and -not ($env:path -match [regex]::Escape("$gitRoot\usr\bin"))) { + Write-Debug "Adding $gitRoot\usr\bin to the path" + $newPath = "$newPath;$gitRoot\usr\bin" + } + } + + return $newPath + } + + return $env:path +} + +function Import-Git() { + $GitModule = Get-Module -Name Posh-Git -ListAvailable + if ($GitModule | Select-Object version | Where-Object version -le ([version]"0.6.1.20160330")) { + Import-Module Posh-Git > $null + } + if ($GitModule | Select-Object version | Where-Object version -ge ([version]"1.0.0")) { + Import-Module Posh-Git > $null + $GitPromptSettings.AnsiConsole = $false + } + if (-not $GitModule) { + Write-Host -NoNewline "`r`n" + Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart Cmder." + Write-Host -NoNewline "`r$([char]0x1B)[A" + return $false + } + # Make sure we only run once by always returning true + return $true +} + +function checkGit($Path) { + if (-not (Get-Command git -ErrorAction SilentlyContinue)) { + return + } + if (-not (Test-Path -Path (Join-Path $Path '.git'))) { + $SplitPath = Split-Path $path + if ($SplitPath) { checkGit($SplitPath) } + return + } + if (getGitStatusSetting -eq $true) { + if ($null -eq $env:gitLoaded) { + $env:gitLoaded = Import-Git + } + if ($env:gitLoaded -eq $true) { + Write-VcsStatus + } + } + else { + $headContent = Get-Content (Join-Path $Path '.git/HEAD') + if ($headContent -like "ref: refs/heads/*") { + $branchName = $headContent.Substring(16) + } + else { + $branchName = "HEAD detached at $($headContent.Substring(0, 7))" + } + Write-Host " [$branchName]" -NoNewline -ForegroundColor White + } +} + +function getGitStatusSetting() { + $gitStatus = (git --no-pager config -l) | Out-String + + foreach ($line in $($gitStatus -split "`r`n")) { + if (($line -match 'cmder.status=false') -or ($line -match 'cmder.psstatus=false')) { + return $false + } + } + + return $true +}