Skip to content

Instantly share code, notes, and snippets.

@Trucido
Last active Mar 18, 2019
Embed
What would you like to do?
posh prompt nonsense
############################################################################################################################################
## Prompt ##
############################################################################################################################################
Clear-Host
[ScriptBlock]$Prompt = {
$origLastExitCode = $global:LASTEXITCODE
Set-StrictMode -Version 'Latest'
$gitLoaded = $false # skip stupid git module, adds ~1000ms to startup time.
#
# PATHS
#
<#
A UNC path has no drive so it's better to use the ProviderPath e.g. "\\server\share".
However for any path with a drive defined, it's better to use the Path property.
In this case, ProviderPath is "\LocalMachine\My"" whereas Path is "Cert:\LocalMachine\My".
The latter is more desirable.
#>
$CurrentLocation = $ExecutionContext.SessionState.Path.CurrentLocation
$_CD_ = if($CurrentLocation.Drive){ $CurrentLocation.Path }else{ $CurrentLocation.ProviderPath }
$tpwd = $_CD_ -Replace [Regex]::Escape("$HOME"),'~' -Replace '^[^:]+::','' # Replace any paths containing $HOME with '~'
$spwd = $tpwd -Replace '\\(\.?)([^\\])[^\\]*(?=\\)','\$1$2' # Abreviates each dir to 1 char except for last
$PWDMaxLen = [int]'32' # Max chars in current tilde'd path before switching to abreviation
$PPWD = if($tpwd.Length -and ($tpwd.Length -le $PWDMaxLen)){ $tpwd }else{ $spwd }
# check vars if not set
$PS_VERSION = [string]$PSVersionTable.PSVersion
$SHELL = [string]$ShellId+'.'+$PSEdition+' '+$PS_Version
if(!$USER){ $USER = $env:UserName }
if(!$HOME){ $HOME = $env:UserProfile }
if(!$HOSTNAME){ $HOSTNAME = [Net.Dns]::GetHostName() }
if($null -eq $IsAdmin){ [bool]$IsAdmin = ([Security.Principal.WindowsPrincipal](
[Security.Principal.WindowsIdentity]::GetCurrent()
)).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) }
#
# Colors (Note: PS5 has issues with backtick escape color codes, so use [char] for escapes)
#
$fg = @{
# 'black' = "$([char]0x1b)[30m"
# 'red' = "$([char]0x1b)[31m"
'green' = "$([char]0x1b)[32m"
'yellow' = "$([char]0x1b)[33m"
# 'blue' = "$([char]0x1b)[34m"
# 'magenta' = "$([char]0x1b)[35m"
# 'cyan' = "$([char]0x1b)[36m"
# 'white' = "$([char]0x1b)[37m"
}
# bold, though technically "bright", but same difference
$fg_bold = @{
# 'gray' = "$([char]0x1b)[90m"
# 'black' = "$([char]0x1b)[90m"
'red' = "$([char]0x1b)[91m"
# 'green' = "$([char]0x1b)[92m"
# 'yellow' = "$([char]0x1b)[93m"
'blue' = "$([char]0x1b)[94m"
# 'magenta' = "$([char]0x1b)[95m"
# 'cyan' = "$([char]0x1b)[96m"
# 'white' = "$([char]0x1b)[97m"
}
$c_reset = "$([char]0x1b)[0m"
$c_user = if($IsAdmin){ "$($fg_bold['red'])" }else{ "$($fg['green'])" }
$nl = "$([char]10)" # newline
#
# Main prompt line: User@Hostname shell.name.edition n.n.nn ~\foo\bar + newline + '> '
#
"$($c_user+$USER+'@'+$HOSTNAME+$fg_bold['blue']+' '+$SHELL+' '+$fg['yellow']+$PPWD+$c_reset+$(if($gitLoaded-and(Test-Path ${_CD_}\.git)){Write-VcsStatus})+
$nl+$('>' * ($nestedPromptLevel + 1)) ) "
#
# Window Title (short path or only current directory if Length <= 7)
#
$wpwd = if($spwd.Length -le 7){ $spwd }else{ try{ Split-Path $_CD_ -Leaf }catch{ "$([char]8734)" } }
$Host.UI.RawUI.WindowTitle = "$($(if($IsAdmin){'Admin: '})+$wpwd)" # prefix 'Admin: ' if elevated, else just path or cwd
#
# [Environment]::CurrentDirectory
#
[ScriptBlock]$locationChangedHandler = {
try {
# Update CurrentDirectory so .NET sees same PSPath as powershell
# Note: Must use Filesystem provider, PSDrives and network paths are invalid
[System.Environment]::CurrentDirectory = $ExecutionContext.SessionState.Path.CurrentFileSystemLocation
} catch [System.UnauthorizedAccessException],
[System.Management.Automation.MethodInvocationException],
[System.Management.Automation.SetValueInvocationException] {
# Catch UnauthorizedAccessException if any directories in path not readable
$Error.Remove($error[0])
# And as a last ditch effort, try `Get-Location` cmdlet
try {
[System.Environment]::CurrentDirectory = Get-Location -PSProvider FileSystem
} catch {}
}
}
# Note: PS < v6 does not have LocationChangedAction, so invoke scriptblock instead for compatibility.
# PS6: `$ExecutionContext.InvokeCommand.LocationChangedAction = $locationChangedHandler`
& $locationChangedHandler
# Restore LastExitCode in case we contaminated it
$global:LASTEXITCODE = $origLastExitCode
Remove-Variable origLASTEXITCODE
return " "
# .Link
# https://go.microsoft.com/fwlink/?LinkID=225750
# .ExternalHelp System.Management.Automation.dll-help.xml
}
# Tell PSReadline which part of the prompt to change red for interactive syntax validation. (PS6 only or PSReadline >= 2)
if ($IsCoreCLR -or (Get-Module PSReadLine).Version.Major -ge 2) {
Set-PSReadLineOption -PromptText '> '
}
# Set prompt readonly to prevent unexpected altering of prompt (without -Force)
Set-Item 'Function:\Prompt' -Value $Prompt -Force -Option:ReadOnly -ErrorAction:Ignore -Verbose:$false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment