Scripts/Example.ps1
|
Remove-Module -Name CliScrollMenu -ErrorAction SilentlyContinue; Import-Module -Name CliScrollMenu -Force -Verbose:$true $global:Props = @{ SelectedItem = $null } $global:Display = @{ Selected = "No item selected" } function Write-Log { <# .SYNOPSIS Writes a message to the log file with a timestamp. .DESCRIPTION Writes a message to the log file with a timestamp. This is useful for recording important events or user actions for later review. .PARAMETER Message The message to write to the log file. .EXAMPLE Write-Log "User selected an item." Writes "User selected an item." to the log file with a timestamp. #> param( [Parameter(ValueFromPipeline = $true)] [string]$Message ) process { $logFile = "cliScrollMenu.log" $timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' "$timestamp - $Message" | Add-Content -Path $logFile } } Function Get-ConsoleWidth { <# .SYNOPSIS Returns the width of the current PowerShell Console .DESCRIPTION Returns the width of the current PowerShell Console .EXAMPLE $width = Get-ConsoleWidth Stores the Console Width into the $width variable. #> $width = (Get-Host).UI.RawUI.WindowSize.Width if ($width -le 0) { $width = 80 # Default fallback width } return $width } Function Get-ConsoleHeight { <# .SYNOPSIS Returns the height of the current PowerShell Console .DESCRIPTION Returns the height of the current PowerShell Console .EXAMPLE $height = Get-ConsoleHeight Stores the Console Height into the $height variable. #> $height = (Get-Host).UI.RawUI.WindowSize.Height if ($height -le 0) { $height = 25 # Default fallback height } return $height } Function Write-Both { <# .SYNOPSIS Writes a message to both the console and the log file. .DESCRIPTION Writes a message to both the console and the log file. This is useful for ensuring important messages are visible to the user and also recorded in the log for later review. .PARAMETER Message The message to write to the console and log file. .EXAMPLE Write-Both "This is a test message." Writes "This is a test message." to both the console and the log file. #> param( [Parameter(ValueFromPipeline = $true)] [string]$Message ) process { Write-Log $Message Write-Output $Message } } Function Invoke-FileBrowser { <# .SYNOPSIS A simple file browser implemented using Show-ListMenu to navigate through directories and select files. .DESCRIPTION This function allows the user to browse through the file system starting from a specified path. It displays the contents of the current directory as a menu, allowing the user to navigate and select a file or folder. .PARAMETER Path The initial path to start browsing from. This can be any valid directory path. .EXAMPLE Invoke-FileBrowser -Path "C:\Users\Example\Documents" Starts the file browser at the "C:\Users\Example\Documents" directory, allowing the user to navigate and select files or folders within that directory. #> param( [string]$Path ) $files = @(Get-ChildItem -Path $Path -ErrorAction SilentlyContinue) if ($files.Count -eq 0) { Write-Host "Downloads folder is empty" -ForegroundColor Yellow return } $currentPath = $Path $lastResult = "" while ($true) { $parentPath = Split-Path -Path $currentPath -Parent $items = [array]@() #add all $files as items too foreach ($file in $files) { $items += [pscustomobject]@{Name=""; DisplayName=$file.Name; Value=$file } } $items += @( [pscustomobject]@{Name=""; DisplayName=". (Select Current Folder)"; Value=$currentPath ; DisableMultiSelect=$true}, [pscustomobject]@{Name=""; DisplayName=".. (Go Up to Parent Folder)"; Value=$parentPath ; DisableMultiSelect=$true}, [pscustomobject]@{Name=""; DisplayName="Exit Browser"; Value="Exit Browser" ; DisableMultiSelect=$true} ) $selected = Show-ListMenu -MenuItems $items -MenuName $currentPath -Force -Multi -LastResult $lastResult if ($selected -is [array]) { $lastResult = "Multiple selection is not supported in this file browser." continue } elseif ($selected -is [System.IO.DirectoryInfo] -or $selected -eq $parentPath) { $currentPath = if ($selected -is [System.IO.DirectoryInfo]) { $selected.FullName } else { $parentPath } $files = @(Get-ChildItem -Path $currentPath -ErrorAction SilentlyContinue) if ($items.Count -eq 0) { $lastResult = "This folder is empty" continue } } elseif ($selected -eq "Exit Browser") { break } else { if ($selected -is [string]) { $selected = Get-Item -Path $currentPath } Write-Output $selected break } } } Function Update-SelectedItem { <# .SYNOPSIS Updates the selected item in the properties and display objects. .DESCRIPTION This function updates the selected item in the properties and display objects, ensuring that the UI reflects the currently selected item. .PARAMETER Props The properties object containing the selected item. .PARAMETER Display The display object containing the selected item information. .PARAMETER SelectedItem The currently selected item. #> param( [PSCustomObject]$SelectedItem ) if ($SelectedItem) { $global:Props.SelectedItem = $SelectedItem $global:Display.Selected = $SelectedItem.FullName } else { $global:Display.Selected = "No item selected" } } function Add-BigDisplayItem { <# .SYNOPSIS Adds a big display item to the menu, which is shown in the footer area. .DESCRIPTION This function adds a big display item to the menu, which is shown in the footer area. It can be used to display important information or status updates to the user. .PARAMETER Name The name of the display item, used for reference in the display object. .PARAMETER DisplayName The text to display for this item in the footer. .EXAMPLE Add-BigDisplayItem -Name "Status" -DisplayName "Current Status: OK" Adds a big display item named "Status" with the text "Current Status: OK" to the menu footer. #> param( [string]$Name = "Default", [string]$DisplayName = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' ) $global:Display.$Name = $DisplayName } $width = Get-ConsoleWidth $height = Get-ConsoleHeight $heading = "kinda bad file browser" $subHeading = "K.B.F.B" $menuFillChar = "#" Set-MenuOption -HeadingColor DarkCyan -MenuNameColor DarkGray -SubHeadingColor Green -FooterTextColor DarkGray Set-MenuOption -Heading $heading -SubHeading $subHeading -MenuFillChar $menuFillChar -MenuFillColor DarkYellow Set-MenuOption -HeadingColor DarkCyan -MenuNameColor DarkGray -SubHeadingColor Green -FooterTextColor DarkGray Set-MenuOption -MaxWidth $width -MaxHeight $height $newMenu = @{ Name = "Main" DisplayName = "* * * M a i n M e n u * * *" } $subMenu = @{ Name = "SubMenu" DisplayName = "* * * S u b M e n u * * *" } $subSubMenu = @{ Name = "SubSubMenu" DisplayName = "* * * S u b S u b M e n u * * *" } $goToSubItem = @{ Name = "GoToSub" DisplayName = "Go to Sub Menu (demo of submenu navigation)" Action = { Show-SubMenu -MenuName SubMenu} } $goToSubSubItem = @{ Name = "GoToSubSub" DisplayName = "Go down another level to Sub Sub Menu (demo of submenu navigation)" Action = { Show-SubMenu -MenuName SubSubMenu} } $multiSelectItem = @{ Name = "MultiSelectDemo" DisplayName = "Multi-Select List Menu (demo of using Show-ListMenu with -Multi)" Action = { $items = @( [pscustomobject]@{Name=""; DisplayName="Option 1"; Value=1; DisableMultiSelect=$false}, [pscustomobject]@{Name=""; DisplayName="Option 2"; Value=2; DisableMultiSelect=$false}, [pscustomobject]@{Name=""; DisplayName="Option 3"; Value=3; DisableMultiSelect=$false}, [pscustomobject]@{Name=""; DisplayName="Cancel"; Value=$null; DisableMultiSelect=$true} ) $selected = Show-ListMenu -MenuItems $items -MenuName "Multi-Select Demo" -Multi if ($selected -is [array]) { Write-Both "You selected: $($selected -join ', ')" } elseif ($selected) { Write-Both "You selected: $selected" } else { Write-Both "No items selected." } } } $browseFolderItem = @{ Name = "SelectItem" DisplayName = "Select Item (demo of using Show-ListMenu to create a file browser)" Action = { $originalPath = $env:USERPROFILE $selectedItem = Invoke-FileBrowser -Path $originalPath if ($selectedItem) { Write-Output $selectedItem Update-SelectedItem -SelectedItem $selectedItem Write-Log "Selected: $($selectedItem.FullName)" } else { Write-Host "No item selected" -ForegroundColor Yellow } } } $copySelectedItem = @{ Name = "CopySelected" DisplayName = "Copy Selected Item (demo of using props to pass data)" Action = { if ($global:Props.SelectedItem) { $path = if ($global:Props.SelectedItem.DirectoryName) { $global:Props.SelectedItem.DirectoryName } else { (Get-Item $global:Props.SelectedItem).Parent } $selected = Invoke-FileBrowser -Path $path if ($selected) { if ($selected.PSIsContainer) { $selected = Join-Path -Path $selected.FullName -ChildPath $global:Props.SelectedItem.Name } else { $answer = read-host "Overwrite $($selected.FullName) (yes/no)? " if ($answer -ne 'yes') { Write-Both "Copy cancelled by user." return } } Write-Both "Copying item: $($global:Props.SelectedItem.FullName) to $(if ($selected.FullName) { $selected.FullName } else { $selected })." if ($selected.FullName) { Update-SelectedItem -Props $global:Props -Display $global:Display -SelectedItem $selected } } else { Write-Both "No destination selected to copy the item to." } } else { Write-Both "No item selected to copy" } } } $moveSelectedItem = @{ Name = "MoveSelected" DisplayName = "Move Selected Item (demo of using props to pass data)" Action = { if ($global:Props.SelectedItem) { $path = if ($global:Props.SelectedItem.DirectoryName) { $global:Props.SelectedItem.DirectoryName } else { (Get-Item $global:Props.SelectedItem).Parent } $selected = Invoke-FileBrowser -Path $path if ($selected) { if ($selected.PSIsContainer) { $selected = Join-Path -Path $selected.FullName -ChildPath $global:Props.SelectedItem.Name } else { $answer = read-host "Overwrite $($selected.FullName) (yes/no)? " if ($answer -ne 'yes') { Write-Both "Move cancelled by user." return } } Write-Both "Moving item: $($global:Props.SelectedItem.FullName) to $(if ($selected.FullName) { $selected.FullName } else { $selected })." if ($selected.FullName) { Update-SelectedItem -Props $global:Props -Display $global:Display -SelectedItem $selected } } else { Write-Both "No destination selected to move the item to." } } else { Write-Both "No item selected to move" } } } $deleteSelectedItem = @{ Name = "DeleteSelected" DisplayName = "Delete Selected Item (demo of using props to pass data)" Action = { if ($global:Props.SelectedItem) { Write-Both "Deleting item: $($global:Props.SelectedItem.FullName)." } else { Write-Both "No item selected to delete" } } } $writeHostItem = @{ Name = "WriteHost" DisplayName = "Send Remote Command" Action = { $text = Read-Host "Send?" Write-Both $text } } # Create a new menu Item $menuItem = New-MenuItem @goToSubItem -DisableConfirm # Create a new menu (first menu will become the main menu) $mainMenu = New-Menu @newMenu # Add menu item to the menu named 'Main' $menuItem | Add-MenuItem -Menu Main $mainMenu | New-MenuItem @browseFolderItem -DisableConfirm $mainMenu | New-MenuItem @copySelectedItem -DisableConfirm $mainMenu | New-MenuItem @moveSelectedItem -DisableConfirm $mainMenu | New-MenuItem @deleteSelectedItem -DisableConfirm $mainMenu | New-MenuItem @multiSelectItem -DisableConfirm Add-BuiltInMenuItem -MenuName Main -Item 'PSVersion' Add-BuiltInMenuItem -MenuName Main -Item 'Timestamp' Add-BuiltInMenuItem -MenuName Main -Item 'Exit' # Create a new menu (sub-menu) $subMenu = New-Menu @subMenu | New-MenuItem @writeHostItem -DisableConfirm # Add menu item to the menu named 'SubMenu' $subMenu | New-MenuItem @goToSubSubItem -DisableConfirm Add-BuiltInMenuItem -MenuName SubMenu -Item 'GoToParent' Add-BuiltInMenuItem -MenuName SubMenu -Item 'GoToMainMenu' Add-BuiltInMenuItem -MenuName SubMenu -Item 'Exit' # Create a new menu (sub-sub-menu) $subSubMenu = New-Menu @subSubMenu | New-MenuItem @writeHostItem -DisableConfirm # Add menu item to the menu named 'SubSubMenu' Add-BuiltInMenuItem -MenuName SubSubMenu -Item 'GoToParent' Add-BuiltInMenuItem -MenuName SubSubMenu -Item 'GoToMainMenu' Add-BuiltInMenuItem -MenuName SubSubMenu -Item 'Exit' #Add-BigDisplayItem -Name "FooterInfo" -DisplayName "This is a big display item in the footer. It can be used to show important information or status updates to the user." #Add-BigDisplayItem Clear-Host Show-SubMenu -MenuName Main |