Private/Read-AACSelection.ps1
|
function Read-AACSelection { <# .SYNOPSIS Asks the operator to pick one or more items from a list - a Spectre.Console selection prompt, moved with the arrow keys - and returns the chosen ones. .DESCRIPTION -Multiple: a check list (space to toggle, Enter to accept), at least one item required. Otherwise a single choice. Items are shown with -Label (a script block on each item; the item as text by default). Only at an interactive console: in a script, a CI job or with redirected output there is no one to ask, so it stops with -Hint (what to pass instead) rather than waiting forever. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string] $Title, [Parameter(Mandatory)] [object[]] $Item, [scriptblock] $Label = { param($It) [string]$It }, [switch] $Multiple, [string] $Hint = 'Pass the values as parameters instead.' ) if (-not [Spectre.Console.AnsiConsole]::Profile.Capabilities.Interactive -or [Console]::IsInputRedirected) { throw "There's no interactive console to ask in. $Hint" } # Labels must be unique for the prompt to map back to the items. $byLabel = [ordered]@{} foreach ($it in $Item) { $text = [string](& $Label $it) $n = 2 $unique = $text while ($byLabel.Contains($unique)) { $unique = "$text ($n)"; $n++ } $byLabel[$unique] = $it } $console = [Spectre.Console.AnsiConsole]::Console if ($Multiple) { $prompt = [Spectre.Console.MultiSelectionPrompt[string]]::new() $prompt.Title = $Title $prompt.PageSize = 15 $prompt.Required = $true $prompt.InstructionsText = '[grey58](space to choose, enter to accept)[/]' foreach ($text in $byLabel.Keys) { $null = $prompt.AddChoice([Spectre.Console.Markup]::Escape($text)) } $chosen = @($prompt.Show($console)) } else { $prompt = [Spectre.Console.SelectionPrompt[string]]::new() $prompt.Title = $Title $prompt.PageSize = 15 foreach ($text in $byLabel.Keys) { $null = $prompt.AddChoice([Spectre.Console.Markup]::Escape($text)) } $chosen = @($prompt.Show($console)) } # Back from the escaped text to the items. foreach ($text in $byLabel.Keys) { if ($chosen -contains [Spectre.Console.Markup]::Escape($text)) { $byLabel[$text] } } } |