Skip to content

Instantly share code, notes, and snippets.

@scrthq
Last active August 21, 2019 06:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scrthq/d11a0c90a83b0cdcca144c3e2a44aa2e to your computer and use it in GitHub Desktop.
Save scrthq/d11a0c90a83b0cdcca144c3e2a44aa2e to your computer and use it in GitHub Desktop.
PowerShell Profile + Prompt
try {
Import-Module posh-git -ErrorAction Stop
}
catch {
Install-Module posh-git -Scope CurrentUser -Repository PSGallery
Import-Module posh-git
}
function Get-PSVersion {
<#
.SYNOPSIS
Gets the short formatted PSVersion string for use in a prompt or wherever else desired.
.DESCRIPTION
Gets the short formatted PSVersion string for use in a prompt or wherever else desired.
.PARAMETER Places
How many decimal places you would like the returned version string to be. Defaults to $PSProfile.Settings.PSVersionStringLength if present.
.EXAMPLE
Get-PSVersion -Places 2
Returns `6.2` when using PowerShell 6.2.2, or `5.1` when using Windows PowerShell 5.1.18362.10000
#>
[OutputType('System.String')]
[CmdletBinding()]
Param (
[parameter(Position = 0)]
[AllowNull()]
[int]
$Places = $global:PSProfile.Settings.PSVersionStringLength
)
Process {
$version = $PSVersionTable.PSVersion.ToString()
if ($null -ne $Places) {
$split = ($version -split '\.')[0..($Places - 1)]
if ("$($split[-1])".Length -gt 1) {
$split[-1] = "$($split[-1])".Substring(0,1)
}
$joined = $split -join '.'
if ($version -match '[a-zA-Z]+') {
$joined += "-$(($Matches[0]).Substring(0,1))"
if ($version -match '\d+$') {
$joined += $Matches[0]
}
}
$joined
}
else {
$version
}
}
}
function Get-Elapsed {
<#
.Synopsis
Get the time span elapsed during the execution of command (by default the previous command)
.Description
Calls Get-History to return a single command and returns the difference between the Start and End execution time
.Notes
Base borrowed graciously from @jaykul
#>
[CmdletBinding()]
param(
[Parameter()]
[int]$Id,
[Parameter()]
[string]$Format = "{0:h\:mm\:ss\.ffff}"
)
$null = $PSBoundParameters.Remove("Format")
$LastCommand = Get-History -Count 1 @PSBoundParameters
if (!$LastCommand) {
return ""
}
$Duration = $LastCommand.EndExecutionTime - $LastCommand.StartExecutionTime
$Format -f $Duration
}
function Test-IfGit {
<#
.SYNOPSIS
Tests if the current path is in a Git repo folder and returns the basic details as an object if so. Useful in prompts when determining current folder's Git status
.DESCRIPTION
Tests if the current path is in a Git repo folder and returns the basic details as an object if so. Useful in prompts when determining current folder's Git status
.EXAMPLE
Test-IfGit
#>
[CmdletBinding()]
Param ()
Process {
try {
$topLevel = git rev-parse --show-toplevel *>&1
if ($topLevel -like 'fatal: *') {
$Global:Error.Remove($Global:Error[0])
$false
}
else {
$origin = git remote get-url origin
$repo = Split-Path -Leaf $origin
[PSCustomObject]@{
TopLevel = (Resolve-Path $topLevel).Path
Origin = $origin
Repo = $(if ($repo -notmatch '(\.git|\.ssh|\.tfs)$') {
$repo
}
else {
$repo.Substring(0,($repo.LastIndexOf('.')))
})
}
}
}
catch {
$false
$Global:Error.Remove($Global:Error[0])
}
}
}
function Get-PathAlias {
<#
.SYNOPSIS
Gets the Path alias using either the short name from $PSProfile.GitPathMap or a path alias stored in $PSProfile.PathAliases, falls back to using a shortened version of the root drive + current directory.
.DESCRIPTION
Gets the Path alias using either the short name from $PSProfile.GitPathMap or a path alias stored in $PSProfile.PathAliases, falls back to using a shortened version of the root drive + current directory.
.PARAMETER Path
The full path to get the PathAlias for. Defaults to $PWD.Path
.PARAMETER DirectorySeparator
The desired DirectorySeparator character. Defaults to $global:PathAliasDirectorySeparator if present, falls back to [System.IO.Path]::DirectorySeparatorChar if not.
.EXAMPLE
Get-PathAlias
#>
[CmdletBinding()]
Param (
[parameter(Position = 0)]
[string]
$Path = $PWD.Path,
[parameter(Position = 1)]
[string]
$DirectorySeparator = $(if ($null -ne $global:PathAliasDirectorySeparator) {
$global:PathAliasDirectorySeparator
}
else {
[System.IO.Path]::DirectorySeparatorChar
})
)
Begin {
try {
$origPath = $Path
if ($null -eq $global:PSProfile) {
$global:PSProfile = @{
Settings = @{
PSVersionStringLength = 3
}
PathAliasMap = @{
'~' = $env:USERPROFILE
}
}
}
elseif ($null -eq $global:PSProfile._internal) {
$global:PSProfile._internal = @{
PathAliasMap = @{
'~' = $env:USERPROFILE
}
}
}
elseif ($null -eq $global:PSProfile._internal.PathAliasMap) {
$global:PSProfile._internal.PathAliasMap = @{
'~' = $env:USERPROFILE
}
}
if ($gitRepo = Test-IfGit) {
$gitIcon = [char]0xe0a0
$key = $gitIcon + $gitRepo.Repo
if (-not $global:PSProfile._internal.PathAliasMap.ContainsKey($key)) {
$global:PSProfile._internal.PathAliasMap[$key] = $gitRepo.TopLevel
}
}
$leaf = Split-Path $Path -Leaf
if (-not $global:PSProfile._internal.PathAliasMap.ContainsKey('~')) {
$global:PSProfile._internal.PathAliasMap['~'] = $env:USERPROFILE
}
Write-Verbose "Alias map => JSON: $($global:PSProfile._internal.PathAliasMap | ConvertTo-Json -Depth 5)"
$aliasKey = $null
$aliasValue = $null
foreach ($hash in $global:PSProfile._internal.PathAliasMap.GetEnumerator() | Sort-Object { $_.Value.Length } -Descending) {
if ($Path -like "$($hash.Value)*") {
$Path = $Path.Replace($hash.Value,$hash.Key)
$aliasKey = $hash.Key
$aliasValue = $hash.Value
Write-Verbose "AliasKey [$aliasKey] || AliasValue [$aliasValue]"
break
}
}
}
catch {
Write-Error $_
return $origPath
}
}
Process {
try {
if ($null -ne $aliasKey -and $origPath -eq $aliasValue) {
Write-Verbose "Matched original path! Returning alias base path"
$finalPath = $Path
}
elseif ($null -ne $aliasKey) {
Write-Verbose "Matched alias key [$aliasKey]! Returning path alias with leaf"
$drive = "$($aliasKey)\"
$finalPath = if ((Split-Path $origPath -Parent) -eq $aliasValue) {
"$($drive)$($leaf)"
}
else {
"$($drive)$([char]0x2026)\$($leaf)"
}
}
else {
$drive = (Get-Location).Drive.Name + ':\'
Write-Verbose "Matched base drive [$drive]! Returning base path"
$finalPath = if ($Path -eq $drive) {
$drive
}
elseif ((Split-Path $Path -Parent) -eq $drive) {
"$($drive)$($leaf)"
}
else {
"$($drive)..\$($leaf)"
}
}
if ($DirectorySeparator -notin @($null,([System.IO.Path]::DirectorySeparatorChar))) {
$finalPath.Replace(([System.IO.Path]::DirectorySeparatorChar),$DirectorySeparator)
}
else {
$finalPath
}
}
catch {
Write-Error $_
return $origPath
}
}
}
function global:prompt {
$lastStatus = $?
$lastColor = if ($lastStatus -eq $true) {
"Green"
}
else {
"Red"
}
Write-Host "[" -NoNewline
Write-Host -ForegroundColor Cyan "#$($MyInvocation.HistoryId)" -NoNewline
Write-Host "] " -NoNewline
Write-Host "[" -NoNewLine
$verColor = @{
ForegroundColor = if ($PSVersionTable.PSVersion.Major -eq 7) {
"Yellow"
}
elseif ($PSVersionTable.PSVersion.Major -eq 6) {
"Magenta"
}
else {
"Cyan"
}
}
Write-Host @verColor ("PS {0}" -f (Get-PSVersion)) -NoNewline
Write-Host "] " -NoNewline
Write-Host "[" -NoNewline
Write-Host -ForegroundColor $lastColor ("{0}" -f (Get-Elapsed)) -NoNewline
Write-Host "] [" -NoNewline
Write-Host ("{0}" -f $(Get-PathAlias)) -NoNewline -ForegroundColor DarkYellow
Write-Host "]" -NoNewline
if ($PWD.Path -notlike "\\*" -and $env:DisablePoshGit -ne $true -and (Test-IfGit)) {
Write-VcsStatus
$GitPromptSettings.EnableWindowTitle = "PS {0} @" -f (Get-PSVersion -Places 3)
}
else {
$Host.UI.RawUI.WindowTitle = "PS {0}" -f (Get-PSVersion -Places 3)
}
"`n>> "
}
try {
Import-Module posh-git -ErrorAction Stop
}
catch {
Install-Module posh-git -Scope CurrentUser -Repository PSGallery
Import-Module posh-git
}
$GitPromptSettings.EnableWindowTitle = "Repo Info: "
function Get-Elapsed {
<#
.Synopsis
Get the time span elapsed during the execution of command (by default the previous command)
.Description
Calls Get-History to return a single command and returns the difference between the Start and End execution time
.Notes
Base borrowed graciously from @jaykul
#>
[CmdletBinding()]
param(
[Parameter()]
[int]$Id,
[Parameter()]
[string]$Format = "{0:h\:mm\:ss\.ffff}"
)
$null = $PSBoundParameters.Remove("Format")
$LastCommand = Get-History -Count 1 @PSBoundParameters
if (!$LastCommand) {
return ""
}
$Duration = $LastCommand.EndExecutionTime - $LastCommand.StartExecutionTime
$Format -f $Duration
}
if ($psEditor) {
$cons = "Code"
}
elseif ($env:ConEmuPID) {
$cons = "ConEmu"
}
else {
$cons = "PS"
}
function prompt {
$lastStatus = $?
Write-Host -ForegroundColor Green "<#[$($MyInvocation.HistoryId)] " -NoNewline
if ($PSVersionTable.PSVersion.Major -ge 6) {
Write-Host -ForegroundColor Black -BackgroundColor Cyan "[$("PS {0}" -f $PSVersionTable.PSVersion.ToString())]" -NoNewline
}
else {
Write-Host -ForegroundColor Cyan "[$("PS {0}" -f $PSVersionTable.PSVersion.ToString())]" -NoNewline
}
$lastColor = if ($lastStatus -eq $true) {
"Yellow"
}
else {
"Red"
}
Write-Host -ForegroundColor $lastColor " [$(if (Get-Elapsed){Get-Elapsed}else{"0:00:00.0000"}) @ $(Get-Date -Format T)]" -NoNewline
Write-VcsStatus
Write-Host -ForegroundColor Magenta "`n[$((Get-Location).Path.Replace($env:HOME,'~'))]" -NoNewline
Write-Host "`n[I " -NoNewline
Write-Host -ForegroundColor Red "$([char]9829)" -NoNewline
Write-Host " $cons]" -NoNewline
'>' * ($nestedPromptLevel) + '#> '
}
try {
Import-Module posh-git -ErrorAction Stop
}
catch {
Install-Module posh-git -Scope CurrentUser -Repository PSGallery
Import-Module posh-git
}
$GitPromptSettings.EnableWindowTitle = "Repo Info: "
function Get-Elapsed {
<#
.Synopsis
Get the time span elapsed during the execution of command (by default the previous command)
.Description
Calls Get-History to return a single command and returns the difference between the Start and End execution time
.Notes
Base borrowed graciously from @jaykul
#>
[CmdletBinding()]
param(
[Parameter()]
[int]$Id,
[Parameter()]
[string]$Format = "{0:h\:mm\:ss\.ffff}"
)
$null = $PSBoundParameters.Remove("Format")
$LastCommand = Get-History -Count 1 @PSBoundParameters
if (!$LastCommand) {
return ""
}
$Duration = $LastCommand.EndExecutionTime - $LastCommand.StartExecutionTime
$Format -f $Duration
}
function prompt {
$lastStatus = $?
Write-Host "CMD# " -NoNewline
Write-Host -ForegroundColor Green "[$($MyInvocation.HistoryId)] " -NoNewline
$lastColor = if ($lastStatus -eq $true) {
"Yellow"
}
else {
"Red"
}
Write-Host "| Dir: " -NoNewLine
Write-Host -ForegroundColor Cyan "[$($pwd.Path.Replace($env:HOME,'~'))] " -NoNewline
Write-Host "| Last: " -NoNewLine
Write-Host -ForegroundColor $lastColor "[$(if (Get-Elapsed){Get-Elapsed}else{"0:00:00.0000"})] " -NoNewline
if ((git config -l --local *>&1) -notmatch '^fatal') {
Write-Host "| Git:" -NoNewLine
Write-VcsStatus
}
Write-Host "`nPS " -NoNewline
$verColor = if ($PSVersionTable.PSVersion.Major -lt 6) {
@{
ForegroundColor = 'Cyan'
BackgroundColor = $host.UI.RawUI.BackgroundColor
}
}
else {
@{
ForegroundColor = $host.UI.RawUI.BackgroundColor
BackgroundColor = 'Cyan'
}
}
Write-Host @verColor ("[{0}.{1}]" -f $PSVersionTable.PSVersion.Major,$PSVersionTable.PSVersion.Minor) -NoNewline
('>' * ($nestedPromptLevel + 1)) + ' '
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment