Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Subcommand and flag autocompletion support (bash + zsh) #58

Merged
merged 8 commits into from
Jul 17, 2017

Conversation

mitchellh
Copy link
Owner

@mitchellh mitchellh commented Jul 17, 2017

This is 100% backwards compatible. The only BC note would be: any application using NewCLI will now get Autocompletion enabled automatically. This should result in no notice-able behavior change other than a couple flags being introduced since autocompletion requires "installation" (see below) before any behavior changes.

This adds support for bash and zsh autocompletion of subcommands, flags, and arguments.

The value of autocompletion can be specified via Go callbacks. No need to write any bash.

Under the covers, this PR uses the fantastic and full-featured complete library. However, knowledge of this library is not required to use the cli lib or to get basic subcommand autocompletion. For more complex autocompletion, integration is required but is built right-in to the CLI lib.

Enabling Autocompletion

Autocompletion is opt-in. Users of the CLI lib only need to set Autocomplete to true:

runner := &cli.Cli{
  Commands: ...,

  Autocomplete: true,
}

🎉 With that, subcommand autocompletion automatically happens.

Autocompletion Install/Uninstall

After autocompletion is enabled, the global flags -autocomplete-install and -autocomplete-uninstall are added. When these are present they install or uninstall the autocompletion handler for your shell, respectively. After installation, the shell must be restarted for autocompletion to take effect.

$ terraform -autocomplete-install
...

Subcommand Autocompletion

Subcommand autocompletion comes for free. No additional code required.

Terraform example, assume a tab is typed at the end of each prompt line:

$ terraform f
fmt           force-unlock

$ terraform state p
pull  push

Argument and Flag Autocompletion

Commands may implement the optional CommandAutocomplete interface. This interface allows a command to return autocompletion code for arguments and flags. This allows complex integrations. For example, Nomad uses UUIDs for referencing almost anything and argument autocompletion would look like the following:

$ nomad job-status a
a421c15           afc514d

Or continuing Terraform examples, imagine the -target flag:

$ terraform apply -target a
aws_resource.foo           aws_resource.bar

autocomplete.go Outdated
"github.com/posener/complete/cmd/install"
)

// autocompleteInstaller is an interface to be implemented to peform the
Copy link

Choose a reason for hiding this comment

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

peform -> perform

cli.go Outdated
// If both install and uninstall flags are specified, then error
if c.isAutocompleteInstall && c.isAutocompleteUninstall {
// TODO: Write error message
return 1, nil
Copy link

Choose a reason for hiding this comment

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

Probably should get the error in before merging.

}

// Check if it implements ComandAutocomplete. If so, setup the autocomplete
if c, ok := impl.(CommandAutocomplete); ok {
Copy link

Choose a reason for hiding this comment

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

Would it be worth having these as two interfaces so they can be implemented separately?

Copy link
Owner Author

Choose a reason for hiding this comment

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

Its unnecessary since you can easily return nil for either so I think its cleaner to have one since the "null" implementation is so easy.

cli.go Outdated
c.autocomplete = complete.New(c.Name, cmd)
}

func (c *CLI) initAutocompleteSub(prefix string) complete.Command {
Copy link

Choose a reason for hiding this comment

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

Probably worth a comment that this is a recursive call to walk all the subcommands

Copy link
Owner Author

Choose a reason for hiding this comment

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

Noted to say so.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants