PTAG.psm1

using namespace System.Management.Automation
param()
Function NewTabItem {
    [CmdletBinding()]
    [OutputType([System.Management.Automation.CompletionResult])]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
    param(
        [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Value
        ,
        [Parameter(Position = 1, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $Text = $Value
        ,
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [String]
        $Type = "Unknown"
        ,
        [Parameter()]
        [CompletionResultType]
        $ResultType = "Text"
        ,
        [Parameter(ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [String]
        $ToolTip = $Text
    )

    process {
        New-Object CompletionResult $Value, $Text, $ResultType, $ToolTip
    }
}


Function RegisterArgumentCompleter {
    param(
        [String]
        $CommandName
        ,
        [String]
        $ParameterName
        ,
        [ScriptBlock]
        $ScriptBlock
    )

    if ($PSVersionTable.PSVersion -ge "5.0") {
        if ($CommandName -and $ParameterName) {
            Register-ArgumentCompleter -CommandName $CommandName -ParameterName $ParameterName -ScriptBlock $ScriptBlock
        } elseif ($CommandName) {
            Register-ArgumentCompleter -CommandName $CommandName -ScriptBlock $ScriptBlock
        } else {
            Register-ArgumentCompleter -ParameterName $ParameterName -ScriptBlock $ScriptBlock
        }
    } else {
        if (-not $global:options) { $global:options = @{CustomArgumentCompleters = @{};NativeArgumentCompleters = @{}}}

        if ($CommandName -and $ParameterName) {
            $global:options['CustomArgumentCompleters']["${CommandName}:$ParameterName"] = $ScriptBlock
        } elseif ($CommandName) {
            $global:options['CustomArgumentCompleters'][$CommandName] = $ScriptBlock
        } else {
            $global:options['CustomArgumentCompleters'][$ParameterName] = $ScriptBlock
        }
    }
}

Function FindModule {
    [CmdletBinding()]
    param(
        [String[]]$Name = "*"
        ,
        [Switch]$All
    )

    foreach ($n in $Name) {
        $folder = [System.IO.Path]::GetDirectoryName($n)
        $n = [System.IO.Path]::GetFileName($n)
        $ModulePaths = $Env:PSModulePath -split ";" | Select-Object -Unique | Where-Object {Test-Path $_}

        if ($folder) {
            $ModulePaths = $ModulePaths | ForEach-Object {Join-Path $_ $folder}
        }

        # Note: the order of these is important. They need to be in the order they'd be loaded by the system
        $Files = @(Get-ChildItem -Path $ModulePaths -Recurse -Filter "$n.ps?1" -EA 0; Get-ChildItem -Path $ModulePaths -Recurse -Filter "$n.dll" -EA 0)
        $Files | Where-Object {
                $parent = [System.IO.Path]::GetFileName( $_.PSParentPath )
                return $all -or ($parent -eq $_.BaseName) -or ($folder -and ($parent -eq ([System.IO.Path]::GetFileName($folder))) -and ($n -eq $_.BaseName))
            } | Group-Object PSParentPath | . {process{@($_.Group)[0]}}

        # TODO: Search installed modules as well.

        # Possibly useful in the future
        # | Sort-Object {switch ($_.Extension) {".psd1"{1} ".psm1"{2}}})
    }
}
Register-ArgumentCompleter -Native -CommandName powershell -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)

    $Parameters = '-Command','-ConfigurationName','-EncodedCommand','-ExecutionPolicy','-File','-Help',
    '-InputFormat','-Mta','-NoExit','-NoLogo','-NonInteractive','-NoProfile','-OutputFormat',
    '-PSConsoleFile','-Sta','-Version','-WindowStyle'

    $LastArgument = $commandAst.CommandElements[-1]

    if ($LastArgument -is [System.Management.Automation.Language.CommandParameterAst]) {
        switch ($LastArgument.ParameterName) {
            'Command' {
                break
            }
            'ConfigurationName' {
                break
            }
            'EncodedCommand' {
                break
            }
            'ExecutionPolicy' {
                'Unrestricted', 'RemoteSigned', 'AllSigned', 'Restricted', 'Bypass', 'Undefined' |
                    NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
                break
            }
            'File' {
                break
            }
            'InputFormat' {
                'Text', 'Xml' | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
                break
            }
            'PSConsoleFile' {
                break
            }
            'Version' {
                '1.0', '2.0', '3.0', '4.0', '5.0', '5.1', '6.0' |
                    NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
                break
            }
            'Version' {
                '1.0', '2.0', '3.0', '4.0', '5.0', '5.1', '6.0' |
                    NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
                break
            }
            'WindowStyle' {
                'Normal','Minimized','Maximized','Hidden' |
                    NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
                break
            }
            default {
                $Parameters | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
            }
        }
    } else {
        $Parameters | Where-Object {$_ -like "$wordToComplete*"} |
            NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
    }

    <#
    PowerShell[.exe] [-PSConsoleFile <file> | -Version <version>]
    [-NoLogo] [-NoExit] [-Sta] [-Mta] [-NoProfile] [-NonInteractive]
    [-InputFormat {Text | XML}] [-OutputFormat {Text | XML}]
    [-WindowStyle <style>] [-EncodedCommand <Base64EncodedCommand>]
    [-ConfigurationName <string>]
    [-File <filePath> <args>] [-ExecutionPolicy <ExecutionPolicy>]
    [-Command { - | <script-block> [-args <arg-array>]
                    | <string> [<CommandParameters>] } ]
 
    PowerShell[.exe] -Help | -? | /?
    #>

}

$Completion_AliasName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Alias -Name "$wordToComplete*" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType Command
}

RegisterArgumentCompleter -CommandName "Export-Alias" -ParameterName "Name" -ScriptBlock $Completion_AliasName
RegisterArgumentCompleter -CommandName "Get-Alias" -ParameterName "Name" -ScriptBlock $Completion_AliasName
RegisterArgumentCompleter -CommandName "Set-Alias" -ParameterName "Name" -ScriptBlock $Completion_AliasName
$Completion_Command = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $CommandTypes = "Function","Filter","Cmdlet"
    if ($PSVersionTable.PSVersion -ge "3.0") {
        $CommandTypes += "Workflow"
    }
    Get-Command "$wordToComplete*" -CommandType $CommandTypes |
        NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType Command
}

RegisterArgumentCompleter -CommandName "Get-Alias" -ParameterName "Definition" -ScriptBlock $Completion_Command
RegisterArgumentCompleter -CommandName "Get-Job" -ParameterName "Command" -ScriptBlock $Completion_Command
RegisterArgumentCompleter -CommandName "Get-PSBreakpoint" -ParameterName "Command" -ScriptBlock $Completion_Command
RegisterArgumentCompleter -CommandName "New-Alias" -ParameterName "Value" -ScriptBlock $Completion_Command
RegisterArgumentCompleter -CommandName "Set-Alias" -ParameterName "Value" -ScriptBlock $Completion_Command
RegisterArgumentCompleter -CommandName "Set-PSBreakpoint" -ParameterName "Command" -ScriptBlock $Completion_Command
RegisterArgumentCompleter -CommandName "Trace-Command" -ParameterName "Command" -ScriptBlock $Completion_Command

$Completion_CommandAll = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $CommandTypes = "Function","ExternalScript","Filter","Cmdlet"
    if ($PSVersionTable.PSVersion -ge "3.0") {
        $CommandTypes += "Workflow"
    }
    Get-Command "$wordToComplete*" -CommandType $CommandTypes |
        NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType Command
}

$Completion_CommandNoun = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $CommandTypes = "Function","Filter","Cmdlet"
    if ($PSVersionTable.PSVersion -ge "3.0") {
        $CommandTypes += "Workflow"
    }
    Get-Command -CommandType $CommandTypes | Where-Object {$_.Name -match "^[^-]+-(?<Noun>$wordToComplete.*)"} |
        . {process{$Matches.Noun}} | Sort-Object -Unique | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Command" -ParameterName "Noun" -ScriptBlock $Completion_CommandNoun

$Completion_CommandVerb = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Verb "$wordToComplete*" | Sort-Object Verb | NewTabItem -Value {$_.Verb} -Text {$_.Verb} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Command" -ParameterName "Verb" -ScriptBlock $Completion_CommandVerb
RegisterArgumentCompleter -CommandName "Get-Verb" -ParameterName "Verb" -ScriptBlock $Completion_CommandVerb
$Completion_ComputerRestoreDrive = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSDrive -PSProvider FileSystem "$wordToComplete*" |
        NewTabItem -Value {$_.Root} -Text {$_.Root} -ResultType ProviderContainer
}

RegisterArgumentCompleter -CommandName "Disable-ComputerRestore" -ParameterName "Drive" -ScriptBlock $Completion_ComputerRestoreDrive
RegisterArgumentCompleter -CommandName "Enable-ComputerRestore" -ParameterName "Drive" -ScriptBlock $Completion_ComputerRestoreDrive

$Completion_ComputerRestorePoint = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    foreach ($Point in Get-ComputerRestorePoint -ErrorAction Stop) {
        if ($Point.Description.Length -gt 50) {
            $Description = $Point.Description.SubString(0, 50)
        } else {
            $Description = $Point.Description
        }
        $Text = "{0}: {1} ({2})" -f $Point.SequenceNumber,[DateTime]::ParseExact($Point.CreationTime, "yyyyMMddHHmmss.ffffff-000", $null),$Description
        NewTabItem -Value $Point.SequenceNumber -Text $Text -ResultType ParameterValue
    }
}

RegisterArgumentCompleter -CommandName "Get-ComputerRestorePoint" -ParameterName "RestorePoint" -ScriptBlock $Completion_ComputerRestorePoint
RegisterArgumentCompleter -CommandName "Restore-Computer" -ParameterName "RestorePoint" -ScriptBlock $Completion_ComputerRestorePoint
$Completion_Counter = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-Counter -ListSet * @Parameters | Where-Object {$_.PathsWithInstances -like "*$wordToComplete*"} |
        Sort-Object PathsWithInstances | NewTabItem -Value {$_.PathsWithInstances} -Text {$_.PathsWithInstances} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Counter" -ParameterName "Counter" -ScriptBlock $Completion_Counter
RegisterArgumentCompleter -CommandName "Import-Counter" -ParameterName "Counter" -ScriptBlock $Completion_Counter

$Completion_CounterSet = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-Counter -ListSet "$wordToComplete*" @Parameters | NewTabItem -Value {$_.CounterSetName} -Text {$_.CounterSetName} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Counter" -ParameterName "ListSet" -ScriptBlock $Completion_CounterSet
RegisterArgumentCompleter -CommandName "Import-Counter" -ParameterName "ListSet" -ScriptBlock $Completion_CounterSet

$Completion_CounterFormat = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    "CSV", "TSV", "BLG" | Where-Object {$_ -like "$wordToComplete*"} | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Export-Counter" -ParameterName "FileFormat" -ScriptBlock $Completion_CounterFormat
$Completion_EventEventIdentifier = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Event | NewTabItem -Value {$_.EventIdentifier} -Text {$_.EventIdentifier} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Event" -ParameterName "EventIdentifier" -ScriptBlock $Completion_EventEventIdentifier
RegisterArgumentCompleter -CommandName "Remove-Event" -ParameterName "EventIdentifier" -ScriptBlock $Completion_EventEventIdentifier

$Completion_EventSourceIdentifier = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Event "$Argument*" | Sort-Object SourceIdentifier |
        NewTabItem -Value {$_.SourceIdentifier} -Text {$_.SourceIdentifier} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Event" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Get-EventSubscriber" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "New-Event" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Register-EngineEvent" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Register-ObjectEvent" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Register-WmiEvent" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Register-CimIndicationEvent" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Remove-Event" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Unregister-Event" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier
RegisterArgumentCompleter -CommandName "Wait-Event" -ParameterName "SourceIdentifier" -ScriptBlock $Completion_EventSourceIdentifier

$Completion_EventEventName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    if ($fakeBoundParameter["InputObject"]) {
        Invoke-Expression $fakeBoundParameter["InputObject"] | Get-Member | 
            Where-Object {$_.MemberType -eq "Event" -and $_.Name -like "$wordToComplete*"} |
            NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
    }
}

RegisterArgumentCompleter -CommandName "Register-ObjectEvent" -ParameterName "EventName" -ScriptBlock $Completion_EventEventName
$Completion_EventLogCategory = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Categories = (
        @{'Id'='0';'Name'='None'},
        @{'Id'='1';'Name'='Devices'},
        @{'Id'='2';'Name'='Disk'},
        @{'Id'='3';'Name'='Printers'},
        @{'Id'='4';'Name'='Services'},
        @{'Id'='5';'Name'='Shell'},
        @{'Id'='6';'Name'='System Event'},
        @{'Id'='7';'Name'='Network'}
    )
    $Categories | Where-Object {$_.Name -like "$wordToComplete*"} | NewTabItem -Value {$_.Id} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Write-EventLog" -ParameterName "Category" -ScriptBlock $Completion_EventLogCategory

$Completion_EventLogLogName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-EventLog -List -AsString @Parameters | Where-Object {$_ -like "$wordToComplete*"} |
        NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Clear-EventLog" -ParameterName "LogName" -ScriptBlock $Completion_EventLogLogName
RegisterArgumentCompleter -CommandName "Get-EventLog" -ParameterName "LogName" -ScriptBlock $Completion_EventLogLogName
RegisterArgumentCompleter -CommandName "Limit-EventLog" -ParameterName "LogName" -ScriptBlock $Completion_EventLogLogName
RegisterArgumentCompleter -CommandName "Remove-EventLog" -ParameterName "LogName" -ScriptBlock $Completion_EventLogLogName
RegisterArgumentCompleter -CommandName "Write-EventLog" -ParameterName "LogName" -ScriptBlock $Completion_EventLogLogName

$Completion_HelpName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    if ($wordToComplete -like "about_*") {
        $ProgressPreference = "SilentlyContinue" ## Suppress progress bars
        Get-Help "$wordToComplete*" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
    } else {
        $CommandTypes = "Function","ExternalScript","Filter","Cmdlet","Alias"
        if ($PSVersionTable.PSVersion -ge "3.0") {
            $CommandTypes += "Workflow"
        }
        Get-Command "$wordToComplete*" -CommandType $CommandTypes | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType Command
    }
}

RegisterArgumentCompleter -CommandName "Get-Help" -ParameterName "Name" -ScriptBlock $Completion_HelpName
$Completion_HistoryId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-History | NewTabItem -Value {$_.Id} -Text {$_.CommandLine} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Clear-History" -ParameterName "Id" -ScriptBlock $Completion_HistoryId
RegisterArgumentCompleter -CommandName "Get-History" -ParameterName "Id" -ScriptBlock $Completion_HistoryId
RegisterArgumentCompleter -CommandName "Invoke-History" -ParameterName "Id" -ScriptBlock $Completion_HistoryId
$Completion_ItemPropertyName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Path = "."
    if ($fakeBoundParameter["Path"]) {
        ## TODO:
        #$Path = Resolve-TabExpansionParameterValue $fakeBoundParameter["Path"]
    }
    Get-ItemProperty -Path $Path -Name "$wordToComplete*" | Get-Member | Where-Object {
        (("Property","NoteProperty") -contains $_.MemberType) -and
        (("PSChildName","PSDrive","PSParentPath","PSPath","PSProvider") -notcontains $_.Name)
    } | Select-Object -ExpandProperty Name -Unique | NewTabItem -Value {$_} -Text {$_} -ResultType ProviderItem
}

