StageCoder.psm1

#Region './_PrefixCode.ps1' 0
$Script:Demo = @()
$Script:ManualTiming = $false
$Script:MinPause = 10
$Script:MaxPause = 20
#EndRegion './_PrefixCode.ps1' 5
#Region './Private/Get-DemoIndex.ps1' 0
function Get-DemoIndex {
    [int][System.Environment]::GetEnvironmentVariable(
        'STAGECODER_PS_INDEX'
    ) ?? 0
}
#EndRegion './Private/Get-DemoIndex.ps1' 6
#Region './Private/Set-Index.ps1' 0
function Set-Index ([int]$index = 0) {
    [System.Environment]::SetEnvironmentVariable(
        'STAGECODER_PS_INDEX', 
        $index
    )
}
#EndRegion './Private/Set-Index.ps1' 7
#Region './Private/Waitfor.ps1' 0
function randompause {
    if($Script:Timing -eq 'Manual') {
        waitforkeypress
    } else {
        $pause = Get-Random -Minimum $Script:MinPause -Maximum $Script:MaxPause
        Start-Sleep -Milliseconds $pause
    }
}

function waitforkeypress {
    param([Switch]$PassThru)
    $key = $host.ui.rawui.readkey("NoEcho,IncludeKeyDown,AllowCtrlC")
    if($key.virtualkeycode -eq 0x11 -or $key.virtualkeycode -eq 0x1B) {
        throw "User cancelled"
    }
    if ($PassThru.IsPresent) {
        Write-Output $key
    }
}

function waitforspecifickeypress {
    param($Keys)
    do {
        $key = waitforkeypress -PassThru
    } while ($key.VirtualKeyCode -notin $Keys)
}
#EndRegion './Private/Waitfor.ps1' 27
#Region './Public/Get-Demo.ps1' 0
function Get-Demo {
    [CmdletBinding()]
    param()

    if($null -eq $Script:Demo) {
        throw 'No demo loaded. Please run Set-Demo first.'
    }

    $Script:Demo

}
#EndRegion './Public/Get-Demo.ps1' 12
#Region './Public/Get-DemoCommand.ps1' 0
function Get-DemoCommand {
    [CmdletBinding()]
    [Alias('d')]
    param (
        [Parameter(Mandatory=$false)]
        [int]$Index,

        [Parameter(Mandatory=$false)]
        [switch]$Passthru
    )

    if($null -eq $Script:Demo) {
        throw 'No demo loaded. Please run Set-Demo first.'
    }

    if ($PSBoundParameters.ContainsKey('index')) {
        $CurrentIndex = $index
    }
    else {
        $CurrentIndex = Get-DemoIndex
    }
    
    if ($Script:Demo.Length -ge $CurrentIndex) {
        if ($Passthru) {
            $Script:Demo[$CurrentIndex]
        }
        $Script:Demo[$CurrentIndex] | Set-Clipboard
    }
    else {
        Set-Clipboard -Value ''
    }
    Set-Index ($CurrentIndex + 1)
}
#EndRegion './Public/Get-DemoCommand.ps1' 34
#Region './Public/Reset-Demo.ps1' 0
function Reset-Demo {
    [Alias('r')]
    param(
        [int]$Index = 0
    )
    Set-Index $Index
    Clear-Host
}
#EndRegion './Public/Reset-Demo.ps1' 9
#Region './Public/Set-Demo.ps1' 0
function Set-Demo {
    [CmdletBinding(DefaultParameterSetName = 'Manual')]
    param(
        [Parameter(Mandatory, Position = 1)]
        [string[]]$Demo,

        [Parameter(Position = 2)]
        [string]$Chord = 'ctrl+d',

        [Parameter(Position = 3)]
        [ValidateSet('Manual', 'Timed', 'Instant')]
        [string]$Timing = 'Manual',

        [Parameter(Position = 4)]
        [int]$MinPause = 10,

        [Parameter(Position = 5)]
        [int]$MaxPause = 20
    )
    
    if ($Timing -ne 'Timed') {
        if (
            $PSBoundParameters.ContainsKey('MinPause') -or
            $PSBoundParameters.ContainsKey('MaxPause')
        ) {
            throw 'MinPause and MaxPause are only valid when Timing is Timed'
        }
    }
    
    $Script:Timing = $Timing
    $Script:MinPause = $MinPause
    $Script:MaxPause = $MaxPause
    try {
        $setPSReadLineKeyHandlerSplat = @{
            Chord            = $Chord
            BriefDescription = 'InsertDemoCode'
            Description      = "Insert code from clipboard for demo purpose"
            ScriptBlock      = {
                param($key, $arg)
                try {
                    $ErrorActionPreference = 'Stop'
                    $CurrentIndex = Get-DemoIndex
                    Set-Index ($CurrentIndex + 1)
                    randompause
                    [string[]]$Commands = $Script:Demo[$CurrentIndex] -split [System.Environment]::NewLine
                    for ($i = 0; $i -lt $Commands.Count - 1; $i++) {
                        for ($j = 0; $j -lt $Commands[$i].Length; $j++) {
                            [Microsoft.PowerShell.PSConsoleReadLine]::Insert($Commands[$i][$j])
                            randompause
                        }
                        [Microsoft.PowerShell.PSConsoleReadLine]::AddLine()
                    }
                    for ($j = 0; $j -lt $Commands[$i].Length; $j++) {
                        [Microsoft.PowerShell.PSConsoleReadLine]::Insert($Commands[-1][$j])
                        randompause
                    }
                    waitforspecifickeypress -Keys 0x0D
                    [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
                }
                catch {
                    Set-Index ($CurrentIndex)
                    [Microsoft.PowerShell.PSConsoleReadLine]::CancelLine()
                }
            }
        }
        Get-PSReadLineKeyHandler -Bound | 
            Where-Object { $_.Description -eq $setPSReadLineKeyHandlerSplat.Description } | 
            ForEach-Object { Remove-PSReadLineKeyHandler -Chord $_.Chord }

        Set-PSReadLineKeyHandler @setPSReadLineKeyHandlerSplat
    }
    catch {}
    $Script:Demo = $Demo
    Set-Index
}
#EndRegion './Public/Set-Demo.ps1' 76