Giter Club home page Giter Club logo

powershell-argcomplete-mwe's Introduction

PowerShell with argcomplete

Introduction

argcomplete is a great Python package for tab completion, however, it only works with bash as your shell (and with zsh, fish and tcsh with limited support). PowerShell has also a great command-line interface, but the argcomplete-based applications cannot use its tab completion functionality.

This project provides a straightforward solution how to use argcomplete tab completion functionality in PowerShell.

Content

  • psamwe.py Example script with argcomplete.
  • psamwe.complete.ps1 Script to register psamwe command for tab completion.
  • psamwe.complete.psm1 Module to register psamwe command for tab completion.

How to use the example?

  • Start a new PowerShell window.
  • Clone this project.
  • Create and activate your Python virtual environment as you like.
  • Enter into this project's directory (cd powershell-argcomplete-mwe)
  • pip install --editable .
  • Activate PowerShell tab completion with either of the scripts:
    • Dot-sourcing: . .\psamwe.complete.ps1
    • Import module: Import-Module .\psamwe.complete.psm1
  • Type psamwe
  • Play with Tab or Ctrl+Space auto-completion of psamwe

Background

Register-ArgumentCompleter (link) "registers a custom argument completer. An argument completer allows you to provide dynamic tab completion, at run time for any command that you specify." The main idea is that using this cmdlete we register a script to complete arguments of an alias function which wraps the original command:

  1. A PowerShell function is defined which is a simple alias of the original command:
$PsamwePythonCommand = "&'python .\psamwe.py'"
$PsamweCommandAlias = "psamwe"

Function psamwe {
    Invoke-Expression "$PsamwePythonCommand $args"
}
  1. Using Register-ArgumentCompleter, the command alias is registered for argument completion:
Register-ArgumentCompleter -Native -CommandName $PsamweCommandAlias -ScriptBlock $PsamweArgCompleteScriptBlock

$PsamweArgCompleteScriptBlock script block is called by activating argument completion (by pressing Tab or Ctrl+Space)

  1. $PsamweArgCompleteScriptBlock script block mimics bash by setting up special environment variables on a similiar way:
New-Item -Path Env: -Name _ARGCOMPLETE -Value 1 | Out-Null # Enables tab completion in argcomplete
New-Item -Path Env: -Name COMP_TYPE -Value 9 | Out-Null # Constant
New-Item -Path Env: -Name _ARGCOMPLETE_IFS -Value " " | Out-Null # Separator of the items
New-Item -Path Env: -Name _ARGCOMPLETE_SUPPRESS_SPACE -Value 1 | Out-Null # Constant
New-Item -Path Env: -Name _ARGCOMPLETE_COMP_WORDBREAKS -Value "" | Out-Null # Constant
New-Item -Path Env: -Name COMP_POINT -Value $cursorPosition | Out-Null # Refers to the last character of the current line
New-Item -Path Env: -Name COMP_LINE -Value $line | Out-Null # Current line

argcomplete uses these variables as input to determine the completion suggestions.

  1. argcomplete writes the result into an output stream. Per default, it uses file descriptor 8 which is not supported by Powershell. Instead, psamwe.py scripts changes the output stream to stdout. However, this change would break the bash experience. Therefore, a new environment variable has been introduced to specify that the completion is triggered by PowerShell:
New-Item -Path Env: -Name _ARGCOMPLETE_POWERSHELL -Value 1 | Out-Null

This environment variable is used in psamwe.py:

output_stream = None
if "_ARGCOMPLETE_POWERSHELL" in os.environ:
    output_stream = codecs.getwriter("utf-8")(sys.stdout.buffer)
argcomplete.autocomplete(parser, output_stream=output_stream)
  1. Finally, the script just executes the original command. Due to the set environment variables, argcomplete will execute the autocomplete function and writes the result back to stdout which is redirected into a variable. Splitting this result into separated lines are the results of argument completion which are presented by the command-line window to the user:
Invoke-Expression $PsamwePythonCommand -OutVariable completionResult -ErrorVariable errorOut -ErrorAction SilentlyContinue | Out-Null
...
$items = $completionResult.Split()
if ($items -eq $completionResult) {
    "$items "
}
else {
    $items
}
  1. There are a few minor tricks in the pre- and post-processing parts to mimic the bash experience as much as possible. These can be freely modified to adapt the behaviour to specific needs.

powershell-argcomplete-mwe's People

Contributors

tibortakacs avatar

Forkers

god-damnit-all

powershell-argcomplete-mwe's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.