Skip to content

Instantly share code, notes, and snippets.

@JKamsker
Created July 30, 2023 23:20
Show Gist options
  • Save JKamsker/f31428a9ad8a181fd961314254c834a5 to your computer and use it in GitHub Desktop.
Save JKamsker/f31428a9ad8a181fd961314254c834a5 to your computer and use it in GitHub Desktop.
AutoComplete Ideas
$script:process = $null
$script:path = "C:\Users\W31rd0\source\repos\work\Apro\Apro.AutoUpdater\ApGet\bin\Debug\net6.0\ApGet.exe"
$script:logPath = "C:\Users\W31rd0\Downloads\tmp\gpt\log.log"
$script:useCompletionServer = $false
function Invoke-ApGet {
# call external debugger
return & $script:path $args
}
function Invoke-StartServer {
# if not useCompletionServer return
if (-not $script:useCompletionServer) {
return
}
$shouldStart = $script:process -eq $null -or $script:process.HasExited
if (-not $shouldStart) {
return
}
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = $script:path
$startInfo.RedirectStandardInput = $true
$startInfo.RedirectStandardOutput = $true
$startInfo.UseShellExecute = $false
# $startInfo.ArgumentList = @("cli", "complete", "--server", "--format", "json")
$startArgs = @("cli", "complete", "--server", "--format", "json") -join ' '
$startInfo.Arguments = $startArgs
$script:process = New-Object System.Diagnostics.Process
$script:process.StartInfo = $startInfo
try {
$script:process.Start() | Out-Null
}
catch {
Write-Error "Failed to start the process: $_"
return
}
}
function Invoke-Initialization {
Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
if ($null -ne $script:process -and -not $script:process.HasExited) {
$script:process.StandardInput.WriteLine("exit") # This might need to change depending on how to close your program
$script:process.WaitForExit()
"Process exiting" | Out-File -FilePath $script:logPath -Append
}
} | Out-Null
Register-CompleterFor -name "ApGet"
Register-CompleterFor -name "apget"
Register-CompleterFor -name "Invoke-ApGet"
}
function Invoke-Completer {
param (
[Parameter(Mandatory = $true)] $wordToComplete,
[Parameter(Mandatory = $true)] $cursorPosition
)
if ($script:useCompletionServer) {
Invoke-StartServer
if ($script:process -eq $null -or $script:process.HasExited) {
Invoke-Initialization
}
if ($script:process -eq $null) {
Write-Error "Process is not running"
return
}
$stringWords = "$wordToComplete";
$command = @{"command" = $stringWords; "cursorPosition" = $cursorPosition } | ConvertTo-Json -Compress
$script:process.StandardInput.WriteLine($command)
$completionsJsonRaw = $script:process.StandardOutput.ReadLine()
$completions = $completionsJsonRaw | ConvertFrom-Json
return $completions
} else {
$completions = Invoke-ApGet cli complete --position $cursorPosition "$wordToComplete"
return $completions
}
}
# Register-CompleterFor -CommandName ApGet
function Register-CompleterFor {
#appname parameter
param(
[Parameter(Mandatory = $true)]
[string]$name
)
Register-ArgumentCompleter -Native -CommandName $name -ScriptBlock {
param($commandName, $wordToComplete, $cursorPosition)
$completions = @()
# $completions = & "C:\Users\W31rd0\source\repos\work\Apro\Apro.AutoUpdater\ApGet\bin\Debug\net6.0\ApGet.exe" cli complete --position $cursorPosition "$wordToComplete"
# $completionsJsonRaw = Invoke-CompletionRequest --command "$wordToComplete" --position $cursorPosition # returns json string array ["command", "command", ...]
$completions = Invoke-Completer -wordToComplete $wordToComplete -cursorPosition $cursorPosition
if ($completions) {
foreach ($completion in $completions) {
if ($completion -is [string]) {
[System.Management.Automation.CompletionResult]::new($completion, $completion, 'ParameterValue', $completion)
}
else {
$description = $completion.description
if ($description -eq $null) {
$description = $completion.value
}
[System.Management.Automation.CompletionResult]::new($completion.value, $completion.value, 'ParameterValue', $description)
}
}
}
else {
$null
}
}
}
Invoke-Initialization
@JKamsker
Copy link
Author

