Search code examples
bashpowershellrustclap

How to eval program output in PowerShell


I've written a command line utility in Rust, with argument completion provided by the clap_complete crate. This generates Bash and PowerShell completion scripts:

$ ex --completion=bash
_ex() {
    local i cur prev opts cmd
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    cmd=""
    opts=""
...
$ ex --completion=ps
using namespace System.Management.Automation
using namespace System.Management.Automation.Language

Register-ArgumentCompleter -Native -CommandName 'ex' -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)
...

I can support argument completion in new interactive Bash sessions by updating my .bashrc file with this line, which uses process substitution to evaluate the command output:

source <(ex --completion=bash)

How can I do the same thing in PowerShell? I've done a lot of Googling, and found plenty of pages describing how to call external scripts, such as with the Invoke-Expression cmdlet, but nothing that tells me how to eval the output of external scripts.


Solution

  • Invoke-Expression doesn't call a script, it evaluates a string. So the first step is to evaluate, which is basically the same as in bash.

    ex --completion=ps
    

    If this was one line, this would be a string, but it's multiple lines, so this returns an array of strings. You need to join them. Out-String is one way of doing that.

    ex --completion=ps | Out-String
    

    This can be fed into Invoke-Expression.

    ex --completion=ps | Out-String | Invoke-Expression
    

    You can put this line in your powershell profile.