Skip to content

Instantly share code, notes, and snippets.

@VojtechStep
Last active October 5, 2022 05:27
Show Gist options
  • Save VojtechStep/9d2478a63c2c626c0173527b2f86f370 to your computer and use it in GitHub Desktop.
Save VojtechStep/9d2478a63c2c626c0173527b2f86f370 to your computer and use it in GitHub Desktop.
Powerline-style PowerShell prompt (git support and extensible)

About

Custom prompt for Windows PowerShell that implements the Powerline theme This prompt is inspired by the agnoster theme for oh-my-zsh

How to install

  • Install the Powerline-patched fonts for the icons to render correctly.
  • Download the gist files
  • Extract the archive to one of your PowerShell Profile folders (ex. %UserProfile%\Documents\WindowsPowerShell )
  • Open PowerShell
    The first time, it will ask you whether you want to run the scripts. The install.ps1 script will get called on the first run and it will make the files look like you created them, so this warning won't appear again. The script also cleans the directory so you'll be left off with just what you need.

How to modify

To modify colors and variables, edit the Config.ps1 script. Here, you can change the colors, glyphs and some switches for git and the theme. To add/remove segments, comment/uncomment the "print_*" function calls.

How to extend

To add your own segment, add a function, preferably, but not necessairly, to the PromptUtils.ps1 script and then call it from the "prompt" function in profile.ps1. To render the segment, call the "print_segment" function, which accepts 3 parameters: background color, foreground color and the text

