Public/Switch-GreenroomSession.ps1
|
# SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (C) 2026 Tyler Vigario <# .SYNOPSIS Reveal a hidden greenroom session, or hide a revealed one. .DESCRIPTION Replaces `greenroom toggle`. Show it if it is hidden, hide it if it is showing. Switch- is the approved verb whose documented meaning is alternation, which is the honest mapping even though "toggle" reads more obviously. There is no approved Toggle- verb. This exists rather than leaving the caller to branch because the point of a toggle is not caring what state the window is in: press it to bring the session up, press it again to put it away. It is the one thing that would be strictly worse as a conditional, and the natural thing to bind to a hotkey: $i = Get-GreenroomInstance laptop-admin if ($i.Visible) { Hide-GreenroomSession laptop-admin } else { Show-GreenroomSession laptop-admin } VISIBILITY IS READ AT THE POINT OF DECISION, not up front. The script this replaces read IsWindowVisible once near the top and acted on that value later, so anything that changed the window in between -- the operator clicking it, another shell, the session exiting a modal -- made toggle do the exact opposite of what was wanted. The read here is the last thing before the switch is chosen. .PARAMETER Name The instance to switch. Accepts pipeline input, including Greenroom.Instance objects. .PARAMETER NoElevate Do not escalate when the instance runs elevated. Fails instead. .EXAMPLE Switch-GreenroomSession laptop-admin .EXAMPLE Switch-GreenroomSession laptop-admin -WhatIf Reports which direction it would go, without moving the window. .EXAMPLE Get-GreenroomInstance | Switch-GreenroomSession Inverts every session's visibility. #> function Switch-GreenroomSession { [CmdletBinding(SupportsShouldProcess)] [OutputType([void])] param( [Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)] [Alias('Instance')] [string]$Name, [switch]$NoElevate ) process { # Resolve, escalate, gate, act -- the same order as Show- and Hide-, for the # reasons documented on Show-GreenroomSession. $target = Resolve-GreenroomTarget -Name $Name -RequireWindow if (-not $target) { return } # Deliberately NOT $target.Visible, which was read during discovery and may # already be stale. This is the last read before the direction is chosen. $show = -not (Test-WindowVisible -Handle $target.Window) $verb = if ($show) { 'show' } else { 'hide' } # The direction goes in the ShouldProcess description so -WhatIf reports which # way it would go, rather than an unhelpful "would switch". # # Gated before escalation: a new elevated process starts with its own # $WhatIfPreference and $ConfirmPreference, so anything decided only over there # is decided against defaults rather than against what the operator asked for. if (-not $PSCmdlet.ShouldProcess($target.Instance, "Switch-GreenroomSession (would $verb)")) { return } if (-not (Assert-CanActOnInstance -Name $target.Instance -Command 'Switch-GreenroomSession' -NoElevate:$NoElevate)) { return } if (Set-WindowVisible -Handle $target.Window -Show $show) { Write-Verbose "switched '$($target.Instance)' to $verb (claude pid $($target.ClaudePid), window $($target.Window))" return } Write-Error -Category InvalidResult -Message (Get-WindowFailureReason -Name $target.Instance) } } |