Skip to content

Commit

Permalink
Add prompt timeouts
Browse files Browse the repository at this point in the history
  • Loading branch information
ShaunLawrie committed Aug 16, 2024
1 parent 31a3ffa commit 46e54b3
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 7 deletions.
18 changes: 16 additions & 2 deletions PwshSpectreConsole/private/Invoke-SpectrePromptAsync.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,29 @@ function Invoke-SpectrePromptAsync {
#>
param (
[Parameter(Mandatory)]
$Prompt
$Prompt,
[int] $TimeoutSeconds
)

$timeout = $null
if ($TimeoutSeconds) {
$timeout = (Get-Date).AddSeconds($TimeoutSeconds)
Write-SpectreHost "[$script:DefaultValueColor]This prompt times out in $TimeoutSeconds seconds...[/]`n"
}

$cts = [System.Threading.CancellationTokenSource]::new()
try {
$task = $Prompt.ShowAsync([Spectre.Console.AnsiConsole]::Console, $cts.Token)
while (-not $task.AsyncWaitHandle.WaitOne(200)) {
# Waiting for the async task this way allows ctrl-c interrupts to continue to work within the single-threaded PowerShell world
if ($null -ne $timeout -and (Get-Date) -ge $timeout) {
$cts.Cancel()
Write-SpectreHost "`n`n[$script:DefaultValueColor]Prompt timed out[/]"
}
}
if (!$task.IsCanceled) {
return $task.GetAwaiter().GetResult()
}
return $task.GetAwaiter().GetResult()
} finally {
$cts.Cancel()
$task.Dispose()
Expand Down
3 changes: 2 additions & 1 deletion PwshSpectreConsole/public/prompts/Read-SpectreConfirm.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function Read-SpectreConfirm {
[string] $DefaultAnswer = "y",
[string] $ConfirmSuccess,
[string] $ConfirmFailure,
[int] $TimeoutSeconds,
[ColorTransformationAttribute()]
[ArgumentCompletionsSpectreColors()]
[Spectre.Console.Color] $Color = $script:AccentColor
Expand All @@ -55,7 +56,7 @@ function Read-SpectreConfirm {
$confirmationPrompt.InvalidChoiceMessage = "[red]Please select one of the available options[/]"

# Invoke-SpectrePromptAsync supports ctrl-c
$confirmed = (Invoke-SpectrePromptAsync -Prompt $confirmationPrompt) -eq "y"
$confirmed = (Invoke-SpectrePromptAsync -Prompt $confirmationPrompt -TimeoutSeconds $TimeoutSeconds) -eq "y"

if (!$confirmed) {
if (![String]::IsNullOrWhiteSpace($ConfirmFailure)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function Read-SpectreMultiSelection {
[ArgumentCompletionsSpectreColors()]
[Spectre.Console.Color] $Color = $script:AccentColor,
[int] $PageSize = 5,
[int] $TimeoutSeconds,
[switch] $AllowEmpty
)
$spectrePrompt = [Spectre.Console.MultiSelectionPrompt[string]]::new()
Expand All @@ -69,7 +70,7 @@ function Read-SpectreMultiSelection {
$spectrePrompt.HighlightStyle = [Spectre.Console.Style]::new($Color)
$spectrePrompt.InstructionsText = "[$($script:DefaultValueColor.ToMarkup())](Press [$($script:AccentColor.ToMarkup())]space[/] to toggle a choice and press [$($script:AccentColor.ToMarkup())]<enter>[/] to submit your answer)[/]"
$spectrePrompt.MoreChoicesText = "[$($script:DefaultValueColor.ToMarkup())](Move up and down to reveal more choices)[/]"
$selected = Invoke-SpectrePromptAsync -Prompt $spectrePrompt
$selected = Invoke-SpectrePromptAsync -Prompt $spectrePrompt -TimeoutSeconds $TimeoutSeconds

if ($ChoiceLabelProperty) {
$selected = $Choices | Where-Object { $selected -contains $_.$ChoiceLabelProperty }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ function Read-SpectreMultiSelectionGrouped {
[ArgumentCompletionsSpectreColors()]
[Spectre.Console.Color] $Color = $script:AccentColor,
[int] $PageSize = 10,
[int] $TimeoutSeconds,
[switch] $AllowEmpty
)
$spectrePrompt = [Spectre.Console.MultiSelectionPrompt[string]]::new()
Expand Down Expand Up @@ -92,7 +93,7 @@ function Read-SpectreMultiSelectionGrouped {
$spectrePrompt.HighlightStyle = [Spectre.Console.Style]::new($Color)
$spectrePrompt.InstructionsText = "[$($script:DefaultValueColor.ToMarkup())](Press [$($script:AccentColor.ToMarkup())]space[/] to toggle a choice and press [$($script:AccentColor.ToMarkup())]<enter>[/] to submit your answer)[/]"
$spectrePrompt.MoreChoicesText = "[$($script:DefaultValueColor.ToMarkup())](Move up and down to reveal more choices)[/]"
$selected = Invoke-SpectrePromptAsync -Prompt $spectrePrompt
$selected = Invoke-SpectrePromptAsync -Prompt $spectrePrompt -TimeoutSeconds $TimeoutSeconds

if ($ChoiceLabelProperty) {
$selected = $flattenedChoices | Where-Object { $selected -contains $_.$ChoiceLabelProperty }
Expand Down
3 changes: 2 additions & 1 deletion PwshSpectreConsole/public/prompts/Read-SpectreSelection.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function Read-SpectreSelection {
[Spectre.Console.Color] $Color = $script:AccentColor,
[int] $PageSize = 5,
[switch] $EnableSearch,
[int] $TimeoutSeconds,
[ColorTransformationAttribute()]
[ArgumentCompletionsSpectreColors()]
[Spectre.Console.Color] $SearchHighlightColor = $script:AccentColor.Blend([Spectre.Console.Color]::White, 0.7)
Expand All @@ -76,7 +77,7 @@ function Read-SpectreSelection {
$spectrePrompt.SearchEnabled = $EnableSearch
$spectrePrompt.SearchHighlightStyle = [Spectre.Console.Style]::new($SearchHighlightColor)

$selected = Invoke-SpectrePromptAsync -Prompt $spectrePrompt
$selected = Invoke-SpectrePromptAsync -Prompt $spectrePrompt -TimeoutSeconds $TimeoutSeconds

if ($ChoiceLabelProperty) {
$selected = $Choices | Where-Object -Property $ChoiceLabelProperty -Eq $selected
Expand Down
3 changes: 2 additions & 1 deletion PwshSpectreConsole/public/prompts/Read-SpectreText.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function Read-SpectreText {
[ArgumentCompletionsSpectreColors()]
[Spectre.Console.Color] $AnswerColor,
[switch] $AllowEmpty,
[int] $TimeoutSeconds,
[string[]] $Choices
)
$spectrePrompt = [Spectre.Console.TextPrompt[string]]::new($Question, [System.StringComparer]::InvariantCultureIgnoreCase)
Expand All @@ -67,5 +68,5 @@ function Read-SpectreText {
if ($null -ne $Choices) {
$spectrePrompt = [Spectre.Console.TextPromptExtensions]::AddChoices($spectrePrompt, $Choices)
}
return Invoke-SpectrePromptAsync -Prompt $spectrePrompt
return Invoke-SpectrePromptAsync -Prompt $spectrePrompt -TimeoutSeconds $TimeoutSeconds
}

0 comments on commit 46e54b3

Please sign in to comment.