#If this isn't the user using the shell, username@host will be displayed (if enabled)
$DEFAULT_USER='Adalbert'
#True to print username@host event if it's the default user
$PRINT_DEFAULT_USER=$FALSE
#Glyphs
$SEGMENT_DELIMETER_GLYPH=[char]0xE0B0 # î‚°
$PREV_CMD_FAIL_GLYPH=[char]0x2718 # ✘
$BGTASK_GLYPH=[char]0x2699 # âš™
$ELEVATED_GLYPH=[char]0x26A1 # âš¡
$GIT_BRANCH_GLYPH=[char]0xE0A0 # î‚ 
$GIT_DIRTY_GLYPH=[char]0x25CF # ●
$GIT_UNTRACKED_GLYPH=[char]0x271A # ✚
#True to collapse folder names between drive letter and current folder name
$COLLAPSE_DIR=$FALSE
#True to mark git repos with untracked files clean
$DISABLE_UNTRACKED_FILES_DIRTY=$FALSE
#True to only show the npm version if the current folder contains package.json
$NPM_HIDE_NO_PACKAGE=$TRUE
#Segment colors
$PRMT_NUM_BG='Black'
$PRMT_NUM_FG='Blue'
$CONTEXT_BG='Yellow'
$CONTEXT_FG='Black'
$DIR_BG='Blue'
$DIR_FG='Black'
$GIT_CLEAN_BG='Green'
$GIT_CLEAN_FG='Black'
$GIT_DIRTY_BG='Yellow'
$GIT_DIRTY_FG='Black'
$NPM_BG='Magenta'
$NPM_FG='Black'
Get-Content $PSScriptRoot\profile.ps1 > $PSScriptRoot\profile_.ps1
Get-Content $PSScriptRoot\Config.ps1 > $PSScriptRoot\Config_.ps1
Get-Content $PSScriptRoot\PromptUtils.ps1 > $PSScriptRoot\PromptUtils_.ps1
Move-Item $PSScriptRoot\profile_.ps1 $PSScriptRoot\profile.ps1 -Force
Move-Item $PSScriptRoot\Config_.ps1 $PSScriptRoot\Config.ps1 -Force
Move-Item $PSScriptRoot\PromptUtils_.ps1 $PSScriptRoot\PromptUtils.ps1 -Force
Remove-Item $PSScriptRoot\install.ps1
Remove-Item $PSScriptRoot\README.md
. $PSScriptRoot\PromptUtils.ps1
Function elevate_process() {
$file, [string]$arguments = $args
$psi = new-object System.Diagnostics.ProcessStartInfo $file;
$psi.Arguments = $arguments;
$psi.Verb = "runas";
$psi.WorkingDirectory = Get-Location;
[System.Diagnostics.Process]::Start($psi);
}
Function prompt {
print_status
# print_prompt_number
print_context
print_dir
print_npm
print_git
end_segment
return [char]0x200A
}
Set-Alias sudo elevate_process
$CURRENT_BG=$null
$NPM_VERSION=$null
. $PSScriptRoot\Config.ps1
if (Get-Command npm -ErrorAction SilentlyContinue) {
$Global:NPM_VERSION = $(npm --version)
}
if (Test-Path $PSScriptRoot\install.ps1) {
. $PSScriptRoot\install.ps1
}
Function print_segment($bg = 'Black', $fg = 'Blue', $str) {
if($CURRENT_BG -and $CURRENT_BG -ne $bg) {
Write-Host "$SEGMENT_DELIMETER_GLYPH" -ForegroundColor $CURRENT_BG -BackgroundColor $bg -NoNewline
}
$Global:CURRENT_BG = $bg
Write-Host $str -ForegroundColor $fg -BackgroundColor $bg -NoNewline
}
Function end_segment() {
Write-Host "$SEGMENT_DELIMETER_GLYPH" -ForegroundColor $CURRENT_BG -BackgroundColor Black -NoNewline
$Global:CURRENT_BG=$null
$Host.UI.RawUI.WindowTitle="Windows PowerShell v$($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor)"
}
Function print_status() {
if (-Not $?) {
Write-Host "$PREV_CMD_FAIL_GLYPH " -ForegroundColor Red -NoNewline
$flag=$TRUE
}
Get-Job | % {
if ($_.State -eq "Running") {
Write-Host "$BGTASK_GLYPH " -ForegroundColor Cyan -NoNewline
$flag=$TRUE
}
}
if ((whoami /all | select-string S-1-16-12288) -ne $null) {
Write-Host "$ELEVATED_GLYPH " -ForegroundColor Yellow -NoNewline
$flag=$TRUE
}
if ($flag) {$Global:CURRENT_BG='Black'}
}
Function print_prompt_number() {
${Global:CNT_OF_PRMT}++
Write-Host '#' -NoNewline
print_segment $PRMT_NUM_BG $PRMT_NUM_FG $("000000000${GLOBAL:CNT_OF_PRMT}").ToString().Substring($("000000000${GLOBAL:CNT_OF_PRMT}").length-4 , 4)
}
Function print_context() {
if($PRINT_DEFAULT_USER -or ($DEFAULT_USER -ne ${env:UserName})) {
print_segment $CONTEXT_BG $CONTEXT_FG "${env:UserName}@${env:ComputerName}"
}
}
Function print_dir() {
if ($COLLAPSE_DIR -and ((($pwd).ToString().ToCharArray() | Where-Object {$_ -eq '\'} | Measure-Object).Count) -gt 1) {
print_segment $DIR_BG $DIR_FG " $($pwd.Drive.Root)..\$($pwd | Split-Path -Leaf)"
}
else {
print_segment $DIR_BG $DIR_FG " $pwd"
}
}
Function print_git() {
if(Get-Command git -ErrorAction SilentlyContinue) {
if ($(git rev-parse --is-inside-work-tree 2>$null)) {
$branch = $(git symbolic-ref HEAD 2>$null).ToString().Substring(11)
$gitStatus=$(git status | select -last 1)
if (($gitStatus -eq "nothing to commit, working directory clean") -or
(($gitStatus -eq "nothing added to commit but untracked files present (use `"git add`" to track)") -and $DISABLE_UNTRACKED_FILES_DIRTY)) {
print_segment $GIT_CLEAN_BG $GIT_CLEAN_FG "$GIT_BRANCH_GLYPH $branch"
}
elseif ($gitStatus -eq "nothing added to commit but untracked files present (use `"git add`" to track)") {
print_segment $GIT_DIRTY_BG $GIT_DIRTY_FG "$GIT_BRANCH_GLYPH $branch $GIT_UNTRACKED_GLYPH"
}
elseif ($gitStatus -eq "no changes added to commit (use `"git add`" and/or `"git commit -a`")") {
print_segment $GIT_DIRTY_BG $GIT_DIRTY_FG "$GIT_BRANCH_GLYPH $branch $GIT_DIRTY_GLYPH"
}
}
}
}
Function print_npm() {
if ((Get-Command npm -ErrorAction SilentlyContinue) -and (!$NPM_HIDE_NO_PACKAGE -or (Test-Path .\package.json))) {
print_segment $NPM_BG $NPM_FG "npm $NPM_VERSION"
}
}
@lawndoc
Copy link

lawndoc commented Sep 6, 2019

Great setup! Very straightforward to install and configure too, well done!

@VojtechStep
Copy link
Author

Thanks! I honestly forgot about this thing since I moved to Linux, appreciate the praise 😁

@favna
Copy link

favna commented Mar 1, 2020

Thanks! Amazingly easy and super useful!

@thistlillo
Copy link

Hello, when I run powershell and type echo $profile I get C:\Users\user\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1, so I downloaded all of your files in that folder. However, nothing happens and, in particular, install.ps is never run. Any idea why? Thanks!

@VojtechStep
Copy link
Author

When you say "that folder", you mean C:\Users\user\Documents\WindowsPowershell\, right? If so, I think PowerShell is picking up the Microsoft.PowerShell_profile.ps1 before profile.ps1. This could be fixed by either renaming profile.ps1 to Microsoft.PowerShell_profile.ps1, or by deleting Microsoft.PowerShell_profile.ps1. To be honest, I'm not quite sure what the difference between the two is.
Also, as you can see, this gist hasn't been updated in over four years, so you might want to take a look at something more recent, like https://starship.rs/ (I don't personally use it, but I've heard good things)

@thistlillo
Copy link

Yes, I noticed that it has been a while since the last updates. So, thank you twice for your answer and your kindness. And thanks also for the link, I will evaluate it.

At the end (I do not know how) I was able to have the PowerLine prompt, but with an important (to me) missing piece: the active conda environment. I tried also another powerline, but it was missing conda as well.

Thanks again.

@VojtechStep
Copy link
Author

If you need the conda environment in the prompt, I think starship has you covered https://starship.rs/config/#conda

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment