I went down a real rabbit hole today, trying to do something that seems quite simple – opening a new Terminal window with a given profile from a script.
Why? I like my Terminal windows the way nature intended – using a colour scheme that’s close to what I used to use as the default on Solaris. In the macOS Terminal app, there’s a profile called Man Page which is close enough for me, and using it means I can pick a pre-defined default rather than rolling my own every time I’m on a new Mac.
For PowerShell however, this isn’t ideal – PowerShell pretty much assumes you’re using a more Windows-like colour scheme, either white text on black, or white text on dark blue, and the default syntax highlighting often doesn’t work well with a pale yellow background.
This should be easy to fix – I’ll grab the default colours for Microsoft’s “Campbell Powershell” colour theme and make a Profile for the macOS Terminal. Surely there’ll then be an easy way to programmatically open a new window using this profile? Surely…
Well, gentle reader, as it turns out, it’s nowhere near that simple.
Were Terminal just about any other app, I could fire off a quick one-liner in AppleScript like so:
tell application "Terminal" to make new window with profile "Campbell Powershell"
or even the slightly more convoluted
tell application "Terminal" to do script "" in (make new window with profile "Campbell Powershell")
But, no, if it worked like that, I wouldn’t need to write this post, and you wouldn’t be reading it.
To cut a long story short, I ended up resorting to having to use GUI scripting via System Events in AppleScript. Yes, it’s a messy hack. No, it’s not portable to different languages. Yes, I wish it weren’t like this. But here we are. My one-liner:
tell application "System Events" to tell process "Terminal" to click menu item "Campbell Powershell" of menu "new window" of menu item "new window" of menu "Shell" of menu bar item "Shell" of menu bar 1
I know AppleScript has a reputation as a read-only language, but this really stretches the metaphor of writing code in plain English.
I have no idea why I have to target a menu “Shell” of menu bar item “Shell”, etc, aren’t they one and the same thing? Apparently to System Events they’re not. Whatever.
I now have this snippet in my .zprofile file so that when I type pwsh, it fires up a new Terminal window in the correct colours with /usr/local/bin/pwsh as the shell. It’s not very clean, but it works. The redirection to /dev/null is because the existing Terminal window would echo the AppleScript and I really didn’t have the will to dig any deeper into why, and how to stop it, so I just hit it with a hammer instead.
pwsh() {
osascript -e 'tell application "System Events" to tell process "Terminal" to click menu item "Campbell Powershell" of menu "new window" of menu item "new window" of menu "Shell" of menu bar item "Shell" of menu bar 1' > /dev/null
}
For reference, the colours are:
background: #012456
text: #CCCCCC
cursor colour: #FFFFFF
ANSI Colours
black: #0C0C0C
red: #C50F1F
green: #13A10E
yellow: #C19C00
blue: #0037DA
magenta: #881798
cyan: #3A96DD
white: #CCCCCC
bright black: #767676
bright red: #E74856
bright green: #16C60C
bright yellow: #F9F1A5″
bright blue: #3B78FF
bright magenta: #B4009E
bright cyan: #61D6D6
bright white: #F2F2F2