Compare commits

..

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
7510436f7d Initial plan 2025-11-06 14:58:03 +00:00
David Refoua
f6eb7aa4f8 Improve path enhancement handling in lib_path.cmd
Refactor path enhancement logic for clarity and robustness.
2025-11-06 18:26:41 +03:30
18 changed files with 267 additions and 734 deletions

View File

@@ -19,25 +19,10 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out the repository under $GITHUB_WORKSPACE, so the job can access it
- uses: actions/checkout@v6
- uses: actions/checkout@v5
with:
fetch-depth: 0 # fetch all history for all branches and tags
- name: Summary - Merge operation started
shell: bash
run: |
echo "## 🔀 Update Branches - Workflow Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Merge Operation" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
echo "| Source Branch | \`master\` |" >> $GITHUB_STEP_SUMMARY
echo "| Target Branch | \`development\` |" >> $GITHUB_STEP_SUMMARY
echo "| Triggered by | @${{ github.actor }} |" >> $GITHUB_STEP_SUMMARY
echo "| Commit | \`${{ github.sha }}\` |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Runs a single command using the runners shell
- name: Merge master into development
run: |
@@ -46,15 +31,3 @@ jobs:
git checkout development
git merge --no-ff master
git push origin development
- name: Summary - Merge completed
if: success()
shell: bash
run: |
echo "### ✅ Merge Successful" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The \`master\` branch has been successfully merged into \`development\`." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Merge type:** No fast-forward merge" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "> The development branch is now synchronized with the latest changes from master." >> $GITHUB_STEP_SUMMARY

View File

@@ -35,25 +35,10 @@ jobs:
discussions: write
steps:
- name: Check out repository code (Action from GitHub)
uses: actions/checkout@v6
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Summary - Repository checkout
shell: pwsh
run: |
echo "## 📦 Build Cmder - Workflow Summary" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "### Repository Information" >> $env:GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $env:GITHUB_STEP_SUMMARY
echo "| Repository | \`${{ github.repository }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ github.ref_name }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Commit | \`${{ github.sha }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Actor | @${{ github.actor }} |" >> $env:GITHUB_STEP_SUMMARY
echo "| Workflow | \`${{ github.workflow }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2
@@ -62,40 +47,11 @@ jobs:
working-directory: scripts
run: .\build.ps1 -Compile -verbose
- name: Summary - Build completed
if: success()
shell: pwsh
run: |
echo "### ✅ Build Status" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Cmder launcher successfully compiled." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Pack the built files
shell: pwsh
working-directory: scripts
run: .\pack.ps1 -verbose
- name: Summary - Package artifacts
if: success()
shell: pwsh
run: |
echo "### 📦 Artifacts Created" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "| Artifact | Size | Hash (SHA256) |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- | --- |" >> $env:GITHUB_STEP_SUMMARY
$artifacts = @("cmder.zip", "cmder.7z", "cmder_mini.zip")
foreach ($artifact in $artifacts) {
$path = "build/$artifact"
if (Test-Path $path) {
$size = (Get-Item $path).Length / 1MB
# Truncate hash to first 16 chars for summary readability (full hash in hashes.txt)
$hash = (Get-FileHash $path -Algorithm SHA256).Hash.Substring(0, 16)
echo "| \`$artifact\` | $([math]::Round($size, 2)) MB | \`$hash...\` |" >> $env:GITHUB_STEP_SUMMARY
}
}
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Upload artifact (cmder.zip)
uses: actions/upload-artifact@v5
with:
@@ -121,19 +77,6 @@ jobs:
path: build/hashes.txt
name: hashes.txt
- name: Summary - Artifacts uploaded
if: success()
shell: pwsh
run: |
echo "### ☁️ Upload Status" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "All artifacts successfully uploaded to GitHub Actions:" >> $env:GITHUB_STEP_SUMMARY
echo "- ✅ \`cmder.zip\`" >> $env:GITHUB_STEP_SUMMARY
echo "- ✅ \`cmder.7z\`" >> $env:GITHUB_STEP_SUMMARY
echo "- ✅ \`cmder_mini.zip\`" >> $env:GITHUB_STEP_SUMMARY
echo "- ✅ \`hashes.txt\`" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Create Release
uses: softprops/action-gh-release@v2
with:
@@ -145,18 +88,3 @@ jobs:
draft: true
generate_release_notes: true
if: startsWith(github.ref, 'refs/tags/')
- name: Summary - Release created
if: startsWith(github.ref, 'refs/tags/')
shell: pwsh
run: |
echo "### 🚀 Release Information" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Draft release created for tag: **\`${{ github.ref_name }}\`**" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Release includes:" >> $env:GITHUB_STEP_SUMMARY
echo "- Full version (\`cmder.zip\`, \`cmder.7z\`)" >> $env:GITHUB_STEP_SUMMARY
echo "- Mini version (\`cmder_mini.zip\`)" >> $env:GITHUB_STEP_SUMMARY
echo "- File hashes (\`hashes.txt\`)" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "> ⚠️ Release is in **draft** mode. Please review and publish manually." >> $env:GITHUB_STEP_SUMMARY

View File

@@ -45,22 +45,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Summary - CodeQL analysis started
shell: pwsh
run: |
echo "## 🔒 CodeQL Security Analysis - Workflow Summary" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "### Analysis Configuration" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $env:GITHUB_STEP_SUMMARY
echo "| Repository | \`${{ github.repository }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ github.ref_name }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Language | \`${{ matrix.language }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Commit | \`${{ github.sha }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
uses: actions/checkout@v5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
@@ -82,28 +67,7 @@ jobs:
working-directory: scripts
run: .\build.ps1 -Compile -verbose
- name: Summary - Build status
if: success()
shell: pwsh
run: |
echo "### ✅ Build Completed" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Cmder launcher built successfully for CodeQL analysis." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
- name: Summary - Analysis completed
if: success()
shell: pwsh
run: |
echo "### 🔍 CodeQL Analysis Results" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "✅ CodeQL security analysis completed successfully." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "**Language analyzed:** \`${{ matrix.language }}\`" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "> Check the Security tab for detailed findings and recommendations." >> $env:GITHUB_STEP_SUMMARY

View File

@@ -38,78 +38,17 @@ jobs:
continue-on-error: false
steps:
- uses: actions/checkout@v6
- name: Summary - Test execution started
shell: pwsh
run: |
echo "## 🧪 Run Tests - Workflow Summary" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "### Test Environment" >> $env:GITHUB_STEP_SUMMARY
echo "| Property | Value |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $env:GITHUB_STEP_SUMMARY
echo "| Repository | \`${{ github.repository }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ github.ref_name }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Commit | \`${{ github.sha }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "| Runner OS | \`${{ runner.os }}\` |" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- uses: actions/checkout@v5
- name: Initialize vendors
shell: pwsh
working-directory: scripts
run: .\build.ps1 -verbose
- name: Summary - Vendor initialization
if: success()
shell: pwsh
run: |
echo "### ⚙️ Vendor Initialization" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "✅ Vendor dependencies initialized successfully." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- name: Summary - Test results table header
if: success()
shell: pwsh
run: |
echo "### 📋 Test Results" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "| Test | Status |" >> $env:GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $env:GITHUB_STEP_SUMMARY
- name: Testing Clink Shell
run: |
cmd /c vendor\init.bat /v /d /t
- name: Summary - Clink Shell test
if: success()
shell: pwsh
run: |
echo "| Clink Shell | ✅ Passed |" >> $env:GITHUB_STEP_SUMMARY
- name: Testing PowerShell
run: |
PowerShell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "$env:CMDER_DEBUG='1'; . 'vendor\profile.ps1'"
- name: Summary - PowerShell test
if: success()
shell: pwsh
run: |
echo "| PowerShell | ✅ Passed |" >> $env:GITHUB_STEP_SUMMARY
PowerShell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "Invoke-Expression '. ''vendor\profile.ps1'''"
- name: Testing Bash
run: |
bash vendor/cmder.sh
- name: Summary - Bash test
if: success()
shell: pwsh
run: |
echo "| Bash | ✅ Passed |" >> $env:GITHUB_STEP_SUMMARY
- name: Summary - All tests completed
if: success()
shell: pwsh
run: |
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "### ✅ All Tests Completed" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "All shell environments tested successfully!" >> $env:GITHUB_STEP_SUMMARY

View File

@@ -24,18 +24,10 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Summary - Workflow started
shell: pwsh
run: |
echo "## 📦 Update Vendor - Workflow Summary" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "Checking for vendor dependency updates..." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
- id: make-changes
name: Checking for updates
env:
@@ -59,24 +51,6 @@ jobs:
Set-GHVariable -Name LIST_UPDATED -Value $listUpdated.Trim(', ')
echo "UPDATE_MESSAGE<<<EOF`n$updateMessage`n<EOF" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- name: Summary - Update check results
shell: pwsh
run: |
$count = $env:COUNT_UPDATED
if ($count -eq 0) {
echo "### ✅ No Updates Available" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "All vendor dependencies are up to date." >> $env:GITHUB_STEP_SUMMARY
} else {
$word = if ($count -eq 1) { 'dependency' } else { 'dependencies' }
echo "### 🔄 Updates Found" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "**$count** vendor $word updated:" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "$env:UPDATE_MESSAGE" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
}
- uses: peter-evans/create-pull-request@v7
if: env.COUNT_UPDATED > 0
with:
@@ -89,17 +63,3 @@ jobs:
commit-message: '⬆️ Update dependencies (${{ env.LIST_UPDATED }})'
branch: update-vendor
base: master
- name: Summary - Pull request created
if: env.COUNT_UPDATED > 0
shell: pwsh
run: |
echo "### 🎉 Pull Request Created" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "A pull request has been created to update the vendor dependencies." >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "**Branch:** \`update-vendor\`" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "**Updated dependencies:** $env:LIST_UPDATED" >> $env:GITHUB_STEP_SUMMARY
echo "" >> $env:GITHUB_STEP_SUMMARY
echo "> Please review and merge the pull request to apply the updates." >> $env:GITHUB_STEP_SUMMARY

View File

@@ -352,10 +352,6 @@ Cmder by default comes with a vendored ConEmu installation as the underlying ter
However, Cmder can in fact run in a variety of other terminal emulators, and even integrated IDEs. Assuming you have the latest version of Cmder, follow the following instructions to get Cmder working with your own terminal emulator.
⚠ *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, 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).
## Upgrading

View File

@@ -27,7 +27,7 @@
.EXAMPLE
.\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
AUTHORS
Samuel Vasko, Jack Bennett
@@ -60,7 +60,7 @@ Param(
[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\.."
# Dot source util functions into this scope

View File

@@ -2,18 +2,18 @@
.Synopsis
Pack Cmder
.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
Then unblock the script for execution with UnblockFile .\pack.ps1
.EXAMPLE
.\pack.ps1
Creates default archives for Cmder
Creates default archives for cmder
.EXAMPLE
.\pack.ps1 -verbose
Creates default archives for Cmder with plenty of information
Creates default archives for cmder with plenty of information
.NOTES
AUTHORS
Samuel Vasko, Jack Bennett, Martin Kemp

View File

@@ -32,11 +32,7 @@ Param(
# -whatif switch to not actually make changes
# Path to the vendor configuration source file
[string]$sourcesPath = "$PSScriptRoot\..\vendor\sources.json",
# Include pre-release versions (RC, beta, alpha, etc.)
# By default, only stable releases are considered
[switch]$IncludePrerelease = $false
[string]$sourcesPath = "$PSScriptRoot\..\vendor\sources.json"
)
# Get the root directory of the cmder project.
@@ -83,39 +79,11 @@ function Match-Filenames {
return $position
}
# Checks if a release is a pre-release based on GitHub API flag and version tag keywords
# Pre-release keywords include: -rc (release candidate), -beta, -alpha, -preview, -pre
function Test-IsPrerelease {
param (
[Parameter(Mandatory = $true)]
$release
)
# Check if marked as pre-release by GitHub
if ($release.prerelease -eq $true) {
return $true
}
# Check for common pre-release keywords in tag name
# This catches versions like v2.50.0-rc, v1.0.0-beta, v1.0.0-alpha, etc.
$prereleaseKeywords = @('-rc', '-beta', '-alpha', '-preview', '-pre')
foreach ($keyword in $prereleaseKeywords) {
if ($release.tag_name -ilike "*$keyword*") {
return $true
}
}
return $false
}
# Uses the GitHub api in order to fetch the current download links for the latest releases of the repo.
function Fetch-DownloadUrl {
param (
[Parameter(Mandatory = $true)]
$urlStr,
[Parameter(Mandatory = $false)]
[bool]$includePrerelease = $false
$urlStr
)
$url = [uri] $urlStr
@@ -159,13 +127,6 @@ function Fetch-DownloadUrl {
}
:loop foreach ($i in $info) {
# Skip pre-release versions unless explicitly included
# Pre-releases include RC (Release Candidate), beta, alpha, and other test versions
if (-not $includePrerelease -and (Test-IsPrerelease $i)) {
Write-Verbose "Skipping pre-release version: $($i.tag_name)"
continue
}
if (-not ($i.assets -is [array])) {
continue
}
@@ -203,26 +164,12 @@ function Fetch-DownloadUrl {
# Special case for archive downloads of repository
if (($null -eq $downloadLinks) -or (-not $downloadLinks)) {
if ((($p | ForEach-Object { $_.Trim('/') }) -contains "archive")) {
# Find the first release that matches our pre-release filtering criteria
$selectedRelease = $null
foreach ($release in $info) {
# Apply the same filtering logic
if (-not $includePrerelease -and (Test-IsPrerelease $release)) {
continue
}
# Use the first release that passes the filter
$selectedRelease = $release
break
}
if ($selectedRelease -and $selectedRelease.tag_name) {
for ($i = 0; $i -lt $p.Length; $i++) {
if ($p[$i].Trim('/') -eq "archive") {
$p[$i + 1] = $selectedRelease.tag_name + ".zip"
$downloadLinks = $url.Scheme + "://" + $url.Host + ($p -join '')
return $downloadLinks
}
if ((($p | ForEach-Object { $_.Trim('/') }) -contains "archive") -and $info[0].tag_name) {
for ($i = 0; $i -lt $p.Length; $i++) {
if ($p[$i].Trim('/') -eq "archive") {
$p[$i + 1] = $info[0].tag_name + ".zip"
$downloadLinks = $url.Scheme + "://" + $url.Host + ($p -join '')
return $downloadLinks
}
}
}
@@ -268,7 +215,7 @@ foreach ($s in $sources) {
Write-Verbose "Old Link: $($s.url)"
$downloadUrl = Fetch-DownloadUrl $s.url -includePrerelease $IncludePrerelease
$downloadUrl = Fetch-DownloadUrl $s.url
if (($null -eq $downloadUrl) -or ($downloadUrl -eq '')) {
Write-Verbose "No new links were found"

View File

@@ -172,13 +172,13 @@ function Register-Cmder() {
# Text for the context menu item.
$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")
, # Commands the context menu will execute.
$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')
)
Begin

154
vendor/clink.lua vendored
View File

@@ -7,7 +7,7 @@
-- luacheck: globals uah_color cwd_color lamb_color clean_color dirty_color conflict_color unknown_color
-- luacheck: globals prompt_homeSymbol prompt_lambSymbol prompt_type prompt_useHomeSymbol prompt_useUserAtHost
-- luacheck: globals prompt_singleLine prompt_includeVersionControl
-- luacheck: globals prompt_overrideGitStatusOptIn
-- luacheck: globals prompt_overrideGitStatusOptIn prompt_overrideSvnStatusOptIn
-- luacheck: globals clink io.popenyield os.isdir settings.get
-- At first, load the original clink.lua file
@@ -350,8 +350,13 @@ end
-- @return {false|mercurial branch information}
---
local function get_hg_branch()
-- Return the branch information.
local file = io.popen("hg branch 2>nul")
-- Return the branch information. The default is to get just the
-- branch name, but you could e.g. use the "hg-prompt" extension to
-- get more information, such as any applied mq patches. Here's an
-- example of that:
-- local cmd = "hg prompt \"{branch}{status}{|{patch}}{update}\""
local cmd = "hg branch 2>nul"
local file = io.popen(cmd)
if not file then
return false
end
@@ -419,33 +424,12 @@ local function get_git_status()
return { status = is_status, conflict = conflict_found }
end
---
-- Get the status of working dir
-- @return {bool}
---
local function get_hg_status()
-- The default is to just use the branch name, but you could e.g. use the
-- "hg-prompt" extension to get more information, such as any applied mq
-- patches. Here's an example of that:
-- "hg prompt \"{branch}{status}{|{patch}}{update}\""
local pipe = io_popenyield("hg status -amrd 2>&1")
if not pipe then
return { error = true }
end
local output = pipe:read('*all')
pipe:close()
local dirty = (output ~= nil and output ~= "")
return { clean = not dirty }
end
---
-- Get the status of working dir
-- @return {bool}
---
local function get_svn_status()
local file = io_popenyield("svn status -q 2>nul")
local file = io_popenyield("svn status -q")
if not file then
return { error = true }
end
@@ -536,6 +520,14 @@ local function git_prompt_filter()
return false
end
-- Colors for git status
local colors = {
clean = get_clean_color(),
dirty = get_dirty_color(),
conflict = get_conflict_color(),
nostatus = get_unknown_color()
}
local git_dir = get_git_dir()
local color
if git_dir then
@@ -555,19 +547,18 @@ local function git_prompt_filter()
local gitConflict = gitInfo.conflict
if gitStatus == nil then
color = get_unknown_color()
color = colors.nostatus
elseif gitStatus then
color = get_clean_color()
color = colors.clean
else
color = get_dirty_color()
color = colors.dirty
end
if gitConflict then
color = get_conflict_color()
color = colors.conflict
end
local result = " "..color.."("..branch..")"
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", result)
clink.prompt.value = gsub_plain(clink.prompt.value, "{git}", " "..color.."("..branch..")")
return false
end
end
@@ -577,18 +568,6 @@ local function git_prompt_filter()
return false
end
local function get_hg_info_table()
local info = clink_promptcoroutine(function ()
return get_hg_status() or {}
end)
if not info then
info = cached_info.hg_info or {}
else
cached_info.hg_info = info
end
return info
end
local function hg_prompt_filter()
-- Don't do any hg processing if the prompt doesn't want to show hg info.
@@ -598,30 +577,33 @@ local function hg_prompt_filter()
local hg_dir = get_hg_dir()
if hg_dir then
local branch = get_hg_branch()
if branch and
-- Colors for mercurial status
local colors = {
clean = get_clean_color(),
dirty = get_dirty_color(),
nostatus = get_unknown_color()
}
local output = get_hg_branch()
-- strip the trailing newline from the branch name
local n = #output
while n > 0 and output:find("^%s", n) do n = n - 1 end
local branch = output:sub(1, n)
if branch ~= nil and
string.sub(branch,1,7) ~= "abort: " and -- not an HG working copy
(not string.find(branch, "is not recognized")) then -- 'hg' not in path
-- If in a different repo or branch than last time, discard cached info
if cached_info.hg_dir ~= hg_dir or cached_info.hg_branch ~= branch then
cached_info.hg_info = nil
cached_info.hg_dir = hg_dir
cached_info.hg_branch = branch
local color = colors.clean
local pipe = io.popen("hg status -amrd 2>&1")
if pipe then
output = pipe:read('*all')
pipe:close()
if output ~= nil and output ~= "" then color = colors.dirty end
end
local hgInfo = get_hg_info_table()
local color
if not hgInfo or hgInfo.error then
color = get_unknown_color()
elseif hgInfo.clean then
color = get_clean_color()
else
color = get_dirty_color()
end
local result = " "..color.."("..branch..")"
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", result)
local result = color .. "(" .. branch .. ")"
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", " "..result)
return false
end
end
@@ -630,18 +612,6 @@ local function hg_prompt_filter()
clink.prompt.value = gsub_plain(clink.prompt.value, "{hg}", "")
end
local function get_svn_info_table()
local info = clink_promptcoroutine(function ()
return get_svn_status() or {}
end)
if not info then
info = cached_info.svn_info or {}
else
cached_info.svn_info = info
end
return info
end
local function svn_prompt_filter()
-- Don't do any svn processing if the prompt doesn't want to show svn info.
@@ -649,6 +619,13 @@ local function svn_prompt_filter()
return false
end
-- Colors for svn status
local colors = {
clean = get_clean_color(),
dirty = get_dirty_color(),
nostatus = get_unknown_color()
}
local svn_dir = get_svn_dir()
if svn_dir then
-- if we're inside of svn repo then try to detect current branch
@@ -660,16 +637,29 @@ local function svn_prompt_filter()
cached_info.svn_dir = svn_dir
cached_info.svn_branch = branch
end
local svnInfo = get_svn_info_table()
-- Get the svn status using coroutine if available and option is enabled. Otherwise use a blocking call
local svnStatus
if clink.promptcoroutine and io.popenyield and settings.get("prompt.async") and prompt_overrideSvnStatusOptIn then -- luacheck: no max line length
svnStatus = clink_promptcoroutine(function ()
return get_svn_status()
end)
-- If the status result is pending, use the cached version instead, otherwise store it to the cache
if svnStatus == nil then
svnStatus = cached_info.svn_info
else
cached_info.svn_info = svnStatus
end
else
svnStatus = get_svn_status()
end
local color
if not svnInfo or svnInfo.error then
color = get_unknown_color()
elseif svnInfo.clean then
color = get_clean_color()
if not svnStatus or svnStatus.error then
color = colors.nostatus
elseif svnStatus.clean then
color = colors.clean
else
color = get_dirty_color()
color = colors.dirty
end
clink.prompt.value = gsub_plain(clink.prompt.value, "{svn}", " "..color.."("..branch..")")

View File

@@ -38,6 +38,11 @@ prompt_includeVersionControl = true
-- NOTE: This only takes effect if using Clink v1.2.10 or higher.
prompt_overrideGitStatusOptIn = false
-- OPTIONAL. If true then always ignore the cmder.status and cmder.cmdstatus svn config settings and run the svn prompt commands in the background.
-- default is false
-- NOTE: This only takes effect if using Clink v1.2.10 or higher.
prompt_overrideSvnStatusOptIn = false
-- Prompt Attributes
--
-- Colors: https://github.com/cmderdev/cmder/wiki/Customization#list-of-colors

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
gitConfig=$(git --no-pager config -l 2>/dev/null) || return 0 # treat failure as enabled
# Check if git status display for Cmder is disabled via config
# Matches: cmder.status=false or cmder.shstatus=false (Bash-specific)
if [[ $gitConfig =~ (^|$'\n')cmder\.(sh)?status=false($|$'\n') ]]
# Check if git status for Cmder is disabled
if [[ $gitConfig =~ (^|$'\n')cmder\.status=false($|$'\n') ]] || \
[[ $gitConfig =~ (^|$'\n')cmder\.shstatus=false($|$'\n') ]]
then
return 1 # disabled
fi
@@ -47,41 +47,9 @@ 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
# Taken parts from https://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<space>
PS1="$PS1${MSYSTEM:+\[\033[35m\]$MSYSTEM }" # show MSYSTEM in purple (if set)
@@ -102,7 +70,7 @@ else
PS1="$PS1"'\[\033[36m\]' # change color to cyan
PS1="$PS1"'`__git_ps1`' # bash function
else
PS1="$PS1"'\[\033[37;1m\]' # change color to white
PS1="$PS1"'\[\033[37;1m\]' # change color to white
PS1="$PS1"'`getSimpleGitBranch`'
fi
fi
@@ -112,14 +80,9 @@ 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
MSYS2_PS1="$PS1" # for detection by MSYS2 SDK's bash.basrc
# Evaluate all user-specific Bash completion scripts (if any)
if test -z "$WINELOADERNOEXEC"

5
vendor/init.bat vendored
View File

@@ -222,9 +222,6 @@ 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
@@ -358,7 +355,7 @@ setlocal enabledelayedexpansion
if defined git_locale (
REM %print_debug% init.bat "Env Var - git_locale=!git_locale!"
if not defined LANG (
for /F "delims=" %%F in ('"!git_locale!" -uU 2') do (
for /F "delims=" %%F in ('!git_locale! -uU 2') do (
set "LANG=%%F"
)
)

View File

@@ -91,13 +91,13 @@ exit /b
if /i "!position!" == "append" (
if "!found!" == "0" (
echo "!PATH!"|!WINDIR!\System32\findstr >nul /I /R /C:";!find_query!\"$"
echo "!PATH!"|!WINDIR!\System32\findstr >nul /I /R /C:";!find_query!$"
call :set_found
)
%print_debug% :enhance_path "Env Var END PATH !find_query! - found=!found!"
) else (
if "!found!" == "0" (
echo "!PATH!"|!WINDIR!\System32\findstr >nul /I /R /C:"^\"!find_query!;"
echo "!PATH!"|!WINDIR!\System32\findstr >nul /I /R /C:"^!find_query!;"
call :set_found
)
%print_debug% :enhance_path "Env Var BEGIN PATH !find_query! - found=!found!"
@@ -190,13 +190,28 @@ exit /b
exit /b 1
)
rem Parse arguments robustly:
rem Accept either public form: "[dir_path]" [max_depth] [append]
rem or internal recursive form: "[dir_path]" [depth] [max_depth] [append]
set "depth=%~2"
set "max_depth=%~3"
set "position="
if "%~4" neq "" if /i "%~4" == "append" (
set "position=%~4"
) else (
set "position="
if /i "%~4" == "append" set "position=append"
if /i "%~3" == "append" (
set "position=append"
set "max_depth="
)
if not defined depth set "depth=0"
if not defined max_depth (
if defined depth (
rem If only one numeric argument provided, treat it as max_depth
set "max_depth=%depth%"
set "depth=0"
) else (
set "max_depth=1"
)
)
dir "%add_path%" 2>NUL | findstr -i -e "%find_pathext%" >NUL
@@ -232,8 +247,6 @@ exit /b
call :loop_depth
)
set "PATH=%PATH%"
exit /b
:set_depth

109
vendor/profile.ps1 vendored
View File

@@ -7,11 +7,15 @@
$CMDER_INIT_START = Get-Date
# Determine the script root if not already set
# 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) {
@@ -24,61 +28,40 @@ if (!$ENV:CMDER_ROOT) {
# Remove trailing '\'
$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)
# 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.
$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) ) {
if(-not $moduleInstallerAvailable -and -not $env:PSModulePath.Contains($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'!"
}
$gitVersionVendor = (readVersion -gitPath "$ENV:CMDER_ROOT\vendor\git-for-windows\cmd")
Write-Debug "GIT VENDOR: ${gitVersionVendor}"
# Read vendored Git Version
$gitVendorPath = Join-Path $ENV:CMDER_ROOT 'vendor\git-for-windows\cmd'
$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] and Compare with vendored if found.
foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) {
Write-Debug "GIT USER PATH: $($git.Path)"
Write-Debug "GIT PATH: {$git.Path}"
$gitDir = Split-Path -Path $git.Path
$gitDir = Get-GitShimPath -GitPath $gitDir
$gitVersionUser = Get-GitVersion -GitPath $gitDir
Write-Debug "GIT USER VERSION: ${gitVersionUser}"
$gitDir = isGitShim -gitPath $gitDir
$gitVersionUser = (readVersion -gitPath $gitDir)
Write-Debug "GIT USER: ${gitVersionUser}"
$useGitVersion = Compare-GitVersion -UserVersion $gitVersionUser -VendorVersion $gitVersionVendor
$useGitVersion = compare_git_versions -userVersion $gitVersionUser -vendorVersion $gitVersionVendor
Write-Debug "Using Git Version: ${useGitVersion}"
# Use user installed Git
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') {
$gitPathUser = $gitDir.subString(0, $gitDir.Length - 12)
$gitPathUser = ($gitDir.subString(0,$gitDir.Length - 12))
} 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) {
@@ -89,7 +72,7 @@ foreach ($git in (Get-Command -ErrorAction SilentlyContinue 'git')) {
}
}
# Use vendored Git if no user Git found or user Git is older than vendored Git
# 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'
@@ -99,43 +82,23 @@ 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 = Set-GitPath -GitRoot "$ENV:GIT_INSTALL_ROOT" -GitType $ENV:GIT_INSTALL_TYPE -GitPathUser $gitPathUser
$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
# Invoked when Enter is pressed to submit a command
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 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
# 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
# Check if we're currently running under Admin privileges.
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal] $identity
$adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator
@@ -144,7 +107,7 @@ $env:gitLoaded = $null
$Host.UI.RawUI.ForegroundColor = "White"
Microsoft.PowerShell.Utility\Write-Host "PS " -NoNewline -ForegroundColor $color
Microsoft.PowerShell.Utility\Write-Host $pwd.ProviderPath -NoNewLine -ForegroundColor Green
Show-GitStatus -Path $pwd.ProviderPath
checkGit($pwd.ProviderPath)
Microsoft.PowerShell.Utility\Write-Host "`nλ" -NoNewLine -ForegroundColor "DarkGray"
}
@@ -233,28 +196,6 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS
[ScriptBlock]$Prompt = {
$lastSUCCESS = $?
$realLastExitCode = $LastExitCode
# 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
Microsoft.PowerShell.Utility\Write-Host -NoNewline "$([char]0x200B)`r$([char]0x1B)[K"
if ($lastSUCCESS -or ($LastExitCode -ne 0)) {
@@ -263,12 +204,6 @@ if ( $(Get-Command prompt).Definition -match 'PS \$\(\$executionContext.SessionS
PrePrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline
CmderPrompt
PostPrompt | Microsoft.PowerShell.Utility\Write-Host -NoNewline
# 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)"
}
$global:LastExitCode = $realLastExitCode
return " "
}

View File

@@ -1,250 +1,178 @@
function Get-GitVersion {
param(
[Parameter(Mandatory = $true)]
[string]$GitPath
)
function readVersion($gitPath) {
$gitExecutable = "${gitPath}\git.exe"
$gitExecutable = Join-Path $GitPath "git.exe"
if (-not (Test-Path $gitExecutable)) {
if (-not (Test-Path "$gitExecutable")) {
return $null
}
# Execute 'git --version' and capture output
$gitVersion = & $gitExecutable --version 2>$null
$gitVersion = (cmd /c "${gitExecutable}" --version)
if ($gitVersion -match 'git version\s+(\S+)') {
return $Matches[1]
if ($gitVersion -match 'git version') {
($trash1, $trash2, $gitVersion) = $gitVersion.split(' ', 3)
} else {
pause
return $null
}
Write-Debug "Git executable path: $gitExecutable"
Write-Error "'git --version' returned an improper version string!"
Write-Error "Unable to determine Git version from output: $gitVersion"
return $null
return $gitVersion.toString()
}
function Get-GitShimPath {
param(
[Parameter(Mandatory = $true)]
[string]$GitPath
)
# Check if there is a shim file - if yes, read the actual executable path
function isGitShim($gitPath) {
# check if there is a shim file - if yes, read the actual executable path
# See: github.com/ScoopInstaller/Shim
$shimFile = Join-Path $GitPath "git.shim"
if (Test-Path $shimFile) {
$shimContent = Get-Content $shimFile -Raw
if ($shimContent -match '^\s*path\s*=\s*(.+)\s*$') {
$GitPath = $Matches[1].Trim().Replace('\git.exe', '')
}
if (Test-Path "${gitPath}\git.shim") {
$shim = (get-content "${gitPath}\git.shim")
($trash, $gitPath) = $shim.replace(' ', '').split('=')
$gitPath = $gitPath.replace('\git.exe', '')
}
return $GitPath
return $gitPath.toString()
}
function Compare-Version {
param(
[Parameter(Mandatory = $false)]
[AllowNull()]
[string]$UserVersion,
[Parameter(Mandatory = $false)]
[AllowNull()]
[string]$VendorVersion
)
if ([string]::IsNullOrEmpty($UserVersion)) { return -1 }
if ([string]::IsNullOrEmpty($VendorVersion)) { return 1 }
# Split version strings by dots to compare segment by segment
# For "2.49.0.windows.1", we get: ["2", "49", "0", "windows", "1"]
$userParts = $UserVersion -split '\.'
$vendorParts = $VendorVersion -split '\.'
$maxLength = [Math]::Max($userParts.Count, $vendorParts.Count)
for ($i = 0; $i -lt $maxLength; $i++) {
$userPart = if ($i -lt $userParts.Count) { $userParts[$i] } else { '' }
$vendorPart = if ($i -lt $vendorParts.Count) { $vendorParts[$i] } else { '' }
# Check if both parts are purely numeric
$userIsNumeric = $userPart -match '^\d+$'
$vendorIsNumeric = $vendorPart -match '^\d+$'
if ($userIsNumeric -and $vendorIsNumeric) {
# Both numeric: compare as integers (so 49 > 5, not lexicographic)
$userNum = [int]$userPart
$vendorNum = [int]$vendorPart
if ($userNum -gt $vendorNum) { return 1 }
if ($userNum -lt $vendorNum) { return -1 }
}
elseif ($userIsNumeric -and -not $vendorIsNumeric) {
# Numeric segment comes before text segment (e.g., "2.0" < "2.0.rc1")
return -1
}
elseif (-not $userIsNumeric -and $vendorIsNumeric) {
# Text segment comes after numeric segment
return 1
}
else {
# Both are text: use case-insensitive lexicographic comparison
$cmp = [string]::Compare($userPart, $vendorPart, $true)
if ($cmp -ne 0) { return [Math]::Sign($cmp) }
}
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-GitVersion {
param(
[Parameter(Mandatory = $false)]
[AllowNull()]
[string]$UserVersion,
[Parameter(Mandatory = $false)]
[AllowNull()]
[string]$VendorVersion
)
function compare_git_versions($userVersion, $vendorVersion) {
$result = compareVersions -userVersion $userVersion -vendorVersion $vendorVersion
$result = Compare-Version -UserVersion $UserVersion -VendorVersion $VendorVersion
Write-Debug "Compare Versions Result: $result"
Write-Debug "Compare Versions Result: ${result}"
if ($result -ge 0) {
return $UserVersion
return $userVersion
}
else {
return $vendorVersion
}
return $VendorVersion
}
function Set-GitPath {
param(
[Parameter(Mandatory = $true)]
[string]$GitRoot,
[Parameter(Mandatory = $true)]
[string]$GitType,
[Parameter(Mandatory = $false)]
[string]$GitPathUser
)
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..."
if ($GitType -ne 'VENDOR') {
return $env:Path
}
$newPath = $env:Path
# Replace user Git path with vendored Git if user path exists
if ($GitPathUser) {
Write-Verbose "Cmder 'profile.ps1': Replacing older user Git path '$GitPathUser' with newer vendored Git path '$GitRoot' in the system path..."
$newPath = $newPath -ireplace [regex]::Escape($GitPathUser), $GitRoot
} else {
# Add Git cmd directory to the path
$gitCmd = Join-Path $GitRoot "cmd"
if (-not ($newPath -match [regex]::Escape($gitCmd))) {
Write-Debug "Adding $gitCmd to the path"
$newPath = "$gitCmd;$newPath"
$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 mingw[32|64]\bin directories to the path, if they exist and not already present
# Prefer mingw64 on 64-bit systems, mingw32 on 32-bit systems
$is64Bit = [Environment]::Is64BitOperatingSystem
$mingwDirs = if ($is64Bit) { @('mingw64', 'mingw32') } else { @('mingw32') }
# 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"
}
foreach ($mingw in $mingwDirs) {
$mingwBin = Join-Path $GitRoot "$mingw\bin"
if ((Test-Path $mingwBin) -and -not ($newPath -match [regex]::Escape($mingwBin))) {
Write-Debug "Adding $mingwBin to the path"
$newPath = "$newPath;$mingwBin"
break
# 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"
}
}
# Add usr\bin directory to the path
$usrBin = Join-Path $GitRoot "usr\bin"
if ((Test-Path $usrBin) -and -not ($newPath -match [regex]::Escape($usrBin))) {
Write-Debug "Adding $usrBin to the path"
$newPath = "$newPath;$usrBin"
}
return $newPath
}
return $newPath
return $env:path
}
function Import-Git {
$gitModule = Get-Module -Name Posh-Git -ListAvailable
if (-not $gitModule) {
Microsoft.PowerShell.Utility\Write-Host -NoNewline "`r`n"
Write-Warning "Missing git support, install posh-git with 'Install-Module posh-git' and restart Cmder."
Microsoft.PowerShell.Utility\Write-Host -NoNewline "`r$([char]0x1B)[A"
return $false
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
}
# Import posh-git module (works for all versions)
Import-Module Posh-Git -ErrorAction SilentlyContinue | Out-Null
# Apply version-specific settings for posh-git 1.0.0+
if (($gitModule.Version -ge [version]"1.0.0") -and (Get-Variable -Name GitPromptSettings -ErrorAction SilentlyContinue)) {
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 Show-GitStatus {
param(
[Parameter(Mandatory = $true)]
[string]$Path
)
function checkGit($Path) {
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
return
}
$gitDir = Join-Path $Path '.git'
if (-not (Test-Path $gitDir)) {
$parentPath = Split-Path $Path
if ($parentPath) {
Show-GitStatus -Path $parentPath
}
if (-not (Test-Path -Path (Join-Path $Path '.git'))) {
$SplitPath = Split-Path $path
if ($SplitPath) { checkGit($SplitPath) }
return
}
if (Get-GitStatusSetting) {
if (getGitStatusSetting -eq $true) {
if ($null -eq $env:gitLoaded) {
$env:gitLoaded = Import-Git
}
if ($env:gitLoaded -eq $true) {
Write-VcsStatus
}
} else {
$headFile = Join-Path $gitDir 'HEAD'
if (Test-Path $headFile) {
$headContent = Get-Content $headFile -Raw
if ($headContent -match 'ref: refs/heads/(.+)') {
$branchName = $Matches[1].Trim()
} else {
$shortHash = $headContent.Substring(0, [Math]::Min(7, $headContent.Length))
$branchName = "HEAD detached at $shortHash"
}
Microsoft.PowerShell.Utility\Write-Host " [$branchName]" -NoNewline -ForegroundColor White
}
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 Get-GitStatusSetting {
$gitConfig = git --no-pager config -l 2>$null | Out-String
function getGitStatusSetting() {
$gitStatus = (git --no-pager config -l) | Out-String
# Check if git status display is disabled via config
# Matches: cmder.status=false or cmder.psstatus=false (PowerShell-specific)
if ($gitConfig -match '(?m)^cmder\.(ps)?status=false$') {
return $false
foreach ($line in $($gitStatus -split "`r`n")) {
if (($line -match 'cmder.status=false') -or ($line -match 'cmder.psstatus=false')) {
return $false
}
}
return $true

19
vendor/sources.json vendored
View File

@@ -1,27 +1,22 @@
[
{
"name": "git-for-windows",
"version": "2.52.0.windows.1",
"url": "https://github.com/git-for-windows/git/releases/download/v2.52.0.windows.1/PortableGit-2.52.0-64-bit.7z.exe"
"version": "2.49.0.windows.1",
"url": "https://github.com/git-for-windows/git/releases/download/v2.49.0.windows.1/PortableGit-2.49.0-64-bit.7z.exe"
},
{
"name": "clink",
"version": "1.9.5",
"url": "https://github.com/chrisant996/clink/releases/download/v1.9.5/clink.1.9.5.ee6b4f.zip"
"version": "1.7.14",
"url": "https://github.com/chrisant996/clink/releases/download/v1.7.14/clink.1.7.14.843933.zip"
},
{
"name": "conemu-maximus5",
"version": "23.07.24",
"url": "https://github.com/ConEmu/ConEmu/releases/download/v23.07.24/ConEmuPack.230724.7z"
},
{
"name": "windows-terminal",
"version": "1.23.12811.0",
"url": "https://github.com/microsoft/terminal/releases/download/v1.23.12811.0/Microsoft.WindowsTerminal_1.23.12811.0_x64.zip"
"url": "https://github.com/Maximus5/ConEmu/releases/download/v23.07.24/ConEmuPack.230724.7z"
},
{
"name": "clink-completions",
"version": "0.6.7",
"url": "https://github.com/vladimir-kotikov/clink-completions/archive/v0.6.7.zip"
"version": "0.6.2",
"url": "https://github.com/vladimir-kotikov/clink-completions/archive/v0.6.2.zip"
}
]