Skip to content

Commit

Permalink
Merge pull request #230 from jrperritt/posh-command-completion
Browse files Browse the repository at this point in the history
posh command completion; closes #56
  • Loading branch information
rgbkrk committed Aug 5, 2015
2 parents 440face + 82b59b9 commit abe2032
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 9 deletions.
8 changes: 7 additions & 1 deletion docs/configuration.rst
Expand Up @@ -197,6 +197,13 @@ If you'd like to set up command completion yourself (or if you're on a Windows O
you can copy file in the location below to the appropriate directory and source it:
github.com/jrperritt/rack/setup/commandcompletion_bash.sh

If you are using PowerShell and want command-completion, you can run the ``commandcompletion_posh.ps1`` script in the
``setup`` directory. That script will perform normal command-completion for non-rack commands, and rack-specific
completions for ``rack`` commands. A few caveats for PowerShell users:
* The script overrides the ``global:TabExpansion2`` function.
* This should work for PowerShell versions greater than or equal to 3, but it was tested with PowerShell_ISE v4.
* You will get the normal Windows command-completion (with a circular buffer).

Check the version
-----------------

Expand Down Expand Up @@ -233,4 +240,3 @@ config file profile. In either case, the parameter name will be ``auth-url``.
.. _Linux (64 bit): https://ec4a542dbf90c03b9f75-b342aba65414ad802720b41e8159cf45.ssl.cf5.rackcdn.com/0.0.3/Linux/amd64/rack
.. _Windows (64 bit): https://ec4a542dbf90c03b9f75-b342aba65414ad802720b41e8159cf45.ssl.cf5.rackcdn.com/0.0.3/Windows/amd64/rack.exe
.. _Cloud Control panel: https://mycloud.rackspace.com/

6 changes: 4 additions & 2 deletions main.go
Expand Up @@ -3,6 +3,7 @@ package main
import (
"fmt"
"os"
"strings"

"github.com/jrperritt/rack/commands/blockstoragecommands"
"github.com/jrperritt/rack/commands/filescommands"
Expand Down Expand Up @@ -51,8 +52,9 @@ commands have been tested against Rackspace's live API.`
func Cmds() []cli.Command {
return []cli.Command{
{
Name: "init",
Usage: "[Linux/OS X only] Creates the rack man page and sets up command completion for the Bash shell.",
Name: "init",
Usage: strings.Join([]string{"For Linux and OS X, creates the `rack` man page and sets up command completion for the Bash shell.",
"\tFor Windows, creates a `posh_autocomplete.ps1` file in the `$HOME/.rack` directory. You must run the file to set up command completion."}, "\n"),
Action: func(c *cli.Context) {
setup.Init(c)
man()
Expand Down
64 changes: 64 additions & 0 deletions setup/commandcompletion_posh.ps1
@@ -0,0 +1,64 @@
function global:TabExpansion2 {
[CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')]
Param(
[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)]
[string] $inputScript,

[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 1)]
[int] $cursorColumn,

[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)]
[System.Management.Automation.Language.Ast] $ast,

[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)]
[System.Management.Automation.Language.Token[]] $tokens,

[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)]
[System.Management.Automation.Language.IScriptPosition] $positionOfCursor,

[Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)]
[Parameter(ParameterSetName = 'AstInputSet', Position = 3)]
[Hashtable] $options = $null
)

End {
$result = $null

if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet') {
$result = [System.Management.Automation.CommandCompletion]::CompleteInput(
<#inputScript#> $inputScript,
<#cursorColumn#> $cursorColumn,
<#options#> $options)
}
else{
$result = [System.Management.Automation.CommandCompletion]::CompleteInput(
<#ast#> $ast,
<#tokens#> $tokens,
<#positionOfCursor#> $positionOfCursor,
<#options#> $options)
}


if ($result.CompletionMatches.Count -eq 0){
if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet') {
$ast = [System.Management.Automation.Language.Parser]::ParseInput($inputScript, [ref]$tokens, [ref]$null)
}
$text = $ast.Extent.Text
if($text -match '^*rack.exe*') {
$cmd1 = $text -split '\s+'
$end = $cmd1.count - 2
$cmd2 = $cmd1[0..$end]
$cmd3 = $cmd2 -join ' '
$suggestions = Invoke-Expression "$cmd3 --generate-bash-completion"
ForEach($suggestion in $suggestions) {
if($suggestion -match $cmd1[$end + 1]) {
$suggestionObject = New-Object System.Management.Automation.CompletionResult ($suggestion, $suggestion, "Text", $suggestion)
$result.CompletionMatches.Add($suggestionObject)
}
}
}
}

return $result
}
}
91 changes: 85 additions & 6 deletions setup/setup.go
Expand Up @@ -44,14 +44,13 @@ complete -o default -F _cli_bash_autocomplete rack
// Init runs logic for setting up amenities such as command completion.
func Init(c *cli.Context) {
w := c.App.Writer
rackDir, err := util.RackDir()
if err != nil {
fmt.Fprintf(w, "Error running `rack init`: %s\n", err)
return
}
switch runtime.GOOS {
case "linux", "darwin":
rackDir, err := util.RackDir()
if err != nil {
fmt.Fprintf(w, "Error running `rack init`: %s\n", err)
return
}

rackCompletionPath := path.Join(rackDir, "bash_autocomplete")
rackCompletionFile, err := os.Create(rackCompletionPath)
if err != nil {
Expand Down Expand Up @@ -111,8 +110,88 @@ func Init(c *cli.Context) {
fmt.Fprintf(w, "Command completion enabled in %s\n", bashPath)
return
}
case "windows":
rackCompletionPath := path.Join(rackDir, "posh_autocomplete.ps1")
rackCompletionFile, err := os.Create(rackCompletionPath)
if err != nil {
fmt.Fprintf(w, "Error creating `rack` PowerShell completion file: %s\n", err)
return
}
_, err = rackCompletionFile.WriteString(rackPoshAutocomplete)
if err != nil {
fmt.Fprintf(w, "Error writing to `rack` PowerShell completion file: %s\n", err)
return
}
rackCompletionFile.Close()
default:
fmt.Fprintf(w, "Command completion is not currently available for %s\n", runtime.GOOS)
return
}
}

var rackPoshAutocomplete = `
function global:TabExpansion2 {
[CmdletBinding(DefaultParameterSetName = 'ScriptInputSet')]
Param(
[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 0)]
[string] $inputScript,
[Parameter(ParameterSetName = 'ScriptInputSet', Mandatory = $true, Position = 1)]
[int] $cursorColumn,
[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 0)]
[System.Management.Automation.Language.Ast] $ast,
[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 1)]
[System.Management.Automation.Language.Token[]] $tokens,
[Parameter(ParameterSetName = 'AstInputSet', Mandatory = $true, Position = 2)]
[System.Management.Automation.Language.IScriptPosition] $positionOfCursor,
[Parameter(ParameterSetName = 'ScriptInputSet', Position = 2)]
[Parameter(ParameterSetName = 'AstInputSet', Position = 3)]
[Hashtable] $options = $null
)
End {
$result = $null
if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet') {
$result = [System.Management.Automation.CommandCompletion]::CompleteInput(
<#inputScript#> $inputScript,
<#cursorColumn#> $cursorColumn,
<#options#> $options)
}
else{
$result = [System.Management.Automation.CommandCompletion]::CompleteInput(
<#ast#> $ast,
<#tokens#> $tokens,
<#positionOfCursor#> $positionOfCursor,
<#options#> $options)
}
if ($result.CompletionMatches.Count -eq 0){
if ($psCmdlet.ParameterSetName -eq 'ScriptInputSet') {
$ast = [System.Management.Automation.Language.Parser]::ParseInput($inputScript, [ref]$tokens, [ref]$null)
}
$text = $ast.Extent.Text
if($text -match '^*rack.exe*') {
$cmd1 = $text -split '\s+'
$end = $cmd1.count - 2
$cmd2 = $cmd1[0..$end]
$cmd3 = $cmd2 -join ' '
$suggestions = Invoke-Expression "$cmd3 --generate-bash-completion"
ForEach($suggestion in $suggestions) {
if($suggestion -match $cmd1[$end + 1]) {
$suggestionObject = New-Object System.Management.Automation.CompletionResult ($suggestion, $suggestion, "Text", $suggestion)
$result.CompletionMatches.Add($suggestionObject)
}
}
}
}
return $result
}
}
`

0 comments on commit abe2032

Please sign in to comment.