RegisterArgumentCompleter -CommandName "Clear-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Copy-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Get-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Get-ItemPropertyValue" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Move-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Remove-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Rename-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName
RegisterArgumentCompleter -CommandName "Set-ItemProperty" -ParameterName "Name" -ScriptBlock $Completion_ItemPropertyName

$Completion_ItemPropertyPropertyType = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    "String","ExpandString","Binary","DWord","MultiString","Qword","Unknown" | Where-Object {$_ -like "$wordToComplete*"} |
        NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "New-ItemProperty" -ParameterName "PropertyType" -ScriptBlock $Completion_ItemPropertyPropertyType
$Completion_JobId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Job | NewTabItem -Value {$_.Id} -Text {$_.Id} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Debug-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Get-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Receive-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Remove-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Resume-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Stop-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Suspend-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId
RegisterArgumentCompleter -CommandName "Wait-Job" -ParameterName "Id" -ScriptBlock $Completion_JobId

$Completion_JobInstanceId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Job | NewTabItem -Value {$_.InstanceId} -Text {$_.InstanceId} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Debug-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Get-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Receive-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Remove-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Resume-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Stop-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Suspend-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId
RegisterArgumentCompleter -CommandName "Wait-Job" -ParameterName "InstanceId" -ScriptBlock $Completion_JobInstanceId

$Completion_JobName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Job -Name "$wordToComplete*" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Debug-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Get-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Receive-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Remove-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Resume-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Stop-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Suspend-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName
RegisterArgumentCompleter -CommandName "Wait-Job" -ParameterName "Name" -ScriptBlock $Completion_JobName

$Completion_JobJob = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    foreach ($Job in Get-Job -Name "$wordToComplete*") {
        '(Get-Job "{0}")' -f $Job.Name | Sort-Object | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
    }
}

RegisterArgumentCompleter -CommandName "Debug-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
RegisterArgumentCompleter -CommandName "Receive-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
RegisterArgumentCompleter -CommandName "Remove-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
RegisterArgumentCompleter -CommandName "Resume-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
RegisterArgumentCompleter -CommandName "Stop-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
RegisterArgumentCompleter -CommandName "Suspend-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
RegisterArgumentCompleter -CommandName "Wait-Job" -ParameterName "Job" -ScriptBlock $Completion_JobJob
$Completion_ModuleName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}
    $Results = @()

    switch ($commandName) {
        "Get-Module" {
            if ($fakeBoundParameter["All"]) {
                $Parameters["All"] = $true
            }
            if ($fakeBoundParameter["ListAvailable"]) {
                $Parameters["ListAvailable"] = $true
            }
            $Results = Get-Module "$wordToComplete*" @Parameters
            break
        }
        "Import-Module" {
            if ($wordToComplete -notmatch '^\.') {
                $Results = FindModule "$wordToComplete*" | Select-Object @{Name = "Name"; Expression = {$_.BaseName}}
            }
            break
        }
        Default {
            $Results = Get-Module "$wordToComplete*"
        }
    }

    $Results | Sort-Object Name | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Command" -ParameterName "Get-Command" -ScriptBlock $Completion_ModuleName
RegisterArgumentCompleter -CommandName "Get-Module" -ParameterName "Name" -ScriptBlock $Completion_ModuleName
RegisterArgumentCompleter -CommandName "Get-OperationValidation" -ParameterName "ModuleName" -ScriptBlock $Completion_ModuleName
RegisterArgumentCompleter -CommandName "Import-Module" -ParameterName "Name" -ScriptBlock $Completion_ModuleName
RegisterArgumentCompleter -CommandName "Invoke-OperationValidation" -ParameterName "ModuleName" -ScriptBlock $Completion_ModuleName
RegisterArgumentCompleter -CommandName "Remove-Module" -ParameterName "Name" -ScriptBlock $Completion_ModuleName
RegisterArgumentCompleter -CommandName "Update-Help" -ParameterName "Module" -ScriptBlock $Completion_ModuleName

$Completion_ModuleOrSnapin = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    ## TODO: Grab from session instead?
    (Get-Module -ListAvailable "$wordToComplete*") + (Get-PSSnapin "$wordToComplete*") | Sort-Object Name |
        NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Import-PSSession" -ParameterName "Module" -ScriptBlock $Completion_ModuleOrSnapin
RegisterArgumentCompleter -CommandName "Export-PSSession" -ParameterName "Module" -ScriptBlock $Completion_ModuleOrSnapin
$Completion_PrinterName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-CimInstance -ClassName "Win32_Printer" -Filter "Name LIKE '$wordToComplete%'" |
        NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Out-Printer" -ParameterName "Name" -ScriptBlock $Completion_PrinterName
