# encoding: ascii
# api: powershell
# title: Set-Prompt
# description: My command prompt, as always. I leave this in a separate script file and invoke it from my profile. That way I can RE-invoke it to reset my prompt if I have to mess with it for some reason.
# version: 0.1
# type: function
# author: Joel Bennett
# license: CC0
# x-poshcode-id: 3198
# x-archived: 2012-08-01T05:42:39
# x-published: 2012-01-28T22:29:00
#
# I recently embedded my persistent history functionality directly into this prompt function (I used to have that in a per-host profile, as a wrapper around this prompt, but I can’t remember why, and I didn’t like loosing it when I had to re-invoke this script).
#
#.Synopsis
# Sets my favorite prompt function
#.Notes
# I put the id in my prompt because it's very, very useful.
#
# Invoke-History and my Expand-Alias and Get-PerformanceHistory all take command history IDs
# Also, you can tab-complete with "#<id>[Tab]" so .
# For example, the following commands:
# r 4
# ## r is an alias for invoke-history, so this reruns your 4th command
#
# #6[Tab]
# ## will tab-complete whatever you typed in your 6th command (now you can edit it)
#
# Expand-Alias -History 6,8,10 > MyScript.ps1
# ## generates a script from those history items
#
# GPH -id 6, 8
# ## compares the performance of those two commands ...
#
param(
# Controls how much history we keep in the command log
[Int]$PersistentHistoryCount = 30,
# If set, we use a pasteable prompt with <# #> around the prompt info
[Alias("copy","demo")][Switch]$Pasteable,
[Int]$global:MaximumHistoryCount = 2048,
[ConsoleColor]$global:PromptForeground = "Yellow",
[ConsoleColor]$global:ErrorForeground = "Red"
)
# Some stuff goes OUTSIDE the prompt function because it doesn't need re-evaluation
# I set the title in my prompt every time, because I want the current PATH location there,
# rather than in my prompt where it takes up too much space.
# But I want other stuff too. I calculate an initial prefix for the window title
# The title will show the PowerShell version, user, current path, and whether it's elevated or not
# E.g.:"PoSh3 Jaykul@HuddledMasses (ADMIN) - C:\Your\Path\Here (FileSystem)"
if(!$global:WindowTitlePrefix) {
$global:WindowTitlePrefix = "PoSh$($PSVersionTable.PSVersion.Major) ${Env:UserName}@${Env:UserDomain}"
# if you're running "elevated" we want to show that:
$ENV:PROCESS_ELEVATED = ([System.Environment]::OSVersion.Version.Major -gt 5) -and ( # Vista and ...
new-object Security.Principal.WindowsPrincipal (
[Security.Principal.WindowsIdentity]::GetCurrent()) # current user is admin
).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if($ENV:PROCESS_ELEVATED) {
$global:WindowTitlePrefix += " (ADMIN)"
}
}
## Global first-run (profile or first prompt)
if($MyInvocation.HistoryId -eq 1) {
$ProfileDir = Split-Path $Profile.CurrentUserAllHosts
## Import my history
Import-CSV $ProfileDir\.poshhistory | Add-History
}
if($Pasteable) {
# The pasteable prompt starts with "<#PS " and ends with " #>"
# so that you can copy-paste with the prompt and it will still run
function global:prompt {
# FIRST, make a note if there was an error in the previous command
$err = !$?
Write-host "<#PS " -NoNewLine -fore gray
# Make sure Windows and .Net know where we are (they can only handle the FileSystem)
[Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath
try {
# Also, put the path in the title ... (don't restrict this to the FileSystem)
$Host.UI.RawUI.WindowTitle = "{0} - {1} ({2})" -f $global:WindowTitlePrefix,$pwd.Path,$pwd.Provider.Name
} catch {}
# Determine what nesting level we are at (if any)
$Nesting = "$([char]0xB7)" * $NestedPromptLevel
# Generate PUSHD(push-location) Stack level string
$Stack = "+" * (Get-Location -Stack).count
# I used to use Export-CliXml, but Export-CSV is a lot faster
$null = Get-History -Count 30 | Export-CSV $ProfileDir\.poshhistory
# Output prompt string
# If there's an error, set the prompt foreground to the error color...
if($err) { $fg = $global:ErrorForeground } else { $fg = $global:PromptForeground }
# Notice: no angle brackets, makes it easy to paste my buffer to the web
Write-Host "[${Nesting}$($myinvocation.historyID)${Stack}]" -NoNewLine -Foreground $fg
Write-host " #>" -NoNewLine -fore gray
# Hack PowerShell ISE CTP2 (requires 4 characters of output)
if($Host.Name -match "ISE" -and $PSVersionTable.BuildVersion -eq "6.2.8158.0") {
return "$("$([char]8288)"*3) "
} else {
return " "
}
}
} else {
function global:prompt {
# FIRST, make a note if there was an error in the previous command
$err = !$?
# Make sure Windows and .Net know where we are (they can only handle the FileSystem)
[Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath
try {
# Also, put the path in the title ... (don't restrict this to the FileSystem)
$Host.UI.RawUI.WindowTitle = "{0} - {1} ({2})" -f $global:WindowTitlePrefix,$pwd.Path,$pwd.Provider.Name
} catch {}
# Determine what nesting level we are at (if any)
$Nesting = "$([char]0xB7)" * $NestedPromptLevel
# Generate PUSHD(push-location) Stack level string
$Stack = "+" * (Get-Location -Stack).count
# I used to use Export-CliXml, but Export-CSV is a lot faster
$null = Get-History -Count 30 | Export-CSV $ProfileDir\.poshhistory
# Output prompt string
# If there's an error, set the prompt foreground to "Red", otherwise, "Yellow"
if($err) { $fg = $global:ErrorForeground } else { $fg = $global:PromptForeground }
# Notice: no angle brackets, makes it easy to paste my buffer to the web
Write-Host "[${Nesting}$($myinvocation.historyID)${Stack}]:" -NoNewLine -Fore $fg
# Hack PowerShell ISE CTP2 (requires 4 characters of output)
if($Host.Name -match "ISE" -and $PSVersionTable.BuildVersion -eq "6.2.8158.0") {
return "$("$([char]8288)"*3) "
} else {
return " "
}
}
}