We all like to customize our PowerShell profile to our own needs, so there is no right or wrong in how to do this, but I’d like to show you mine nonetheless.
UPDATE: Kirk Munro (@Poshoholic) was good enough to point out that I had a bug in my path shortener, so in the process of rewriting it, I decided to do a small overhaul of my entire PowerShell Profile.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# PowerShell Profile – Øyvind Kallstad | |
# Last updated: 27.11.2014 | |
# Get the original prompt | |
$originalPrompt = (Get-Item function:prompt).ScriptBlock | |
# define our new custom prompt | |
$customPrompt = { | |
$currentLocaction = $executionContext.SessionState.Path.CurrentLocation.ToString() | |
$host.UI.RawUI.WindowTitle = $currentLocaction.Replace('Microsoft.PowerShell.Core\','') | |
Write-Host '[' –NoNewLine | |
if (Test-Path variable:/PSDebugContext) { | |
Write-Host 'DBG' –NoNewline –ForegroundColor 'Red' | |
} | |
elseif(Invoke-IsAdmin){ | |
Write-Host "$($env:COMPUTERNAME)" –NoNewLine –ForegroundColor 'Red' | |
} | |
else{ | |
Write-Host "$($env:COMPUTERNAME)" –NoNewLine –ForegroundColor 'DarkGray' | |
} | |
Write-Host "] $(Invoke-PathShortener $currentLocaction)$('>' * ($nestedPromptLevel + 1))" –NoNewLine | |
return ' ' | |
} | |
# define a demo prompt | |
$demoPrompt = { | |
$host.UI.RawUI.WindowTitle = $executionContext.SessionState.Path.CurrentLocation.ToString() | |
return '[Øyvind Kallstad] > ' | |
} | |
function Set-Prompt { | |
param ([ScriptBlock] $ScriptBlock) | |
$null = New-Item –Path function:prompt –Value $ScriptBlock –Force | |
} | |
function Invoke-PathShortener { | |
<# | |
.SYNOPSIS | |
Path Shortener | |
.NOTES | |
Author: Øyvind Kallstad | |
Date: 27.11.2014 | |
Version: 1.0 | |
#> | |
[CmdletBinding()] | |
param ( | |
# Path to shorten. | |
[Parameter(Position = 0)] | |
[ValidateNotNullorEmpty()] | |
[string] $Path, | |
# Defines how many path levels to keep after the root before shortening. | |
[Parameter(Position = 1)] | |
[int] $KeepAfterRoot = 1 | |
) | |
$regexString = '^(.+:{1,2}|\\{2}.+?\\.+?(?=\\))(.*)' | |
$separator = [System.IO.Path]::DirectorySeparatorChar | |
# first we need to clean up the path | |
if ($path.StartsWith('Microsoft.PowerShell.Core\FileSystem')) { | |
$path = $path.Replace('Microsoft.PowerShell.Core\FileSystem::','') | |
} | |
elseif ($path.StartsWith('Microsoft.PowerShell.Core')) { | |
$path = $path.Replace('Microsoft.PowerShell.Core\','') | |
} | |
# use regex to separate the root from the rest of the path | |
$matches = [regex]::Matches($path,$regexString) | |
$pathRoot = $matches.Groups[1].Value | |
$pathRest = ($matches.Groups[2].Value).TrimStart('\') | |
# split on the separator character to get an array of path parts | |
$pathParts = $pathRest.Split($separator) | |
# put together the outpath string | |
if ($pathParts) { | |
if ($pathParts.Length -ge ($KeepAfterRoot + 2)) { | |
$outPath += $pathRoot | |
for ($i = 0; $i -lt $KeepAfterRoot; $i++) { | |
$outPath += $separator + $pathParts[$i] | |
} | |
$outPath += '…' + $separator + $pathParts[-1] | |
} | |
else { $outPath += $pathRoot + $separator + $pathRest } | |
} | |
else { $outPath += $pathRoot } | |
Write-Output $outPath | |
} | |
function Open-SublimeText{ | |
# Øyvind Kallstad //2014 | |
[CmdletBinding()] | |
param( | |
[Parameter(ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)] | |
[string[]]$Path | |
) | |
BEGIN{ | |
if(-not(Test-Path –Path $env:ProgramFiles –Filter '\Sublime Text *\sublime_text.exe')){break} | |
$p = @() | |
} | |
PROCESS{ | |
foreach ($thisPath in $Path) { | |
$p += $thisPath | |
} | |
} | |
END{ | |
$exe = ((Get-Item "$($env:ProgramFiles)\Sublime Text *\sublime_text.exe" | Sort-Object 'LastWriteTime' –Descending | Select-Object –First 1).FullName) | |
& $exe $p | |
} | |
} | |
function Invoke-GetLocationEx { (Get-Location).ToString() } | |
function Invoke-IsAdmin { | |
$windowsIdentity=[System.Security.Principal.WindowsIdentity]::GetCurrent() | |
$windowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($windowsIdentity) | |
$adm=[System.Security.Principal.WindowsBuiltInRole]::Administrator | |
Write-Output ($windowsPrincipal.IsInRole($adm)) | |
} | |
Set-Alias –Name 'st' –Value 'Open-SublimeText' | |
Set-Alias –Name 'pwd' –Value 'Invoke-GetLocationEx' –Option 'AllScope' –Force | |
Set-Prompt $customPrompt | |
Set-Location –Path 'E:\Users\ojk\Documents\Scripts' | |
$env:Path += ';C:\Program Files (x86)\ConfigMgr 2012 Toolkit R2\ClientTools' | |
if ($Host.Name -eq 'Windows PowerShell ISE Host') { | |
Import-Module 'ISESteroids' | |
Start-Sleep –Seconds 2 | |
Start-ISERegex | |
} |
I start by saving the original PowerShell prompt. I then define my new custom prompt, as well as a third demo prompt. I created a short function (Set-Prompt) that I can use to change my prompt on the fly with the prompts I have predefined in my profile.
Next I have my new and improved path shortener, that now also works when using PowerShell providers like registry, variable etc.
I have also created a function that lets me open files for editing in Sublime Text, as well as an extension function of Get-Location (that I later use when overriding the pwd alias further down).
I also converted my old code to check if the current user is running as admin to a function instead.
Next are my alias definitions, followed by setting the new prompt, my custom location and updating my environment variables.
Lastly I load my modules. I have included a check for ISE so that I can use the same profile for both ISE and the normal host.
That’s it. Any comments and suggestions are always welcome!
My profile looks alot like Ed Wilson’s. I copied his years ago, but I like what you’re doing with yours as well. I plan on stealing some of your ideas too, after I take a nap.
LikeLike
heh.. no sweat. Steal all you like 🙂
LikeLike