Skip to content

Instantly share code, notes, and snippets.

@adbertram
Last active March 15, 2024 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adbertram/180f7693eb5a3af7e5a4c4fc888960f1 to your computer and use it in GitHub Desktop.
Save adbertram/180f7693eb5a3af7e5a4c4fc888960f1 to your computer and use it in GitHub Desktop.
An interactive PowerShell function to select items from a collection based on the first letter
function SelectItem {
<#
.SYNOPSIS
Selects an item from a provided list based on keyboard input.
.DESCRIPTION
The SelectItem function allows the user to select an item from a given list of strings by typing the first letter of the
item. The function iterates through the items that start with the given letter, allowing the user to press the same letter
repeatedly to cycle through the options. Selection is confirmed with the Enter key.
.PARAMETER Item
An array of strings from which the user can select. This parameter is mandatory and cannot be null or empty.
.EXAMPLE
$items = 'Red', 'Orange', 'Yellow', 'Green', 'Blue'
SelectItem -Item $items
This example will prompt the user to select a color by typing the first letter of the color name. Pressing the Enter key
confirms the selection.
.NOTES
This function uses the host's UI RawUI.ReadKey method to capture key presses without echoing them to the console. It's
designed for interactive terminal sessions and may not work as expected in non-interactive environments or IDEs that do
not support RawUI functionality.
#>
param(
[Parameter(Mandatory)] # Indicates that this parameter must be provided for the function to execute
[ValidateNotNullOrEmpty()] # Ensures the parameter value is not null or an empty string
[string[]]$Item # Array of strings representing the items to select from
)
# Initialize variables for navigating and selecting items
$currentIndex = -1 # Index for the current item selection
$lastKey = $null # Stores the last key pressed by the user
$currentMatch = $null # Stores the currently matched item based on user input
$currentDisplay = "" # Variable to hold the display value of the current item selection
do {
# Capture the key press from the user without echoing it to the terminal
$keyPress = $host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
# Convert the virtual key code to a character and make it uppercase
$keyChar = [char]$keyPress.VirtualKeyCode
$keyChar = $keyChar.ToString().ToUpper()
if ($keyPress.VirtualKeyCode -eq 13) {
# If Enter key is pressed, exit the loop
break
}
if ($lastKey -ne $keyChar) {
# If a different key is pressed, reset the index to 0 and update the last key
$currentIndex = 0
$lastKey = $keyChar
} else {
# If the same key is pressed consecutively, increment the index to navigate through matches
$currentIndex++
}
# Filter the items based on the starting letter matching the pressed key
[array]$itemMatches = $Item | Where-Object { $_ -match "^$lastKey" }
if ($itemMatches) {
if ($currentIndex -ge $itemMatches.Count) {
$currentIndex = 0 # Reset the index if it exceeds the number of matches
}
if ($itemMatches.Count -gt 0) {
$currentMatch = $itemMatches[$currentIndex] # Update the current match based on the index
} else {
$currentMatch = $null
}
# Clear the previous display output
$clearLength = $currentDisplay.Length
$clearMsg = " " * $clearLength
Write-Host "`r$clearMsg" -NoNewline # Use spaces to clear the display
if ($null -ne $currentMatch) {
$currentDisplay = $currentMatch
Write-Host "`r$currentDisplay" -NoNewline # Display the current match
} else {
$currentDisplay = "No match found for `"$lastKey`"" # Display no match message if no matches are found
Write-Host "`r$currentDisplay" -NoNewline
}
}
} while ($keyPress.VirtualKeyCode -ne 13) # Continue looping until the Enter key is pressed
# Output the selected item or a message indicating no selection was made
if ($null -ne $currentMatch) {
$currentMatch
} else {
Write-Host "`nNo selection made."
}
}
## Example usage
$colors = @(
'Red',
'Orange',
'Yellow',
'Green',
'Blue',
'Indigo',
'Violet',
'Black',
'White',
'Grey',
'Cyan',
'Magenta',
'Maroon',
'Navy',
'Olive',
'Purple',
'Teal',
'Lime',
'Silver',
'Gold',
'Beige',
'Coral',
'Ivory',
'Khaki',
'Lavender',
'Salmon',
'Tan',
'Turquoise',
'DarkBlue',
'DeepPink',
'LightGreen',
'MediumBlue',
'Orchid',
'PaleGreen',
'RoyalBlue',
'SlateGray',
'SpringGreen',
'SteelBlue',
'Tomato',
'YellowGreen'
)
Write-Host "Pick a color by pressing the first letter."
SelectItem -Item $colors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment