DEV Community

Cover image for Customising PowerShell Prompt
Ivan G
Ivan G

Posted on

Customising PowerShell Prompt

PowerShell is extremely customisable. One of the things you can customise is the prompt (the place where you type commands to execute).

The Prompt function determines the appearance of the PowerShell prompt. PowerShell comes with a built-in Prompt function, but you can override it by defining your own Prompt function.

The Prompt function has the following syntax:

function Prompt { <function-body> }
Enter fullscreen mode Exit fullscreen mode

The reponsibility of this function is to basically draw the prompt to the user. If you use PowerShell daily, you might want to change how the prompt looks. I'll just go over things I've personally customised.

"Shout"

First, I find the standard prompt too busy - I just want to display the "shout" symbol, like that

This is the only piece of code I need to add to override the built-in behavior:

function Prompt
{
    Write-Host "🔊"

    return " "
}
Enter fullscreen mode Exit fullscreen mode

The symbol is an Emoji, but that's OK to use it as I use Windows Terminal which supports Emoji everywhere, including tab headers!

Long Path

I'd also like to see as less as possible in my terminal, as long as I don't need this information. For this reason I'm putting current directory path in the tab name. However, when path is long, it will make tab as wide as my window, which is unnacceptable, as it will hide other tabs. The way I fixed it is the following:

  • if current path is shorter than 20 characters, i'll put the title in the tab name
  • otherwise, display only the last 20 chars in tab path, and display full path in the termianl window itself.

Here is how it looks like. Short title:

Long title:

And here is the snippet that programs this behavior:

function Prompt
{
    $maxTitleLength = 20

    $path = $pwd.ProviderPath
    $path = $path.Replace($env:HOME, "~")

    $title = $path
    if($title.Length -gt 2) {
        $title = $title.Substring(2)
    }
    $title = $title.Replace("\", "/")

    $shortTitle = $title
    if($shortTitle.Length -gt $maxTitleLength) {
        $shortTitle = "💨 $($shortTitle.Substring($shortTitle.Length - $maxTitleLength))"
    }

    $Host.UI.RawUI.WindowTitle = $shortTitle

    if($shortTitle -ne $title) {
        Write-Host "🌟 $path" -ForegroundColor Gray
    }

    Write-Host "🔊" -ForegroundColor Green -NoNewline

    return " "
}
Enter fullscreen mode Exit fullscreen mode

Git Status

In addition to this, I'm using posh-git for displaying the git status if I'm located inside a git repo. Unfortunately, I don't like the standard prompt that posh-git enforces you to use, and it also cuts off quite a bit of screen space. What I'd like is to print out Git status on a separate line, and only if I'm in the git directory.

I'd like it to look like the following:

I'm not going to go into internals how posh-git works and just present the final solution.

First, in my powershell profile, in the beginning of the file:

Import-Module -Name posh-git -ErrorAction SilentlyContinue
$global:GitPromptSettings.BeforeStatus = ""
$global:GitPromptSettings.AfterStatus = ""
$global:GitPromptSettings.PathStatusSeparator = ""
Enter fullscreen mode Exit fullscreen mode

This turns off some extra formatting I don't want to see.

And the final Prompt function enabling all 3 features described here:

function Prompt
{
    $realLASTEXITCODE = $LASTEXITCODE
    $maxTitleLength = 20

    $path = $pwd.ProviderPath
    $path = $path.Replace($env:HOME, "~")

    $poshGit = Write-VcsStatus

    $global:LASTEXITCODE = $realLASTEXITCODE

    $title = $path
    if($title.Length -gt 2) {
        $title = $title.Substring(2)
    }
    $title = $title.Replace("\", "/")

    $shortTitle = $title
    if($shortTitle.Length -gt $maxTitleLength) {
        $shortTitle = "💨 $($shortTitle.Substring($shortTitle.Length - $maxTitleLength))"
    }

    $Host.UI.RawUI.WindowTitle = $shortTitle

    if($shortTitle -ne $title) {
        Write-Host "🌟 $path" -ForegroundColor Gray
    }

    if($null -ne $poshGit) {
        Write-Host "🌴 " -NoNewline
        Write-Host $poshGit
    }

    if($IsAdmin) {
        Write-Host "[admin]" -ForegroundColor Red -NoNewline
    }

    Write-Host "🔊" -ForegroundColor Green -NoNewline

    return " "
}
Enter fullscreen mode Exit fullscreen mode

This article was originally published on Isoline Blog

Top comments (2)

Collapse
 
thomasrayner profile image
Thomas Rayner

Nice post! I've blown way too much time on my PS prompt. I actually did a session on it at PowerShell Summit.

youtu.be/SdQYooRg7Cw?list=PLZFOfzt...

Collapse
 
aloneguid profile image
Ivan G

Wow nice work, thanks for posting this.