Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 97 additions & 34 deletions PesterExplorer/Private/Get-ListPanel.ps1
Original file line number Diff line number Diff line change
@@ -1,36 +1,59 @@
function Get-ListPanel {
<#
.SYNOPSIS
Create a list panel for displaying items in a TUI.

.DESCRIPTION
This function generates a list panel that displays items in a TUI (Text User
Interface) using Spectre.Console. It formats the items based on whether they
are selected or not, and handles special cases like parent directories.

.PARAMETER List
An array of strings to display in the list. Each item can be a file path,
a test name, or a special item like '..' for parent directories.

.PARAMETER SelectedItem
The item that is currently selected in the list. This will be highlighted
differently from unselected items.

.EXAMPLE
Get-ListPanel -List @('file1.txt', 'file2.txt', '..') -SelectedItem 'file1.txt'

This example creates a list panel with three items, highlighting 'file1.txt'
as the selected item.
.NOTES
This is meant to be called by the main TUI function: Show-PesterResult
<#
.SYNOPSIS
Create a list panel for displaying items in a TUI.

.DESCRIPTION
This function generates a list panel that displays items in a TUI (Text User
Interface) using Spectre.Console. It formats the items based on whether they
are selected or not, and handles special cases like parent directories.

The function supports viewport management, showing only a subset of items
when the list is longer than the available display height.

.PARAMETER List
An array of strings to display in the list. Each item can be a file path,
a test name, or a special item like '..' for parent directories.

.PARAMETER SelectedItem
The item that is currently selected in the list. This will be highlighted
differently from unselected items.

.PARAMETER SelectedPane
Indicates which pane is currently selected. Affects the border color of the panel.

.PARAMETER ListScrollPosition
The scroll position within the list. Used for viewport management when the list
is longer than the available display height.

.PARAMETER ListHeight
The height of the list display area. When specified and the list is longer,
viewport management is applied to show only visible items.

.EXAMPLE
Get-ListPanel -List @('file1.txt', 'file2.txt', '..') -SelectedItem 'file1.txt'

This example creates a list panel with three items, highlighting 'file1.txt'
as the selected item.

.EXAMPLE
Get-ListPanel -List $longList -SelectedItem 'item5' -ListScrollPosition 2 -ListHeight 10

This example creates a list panel with viewport management, starting from scroll
position 2 and displaying up to 10 items.

.NOTES
This is meant to be called by the main TUI function: Show-PesterResult
#>
[CmdletBinding()]
param (
[array]
$List,
[string]
$SelectedItem,
[string]$SelectedPane = "list"
[CmdletBinding()]
param (
[array]
$List,
[string]
$SelectedItem,
[string]$SelectedPane = "list",
[int]$ListScrollPosition = 0,
[int]$ListHeight = 0
)
$paneColor = if($SelectedPane -ne "list") {
# If the selected pane is not preview, return an empty panel
Expand Down Expand Up @@ -86,8 +109,48 @@ function Get-ListPanel {
Format-SpectrePadded -Padding 0
}
}
}
$results |
Format-SpectreRows |
}

# Apply viewport scrolling if list height is specified and list is long
if ($ListHeight -gt 0 -and $List.Count -gt $ListHeight) {
Write-Debug "Applying list viewport scrolling. List count: $($List.Count), Height: $ListHeight, Scroll: $ListScrollPosition"

# Calculate which items to show based on scroll position and height
$visibleResults = @()

# Add scroll indicator if not at top
if ($ListScrollPosition -gt 0) {
$visibleResults += "[grey]...[/]" | Write-SpectreHost -PassThru | Format-SpectrePadded -Padding 0
}

# Calculate available height (subtract 1 if we added scroll indicator)
$availableHeight = $ListHeight
if ($ListScrollPosition -gt 0) {
$availableHeight--
}

# Add items starting from scroll position
$itemsAdded = 0
for ($i = $ListScrollPosition; $i -lt $results.Count -and $itemsAdded -lt $availableHeight; $i++) {
$visibleResults += $results[$i]
$itemsAdded++
}

# Add more indicator if there are more items below
if (($ListScrollPosition + $itemsAdded) -lt $results.Count) {
if ($itemsAdded -eq $availableHeight) {
# Replace last item with more indicator if we're at max height
$visibleResults[-1] = "[grey]...more[/]" | Write-SpectreHost -PassThru | Format-SpectrePadded -Padding 0
} else {
# Add more indicator if there's space
$visibleResults += "[grey]...more[/]" | Write-SpectreHost -PassThru | Format-SpectrePadded -Padding 0
}
}

$results = $visibleResults
}

