Customizing your PowerShell prompt is an easy way to level-up your productivity in PowerShell. Here’s an update to my 2013 post that shows how my current prompt is constructed.

I’m inspired to write this by a (relatively) recent blog post by Brad Wilson (of xUnit fame) detailing his own PowerShell prompt.

Here’s a snapshot of my PowerShell window:

  • The window title shows the current path, prefixed by [Admin] if the window is elevated.
  • The prompt itself is three lines high, starting with the current path.
  • The second line of the prompt is the git status, as shown by poshgit.
  • The third line starts with the exit code of the prior command if it failed - helping to highlight commands that fail.
  • The current time is shown in 24 hour format.
  • If the window is elevated we display [Admin], then finishing with PS>.

Here’s my PowerShell Microsoft.PowerShell_profile.ps1 file, with annotation on how it works.

After importing the poshgit module, we slightly reconfigure its display to work in our context:

Import-Module 'C:\GitHub\posh-git\src\posh-git.psd1'
$global:GitPromptSettings.BeforeText = "["
$global:GitPromptSettings.EnableWindowTitle = $null

We now define a new Prompt function, caching the exit code from the last command so we have it for later use.

# Define a new prompt
function Prompt {
    $realLASTEXITCODE = $LASTEXITCODE 

A little .NET magic allows us to work out whether we’re currently running as an elevated user, and we define the $adminHeader value appropriately.

    $currentUser = [Security.Principal.WindowsPrincipal](
        [Security.Principal.WindowsIdentity]::GetCurrent())
    $isAdminProcess = $currentUser.IsInRole(
        [Security.Principal.WindowsBuiltInRole]::Administrator) 
    $adminHeader = if ($isAdminProcess) { '[Admin] ' } else { '' } 

Observe that our $adminHeader includes a trailing space so that things are presented nicely. If we hard coded the trailing space at output (below), we’d end up with a double space when not elevated.

Next, we set the title of the window and start writing the actual prompt (the call to Write-VcsStatus invokes poshgit).

    $Host.UI.RawUI.WindowTitle = "$adminHeader$pwd"

    Write-Host
    Write-Host (join-path $pwd.ProviderPath "\")
    Write-VcsStatus 

If we’re not currently inside a git repo, posh-git will have written out a summary; if not, our cursor will still be at the lefthand margin. We use this to work out whether we need to move to the next line.

    if ($host.UI.RawUI.CursorPosition.X -gt 0) { Write-Host }

For the last line of the prompt, we start by writing out the exit code from the last command, if it wasn’t zero (i.e. successful). We cached this at the start of the prompt function, above.

    if ($realLASTEXITCODE -ne 0) {
      write-host " ⌧ $realLASTEXITCODE " -NoNewLine -BackgroundColor Red -ForegroundColor white
      write-host " " -NoNewline
    }

Now we write the current time (using a 24-hour clock) and the rest of our prompt. Including the current time in the prompt lets me easily see how long programs take to run.

    $now = get-date -format "HH:mm:ss"
    
    $global:LASTEXITCODE = 0
    return "$now $($adminHeader)PS> " 
}

Finishing the prompt with PS> helps anyone reading over my shoulder to find the end of the prompt.

Comments

blog comments powered by Disqus
Next Post
Sharpen The Saw #29  12 Feb 2018
Prior Post
Sharpen The Saw #28  05 Feb 2018
Related Posts
Using Constructors  27 Feb 2023
An Inconvenient API  18 Feb 2023
Method Archetypes  11 Sep 2022
A bash puzzle, solved  02 Jul 2022
A bash puzzle  25 Jun 2022
Improve your troubleshooting by aggregating errors  11 Jun 2022
Improve your troubleshooting by wrapping errors  28 May 2022
Keep your promises  14 May 2022
When are you done?  18 Apr 2022
Fixing GitHub Authentication  28 Nov 2021
Archives
February 2018
2018