JKamsker commented Jul 31, 2023

Old:

$script:process = $null
function Invoke-ApGet {
    # call external debugger


    return & "C:\Users\W31rd0\source\repos\work\Apro\Apro.AutoUpdater\ApGet\bin\Debug\net6.0\ApGet.exe" $args
}

# Register-CompleterFor -CommandName ApGet
function Register-CompleterFor {
    #appname parameter
    param(
        [Parameter(Mandatory = $true)]
        [string]$name
    )

    Register-ArgumentCompleter -Native -CommandName $name -ScriptBlock {
        param($commandName, $wordToComplete, $cursorPosition)
        $completions = @()
        # $completions = & "C:\Users\W31rd0\source\repos\work\Apro\Apro.AutoUpdater\ApGet\bin\Debug\net6.0\ApGet.exe" cli complete --position $cursorPosition "$wordToComplete"
        $completionsJsonRaw = Invoke-CompletionRequest --position $cursorPosition --command "$wordToComplete" # returns json string array ["command", "command", ...]
        $completions = $completionsJsonRaw | ConvertFrom-Json
        
        if ($completions) {
            foreach ($completion in $completions) {
                [System.Management.Automation.CompletionResult]::new($completion, $completion, 'ParameterValue', $completion)
            }
        }
        else {
            $null
        }
    }
}

function Start-Program {
    $startInfo = New-Object System.Diagnostics.ProcessStartInfo
    $startInfo.FileName = "C:\Users\W31rd0\source\repos\work\Apro\Apro.AutoUpdater\ApGet\bin\Debug\net6.0\ApGet.exe"
    $startInfo.RedirectStandardInput = $true
    $startInfo.RedirectStandardOutput = $true
    $startInfo.UseShellExecute = $false
    # $startInfo.ArgumentList = @("cli", "complete", "--server", "--format", "json")
    $startArgs = @("cli", "complete", "--server", "--format", "json") -join ' '
    $startInfo.Arguments = $startArgs


    $script:process = New-Object System.Diagnostics.Process
    $script:process.StartInfo = $startInfo

    try {
        $script:process.Start() | Out-Null
    }
    catch {
        Write-Error "Failed to start the process: $_"
        return
    }

    Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
        if ($null -ne $script:process) {
            $script:process.StandardInput.WriteLine("exit") # This might need to change depending on how to close your program
            $script:process.WaitForExit()
            "Process exiting" | Out-File -FilePath "C:\Users\W31rd0\Downloads\tmp\gpt\log.log" -Append
        }
    } | Out-Null

    # Register-ArgumentCompleter -Native -CommandName 'Invoke-ApGet'

    Register-CompleterFor -name "ApGet"
    Register-CompleterFor -name "apget"

    Register-CompleterFor -name "Invoke-ApGet"

    Write-Host "Program started"
}

function Invoke-CompletionRequest {
    param(
        [Parameter(Mandatory = $true)]$command,
        [Parameter(Mandatory = $true)]$position
    )


    if ($script:process -eq $null -or $script:process.HasExited) {
        Start-Program
    }

    if ($script:process -eq $null) {
        Write-Error "Process is not running"
        return
    }

    # {"command": "cli", "position": 0}
    $command = @{"command" = $command; "position" = $position} | ConvertTo-Json -Compress

    # # join with surrounding quotes
    # $command = @($args) -join '" "'
    # $command = '"{0}"' -f $command
    # # write-host "Command: $command"
    $script:process.StandardInput.WriteLine($command) # returns json string array ["command", "command", ...]

    return $script:process.StandardOutput.ReadLine()
}

# Start-Program

Export-ModuleMember -Function Invoke-ApGet
Export-ModuleMember -Function Invoke-CompletionRequest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment