Skip to content

{Core} Proof of concept for PowerShell argument completion#13576

Draft
tibortakacs wants to merge 2 commits intoAzure:devfrom
tibortakacs:poc_powershell_argcomplete
Draft

{Core} Proof of concept for PowerShell argument completion#13576
tibortakacs wants to merge 2 commits intoAzure:devfrom
tibortakacs:poc_powershell_argcomplete

Conversation

@tibortakacs
Copy link
Copy Markdown

@tibortakacs tibortakacs commented May 19, 2020

Resolve #2324

Require kislyuk/argcomplete#302

This is a proof of concept implementation of Azure CLI argument completion in PowerShell.

Not ready to be merged.

It is based on this approach, please find the details there:
https://github.com/tibortakacs/powershell-argcomplete

How to use:

  • Install Azure CLI on the normal way.
  • . az.completion.ps1 (Dot source the completion script).
  • Use tab or ctrl+space to invoke argument completion on PowerShell.

@yonzhan yonzhan requested a review from fengzhou-msft May 20, 2020 00:00
@yonzhan yonzhan added this to the S171 milestone May 20, 2020
@yonzhan
Copy link
Copy Markdown
Collaborator

yonzhan commented May 20, 2020

Nice PoC to support PowerShell argument completion

@yonzhan yonzhan requested review from arrownj and haroldrandom May 20, 2020 00:00
@jiasli
Copy link
Copy Markdown
Member

jiasli commented May 20, 2020

+ Azure PowerShell owner of auto-complete @isra-fel

@jiasli
Copy link
Copy Markdown
Member

jiasli commented May 20, 2020

FYI, this is the corresponding Bash script to enable auto-complete using argcomplete:

$ register-python-argcomplete az

# Run something, muting output or redirecting it to the debug stream
# depending on the value of _ARC_DEBUG.
__python_argcomplete_run() {
    if [[ -z "$_ARC_DEBUG" ]]; then
        "$@" 8>&1 9>&2 1>/dev/null 2>&1
    else
        "$@" 8>&1 9>&2 1>&9 2>&1
    fi
}

_python_argcomplete() {
    local IFS=$'\013'
    local SUPPRESS_SPACE=0
    if compopt +o nospace 2> /dev/null; then
        SUPPRESS_SPACE=1
    fi
    COMPREPLY=( $(IFS="$IFS" \
                  COMP_LINE="$COMP_LINE" \
                  COMP_POINT="$COMP_POINT" \
                  COMP_TYPE="$COMP_TYPE" \
                  _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" \
                  _ARGCOMPLETE=1 \
                  _ARGCOMPLETE_SUPPRESS_SPACE=$SUPPRESS_SPACE \
                  __python_argcomplete_run "$1") )
    if [[ $? != 0 ]]; then
        unset COMPREPLY
    elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "$COMPREPLY" =~ [=/:]$ ]]; then
        compopt -o nospace
    fi
}
complete -o nospace -o default -o bashdefault -F _python_argcomplete az

@isra-fel
Copy link
Copy Markdown
Member

An idea about how to enable autocomplete on startup: we can tell the user to add a line to their powershell profile, to be specific:

  1. Edit $PROFILE (this is a powershell variable that points to the actual url of the profile file), append a line: . az.completion.ps1

And I think a more official(pro) way is to publish this as a powershell module for example AzCliUtil, and expose this function as a cmdlet such as "Enable-AzCliAutoComplete". In this case customers will need to:

  1. Install-Module AzCliUtil
  2. Edit $PROFILE, append a line Enable-AzCliAutoComplete

# If there is only one completion item, it will be immediately used. In this case
# a trailing space is important to show the user that the complition for the current
# item is ready.
$items = $completionResult.Split()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Invoke-Expression failed, $completionResult will not have a Split() method and will error out.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid point. However, PowerShell argument completion engine hides all error, but you are right, it is better to cause any unexpected error. I have added a simple check there.

@jiasli jiasli modified the milestones: S171, Backlog May 20, 2020
@jiasli jiasli changed the title Proof of concept for PowerShell argument completion. {Core} Proof of concept for PowerShell argument completion May 20, 2020
* Only do Split if there were any result.
* Invoke-Expression exits from the script block in case of error. This
commit suppresses this with an empty try-catch block.
@itpropro
Copy link
Copy Markdown

Hi,
Any updates on this issue/PR?

# Since the environment variables are set, the argcomplete.autocomplete(...) function will be executed.
# The result will be printed on the standard output (see the details in the Python file).
try {
Invoke-Expression $AzCommand -OutVariable completionResult -ErrorVariable errorOut -ErrorAction SilentlyContinue | Out-Null
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no need to use Invoke-Expression here, instead, you should use:

Suggested change
Invoke-Expression $AzCommand -OutVariable completionResult -ErrorVariable errorOut -ErrorAction SilentlyContinue | Out-Null
$completionResult = & $AzCommand

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is no longer applicable with the larger comment above, but leaving here as informing when not to use Invoke-Expression

Copy link
Copy Markdown

@SteveL-MSFT SteveL-MSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very interesting approach, some rework on the PowerShell side of things

}

# Mock bash with environment variable settings
New-Item -Path Env: -Name _ARGCOMPLETE -Value 1 | Out-Null # Enables tab complition in argcomplete
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very creative approach using the bash completer, however, since these env vars are for the process and gets inherited by az and then removed, it would be better to use .NET API to start the process and leveraging https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.environmentvariables?view=net-6.0#system-diagnostics-processstartinfo-environmentvariables

It would look something like:

$env = @{
  _ARGCOMPLETE = 1
  COMP_TYPE = 9
  _ARGCOMPLETE_IFS = " "
}

$psi = [System.Diagnostics.ProcessStartInfo]::new($AzCommand)
$psi.RedirectStandardError = $true
$psi.RedirectStandardOutput = $true

foreach ($var in $env.keys) {
  $psi.Environment.Add($var, $env.$var)
}

$az = [System.Diagnostics.Process]::Start($psi)
$az.Start()
$az.WaitForExit()
$completionResult = $az.StandardOutput.ReadToEnd()

# Since the environment variables are set, the argcomplete.autocomplete(...) function will be executed.
# The result will be printed on the standard output (see the details in the Python file).
try {
Invoke-Expression $AzCommand -OutVariable completionResult -ErrorVariable errorOut -ErrorAction SilentlyContinue | Out-Null
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is no longer applicable with the larger comment above, but leaving here as informing when not to use Invoke-Expression

@@ -0,0 +1,67 @@
$AzCommand = "az"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole script should probably be in a Enable-AzCompletion cmdlet and shouldn't be repeated in both a ps1 and psm1

@mgreenegit
Copy link
Copy Markdown
Member

Thank you for this contribution @tibortakacs. Please see the feedback above.

@yonzhan yonzhan requested review from bebound and removed request for arrownj and haroldrandom May 24, 2022 03:07
@mgreenegit
Copy link
Copy Markdown
Member

Following up @tibortakacs
Thank you!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support autocompletion in command line PowerShell console.

8 participants