Skip to content

Instantly share code, notes, and snippets.

@binaryfunt
Last active May 20, 2024 12:54
Show Gist options
  • Save binaryfunt/fab7efd33ed8922a4ed0d362a26cb99c to your computer and use it in GitHub Desktop.
Save binaryfunt/fab7efd33ed8922a4ed0d362a26cb99c to your computer and use it in GitHub Desktop.
Posh-git style powershell prompt
# IPython-like history search:
Set-PSReadLineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadLineKeyHandler -Key DownArrow -Function HistorySearchForward
function Get-BranchName () {
try {
$branch = git rev-parse --abbrev-ref HEAD
if ($branch -eq "HEAD") {
# we're probably in detached HEAD state
$tag = git describe --tags --exact-match
if ($tag) {
return "($tag)"
}
$sha = git rev-parse --short HEAD
if ($sha) {
return "($sha...)"
}
$isBare = git rev-parse --is-bare-repository
if ($isBare -eq "true") {
return "(BARE)"
}
# probably an empty repo
return "(HEAD)"
}
# else we're on an actual branch, so print it
return $branch
} catch {
return "(UNKNOWN)"
}
}
function Get-TrackingStatus () {
$color = "cyan"
try {
$status = git status -sb
$hasUpstream = $status | Select-String -Pattern '^## .*(\.\.\.)'
$gone = $status | Select-String -Pattern '^## .* \[gone\]'
if ($gone) {
$str = [char]0x00D7
} elseif ($hasUpstream) {
$match = $status | Select-String -Pattern '^## .*\[ahead (\d+)'
try {
$aheadNum = $match.Matches.Groups[1]
} catch {}
$match = $status | Select-String -Pattern '^## .*behind (\d+)\]'
try {
$behindNum = $match.Matches.Groups[1]
} catch {}
if ($aheadNum -and $behindNum) {
$str = "$([char]0x2193)$behindNum $([char]0x2191)$aheadNum"
$color = "yellow"
} elseif ($aheadNum) {
$str = "$([char]0x2191)$aheadNum"
$color = "green"
} elseif ($behindNum) {
$str = "$([char]0x2193)$behindNum"
$color = "red"
} else {
$str = [char]0x2261
}
} else {
$str = "?"
}
} catch {
$str = "?"
}
return $str, $color, $status
}
function Write-Status () {
$branchStr = Get-BranchName
$trackingStr, $trackingColor, $status = Get-TrackingStatus
if ($status) {
$match = $status | Select-String -Pattern '^([MARC][ MD]|D[ RC])'
$stagedChanges = $match.Matches.Count
$match = $status | Select-String -Pattern '^([ MARC][MD]| A|[ D][RC])'
$unstagedChanges = $match.Matches.Count
$match = $status | Select-String -Pattern '^(D[DU]|A[AU]|U[DAU])'
$conflicts = $match.Matches.Count
$match = $status | Select-String -Pattern '^\?\?'
$untrackedFiles = $match.Matches.Count
}
Write-Host " [" -NoNewline -ForegroundColor "gray"
Write-Host "$branchStr $trackingStr" -NoNewline -ForegroundColor $trackingColor
if ($stagedChanges) {
Write-Host " ~$stagedChanges" -NoNewline -ForegroundColor "darkgreen"
if ($unstagedChanges -or $conflicts -or $untrackedFiles) {
Write-Host " |" -NoNewline -ForegroundColor "gray"
}
}
if ($unstagedChanges) {
Write-Host " ~$unstagedChanges" -NoNewline -ForegroundColor "darkred"
}
if ($conflicts) {
Write-Host " !$conflicts" -NoNewline -ForegroundColor "darkred"
}
if ($untrackedFiles) {
Write-Host " ?$untrackedFiles" -NoNewline -ForegroundColor "darkred"
}
Write-Host "]" -NoNewline -ForegroundColor "gray"
}
function prompt {
$base = "PS"
$path = "$($executionContext.SessionState.Path.CurrentLocation)"
$userPrompt = "$('>' * ($nestedPromptLevel + 1)) "
Write-Host "`n$base $path" -NoNewline
if (git rev-parse --git-dir) {
Write-Status
}
return $userPrompt
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment