kurukuru-pwsh.psm1
$KurukuruPatterns = [array]::AsReadOnly(([Kurukuru.Patterns].GetFields("Public, Static") | Where-Object { $_.FieldType -EQ [Kurukuru.Pattern] } | ForEach-Object { $ret = $_.GetValue($null) $ret | Add-Member 'Name' $_.Name return $ret } )) $script:KurukuruPatternsTable = @{} foreach ($p in $KurukuruPatterns) { $KurukuruPatternsTable[$p.Name] = $p } $script:EnabledThreadJob = (Get-Command Start-ThreadJob) function ConvertToSymbolDefinition { [OutputType([Kurukuru.SymbolDefinition])] param( [Parameter(Mandatory = $true, Position = 0)] $StringOrSymbol ) if ($StringOrSymbol -is [Kurukuru.SymbolDefinition]) { return $StringOrSymbol } else { return [Kurukuru.SymbolDefinition]::new($StringOrSymbol, $StringOrSymbol) } } function Get-KurukuruPattern { [OutputType([Kurukuru.Pattern[]])] param ( [Parameter(Mandatory = $false, Position = 0, ValueFromRemainingArguments)] $Pattern ) if ($Pattern) { $Pattern | ForEach-Object { if ($_ -is [Kurukuru.Pattern]) { $_ } else { $KurukuruPatternsTable[$_] } } } else { $KurukuruPatterns } } function Stop-Spiner { param( [Parameter(Mandatory, Position = 0)] $Spinners ) if ($EnabledThreadJob) { $Spinners | ForEach-Object { Start-ThreadJob -ArgumentList @($_) -ScriptBlock { param($s) $s.Info() } } | Receive-Job -Wait -AutoRemoveJob } else { $Spinners | ForEach-Object { $_.Info() } } } function Show-KurukuruSample { param( [Parameter(ValueFromRemainingArguments)] [array] $Pattern ) $Patterns = (Get-KurukuruPattern $Pattern) if (-not $Patterns) { return } $Spinners = [System.Collections.Generic.LinkedList[Kurukuru.Spinner]]::new() try { foreach ($p in $Patterns) { $height = [math]::Max($Host.UI.RawUI.BufferSize.Height - 2, 1) $over = $Spinners.Count - $height if ($over -ge 0) { [Console]::Write("Press key. Enter: next line, n: next page, q: Quit") :read while ($true) { $key = [Console]::ReadKey($true) switch ($key.Key) { ([ConsoleKey]::Q) { return } ([ConsoleKey]::Enter) { break read } ([ConsoleKey]::N) { $over = $Spinners.Count break read } } } $overSpinners = [System.Collections.ArrayList]::new() for ($i = 0; $i -lt $over; $i++) { $overSpinners.Add($Spinners.First.Value) $Spinners.RemoveFirst() } Stop-Spiner $overSpinners } if ($p.Frames -and $p.Frames[0]) { $sp = (New-Spinner -Text $p.Name -Pattern $p -SymbolInfo $p.Frames[0]) } else { $sp = (New-Spinner -Text $p.Name -Pattern $p -SymbolInfo "") } $sp.Start() $Spinners.Add($sp) } [Console]::Write("Press any key to exit.") [Console]::ReadKey($true) | Out-Null } finally { Stop-Spiner $Spinners } } function Start-Kurukuru { [CmdletBinding()] [OutputType([Kurukuru.Spinner[]])] param ( [Parameter(Mandatory, Position = 0, ParameterSetName = 'Spinner', ValueFromPipeline)] [Kurukuru.Spinner[]] $Spinner, [Parameter(ParameterSetName = 'Spinner')] [switch] $PassThru, [Parameter(ParameterSetName = 'Spinner')] [switch] $NoDispose, [Parameter(Mandatory, Position = 0, ParameterSetName = 'WithInitialization')] [scriptblock] $InitializationScript, [Parameter(Mandatory, Position = 0, ParameterSetName = 'WithoutInitialization')] [Parameter(Mandatory, Position = 1, ParameterSetName = 'WithInitialization')] [scriptblock] $ScriptBlock, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] [string] $Text = '', [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] [string] $SucceedText = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] [string] $FailedText = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] $Pattern = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] [Nullable[System.ConsoleColor]] $Color = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] $SymbolSucceed = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] $SymbolFailed = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] $SymbolWarn = $null, [Parameter(ParameterSetName = 'WithoutInitialization')] [Parameter(ParameterSetName = 'WithInitialization')] $SymbolInfo = $null ) begin { $Spinners = [System.Collections.ArrayList]::new() if ($PSCmdlet.ParameterSetName -in @('WithoutInitialization', 'WithInitialization')) { if ($ScriptBlock.Equals($InitializationScript)) { $InitializationScript = $null } if (-not $Pattern) { $Pattern = $null } elseif ($Pattern -is [Kurukuru.Pattern]) { $Pattern = [Kurukuru.Pattern]$Pattern } else { $Pattern = [Kurukuru.Pattern]$KurukuruPatternsTable[$Pattern] if (-not $Pattern) { Write-Warning "Invalid Pattern Name: $Pattern" } } $s = New-Spinner ` -Text $Text ` -Pattern $Pattern ` -Color $Color ` -SymbolSucceed $SymbolSucceed ` -SymbolFailed $SymbolFailed ` -SymbolWarn $SymbolWarn ` -SymbolINfo $SymbolINfo ` -SucceedText $SucceedText ` -FailedText $FailedText ` -ScriptBlock $ScriptBlock if ($InitializationScript) { & $InitializationScript $s } $Spinners.Add($s) | Out-Null } } process { if ($Spinner) { $Spinners.AddRange($Spinner) | Out-Null } } end { try { foreach ($s in $Spinners) { $s.Start() | Out-Null } $jobScript = { param([Kurukuru.Spinner]$s) try { if ($s.ScriptBlock) { & $s.ScriptBlock $s } if ($s.Stopped) { return } $text = $s.SucceedText if (-not $text) { $text = $s.Text } $s.Succeed($text) } catch { if ($s.Stopped) { return } $text = $s.FailedText if (-not $text) { $text = $s.Text } $s.Fail($text) } } if ($Spinners.Count -eq 1) { $jobScript.Invoke($Spinners[0]) } elseif ($EnabledThreadJob) { $Spinners | ForEach-Object { Start-ThreadJob -ThrottleLimit 1000000 -ScriptBlock $jobScript -ArgumentList @($_) } | Receive-Job -Wait -AutoRemoveJob | Out-Null } else { $Spinners | ForEach-Object { & $jobScript $_ } | Out-Null } if ($PassThru) { return $Spinners } return } finally { if (-not $NoDispose) { $Spinners.Dispose() } } } } function New-Spinner { [CmdletBinding()] [OutputType([Kurukuru.Spinner])] param( [Parameter(Mandatory, Position = 0)] [AllowEmptyString()] [string] $Text, [Parameter(Position = 1)] $Pattern, [Nullable[System.ConsoleColor]] $Color = $null, $SymbolSucceed = $null, $SymbolFailed = $null, $SymbolWarn = $null, $SymbolInfo = $null, [string] $SucceedText = $null, [string] $FailedText = $null, $FallbackPattern = $null, [scriptblock] $ScriptBlock ) if ($null -eq $Pattern) {} elseif ($Pattern -isnot [Kurukuru.Pattern]) { $Pattern = [Kurukuru.Patterns].GetField($Pattern).GetValue($null) } if ($null -eq $FallbackPattern) {} elseif ($FallbackPattern -is [string]) { $FallbackPattern = [Kurukuru.Patterns].GetField($FallbackPattern).GetValue($null) } $spinner = [Kurukuru.Spinner]::new($Text, $Pattern, $Color, $true, $FallbackPattern) if ($SymbolSucceed) { $spinner.SymbolSucceed = (ConvertToSymbolDefinition $SymbolSucceed) } if ($SymbolFailed) { $spinner.SymbolFailed = (ConvertToSymbolDefinition $SymbolFailed) } if ($SymbolWarn) { $spinner.SymbolWarn = (ConvertToSymbolDefinition $SymbolWarn) } if ($SymbolInfo) { $spinner.SymbolInfo = (ConvertToSymbolDefinition $SymbolInfo) } if ($null -ne $SucceedText) { Add-Member SucceedText $SucceedText -InputObject $spinner } if ($null -ne $FailedText) { Add-Member FailedText $FailedText -InputObject $spinner } if ($ScriptBlock) { Add-Member ScriptBlock $ScriptBlock -InputObject $spinner } return $spinner } function New-KurukuruPattern { [CmdletBinding(PositionalBinding = $false)] [OutputType([Kurukuru.Pattern])] param( [Parameter(Mandatory, ValueFromRemainingArguments)] [string[]] $Frames, [Parameter()] [int] $Interval = 100 ) [Kurukuru.Pattern]::new($Frames, $Interval) } $patternCompleter = { param( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter ) foreach ($p in ($KurukuruPatterns)) { if ($p.Name.ToLower().StartsWith($wordToComplete.ToLower())) { [System.Management.Automation.CompletionResult]::new( $p.Name, $p.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, "$($p.Frames) Interval=$($p.Interval)" ) } } } Register-ArgumentCompleter -CommandName New-Spinner, Start-Kurukuru, Start-KurukuruSleep, Get-KurukuruPattern, Show-KurukuruSample -ParameterName Pattern -ScriptBlock $patternCompleter Register-ArgumentCompleter -CommandName New-Spinner -ParameterName FallbackPattern -ScriptBlock $patternCompleter Register-ArgumentCompleter -CommandName New-Spinner, Start-Kurukuru -ParameterName Color -ScriptBlock { param( $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter ) foreach ($item in ([System.Enum]::GetNames([System.ConsoleColor]))) { if ($item.ToLower().StartsWith($wordToComplete.ToLower())) { [System.Management.Automation.CompletionResult]::new( $item, $item, [System.Management.Automation.CompletionResultType]::ParameterValue, $item ) } } } Export-ModuleMember -Variable KurukuruPatterns |