Instantly share code, notes, and snippets.
Last active
August 4, 2020 04:21
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save M1kep/ef5fa0009ade4f55474b4e36c5b3d709 to your computer and use it in GitHub Desktop.
A PowerShell example of using a stack for breadcrumb like navigation
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
# Initialize the Stack | |
$breadCrumb = [System.Collections.Stack]::new() | |
# Push Page "1" | |
$breadCrumb.Push(1) | |
#Initialize empty Pages object | |
$Pages = @{} | |
function New-Choice { | |
[CmdletBinding()] | |
param ( | |
[Parameter()] | |
[String] | |
$Name, | |
[Parameter()] | |
[String] | |
$Description | |
) | |
New-Object -TypeName 'System.Management.Automation.Host.ChoiceDescription' -ArgumentList $Name, $Description | |
} | |
function Request-NextPageFromUser { | |
[CmdletBinding()] | |
param ( | |
[Parameter()] | |
[String] | |
$Title, | |
[Parameter()] | |
[String] | |
$Message, | |
[Parameter()] | |
[Object[]] | |
$Options | |
) | |
$responseMap = $Options.ID | |
$menuOptions = @() | |
$Options.ForEach{ | |
$menuOptions += New-Choice -Name "&$($_.Prompt)" -Description $_.Help | |
} | |
$menuOptions += Get-BackAndMenuOptions | |
$responseIndex = $host.ui.PromptForChoice($Title, $Message, $menuOptions, 0) | |
Update-BreadCrumb -ResponseMap $responseMap -ResponseIndex $responseIndex | |
} | |
function New-Page { | |
[CmdletBinding()] | |
param ( | |
[Parameter()] | |
[String] | |
$Name, | |
[Parameter()] | |
[Int] | |
$PageID, | |
[Parameter()] | |
[scriptblock] | |
$Function, | |
[Parameter()] | |
[String] | |
$Prompt, | |
[Parameter()] | |
[String] | |
$Help | |
) | |
$Pages[$Name] = @{ | |
ID = $PageID | |
Function = $Function | |
Prompt = $Prompt | |
Help = $Help | |
} | |
} | |
function Get-BackAndMenuOptions { | |
@( | |
New-Choice '&Go Back' 'Go back a page' | |
New-Choice '&Main Menu' 'Go back to main menu' | |
) | |
} | |
function Update-BreadCrumb { | |
[CmdletBinding()] | |
param ( | |
[Parameter()] | |
[Int[]] | |
$ResponseMap, | |
[Parameter()] | |
[Int] | |
$ResponseIndex | |
) | |
if ($ResponseIndex -ge ($ResponseMap.Count)) { | |
$tmpIndex = $ResponseIndex - $ResponseMap.Count | |
switch ($tmpIndex) { | |
0 { | |
#Go Back Option | |
#Double check that we aren't at the end | |
if ($breadCrumb.Count -gt 1) { | |
$breadCrumb.Pop() | Out-Null | |
} | |
break | |
} | |
1 { | |
#Main Menu Option | |
$breadCrumb.Clear() | |
$breadCrumb.Push(1) | |
break | |
} | |
} | |
} else { | |
$mappedPageID = $ResponseMap[$responseIndex] | |
# If the pageID is the same, don't add it. We don't want to create a list of the same page | |
if (-not ($breadCrumb.Peek() -eq $mappedPageID)) { | |
$breadCrumb.Push($ResponseMap[$responseIndex]) | |
} | |
} | |
} | |
function PeopleMenu { | |
$Title = "People Main Menu" | |
Request-NextPageFromUser -Title $Title -Options @($Pages["ListPeople"]) | |
} | |
function ListPeople { | |
$Title = "List People Page" | |
$people = @( | |
"Vex", | |
"Jaykul", | |
"Jborean" | |
"Syrup" | |
) | |
Write-Host $($people -join "`n") | |
Request-NextPageFromUser -Title $Title -Options @($Pages["ListPeople"]) | |
} | |
function CarMenu { | |
$Title = "Car Main Menu" | |
Request-NextPageFromUser -Title $Title -Options @($Pages["ListCars"]) | |
} | |
function ListCars { | |
$Title = "List Cars Page" | |
$cars = @( | |
"SUV", | |
"Van", | |
"Sedan" | |
) | |
Write-Host $($cars -join "`n") | |
Request-NextPageFromUser -Title $Title -Options @($Pages["ListCars"]) | |
} | |
function MainMenu { | |
$Title = "People and Car Main Menu" | |
Request-NextPageFromUser -Title $Title -Options @($Pages["CarMenu"], $Pages["PeopleMenu"]) | |
} | |
#Define pages for easier reference in script | |
New-Page -Name 'MainMenu' -PageID 1 -Function $Function:MainMenu -Prompt 'Main Menu' -Help 'Goto the Main Menu' | |
New-Page -Name 'CarMenu' -PageID 2 -Function $Function:CarMenu -Prompt 'Car Menu' -Help 'Goto the Car Menu' | |
New-Page -Name 'PeopleMenu' -PageID 3 -Function $Function:PeopleMenu -Prompt 'People Menu' -Help 'Goto the People Menu' | |
New-Page -Name 'ListCars' -PageID 4 -Function $Function:ListCars -Prompt 'List Cars' -Help 'List all of the cars' | |
New-Page -Name 'ListPeople' -PageID 5 -Function $Function:ListPeople -Prompt 'List People' -Help 'List all of the people' | |
$pageFuncMap = @{} | |
#Map each PageID to it's respective function | |
$Pages.Values.ForEach{ | |
$pageFuncMap[$_.ID] = $_.Function | |
} | |
while ($true) { | |
$currentBreadCrumb = $breadCrumb.ToArray() | |
#Reverse array because a stack is Last In First Out | |
[array]::Reverse($currentBreadCrumb) | |
# Get Function Names for this example | |
$currentBreadCrumbWithNames = $currentBreadCrumb.forEach{ $pageFuncMap[$_].Ast.Name } | |
Write-Host "Current BreadCrumb: $($currentBreadCrumbWithNames -join ' --> ')" | |
& $pageFuncMap[$breadCrumb.Peek()] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment