Back in December, I read an article by Jessica Joy Kerr on moving from the traditional UNIXy shells to Powershell which caught my interest. I’ve changed shells a few times before and found an improvement each time, so I thought I’d challenge myself to two months with Powershell on Linux and Mac.
What I hadn’t noticed at the time was that Jessica was using Windows. When I’ve been a C # developer, I found Powershell to be a great tool to use compared to the UX hell that is the usual command-line experience on Windows systems. So during this trial, I was working primarily on a Ubuntu machine and using my Mac at home.
So is it worth switching?
My first question was can I get to the minimum acceptable experience, which for me is defined by the robbyrussel theme from ohmyzsh as:
There is an ohmyzsh module for Powershell , with the amusing name of ‘oh my posh’, but you’d be surprised to find all it does is set the prompt and misses the useful aliases and tabbing behavior that comes from ohmyzsh. Even worse, the prompts often break when you aren’t on Windows so I figured I’d try and DIY it.
Now, customizing your prompt in Bash and Zsh is a matter of adding a bunch of hieroglyphics to an environment variable called PS1 . It’s a dark art at first. So I was quite delighted to find the creators of Powershell had eschewed the environment variable approach to replace it with a function call.
All you need to do to set your prompt in Powershell is override the Prompt function with whatever you want. So a minimal prompt could be:
function Prompt { Write -Host
) '>' ) -NoNewlinerecommending using techniques that don't work cross-platform as best practice.
return
Which is pretty neat, as you can add whatever you want in a straightforward way. From this, I found a Git module which provides you with a Get-GitStatus function, which we will come back to. With that, it was simple to add the elements that make up my preferred prompt:
function Prompt {Check to see if the last command was successful
if
(($?
({ {Write -Host
) '➜'
) -NoNewline
) -ForegroundColor(Green) (Green
else
({ {Write -Host
) '➜'
) -NoNewline
) -ForegroundColor(Red) (Red)
Write out the current directory name Write -Host
) (
“
Split -Path
) -path
) $ pwd
) -Leaf )))
) -NoNewline
- ForegroundColor Cyan if in a git repo, print out the branch name and any changesgitStatusGet- GitStatus
if
(($ gitStatus
({ {Write -Host
) "git :(" - NoNewline - ForegroundColor Blue
Write -Host
) $ (
$ gitStatus
. Branch
- NoNewline - ForegroundColor
) "-NoNewline -ForegroundColor Red." Write-Host "
) "Blue({ {
(0) ()
if
(($ gitStatus . Working .
Length
- gt
Write -Host
) (
“
:: ConvertFromUtf ()) - NoNewline - ForegroundColor (Yellow)
.
return
You can see my entire profile in this gist .
Another distinguishing feature of Powershell is how profiles work. Rather than searching in a myriad of profile files in
/ etc and your home directory, there is only one place to set things, which you can easily access via the $ profile
variable. Socode $ profile opens your profile, or makes a new one, in VSCode.
I mentioned using a module back there which provided Get-GitStatus . Powershell has a first-class module system built into itself. You can install any publically available module using Install-Module some-module which is excellent for organizing community efforts.
The modules I’ve installed are:
posh-git for Get-GitStatus git-aliases for the same git aliases as ohmyzsh PSReadLine to recreate the tabbing behavior from zsh (rather than Bash) (nvm) since nvm (is a shell function rather than a file, this recreates it in Powershell. An excellent module I ' ve used on other shells is the z 'jump around' module. This builds a history of directories you frequent then gives you a command to quickly jump back into them. Unfortunately, the Powershell module did not work on Linux, so I fixed thatThis problem shows one of my major gripes with Powershell. It comes in two flavors, a ‘desktop’ edition (read: old Windows boxes) and a ‘core’ edition which is cross-platform. Unfortunately, the module ecosystem has folks mainly targetting the ‘desktop’ edition, so a lot of modules explode when you install them.
Even the semi-official standards documents
Before I felt comfortable submitting a pull request to a real repository, I wanted to get used to coding in the Powershell language, which turns out to be a very nice language to use. I did the usual Roman Numerals, Bowling Scores and Urnfield problems that I do with all languages to get used to them. You can see that code on Github .
There's even a unit testing framework called Pester which makes testing possible in a modern fashion. Here is my attempt at solving the Urnfield problem inlined with tests.
[Parameter(Mandatory = $True)] $ amount
) ones$ $ amount
(%)(5)fives
[math] :: floor ( $ amount/ 5 ) / '
It is) ones
'
$ fivesls | head -n 3 In Powershell, it's $ (dir) [0..2] since the dir command is returning an array which I can index into.'handles numbers less than 5 '{
(1)(should (Be - Be
|'/'
(2)(should (Be - Be
|'//'
(3)(should (Be - Be (// '///'
|(4)(should (Be - Be (// // // '
|It is
'handles the magic 5 ' {
(5)(should (Be - Be
|''It is
I'd do something like'handles other interesting numbers under ()(
(6)(should (Be - Be
|'/ '
(ShouldOne of the significant advantages of Powershell is that it pipes (objects) rather than strings between programs. For example, if you do a ls in bash, it returns a string output of files. When you do that in Powershell, it returns a list of files. The default behavior is then to print these objects.
For example, if we wanted to get the first three files from ls
Small things like this clean up complicated pipes.
For example with the Get-GitStatus command you get an object back like:
HasWorking: True Upstream: origin / master Branch: master UpstreamGone: False RepoName: techblog AheadBy: 0 StashCount: 0 BehindBy: 0 Working: {_posts / 2020 - - 29 - a-month-with-powershell.md, Gemfile.lock, _posts / 2020 - - 12 - the-four-s-technique.md} HasUntracked: True HasIndex: False GitDir: /home/wrightj/projects/joejag/techblog/.git Index: {}Which you can then use, as I do for my prompt, via $ (Get-GitStatus) .Branch
Sounds good right, but there are downsides to using Powershell on a UNIX. One of which is that commands you find on StackOverflow may not work anymore. For example, I wanted to check the TLS cert on this domain on the command line; a quick Google told me to use echo | openssl s_client -showcerts -servername joejag.com -connect joejag.com: 823 2> / dev / null | openssl x 443 -inform pem -noout -text which works fine in Bash or Zsh. Still, in Powershell, it throws an error for some reason.
It’s easier to switch to another shell then work out what’s wrong in Powershell.
When I wrote my zsh article my final question was whether you should change your default shell to Zsh over Bash. With my answer being an emphatic ‘yes!’. Once I had things working well, I tried to do this with Powershell, but it’s not possible. If you cat / etc / shells you can see what's available on your system. For me, that’s:
# / etc / shells: valid login shells / bin / sh / bin / dash / bin / bash / bin / rbash / bin / zsh / usr / bin / zshThis is because Powershell has not been made to work using the POSIX standard for starting shells, which involves reading some environment setup. However, they are working on it
and expect it to be possible when Powershell 7 comes out (I'm using Powershell 6 while writing this).I got around this by putting pwsh in my bash profile to start a new shell. This isn’t perfect, but the best you can do right now.
So to summarise:
Advantages
Powershell is a modern scripting language which is great for writing scriptsFirst-class module ecosystem It's got nice design touches like prompt as a function Disadvantages
You cannot use it as a login shell (yet) UNIX systems are seen as a second class due to the legacy of Powershell 'desktop' vs' core 'versionsSome commands you copy and paste from online won't work PSReadLine isn't perfect, leading to clumsy tabbing behavior I really enjoyed using Powershell as my default sh ell. But I can’t recommend it to anyone else until most of the disadvantages are met. With PS7 coming out as a login shell and the community moving to embrace the ‘core’ version over ’desktop’ then it’ll be in a healthier place than any other shell. But we aren’t there yet.
Read More
GIPHY App Key not set. Please check settings