Windows 10 replaced the Command Prompt (cmd.exe
) with Windows PowerShell (powershell.exe
) as the default command-line interpreter (CLI). PowerShell Core (pwsh.exe
) is the successor to Windows PowerShell. Until recently, I had used the Command Prompt through the Windows Terminal with the DejaVu Sans Mono font and the Solarized Dark colour scheme. What would be required to move to PowerShell Core?
Colours
Solarized provides the accent colours yellow (mapped to the terminal colour DarkYellow
), orange (Red
), red (DarkRed
), magenta (DarkMagenta
), violet (Magenta
), blue (DarkBlue
), cyan (DarkCyan
) and green (DarkGreen
).
$Host.PrivateData
specifies colours for Error
, Warning
, Debug
, Verbose
and Progress
(the progress bar). For example: $Host.PrivateData.ErrorForegroundColor
.
I set Error
red and Warning
yellow (orange seemed too close to red). I set Debug
green (like the colour often used for comments) and Verbose
cyan. For Progress
, I referenced Solarized Light and set base00 (mapped to terminal colour Yellow
) on base3 (White
).
Get-PSReadLineOption
returns an object that can be used to specify colours for:
- a
Comment
- a
Keyword
- a
Command
and itsParameter
- a
Member
(property or method) of an object - an
Operator
- a
DefaultToken
- a
Type
- a
Number
(integer or real) - a
String
(delimited by single or double quotation marks) - a
Variable
- a
ContinuationPrompt
Emphasis
or anError
.
For example: (Get-PSReadlineOption).ErrorColor = 'DarkRed'
.
PowerShell comments run from #
to the end of the line or are delimited by <# #>
. I set them green.
The PowerShell language has a number of keywords. I set them magenta.
I set commands and members of objects yellow and their parameters violet (a colour I had not used elsewhere).
I set operators base0 (Blue
), the body text in Solarized Dark.
I set default tokens blue. Default tokens include the names of functions, braces delimiting a script block ({}
), the redirection operators, the grouping operator (()
), the subexpression operator ($()
), the array subexpression operator (@()
), the cast operator ([]
), the dot sourcing operator (.
), the index operator (also []
), the call operator (&
), the background operator (also &
), the pipeline operator (|
), the member access operator (.
) and the static member operator (::
).
I set types to yellow, as it contrasted with the colour used for the delimiting (default) tokens []
.
I set numbers base01 (mapped to terminal colour Green
), the secondary content in Solarized Dark, and strings orange (as close to brown).
PowerShell variable names start with $
. I set them to cyan.
I set the continuation prompt to blue, emphasis to cyan (to follow my choice for Verbose
) and errors to red.
The colours are set in a PowerShell script (Set-Colours.ps1
), invoked in $PROFILE
:
1 2 |
& (Join-Path -Path (Split-Path -Parent -Path $PROFILE) ` -ChildPath 'Set-Colours.ps1') |
Fonts
Windows Terminal ships with computer font Cascadia Code, a font with programming ligatures. Since version 1911.20, another version of the font, Cascadia Code PL, also includes powerline symbols (see tooling below). Font Hasklig provides powerline symbols too but its coverage of programming ligatures is more limited. I switched from DejaVu Sans Mono to Cascadia Code PL.
Tooling
The PowerShell module posh-git
provides an environment for using Git on PowerShell, including Git summary status information in the PowerShell prompt.
The PowerShell module oh-my-posh
builds on posh-git
to provide prompt themes, making use of powerline fonts.
Aliases
PowerShell’s command names are structured (as Verb-Noun) but that structure means that frequently used commands are verbose. However, shorter aliases exist, or can be created, for such commands. For example dir
(Get-Children
), cd
(Set-Location
), copy
(Copy-Item
), move
(Move-Item
), and del
or rmdir
(Remove-Item
).
Shortcuts
In the Command Prompt, I set environment variables to be able to change quickly to the directory for my Haskell projects or my local GitHub repositories (eg cd %Haskell%
). PowerShell allowed for more powerful shortcuts. I created a module script Set-Shortcuts.psm1
that exported functions Set-Haskell
and Set-GitHub
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
<# .SYNOPSIS Wraps a string or an array of strings at the console width without breaking within a word. .PARAMETER linesIn A string or an array of strings. .EXAMPLE Wrap-Item -LinesIn $string .EXAMPLE $string | Wrap-Item #> function Wrap-Item { Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [String[]] $linesIn ) Process { $linesOut = @() $width = $Host.UI.RawUI.BufferSize.Width ForEach ($lineIn In $linesIn) { $lineOut = '' $counter = 0 $lineIn -split '\s+' | ForEach-Object { $len = $_.Length While ($len -gt $width) { $head = $_.Substring(0, $width - $counter - 1) If ($head) { $lineOut = "$lineOut$head`u{23ce}" } $_ = $_.Substring($width - $counter - 1) $linesOut += $lineOut $lineOut = '' $counter = 0 $len = $_.Length } $counter += $len + 1 If ($counter -gt $width + 1) { $linesOut += $lineOut.trim() $lineOut = '' $counter = $_.Length + 1 } $lineOut = "$lineOut$_ " } $linesOut += $lineOut.trim() } $linesOut } } function Set-Shortcut { Param ([String]$shortcutPath, [String]$shortcutType, [String]$shortcut) If (-not $shortcut) { Set-Location $shortcutPath $True } Else { $filePath=Join-Path -Path $shortcutPath -ChildPath $shortcut If (Test-Path $filePath) { Set-Location $filePath $True } Else { Set-Location $shortcutPath (Split-Path (Get-ChildItem -Directory) -Leaf) -Join " " | Wrap-Item | ` Write-Host | Out-Null $False } } } <# .Description Set the location for GitHub repositories or an identified repository. #> function Set-GitHub { Param ([String]$repository) $gitHub='C:\Users\mikep\Documents\Code\GitHub' $gitHubType='repository' If (-not (Set-Shortcut $gitHub $gitHubType $repository)) { Write-Error "$gitHubType not found: $repository" ` -Category ObjectNotFound } } <# .Description Set the location for Haskell projects or an identified project. #> function Set-Haskell { Param ([String]$project) $haskell='C:\Users\mikep\Documents\Code\Haskell' $haskellType='project' If (-not (Set-Shortcut $haskell $haskellType $project)) { Write-Error "$haskellType not found: $project" ` -Category ObjectNotFound } } Export-ModuleMember -Function Set-Haskell, Set-GitHub |