$Completion_ProcessId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    if ($wordToComplete -match '^[0-9]+$') {
        Get-Process @Parameters | Where-Object {$_.Id.ToString() -like "$wordToComplete*"} |
            NewTabItem -Value {$_.Id} -Text {"{0,-4} <# {1} #>" -f ([String]$_.Id),$_.Name} -ResultType ParameterValue
    } else {
        Get-Process -Name "$wordToComplete*" @Parameters |
            NewTabItem -Value {$_.Id} -Text {"{0,-4} <# {1} #>" -f ([String]$_.Id),$_.Name} -ResultType ParameterValue
    }
}

RegisterArgumentCompleter -CommandName "Debug-Process" -ParameterName "Id" -ScriptBlock $Completion_ProcessId
RegisterArgumentCompleter -CommandName "Get-Process" -ParameterName "Id" -ScriptBlock $Completion_ProcessId
RegisterArgumentCompleter -CommandName "Stop-Process" -ParameterName "Id" -ScriptBlock $Completion_ProcessId
RegisterArgumentCompleter -CommandName "Wait-Process" -ParameterName "Id" -ScriptBlock $Completion_ProcessId

$Completion_ProcessName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-Process -Name "$wordToComplete*" @Parameters | Select-Object -ExpandProperty Name -Unique |
        NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Debug-Process" -ParameterName "Name" -ScriptBlock $Completion_ProcessName
RegisterArgumentCompleter -CommandName "Get-Process" -ParameterName "Name" -ScriptBlock $Completion_ProcessName
RegisterArgumentCompleter -CommandName "Stop-Process" -ParameterName "Name" -ScriptBlock $Completion_ProcessName
RegisterArgumentCompleter -CommandName "Wait-Process" -ParameterName "Name" -ScriptBlock $Completion_ProcessName
$Completion_PSDriveName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSDrive "$wordToComplete*" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-PSDrive" -ParameterName "LiteralName" -ScriptBlock $Completion_PSDriveName
RegisterArgumentCompleter -CommandName "Get-PSDrive" -ParameterName "Name" -ScriptBlock $Completion_PSDriveName
RegisterArgumentCompleter -CommandName "Remove-PSDrive" -ParameterName "LiteralName" -ScriptBlock $Completion_PSDriveName
RegisterArgumentCompleter -CommandName "Remove-PSDrive" -ParameterName "Name" -ScriptBlock $Completion_PSDriveName

RegisterArgumentCompleter -ParameterName "PSDrive" -ScriptBlock $Completion_PSDriveName
$Completion_PSHostProcessId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    ## TODO: Is it better to include window title?
    if ($wordToComplete -match '^[0-9]+$') {
        Get-PSHostProcessInfo @Parameters | Where-Object {$_.ProcessId.ToString() -like "$wordToComplete*"} |
            NewTabItem -Value {$_.ProcessId} -Text {"{0,-4} <# {1} #>" -f ([String]$_.ProcessId),$_.ProcessName} -ResultType ParameterValue
    } else {
        Get-PSHostProcessInfo @Parameters | Where-Object {$_.ProcessName -like "$wordToComplete*"} |
            NewTabItem -Value {$_.ProcessId} -Text {"{0,-4} <# {1} #>" -f ([String]$_.ProcessId),$_.ProcessName} -ResultType ParameterValue
    }
}

RegisterArgumentCompleter -CommandName "Enter-PSHostProcess" -ParameterName "Id" -ScriptBlock $Completion_PSHostProcessId
RegisterArgumentCompleter -CommandName "Get-PSHostProcessInfo" -ParameterName "Id" -ScriptBlock $Completion_PSHostProcessId

$Completion_PSHostProcessName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-PSHostProcessInfo -Name "$wordToComplete*" @Parameters | Get-Unique |
        NewTabItem -Value {$_.ProcessName} -Text {$_.ProcessName} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Disable-RunspaceDebug" -ParameterName "ProcessName" -ScriptBlock $Completion_PSHostProcessName
RegisterArgumentCompleter -CommandName "Enable-RunspaceDebug" -ParameterName "ProcessName" -ScriptBlock $Completion_PSHostProcessName
RegisterArgumentCompleter -CommandName "Enter-PSHostProcess" -ParameterName "Name" -ScriptBlock $Completion_PSHostProcessName
RegisterArgumentCompleter -CommandName "Get-PSHostProcessInfo" -ParameterName "Name" -ScriptBlock $Completion_PSHostProcessName
RegisterArgumentCompleter -CommandName "Get-RunspaceDebug" -ParameterName "ProcessName" -ScriptBlock $Completion_PSHostProcessName

$Completion_PSHostProcessAppDomainName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-PSHostProcessInfo @Parameters | Select-Object -ExpandProperty AppDomainName -Unique |
        Where-Object {$_ -like "$wordToComplete*"} | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Disable-RunspaceDebug" -ParameterName "AppDomainName" -ScriptBlock $Completion_PSHostProcessAppDomainName
RegisterArgumentCompleter -CommandName "Enable-RunspaceDebug" -ParameterName "AppDomainName" -ScriptBlock $Completion_PSHostProcessAppDomainName
RegisterArgumentCompleter -CommandName "Enter-PSHostProcess" -ParameterName "AppDomainName" -ScriptBlock $Completion_PSHostProcessAppDomainName
RegisterArgumentCompleter -CommandName "Get-RunspaceDebug" -ParameterName "AppDomainName" -ScriptBlock $Completion_PSHostProcessAppDomainName
$Completion_PSSessionId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSSession | NewTabItem -Value {$_.Id} -Text {$_.Id} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Connect-PSSession" -ParameterName "Id" -ScriptBlock $Completion_PSSessionId
RegisterArgumentCompleter -CommandName "Disconnect-PSSession" -ParameterName "Id" -ScriptBlock $Completion_PSSessionId
RegisterArgumentCompleter -CommandName "Enter-PSSession" -ParameterName "Id" -ScriptBlock $Completion_PSSessionId
RegisterArgumentCompleter -CommandName "Get-PSSession" -ParameterName "Id" -ScriptBlock $Completion_PSSessionId
RegisterArgumentCompleter -CommandName "Receive-PSSession" -ParameterName "Id" -ScriptBlock $Completion_PSSessionId
RegisterArgumentCompleter -CommandName "Remove-PSSession" -ParameterName "Id" -ScriptBlock $Completion_PSSessionId

$Completion_PSSessionInstanceId = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSSession | Where-Object {$_.InstanceId -like "$wordToComplete*"} |
        NewTabItem -Value {$_.InstanceId} -Text {$_.InstanceId} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Connect-PSSession" -ParameterName "InstanceId" -ScriptBlock $Completion_PSSessionInstanceId
RegisterArgumentCompleter -CommandName "Disconnect-PSSession" -ParameterName "InstanceId" -ScriptBlock $Completion_PSSessionInstanceId
RegisterArgumentCompleter -CommandName "Enter-PSSession" -ParameterName "InstanceId" -ScriptBlock $Completion_PSSessionInstanceId
RegisterArgumentCompleter -CommandName "Get-PSSession" -ParameterName "InstanceId" -ScriptBlock $Completion_PSSessionInstanceId
RegisterArgumentCompleter -CommandName "Receive-PSSession" -ParameterName "InstanceId" -ScriptBlock $Completion_PSSessionInstanceId
RegisterArgumentCompleter -CommandName "Remove-PSSession" -ParameterName "InstanceId" -ScriptBlock $Completion_PSSessionInstanceId

$Completion_PSSessionName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSSession -Name "$wordToComplete*" | Sort-Object Name | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Connect-PSSession" -ParameterName "Name" -ScriptBlock $Completion_PSSessionName
RegisterArgumentCompleter -CommandName "Disconnect-PSSession" -ParameterName "Name" -ScriptBlock $Completion_PSSessionName
RegisterArgumentCompleter -CommandName "Enter-PSSession" -ParameterName "Name" -ScriptBlock $Completion_PSSessionName
RegisterArgumentCompleter -CommandName "Get-PSSession" -ParameterName "Name" -ScriptBlock $Completion_PSSessionName
RegisterArgumentCompleter -CommandName "Receive-PSSession" -ParameterName "Name" -ScriptBlock $Completion_PSSessionName
RegisterArgumentCompleter -CommandName "Remove-PSSession" -ParameterName "Name" -ScriptBlock $Completion_PSSessionName

$Completion_PSSessionSession = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSSession -Name "$wordToComplete*" | Sort-Object Name |
        NewTabItem -Value {'(Get-PSSession -Name "{0}")' -f $Session.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Connect-PSSession" -ParameterName "Session" -ScriptBlock $Completion_PSSessionSession
RegisterArgumentCompleter -CommandName "Disconnect-PSSession" -ParameterName "Session" -ScriptBlock $Completion_PSSessionSession
RegisterArgumentCompleter -CommandName "Enter-PSSession" -ParameterName "Session" -ScriptBlock $Completion_PSSessionSession
RegisterArgumentCompleter -CommandName "New-PSSession" -ParameterName "Session" -ScriptBlock $Completion_PSSessionSession
RegisterArgumentCompleter -CommandName "Receive-PSSession" -ParameterName "Session" -ScriptBlock $Completion_PSSessionSession
RegisterArgumentCompleter -CommandName "Remove-PSSession" -ParameterName "Session" -ScriptBlock $Completion_PSSessionSession
$Completion_PSSessionConfigurationName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSSessionConfiguration "$wordToComplete*" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Disable-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName
RegisterArgumentCompleter -CommandName "Enable-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName
RegisterArgumentCompleter -CommandName "Get-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName
RegisterArgumentCompleter -CommandName "Register-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName
RegisterArgumentCompleter -CommandName "Receive-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName
RegisterArgumentCompleter -CommandName "Set-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName
RegisterArgumentCompleter -CommandName "Unregister-PSSessionConfiguration" -ParameterName "Name" -ScriptBlock $Completion_PSSessionConfigurationName

$Completion_PSSessionConfigurationConfigurationTypeName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    ## TODO:
}

RegisterArgumentCompleter -CommandName "Register-PSSessionConfiguration" -ParameterName "ConfigurationTypeName" -ScriptBlock $Completion_PSSessionConfigurationConfigurationTypeName
RegisterArgumentCompleter -CommandName "Set-PSSessionConfiguration" -ParameterName "ConfigurationTypeName" -ScriptBlock $Completion_PSSessionConfigurationConfigurationTypeName
$Completion_PSSnapinName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{"ErrorAction" = "SilentlyContinue"}
    $Snapins = @()

    switch ($commandName) {
        "Add-PSSnapin" {
            $Loaded = @(Get-PSSnapin)
            $Snapins = Get-PSSnapin "$wordToComplete*" -Registered @Parameters | Where-Object {$Loaded -notcontains $_}
            break
        }
        "Remove-PSSnapin" {
            $Loaded = @(Get-PSSnapin)
            $Snapins = Get-PSSnapin "$wordToComplete*" @Parameters | Where-Object {$Loaded -contains $_}
            break
        }
        Default {
            if ($fakeBoundParameter["Registered"]) {
                $Parameters["Registered"] = $true
            }
            $Snapins = Get-PSSnapin "$wordToComplete*" @Parameters
        }
    }

    $Snapins | Sort-Object Name | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Add-PSSnapin" -ParameterName "Name" -ScriptBlock $Completion_PSSnapinName
RegisterArgumentCompleter -CommandName "Get-PSSnapin" -ParameterName "Name" -ScriptBlock $Completion_PSSnapinName
RegisterArgumentCompleter -CommandName "Remove-PSSnapin" -ParameterName "Name" -ScriptBlock $Completion_PSSnapinName
$Completion_ServiceDisplayName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-Service -DisplayName "*$wordToComplete*" @Parameters |
        NewTabItem -Value {$_.DisplayName} -Text {$_.DisplayName} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Service" -ParameterName "DisplayName" -ScriptBlock $Completion_ServiceDisplayName
RegisterArgumentCompleter -CommandName "Restart-Service" -ParameterName "DisplayName" -ScriptBlock $Completion_ServiceDisplayName
RegisterArgumentCompleter -CommandName "Resume-Service" -ParameterName "DisplayName" -ScriptBlock $Completion_ServiceDisplayName
RegisterArgumentCompleter -CommandName "Start-Service" -ParameterName "DisplayName" -ScriptBlock $Completion_ServiceDisplayName
RegisterArgumentCompleter -CommandName "Stop-Service" -ParameterName "DisplayName" -ScriptBlock $Completion_ServiceDisplayName
RegisterArgumentCompleter -CommandName "Suspend-Service" -ParameterName "DisplayName" -ScriptBlock $Completion_ServiceDisplayName

$Completion_ServiceName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{}

    Get-Service -Name "$wordToComplete*" @Parameters | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "New-Service" -ParameterName "DependsOn" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "Restart-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "Resume-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "Set-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "Start-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "Stop-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
RegisterArgumentCompleter -CommandName "Suspend-Service" -ParameterName "Name" -ScriptBlock $Completion_ServiceName
$Completion_VariableName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-Variable "$wordToComplete*" -Scope "Global" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Clear-Variable" -ParameterName "Name" -ScriptBlock $Completion_VariableName
RegisterArgumentCompleter -CommandName "Get-Variable" -ParameterName "Name" -ScriptBlock $Completion_VariableName
RegisterArgumentCompleter -CommandName "Remove-Variable" -ParameterName "Name" -ScriptBlock $Completion_VariableName
RegisterArgumentCompleter -CommandName "Set-Variable" -ParameterName "Name" -ScriptBlock $Completion_VariableName
$Completion_StrictVersion = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    "1.0","2.0","Latest" | Where-Object {$_ -like "$wordToComplete*"} | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Set-StrictMode" -ParameterName "Version" -ScriptBlock $Completion_StrictVersion
$Completion_WinEventFilterHashTable = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    ('@{LogName="*"}','@{ProviderName="*"}','@{Keywords=""}','@{ID=""}','@{Level=""}') |
        NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-WinEvent" -ParameterName "FilterHashTable" -ScriptBlock $Completion_WinEventFilterHashTable

$Completion_WinEventListLog = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{"ErrorAction" = "SilentlyContinue"}

    Get-WinEvent -ListLog "$wordToComplete*" @Parameters | NewTabItem -Value {$_.LogName} -Text {$_.LogName} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-WinEvent" -ParameterName "ListLog" -ScriptBlock $Completion_WinEventListLog

$Completion_WinEventListProvider = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{"ErrorAction" = "SilentlyContinue"}

    Get-WinEvent -ListProvider "$wordToComplete*" @Parameters | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-WinEvent" -ParameterName "ListProvider" -ScriptBlock $Completion_WinEventListProvider

$Completion_WinEventLogName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{"ErrorAction" = "SilentlyContinue"}

    Get-WinEvent -ListLog "$wordToComplete*" @Parameters | NewTabItem -Value {$_.LogName} -Text {$_.LogName} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-WinEvent" -ParameterName "LogName" -ScriptBlock $Completion_WinEventLogName

