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
Bootstrapping a Psake build  01 Sep 2018
A Tale of Minification  17 Feb 2018
Test Coverage History  18 Nov 2017
Tracking time  11 Nov 2017
The day my build broke  04 Nov 2017
NuGet and .NET Core  28 Oct 2017
.NET Core Builds  21 Oct 2017
Test Coverage Reporting  07 Oct 2017
Test Coverage with Opencover  30 Sep 2017
NuGet packaging  23 Sep 2017
More powershell posts »
Archives
February 2018
2018