$results |
Format-SpectreRows |
Format-SpectrePanel -Header "[white]List[/]" -Expand -Color $paneColor
}
154 changes: 102 additions & 52 deletions PesterExplorer/Public/Show-PesterResult.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -70,51 +70,97 @@ function Show-PesterResult {
[Spectre.Console.LiveDisplayContext] $Context
)

#region Initial State
$items = Get-ListFromObject -Object $PesterResult
Write-Debug "Items: $($items.Keys -join ', ')"
$list = [array]$items.Keys
$selectedItem = $list[0]
$stack = [System.Collections.Stack]::new()
$object = $PesterResult
$selectedPane = 'list'
$scrollPosition = 0
#region Initial State
$items = Get-ListFromObject -Object $PesterResult
Write-Debug "Items: $($items.Keys -join ', ')"
$list = [array]$items.Keys
$selectedItem = $list[0]
$stack = [System.Collections.Stack]::new()
$object = $PesterResult
$selectedPane = 'list'
$scrollPosition = 0
$listScrollPosition = 0
#endregion Initial State

while ($true) {
# Check the layout sizes
$sizes = $layout | Get-SpectreLayoutSizes
$previewHeight = $sizes["preview"].Height
$previewWidth = $sizes["preview"].Width
Write-Debug "Preview size: $previewWidth x $previewHeight"
# Check the layout sizes
$sizes = $layout | Get-SpectreLayoutSizes
$previewHeight = $sizes["preview"].Height
$previewWidth = $sizes["preview"].Width
$listHeight = $sizes["list"].Height
Write-Debug "Preview size: $previewWidth x $previewHeight"
Write-Debug "List height: $listHeight"

# Handle input
$lastKeyPressed = Get-LastKeyPressed
if ($null -ne $lastKeyPressed) {
#region List Navigation
if($selectedPane -eq 'list') {
if ($lastKeyPressed.Key -in @("j", "DownArrow")) {
$selectedItem = $list[($list.IndexOf($selectedItem) + 1) % $list.Count]
$scrollPosition = 0
} elseif ($lastKeyPressed.Key -in @("k", "UpArrow")) {
$selectedItem = $list[($list.IndexOf($selectedItem) - 1 + $list.Count) % $list.Count]
$scrollPosition = 0
} elseif ($lastKeyPressed.Key -eq "PageDown") {
$currentIndex = $list.IndexOf($selectedItem)
$newIndex = [Math]::Min($currentIndex + 10, $list.Count - 1)
$selectedItem = $list[$newIndex]
$scrollPosition = 0
} elseif ($lastKeyPressed.Key -eq "PageUp") {
$currentIndex = $list.IndexOf($selectedItem)
$newIndex = [Math]::Max($currentIndex - 10, $list.Count - 1)
$selectedItem = $list[$newIndex]
$scrollPosition = 0
} elseif ($lastKeyPressed.Key -eq "Home") {
$selectedItem = $list[0]
$scrollPosition = 0
} elseif ($lastKeyPressed.Key -eq "End") {
$selectedItem = $list[-1]
$scrollPosition = 0
#region List Navigation
if($selectedPane -eq 'list') {
if ($lastKeyPressed.Key -in @("j", "DownArrow")) {
$selectedItem = $list[($list.IndexOf($selectedItem) + 1) % $list.Count]
$scrollPosition = 0
# Update list scroll position to keep selected item visible
$selectedIndex = $list.IndexOf($selectedItem)
if ($listHeight -gt 0 -and $list.Count -gt $listHeight) {
# If selected item is below visible area, scroll down
if ($selectedIndex -ge ($listScrollPosition + $listHeight - 1)) {
$listScrollPosition = $selectedIndex - $listHeight + 2
}
# If selected item is above visible area, scroll up
elseif ($selectedIndex -lt $listScrollPosition) {
$listScrollPosition = $selectedIndex
}
# Ensure scroll position is within bounds
$listScrollPosition = [Math]::Max(0, [Math]::Min($listScrollPosition, $list.Count - $listHeight))
}
} elseif ($lastKeyPressed.Key -in @("k", "UpArrow")) {
$selectedItem = $list[($list.IndexOf($selectedItem) - 1 + $list.Count) % $list.Count]
$scrollPosition = 0
# Update list scroll position to keep selected item visible
$selectedIndex = $list.IndexOf($selectedItem)
if ($listHeight -gt 0 -and $list.Count -gt $listHeight) {
# If selected item is above visible area, scroll up
if ($selectedIndex -lt $listScrollPosition) {
$listScrollPosition = $selectedIndex
}
# If selected item is below visible area, scroll down
elseif ($selectedIndex -ge ($listScrollPosition + $listHeight - 1)) {
$listScrollPosition = $selectedIndex - $listHeight + 2
}
# Ensure scroll position is within bounds
$listScrollPosition = [Math]::Max(0, [Math]::Min($listScrollPosition, $list.Count - $listHeight))
}
} elseif ($lastKeyPressed.Key -eq "PageDown") {
$currentIndex = $list.IndexOf($selectedItem)
$newIndex = [Math]::Min($currentIndex + 10, $list.Count - 1)
$selectedItem = $list[$newIndex]
$scrollPosition = 0
# Update list scroll position to keep selected item visible
if ($listHeight -gt 0 -and $list.Count -gt $listHeight) {
$listScrollPosition = [Math]::Max(0, [Math]::Min($newIndex - [Math]::Floor($listHeight / 2), $list.Count - $listHeight))
}
} elseif ($lastKeyPressed.Key -eq "PageUp") {
$currentIndex = $list.IndexOf($selectedItem)
$newIndex = [Math]::Max($currentIndex - 10, 0)
$selectedItem = $list[$newIndex]
$scrollPosition = 0
# Update list scroll position to keep selected item visible
if ($listHeight -gt 0 -and $list.Count -gt $listHeight) {
$listScrollPosition = [Math]::Max(0, [Math]::Min($newIndex - [Math]::Floor($listHeight / 2), $list.Count - $listHeight))
}
} elseif ($lastKeyPressed.Key -eq "Home") {
$selectedItem = $list[0]
$scrollPosition = 0
$listScrollPosition = 0
} elseif ($lastKeyPressed.Key -eq "End") {
$selectedItem = $list[-1]
$scrollPosition = 0
# Scroll to bottom to show last item
if ($listHeight -gt 0 -and $list.Count -gt $listHeight) {
$listScrollPosition = $list.Count - $listHeight
} else {
$listScrollPosition = 0
}
} elseif ($lastKeyPressed.Key -in @("Tab", "RightArrow", "l")) {
$selectedPane = 'preview'
} elseif ($lastKeyPressed.Key -eq "Enter") {
Expand All @@ -130,22 +176,24 @@ function Show-PesterResult {
Write-Debug "Pushing item into stack: $($items.Item($selectedItem).Name)"
$stack.Push($object)
$object = $items.Item($selectedItem)
}
$items = Get-ListFromObject -Object $object
$list = [array]$items.Keys
$selectedItem = $list[0]
$scrollPosition = 0
}
$items = Get-ListFromObject -Object $object
$list = [array]$items.Keys
$selectedItem = $list[0]
$scrollPosition = 0
$listScrollPosition = 0
} elseif ($lastKeyPressed.Key -eq "Escape") {
# Move up via Esc key
if($stack.Count -eq 0) {
# This is the top level. Exit the loop.
return
}
$object = $stack.Pop()
$items = Get-ListFromObject -Object $object
$list = [array]$items.Keys
$selectedItem = $list[0]
$scrollPosition = 0
$object = $stack.Pop()
$items = Get-ListFromObject -Object $object
$list = [array]$items.Keys
$selectedItem = $list[0]
$scrollPosition = 0
$listScrollPosition = 0
}
}
else {
Expand All @@ -171,10 +219,12 @@ function Show-PesterResult {

# Generate new data
$titlePanel = Get-TitlePanel -Item $object
$getListPanelSplat = @{
List = $list
SelectedItem = $selectedItem
SelectedPane = $selectedPane
$getListPanelSplat = @{
List = $list
SelectedItem = $selectedItem
SelectedPane = $selectedPane
ListScrollPosition = $listScrollPosition
ListHeight = $listHeight
}
$listPanel = Get-ListPanel @getListPanelSplat

Expand Down
Loading
Loading