$Completion_WinEventProviderName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Parameters = @{"ErrorAction" = "SilentlyContinue"}

    Get-WinEvent -ListProvider "$wordToComplete*" @Parameters | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-WinEvent" -ParameterName "ProviderName" -ScriptBlock $Completion_WinEventProviderName
$Completion_Culture = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::InstalledWin32Cultures) |
        Where-Object {$_.Name -like "$wordToComplete*"} | Sort-Object Name | Select-Object LCID, Name |
        ForEach-Object {if ($_.LCID -eq 127) {$_.Name = "Invariant Language"}; $_} |
        NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -ParameterName "Culture" -ScriptBlock $Completion_Culture
RegisterArgumentCompleter -ParameterName "UICulture" -ScriptBlock $Completion_Culture
RegisterArgumentCompleter -ParameterName "CultureInfo" -ScriptBlock $Completion_Culture
RegisterArgumentCompleter -CommandName "New-WinUserLanguageList" -ParameterName "Language" -ScriptBlock $Completion_Culture
RegisterArgumentCompleter -CommandName "Set-WinSystemLocale" -ParameterName "SystemLocale" -ScriptBlock $Completion_Culture
RegisterArgumentCompleter -CommandName "Set-WinUILanguageOverride" -ParameterName "Language" -ScriptBlock $Completion_Culture
RegisterArgumentCompleter -CommandName "Set-WinUserLanguageList" -ParameterName "LanguageList" -ScriptBlock $Completion_Culture

$Completion_Geoid = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::InstalledWin32Cultures) |
        ForEach-Object {try{[System.Globalization.RegionInfo]$_.Name}catch{}} | Where-Object {$_.DisplayName -like "$wordToComplete*"} |
        Select-Object -Unique | NewTabItem -Value {$_.GeoId} -Text {$_.DisplayName} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Set-WinHomeLocation" -ParameterName "GeoId" -ScriptBlock $Completion_Geoid

$Completion_Locale = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    [System.Globalization.CultureInfo]::GetCultures([System.Globalization.CultureTypes]::InstalledWin32Cultures) |
        Where-Object {$_.Name -like "$wordToComplete*"} | Sort-Object -Property Name | Select-Object LCID, Name |
        ForEach-Object {if ($_.LCID -eq 127) {$_.Name = "Invariant Language"}; $_} |
        NewTabItem -Value {$_.LCID} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Get-WmiObject" -ParameterName "Locale" -ScriptBlock $Completion_Locale
RegisterArgumentCompleter -CommandName "Invoke-WmiMethod" -ParameterName "Locale" -ScriptBlock $Completion_Locale
RegisterArgumentCompleter -CommandName "New-MarkdownHelp" -ParameterName "Locale" -ScriptBlock $Completion_Locale
RegisterArgumentCompleter -CommandName "Remove-WmiObject" -ParameterName "Locale" -ScriptBlock $Completion_Locale
RegisterArgumentCompleter -CommandName "Set-WmiInstance" -ParameterName "Locale" -ScriptBlock $Completion_Locale
$Completion_PSEdition = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    $Editions = @("Desktop","Core")

    $Editions | Where-Object {$_ -like "$wordToComplete*"} | NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -ParameterName "PSEdition" -ScriptBlock $Completion_PSEdition
$Completion_PSProviderName = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    Get-PSProvider "$wordToComplete*" | NewTabItem -Value {$_.Name} -Text {$_.Name} -ResultType ParameterValue
}

RegisterArgumentCompleter -ParameterName "PSProvider" -ScriptBlock $Completion_PSProviderName
$Completion_ParamScope = {
    param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)

    "Global","Local","Script","0" | Where-Object {$_ -like "$wordToComplete*"} |
        NewTabItem -Value {$_} -Text {$_} -ResultType ParameterValue
}

RegisterArgumentCompleter -CommandName "Export-Alias" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope
RegisterArgumentCompleter -CommandName "Get-Alias" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope
RegisterArgumentCompleter -CommandName "Import-Alias" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope
RegisterArgumentCompleter -CommandName "New-Alias" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope
RegisterArgumentCompleter -CommandName "Set-Alias" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope

RegisterArgumentCompleter -CommandName "Get-PSDrive" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope
RegisterArgumentCompleter -CommandName "New-PSDrive" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope
RegisterArgumentCompleter -CommandName "Remove-PSDrive" -ParameterName "Scope" -ScriptBlock $Completion_ParamScope

RegisterArgumentCompleter -CommandName "Clear-Variable" -ParameterName "Scope" -ScriptBlock $Completion_VariableScope
RegisterArgumentCompleter -CommandName "Get-Variable" -ParameterName "Scope" -ScriptBlock $Completion_VariableScope
RegisterArgumentCompleter -CommandName "New-Variable" -ParameterName "Scope" -ScriptBlock $Completion_VariableScope
RegisterArgumentCompleter -CommandName "Remove-Variable" -ParameterName "Scope" -ScriptBlock $Completion_VariableScope
RegisterArgumentCompleter -CommandName "Set-Variable" -ParameterName "Scope" -ScriptBlock $Completion_VariableScope