Functions/Public/Show-CtsDeparture.ps1
|
function Show-CtsDeparture { <# .SYNOPSIS Displays the next departures dynamically at the specified CTS stops .DESCRIPTION Shows a live-updating table of departures in the terminal (press Ctrl+C to exit). Refreshes automatically at the given interval and redraws in place using ANSI escape codes. .EXAMPLE Show-CtsDeparture -Stop Esplanade -Destination Lingolsheim, Robertsau .EXAMPLE Show-CtsDeparture -Stop 'Homme de Fer' -RefreshRate 10 #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Filters')] [OutputType([Void])] param ( # Line names to filter by [Parameter(ParameterSetName = 'Filters')] [ArgumentCompleter([LineCompleter])] [AllowEmptyCollection()] [String[]] $Line, # Stop names to filter by (prefix match) [Parameter(Position = 0, ParameterSetName = 'Filters')] [ArgumentCompleter([StopCompleter])] [AllowEmptyCollection()] [Alias('From')] [String[]] $Stop, # Destination names to filter by (prefix match) [Parameter(Position = 1, ParameterSetName = 'Filters')] [ArgumentCompleter([DestinationCompleter])] [AllowEmptyCollection()] [Alias('To')] [String[]] $Destination, # Only return destinations that exactly match -Destination, excluding same-direction alternatives [Parameter(ParameterSetName = 'Filters')] [Switch] $Strict, # Stop objects from Find-CtsStop to display departures for [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'Object')] [AllowNull()] [Stop[]] $StopObject, # Maximum number of departure times to show per line, stop and destination [Parameter()] [ValidateRange(1, 8)] [Int] $MaxDepartures = 3, # Time between each departure refresh in seconds [Parameter()] [ValidateRange(1, [Int]::MaxValue)] [Int] $RefreshRate = 5, # Bypass the stop and departure caches [Parameter(DontShow)] [Switch] $Force, # Skip writing the cache file to disk [Parameter(ParameterSetName = 'Filters', DontShow)] [Switch] $NoCacheFile ) begin { $Stops = [System.Collections.Generic.List[System.Object]]::new() } process { if ($PSCmdlet.ParameterSetName -eq 'Filters') { $FindParam = @{ Line = $Line Stop = $Stop Destination = $Destination Strict = $Strict Force = $Force NoCacheFile = $NoCacheFile } $StopObject = Find-CtsStop @FindParam } # Gather pipeline objects if ($null -ne $StopObject) { $StopObject | ForEach-Object { $Stops.Add([Stop]$_) } } } end { if ($Stops.Count -eq 0) { Write-Verbose -Message 'CtsDeparture: No stop found with requested filters' return } $LineCount = 0 $GetParam = @{ StopObject = $Stops MaxDepartures = $MaxDepartures Force = $Force } while ($true) { $LastLineCount = $LineCount $LineCount = 0 $ReferenceTime = [DateTime]::Now $DepartureText = [System.Text.StringBuilder]::new() # Move cursor to top position if ($LastLineCount -gt 0) { Write-Host -Object "`e[$($LastLineCount)F" -NoNewline } Get-CtsDeparture @GetParam | Group-Object -Property Stop | ForEach-Object { $MaxLength = $_.Group | ForEach-Object { $_.Line.VisibleLength() } | Measure-Object -Maximum $PadLength = $MaxLength.Maximum + 3 # Stop name as title $null = $DepartureText.AppendLine($_.Name) $LineCount++ # Lines as sub-elements for ($DepId = 0; $DepId -lt $_.Count; $DepId++) { $Departure = $_.Group[$DepId] if ($DepId -lt ($_.Count - 1)) { $null = $DepartureText.Append(" `u{251C}`u{2500} ") } else { $null = $DepartureText.Append(" `u{2514}`u{2500} ") } $null = $DepartureText.Append($Departure.Line.PadRight($PadLength)) # Departures on same line $DepartureTimeText = $Departure.Times | ForEach-Object { $_.PadLeft(5, $ReferenceTime) } $null = $DepartureText.AppendJoin(' ', $DepartureTimeText) $null = $DepartureText.AppendLine() $LineCount++ } } # Erase previous departures if ($LastLineCount -gt 0) { Write-Host -Object "`e[$($LastLineCount)M" -NoNewline } # Print departures Write-Host -Object $DepartureText.ToString() -NoNewline Start-Sleep -Seconds $RefreshRate } } } |