Public/Read-emsPrompt.ps1

<#PSScriptInfo
 
.VERSION 1.0.0
 
.GUID bd13a0b8-bbe9-47d4-aa8f-d09132cc6ffd
 
.AUTHOR enthus Managed Services GmbH
 
.COMPANYNAME enthus Managed Services GmbH
 
#>


#Requires -Version 5.1

<#
    .SYNOPSIS
    Asks the user a question based on a provided array and returns the selected option as a string.
 
    .DESCRIPTION
    This cmdlet presents the user with a choice prompt based on provided options and returns the selected option as a string. Supports default options and automatic pre-selection when only one option is available.
 
    .NOTES
    PSVersion: 5.1.x or 7.2.x
 
    ENVIRONMENT:
    [ ] Azure Automation
    [ ] Azure Function
    [x] Local
    [ ] Nerdio
    [ ] PowerShell Universal
    [ ] Server
    [ ] ...
 
    REQUIRED CONTEXT:
    [ ] Application && Delegated
    [ ] Application
    [ ] Delegated
    [x] User
 
    REQUIRED PERMISSIONS:
    - None
 
    .PARAMETER Options
    Array of strings representing the available options for selection. This parameter is mandatory and cannot be empty.
 
    .PARAMETER Question
    The question to display to the user. This parameter is mandatory and cannot be empty.
 
    .PARAMETER Title
    Optional title for the prompt dialog. If not provided, no title will be displayed.
 
    .PARAMETER DefaultOption
    Optional default option that will be pre-selected if it matches one of the options. If only one option is provided, it will automatically be pre-selected as default.
 
    .INPUTS
    None. This cmdlet does not accept pipeline input.
 
    .OUTPUTS
    System.String. Returns the selected option as a string value.
 
    .EXAMPLE
    $selectedOption = Read-emsPrompt -Options @("Yes", "No") -Question "Do you want to continue?"
 
    Prompts the user with a Yes/No question and returns the selected option.
 
    .EXAMPLE
    $selectedOption = Read-emsPrompt -Options @("Option1", "Option2", "Option3") -Question "Please select an option:" -Title "Configuration" -DefaultOption "Option1"
 
    Prompts the user with multiple options, a title, and a default selection.
 
    .EXAMPLE
    $result = Read-emsPrompt -Options @("prd") -Question "Please enter the stage name you want to use:"
 
    Shows a single option prompt that will automatically pre-select the only available option as default.
#>

function Read-emsPrompt {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Options,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Question,

        [Parameter()]
        [string]$Title = $null,

        [Parameter()]
        [string]$DefaultOption = $null
    )
    $verbosePrefix = "Read-emsPrompt | "

    #region Validation
    if (!(Get-emsIsInteractiveHost)) {
        throw "This function requires an interactive PowerShell host."
    }
    #endregion Validation

    try {
        #region Choice collection creation
        Write-Verbose "$($verbosePrefix)Create choice collection with $($Options.Count) options ..."

        $choices = [System.Collections.ObjectModel.Collection[System.Management.Automation.Host.ChoiceDescription]]::new()

        foreach ($option in $Options) {
            Write-Verbose "$($verbosePrefix)Add option '$option' ..."
            $choices.Add([System.Management.Automation.Host.ChoiceDescription]::new($option, $option))
        }
        #endregion Choice collection creation

        #region Get default option
        $defaultIndex = -1
        if ($Options.Count -eq 1) {
            Write-Verbose "$($verbosePrefix)Single option detected, set as default ..."
            $defaultIndex = 0
        } elseif ($DefaultOption) {
            Write-Verbose "$($verbosePrefix)Set option '$DefaultOption' as default option ..."
            $defaultIndex = [array]::IndexOf($Options, $DefaultOption)

            if ($defaultIndex -lt 0) {
                Write-Warning "Default option '$DefaultOption' not found in options. No default will be set."
            }
        }
        #endregion Get default option

        #region User Prompt
        Write-Verbose "$($verbosePrefix)Prompt user for choice ..."
        $index = $Host.UI.PromptForChoice($Title, $Question, $choices, $defaultIndex)
        $selectedOption = $choices[$index].Label

        Write-Verbose "$($verbosePrefix)>> User selected option '$selectedOption' (index: $index)"
        #endregion User Prompt

        Write-Output $selectedOption
    } catch {
        $errorRecord = [System.Management.Automation.ErrorRecord]::new(
            $_.Exception,
            'PromptSelectionFailed',
            [System.Management.Automation.ErrorCategory]::InvalidOperation,
            $Question
        )
        $PSCmdlet.ThrowTerminatingError($errorRecord)
    }
}