I realize this is old, but it seems to have a lot of traffic from like-minded individuals who want a better menu option than System.Management.Automation.Host.ChoiceDescription
. I was looking for something similar and found this closed question that inspired me to write a menu system that surrounds the choices with a box adapted to the longest choice length or menu title:
┌Choose an option┐
│first │
│second option │
│third │
└────────────────┘
The script only works in Powershell console, not ISE. Using the arrow keys will highlight a selection in reverse video. Hitting enter will return it.
function Show-SimpleMenu ([array]$MenuOptions, [string]$Title ='Choose an option'){
$maxLength = ($MenuOptions | Measure-Object -Maximum -Property Length).Maximum #get longest string length
If($maxLength -lt $Title.Length){$maxLength = $Title.Length}
$highlighted = 0
$MenuTop = [Console]::CursorTop
Do{
[Console]::CursorTop = $MenuTop
Write-Host "┌$($Title.PadRight($maxLength,'─'))┐"
for ($i = 0; $i -lt $MenuOptions.Length;$i++) {
Write-Host "│" -NoNewLine
if ($i -eq $highlighted) {
Write-Host "$(([string]$MenuOptions[$i]).PadRight($maxLength,' '))" -fore $host.UI.RawUI.BackgroundColor -back $host.UI.RawUI.ForegroundColor -NoNewline
} else {
Write-Host "$(([string]$MenuOptions[$i]).PadRight($maxLength,' '))" -fore $host.UI.RawUI.ForegroundColor -back $host.UI.RawUI.BackgroundColor -NoNewline
}
Write-Host "│"
}
Write-Host "└$('─' * ($maxLength))┘"
$keycode = [Console]::ReadKey($true)
If ($keyCode.Key -eq [ConsoleKey]::UpArrow -and $highlighted -gt 0 ) {$highlighted--}
If ($keycode.Key -eq [ConsoleKey]::DownArrow -and $highlighted -lt $MenuOptions.Length - 1) {$highlighted++}
}While($keyCode.Key -ne [ConsoleKey]::Enter -and $keycode.Key -ne [ConsoleKey]::Escape )
If($keyCode.Key -eq [ConsoleKey]::Enter){ $MenuOptions[$highlighted] }
}
Show-SimpleMenu @('first','second option','third')
There is also a multi-select version on GitHub that allows choosing multiple options with the space bar.