Last active
March 15, 2024 12:28
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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