Skip to content

Instantly share code, notes, and snippets.

@bplasmeijer
Created November 28, 2019 08:13
Show Gist options
  • Save bplasmeijer/40e61e55fa043be6a270df40fee7082e to your computer and use it in GitHub Desktop.
Save bplasmeijer/40e61e55fa043be6a270df40fee7082e to your computer and use it in GitHub Desktop.
PowerShell Core custom prompt (use a PowerLine or nerdfonts.com font) and history persistence per machine
#requires -Version 6
function Get-BranchName
{
$currentPath = Get-Location
while ($true)
{
try
{
if ([string]::IsNullOrEmpty($currentPath))
{
return
}
$git = (Join-Path $currentPath "\.git")
if (Test-Path $git)
{
$head = (Get-Content (Join-Path $git "\HEAD") | Out-String).Trim().Replace("ref: refs/heads/", "")
if ([string]::IsNullOrEmpty($head))
{
return
}
return $head
}
$currentPath = Split-Path $currentPath
}
catch
{
throw "GetBranchName failed..."
return
}
}
}
function Write-AnsiVT100
{
param(
[Parameter(Mandatory = $true)]
[ValidateNotNull()]
[string]$Message
,
[Parameter(Mandatory = $false)]
[ValidateNotNull()]
[int]$ForegroundColor = 255
,
[Parameter(Mandatory = $false)]
[ValidateNotNull()]
[int]$BackgroundColor = 0
)
$esc = "$([char]27)"
return "$esc[38;5;$ForegroundColor`m$esc[48;5;$BackgroundColor`m$Message$esc[0m$esc[0m"
}
# persistent history on exit
Register-EngineEvent -SupportEvent PowerShell.Exiting -Action {
# setup
$historyRootPath = Join-Path $PSScriptRoot "\History"
$mergeFilePath = Join-Path $historyRootPath ("\merged-{0}.csv" -f $env:COMPUTERNAME)
# save history
Get-History | Export-Csv -Path (Join-Path $historyRootPath ("\history-{0}-{1}.csv" -f $env:COMPUTERNAME, $PID)) -Append
# merge session history
Get-ChildItem -Path $historyRootPath -Filter ("history-{0}-*.csv" -f $env:COMPUTERNAME) | ForEach-Object {
Import-Csv -Path $_.FullName
} | Sort-Object -Property CommandLine -Unique | Export-Csv -Path $mergeFilePath -Append
# delete old session history
Get-ChildItem -Path $historyRootPath -Filter ("history-{0}-*.csv" -f $env:COMPUTERNAME) | Remove-Item -Force;
}
# setup prompt
function Prompt
{
# was the last command executed successful ?
[bool]$script:success = $?
# shorten and decorate current path
$pathArray = ($ExecutionContext.SessionState.Path.CurrentLocation) -split "\\"
if ($pathArray.Count -gt 3)
{
$driveSegement = $pathArray | Select-Object -First 1
$pathSegment = ($pathArray | Select-Object -Last 3) -join " `u{e0b1} "
$currentLocation = "$driveSegement `u{e0b1} $([char]0x2026) `u{e0b1} $pathSegment"
}
else
{
$currentLocation = $pathArray -join " `u{e0b1} "
}
# measure how long the last command took to execute
$lastCommand = Get-History -Count 1
if ($lastCommand)
{
$duration = $lastCommand.EndExecutionTime - $lastCommand.StartExecutionTime
$elapsed = "{0:h\:mm\:ss\.ffff}" -f $duration
}
else
{
$elapsed = "0:00:00.0000"
}
# get branch name
$branch = Get-BranchName
if ([string]::IsNullOrEmpty($branch))
{
$branch = "n/a"
}
# write prompt
$seperator = "`u{e0b0}"
$prompt = ""
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 0 -BackgroundColor 23
$prompt += Write-AnsiVT100 " `u{26a1} " -ForegroundColor 226 -BackgroundColor 23
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 23 -BackgroundColor 31
$prompt += Write-AnsiVT100 " $elapsed " -ForegroundColor 255 -BackgroundColor 31
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 31 -BackgroundColor 38
$prompt += Write-AnsiVT100 (" {0:HH\:mm\:ss\.ffff} " -f (Get-Date)) -ForegroundColor 0 -BackgroundColor 38
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 38 -BackgroundColor 236
$prompt += Write-AnsiVT100 " $($MyInvocation.HistoryId - 1) " -ForegroundColor 250 -BackgroundColor 236
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 236 -BackgroundColor 36
$prompt += Write-AnsiVT100 " `u{e0a0} $branch " -ForegroundColor 254 -BackgroundColor 36
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 36 -BackgroundColor 237
$prompt += Write-AnsiVT100 " $currentLocation " -ForegroundColor 253 -BackgroundColor 237
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 237 -BackgroundColor 0
$prompt += "`n"
$commandStateColor = @{ $true = 254; $false = 9 }[$script:success]
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 0 -BackgroundColor $commandStateColor
$prompt += Write-AnsiVT100 " `u{2665} " -ForegroundColor 160 -BackgroundColor $commandStateColor
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor $commandStateColor -BackgroundColor 251
$prompt += Write-AnsiVT100 " PS " -ForegroundColor 234 -BackgroundColor 251
$prompt += Write-AnsiVT100 "$seperator" -ForegroundColor 251 -BackgroundColor 0
return $prompt
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment