My Shell: PowerShell
Table of Contents
This is the third post in this series. You can see the first post explaining Terminals, Shells & Prompts. In this post I’ll be covering my specific PowerShell profile settings.
If your interested in my terminal, check out My Terminal: WezTerm.
You can see the latest copy of my config files here: HeyItsGilbert/dotfiles
My goals #
These are my overall goals with my particular setup.
- Configs that I can sync between computers of any OS.
- Allow flexibility to add machine/environment specific options (e.g. work).
- Allow ability to swap any component when I see the next new shiny thing.
PowerShell for every system! #
Surprise! Or not. Unless you stumbled on this page randomly, you probably found this through my various PowerShell social networking posts. I love PowerShell. I love working with Objects, I love how easy it is to learn and teach, and how easy it is to call more advanced .Net methods. After writing a lot of bad bash scripts and even worse sed/awk commands, I’ll use PowerShell as much as I can get away with it.
I take great pride at work for being known as the PowerShell person. I was recently tagged at work with:
cc Gilbert who is a known powershell lover
I’ll be going over my profile which at first glance may seem complex, but I’ll slowly talk through each portion. If you feel like copying it, feel free to take what works for you. See something you think I could improve? Tell me! I love to iterate and improve on my shell experience.
My Profile #
A lot of inspiration for my profile structure and how I optimized it came from Steve Lee’s Optimizing your $Profile. You can see the latest version of my profile on my GitHub.
Here is a high level overview of how my Profile is laid out.
- Variables (single global variable)
- Attempt to load WorkFunctions if it exists.
- Functions
- Alias and helper functions
Initialize-Profile
functionprompt
function
- Safely load starship
Below I’ll walk through each of these.
Work Functions #
One of the patterns you’ll notice is that I always leave a way to add work
specific configs. Here I check if a file in the same directory called
WorkFunctions.ps1
exists and if it does load it.
Functions Over Aliases #
I’ve noticed that loading functions is faster the executing commands such as
Set-Alias
, and my goal is to load my profile as fast as possible. This is
especially true when we get to the sections below on prompt loading.
Intialize-Profile
& prompt
Functions #
This portion is almost directly lifted from Steve’s post (which I highly recommend you read). The difference is what I load in it.
What makes these two functions important is that they only execute the initialization once and only if we are actually presented a prompt. That means that any calls to PowerShell aren’t slowed down by my prompt if no prompt ever loads.
Initialize-Profile
is the real important function. That’s where I set all my
options for PSReadLine and import modules. These are things that we really don’t
want to do in a promptless session.
I Import-Module
some of my favorite modules. Most of them impact the prompt,
shell, and terminal. I’ll spare you all the particulars of all my settings, but
I’ll call out a few of my favorites.
This saves your last commands output to $__
which is super handy.
I conditionally load @mdgrs ShellIntegration script. This adds some escape sequces to your prompt which allows you to do things like double click on the output in the terminal and it’ll highlight appropriately.
This uses the ocgv_history
function (defined in the functions above) to show
my command history in Out-ConsoleGridView thanks to @AndrewPla!
The prompt
function calls the Initialize-Profile if the global variable isn’t
set. If we don’t have starship, then I revert to an old powerline style prompt.
The old prompt code isn’t pretty to look it, but honestly I rarely see it.
Starship #
So the last thing we do is load starship. What does starship do? It overwrites the prompt! So how do we handle this conflict?
What the prompt above does is call the Initialize-Profile
function once.
Starship supports PreCommand by writing a Invoke-Starship-PreCommand
function
in your profile. Now we can leverage all the work from the profile
initialization but still get our sweet Starship prompt.
Hopefully you found something useful for your profile. If there’s something you want to see me go over in more details, let me know in the comments! Feel free to leave feedback or questions. You can also find me on the PowerShell Discord, or the various social networks linked below.
In my next post I’ll be going over escape codes! There’s a ton of great content out there.
Shout out again to @mdgrs for all the awesome shell tools like Shell Integration, and Dynamic Titles.
Also thanks to Mr Andrew Pla for his
ocgv
function.
References #
- Optimizing your $Profile https://devblogs.microsoft.com/powershell/optimizing-your-profile/
- about_Profiles https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-7.3
- fb_powershell cookbook https://github.com/facebook/chef-cookbooks/tree/main/cookbooks/fb_powershell
- @mdgrs ShellIntegration script https://gist.github.com/mdgrs-mei/1599cb07ef5bc67125ebffba9c8f1e37
- @andrewplatech ocgv PS Readline https://www.youtube.com/watch?v=ciJiWQ4FHHI&t=618s
More in this series
- Terminals, Shells, and Prompts
- My Terminal: WezTerm
- My Shell: PowerShell
- My Prompt: Starship