Skip to content

Commit

Permalink
Fix bash completion by allowing kingpin to exit early
Browse files Browse the repository at this point in the history
  • Loading branch information
phamann committed Jun 15, 2020
1 parent 1945fd7 commit 8d6e054
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
## Quick links
- [Installation](#Installation)
- [Usage](#Usage)
- [Bash/ZSH completion](#bashzsh-shell-completion)
- [Development](#Development)
- [Issues](#Issues)

Expand Down Expand Up @@ -102,6 +103,23 @@ Succinct help about any command or subcommand is available via the `-h, --help`
flag. Verbose help about any command or subcommand is available via the help
argument, e.g. `fastly help service`.

## Bash/ZSH Shell Completion
The CLI can generate completions for all commands, subcommands and flags.

By specifying `--completion-bash` as the first argument, the CLI will show possible subcommands. By ending your argv with `--`, hints for flags will be shown.

### Installation by bash_profile

To install the completions source them in your `bash_profile` (or equivalent):
```
eval "$(fastly --completion-script-bash)"
```

Or for ZSH in your `zshrc`:
```
eval "$(fastly --completion-script-zsh)"
```

## Development

The Fastly CLI requires [Go 1.13 or above](https://golang.org). Clone this repo
Expand Down
28 changes: 27 additions & 1 deletion pkg/app/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"io/ioutil"
"os"
"regexp"
"time"

"github.com/fastly/cli/pkg/api"
Expand Down Expand Up @@ -53,6 +54,10 @@ import (
"gopkg.in/alecthomas/kingpin.v3-unstable"
)

var (
completionRegExp = regexp.MustCompile("completion-(?:script-)?(?:bash|zsh)$")
)

// Run constructs the application including all of the subcommands, parses the
// args, invokes the client factory with the token to create a Fastly API
// client, and executes the chosen command, using the provided io.Reader and
Expand All @@ -77,13 +82,22 @@ func Run(args []string, env config.Environment, file config.File, configFilePath
// bindings, because we need to do things like track where a config
// parameter came from.
app := kingpin.New("fastly", "A tool to interact with the Fastly API")
app.Terminate(nil) // don't let kingpin call os.Exit
app.Writers(out, ioutil.Discard) // don't let kingpin write error output
app.UsageContext(&kingpin.UsageContext{
Template: VerboseUsageTemplate,
Funcs: UsageTemplateFuncs,
})

// Prevent kingpin from calling os.Exit, this gives us greater control over
// error states and output contorl flow.
app.Terminate(nil)

// As kingpin generates bash completion as a side-effect of kingpin.Parse we
// allow it to call os.Exit, only if a completetion flag is present.
if isCompletion(args) {
app.Terminate(os.Exit)
}

// WARNING: kingping has no way of decorating flags as being "global"
// therefore if you add/remove a global flag you will also need to update
// the globalFlag map in pkg/app/usage.go which is used for usage rendering.
Expand Down Expand Up @@ -678,3 +692,15 @@ func argsIsHelpJSON(args []string) bool {
args[1] == "--format" &&
args[2] == "json")
}

// isCompletion determines whether the supplied command arguments are for
// bash/zsh completion output.
func isCompletion(args []string) bool {
var found bool
for _, arg := range args {
if completionRegExp.MatchString(arg) {
found = true
}
}
return found
}

0 comments on commit 8d6e054

Please sign in to comment.