Skip to content

Commit

Permalink
Re-organize completion documentation (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoshsadiq committed Jan 3, 2023
1 parent ea5fcb0 commit ff91ef2
Show file tree
Hide file tree
Showing 14 changed files with 267 additions and 288 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![](https://img.shields.io/github/workflow/status/zulucmd/zulu/Test?longCache=tru&label=Test&logo=github%20actions&logoColor=fff)](https://github.com/zulucmd/zulu/actions?query=workflow%3ATest)
[![Test](https://github.com/zulucmd/zulu/actions/workflows/test.yml/badge.svg)](https://github.com/zulucmd/zulu/actions/workflows/test.yml)
[![Go Reference](https://pkg.go.dev/badge/github.com/zulucmd/zulu.svg)](https://pkg.go.dev/github.com/zulucmd/zulu)
[![Go Report Card](https://goreportcard.com/badge/github.com/zulucmd/zulu)](https://goreportcard.com/report/github.com/zulucmd/zulu)

Expand Down
2 changes: 1 addition & 1 deletion completions.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDi
finalCmd.adjustByFlagGroupsForCompletions()

// Note that we want to perform flagname completion even if finalCmd.DisableFlagParsing==true;
// doing this allows for completion of persistant flag names even for commands that disable flag parsing.
// doing this allows for completion of persistent flag names even for commands that disable flag parsing.
//
// When doing completion of a flag name, as soon as an argument starts with
// a '-' we know it is a flag. We cannot use isFlagArg() here as it requires
Expand Down
119 changes: 119 additions & 0 deletions example_hooks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package zulu_test

import (
"fmt"

"github.com/zulucmd/zulu"
)

func ExampleHookFuncE() {
var rootCmd = &zulu.Command{
Use: "root [sub]",
Short: "My root command",
PersistentInitializeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd PersistentInitializeE with args: %v\n", args)
return nil
},
InitializeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd InitializeE with args: %v\n", args)
return nil
},
PersistentPreRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd PersistentPreRunE with args: %v\n", args)
return nil
},
PreRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd PreRunE with args: %v\n", args)
return nil
},
RunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd RunE with args: %v\n", args)
return nil
},
PostRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd PostRunE with args: %v\n", args)
return nil
},
PersistentPostRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd PersistentPostRunE with args: %v\n", args)
return nil
},
FinalizeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd FinalizeE with args: %v\n", args)
return nil
},
PersistentFinalizeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside rootCmd PersistentFinalizeE with args: %v\n", args)
return nil
},
}

var subCmd = &zulu.Command{
Use: "sub [no options!]",
Short: "My subcommand",
PersistentInitializeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd PersistentInitializeE with args: %v\n", args)
return nil
},
InitializeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd InitializeE with args: %v\n", args)
return nil
},
PreRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd PreRunE with args: %v\n", args)
return nil
},
RunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd RunE with args: %v\n", args)
return nil
},
PostRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd PostRunE with args: %v\n", args)
return nil
},
PersistentPostRunE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd PersistentPostRunE with args: %v\n", args)
return nil
},
FinalizeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd FinalizeE with args: %v\n", args)
return nil
},
PersistentFinalizeE: func(cmd *zulu.Command, args []string) error {
fmt.Printf("Inside subCmd PersistentFinalizeE with args: %v\n", args)
return nil
},
}

rootCmd.AddCommand(subCmd)

rootCmd.SetArgs([]string{""})
_ = rootCmd.Execute()
fmt.Println()
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
_ = rootCmd.Execute()

// Output:
// Inside rootCmd PersistentInitializeE with args: []
// Inside rootCmd InitializeE with args: []
// Inside rootCmd PersistentPreRunE with args: []
// Inside rootCmd PreRunE with args: []
// Inside rootCmd RunE with args: []
// Inside rootCmd PostRunE with args: []
// Inside rootCmd PersistentPostRunE with args: []
// Inside rootCmd FinalizeE with args: []
// Inside rootCmd PersistentFinalizeE with args: []
//
// Inside subCmd PersistentInitializeE with args: []
// Inside rootCmd PersistentInitializeE with args: []
// Inside subCmd InitializeE with args: []
// Inside rootCmd PersistentPreRunE with args: [arg1 arg2]
// Inside subCmd PreRunE with args: [arg1 arg2]
// Inside subCmd RunE with args: [arg1 arg2]
// Inside subCmd PostRunE with args: [arg1 arg2]
// Inside subCmd PersistentPostRunE with args: [arg1 arg2]
// Inside rootCmd PersistentPostRunE with args: [arg1 arg2]
// Inside subCmd FinalizeE with args: [arg1 arg2]
// Inside subCmd PersistentFinalizeE with args: [arg1 arg2]
// Inside rootCmd PersistentFinalizeE with args: [arg1 arg2]
}
7 changes: 4 additions & 3 deletions site/content/cobra_differences.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ weight: 30

Zulu is a fork of [spf13/cobra](https://github.com/spf13/cobra). Notable differences between Cobra and Zulu are:

- Replaced [pflag](https://github.com/spf13/pflag) with [zflag](https://github.com/zulucmd/zflag).
- Zulu has no support for [Viper](https://github.com/spf13/viper). Viper only works with [spf13/pflag](https://github.com/spf13/viper), which forked into [zflag](https://github.com/zulucmd/zflag), in use by zulu. Instead, you can use [koanf-zflag](https://github.com/zulucmd/koanf-zflag) package to utilise [knadh/koanf](https://github.com/knadh/koanf).
- Replaced [spf13/pflag](https://github.com/spf13/pflag) with [zulucmd/zflag](https://github.com/zulucmd/zflag).
- Zulu has no support for [Viper](https://github.com/spf13/viper). Viper only works with [spf13/pflag](https://github.com/spf13/viper), which was forked into [zflag](https://github.com/zulucmd/zflag), in use by zulu. Instead, you can use [koanf-zflag](https://github.com/zulucmd/koanf-zflag) package to utilise [knadh/koanf](https://github.com/knadh/koanf).
- Removed all the `*Run` hooks, in favour of `*RunE` hooks. This just simplifies things and avoids duplicated code.
- Added hooks for `InitializeE` and `FinalizeE`.
- Added new `On*` hooks.
Expand All @@ -16,5 +16,6 @@ Zulu is a fork of [spf13/cobra](https://github.com/spf13/cobra). Notable differe
- Added support for grouped commands.
- Removed the legacy bash completions.
- Improved support flags with optional values.
- Removed many old code that was there for backwards compatibility reasons.

Note the above list is not exhaustive, and many of the PRs were merged in from unclosed PRs in the Cobra repo (see the Git log for a link to the original PR).
Note the above list is not exhaustive, and many of the PRs were merged in from unclosed PRs in the Cobra repo. For a full list of changes see [Git history](https://github.com/zulucmd/zulu/compare/e04ec72...main).
1 change: 1 addition & 0 deletions site/content/code/example_hooks_test.go
34 changes: 33 additions & 1 deletion site/content/completions/bash.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,36 @@ weight: 110

## Bash

Please refer to [Shell Completions](_index.md) for details.
Bash completion can be used by calling `command.GenBashCompletion()` or `command.GenBashCompletionFile()`.
It supports descriptions for completions. When calling the functions you must provide it with a parameter indicating if the completions should be annotated with a description; Zulu
will provide the description automatically based on usage information. You can choose to make this option configurable by your users.

```
# With descriptions
$ helm s[tab][tab]
search (search for a keyword in charts) status (display the status of the named release)
show (show information of a chart)
# Without descriptions
$ helm s[tab][tab]
search show status
```

### Dependencies

The bash completion script generated by Zulu requires the `bash_completion` package. You should update the help text of your completion command to show how to install the `bash_completion` package ([Kubectl docs](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion))

### Aliases

You can also configure `bash` aliases for your program and they will also support completions.

```bash
alias aliasname=origcommand
complete -o default -F __start_origcommand aliasname

# and now when you run `aliasname` completion will make
# suggestions as it did for `origcommand`.

$ aliasname <tab><tab>
completion firstcommand secondcommand
```
153 changes: 8 additions & 145 deletions site/content/completions/completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ The currently supported shells are:
- fish
- PowerShell

Zulu will automatically provide your program with a fully functional `completion` command,
Zulu will automatically provide your program with a fully functional `completion` sub-command,
similarly to how it provides the `help` command.

## Default completion command
Zulu's completion scripts provide the following features:
- Supports completion descriptions (like the other shells).
- Small completion script of less than 300 lines.
- Streamlined user experience thanks to a completion behavior aligned with the other shells.

## Default completion sub-command

Zulu provides a few options for the default `completion` command. To configure such options you must set
the `CompletionOptions` field on the *root* command.
Expand Down Expand Up @@ -284,8 +289,7 @@ cmd.RegisterFlagCompletionFunc(flagName, func(cmd *zulu.Command, args []string,
```
#### Descriptions for completions
Zulu provides support for completion descriptions. Such descriptions are supported for each shell
(however, for bash, it is only available in the [completion V2 version](#bash-completion-v2)).
Zulu provides support for completion descriptions. Such descriptions are supported for each shell.
For commands and flags, Zulu will provide the descriptions automatically, based on usage information.
For example, using zsh:
```
Expand All @@ -310,144 +314,3 @@ or
```go
ValidArgs: []string{"bash\tCompletions for bash", "zsh\tCompletions for zsh"}
```
### Bash

#### Dependencies

The bash completion script generated by Zulu requires the `bash_completion` package. You should update the help text of your completion command to show how to install the `bash_completion` package ([Kubectl docs](https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion))

#### Aliases

You can also configure `bash` aliases for your program and they will also support completions.

```bash
alias aliasname=origcommand
complete -o default -F __start_origcommand aliasname

# and now when you run `aliasname` completion will make
# suggestions as it did for `origcommand`.

$ aliasname <tab><tab>
completion firstcommand secondcommand
```
#### Bash

Bash completion is also available. This can be used by calling `GenBashCompletion()` or
`GenBashCompletionFile()`.

Bash completions provides the following features:
- Supports completion descriptions (like the other shells).
- Small completion script of less than 300 lines.
- Streamlined user experience thanks to a completion behavior aligned with the other shells.

`Bash` completion supports descriptions for completions. When calling `GenBashCompletion()` or `GenBashCompletionFile()`
you must provide these functions with a parameter indicating if the completions should be annotated with a description; Zulu
will provide the description automatically based on usage information. You can choose to make this option configurable by
your users.

```
# With descriptions
$ helm s[tab][tab]
search (search for a keyword in charts) status (display the status of the named release)
show (show information of a chart)
# Without descriptions
$ helm s[tab][tab]
search show status
```

### Zsh

Zulu supports native zsh completion generated from the root `zulu.Command`.
The generated completion script should be put somewhere in your `$fpath` and be named
`_<yourProgram>`. You will need to start a new shell for the completions to become available.

Zsh supports descriptions for completions. Zulu will provide the description automatically,
based on usage information. Zulu provides a way to completely disable such descriptions by
using `GenZshCompletionNoDesc()` or `GenZshCompletionFileNoDesc()`. You can choose to make
this a configurable option to your users.
```
# With descriptions
$ helm s[tab]
search -- search for a keyword in charts
show -- show information of a chart
status -- displays the status of the named release
# Without descriptions
$ helm s[tab]
search show status
```
*Note*: Because of backward-compatibility requirements, we were forced to have a different API to disable completion descriptions between `zsh` and `fish`.

#### Zsh completions standardization

Zulu 1.1 standardized its zsh completion support to align it with its other shell completions. Although the API was kept backward-compatible, some small changes in behavior were introduced.
Please refer to [Zsh Completions](zsh.md) for details.

## Fish

Zulu supports native fish completions generated from the root `zulu.Command`. You can use the `command.GenFishCompletion()` or `command.GenFishCompletionFile()` functions. You must provide these functions with a parameter indicating if the completions should be annotated with a description; Zulu will provide the description automatically based on usage information. You can choose to make this option configurable by your users.
```
# With descriptions
$ helm s[tab]
search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release)
# Without descriptions
$ helm s[tab]
search show status
```
*Note*: Because of backward-compatibility requirements, we were forced to have a different API to disable completion descriptions between `zsh` and `fish`.

#### Limitations

* The following flag completion annotations are not supported and will be ignored for `fish`:
* `BashCompFilenameExt` (filtering by file extension)
* `BashCompSubdirsInDir` (filtering by directory)
* The functions corresponding to the above annotations are consequently not supported and will be ignored for `fish`:
* `FlagOptFilename()` (filtering by file extension)
* `FlagOptDirname()` (filtering by directory)
* Similarly, the following completion directives are not supported and will be ignored for `fish`:
* `ShellCompDirectiveFilterFileExt` (filtering by file extension)
* `ShellCompDirectiveFilterDirs` (filtering by directory)

### PowerShell

Zulu supports native PowerShell completions generated from the root `zulu.Command`. You can use the `command.GenPowerShellCompletion()` or `command.GenPowerShellCompletionFile()` functions. To include descriptions use `command.GenPowerShellCompletionWithDesc()` and `command.GenPowerShellCompletionFileWithDesc()`. Zulu will provide the description automatically based on usage information. You can choose to make this option configurable by your users.

The script is designed to support all three PowerShell completion modes:

* TabCompleteNext (default windows style - on each key press the next option is displayed)
* Complete (works like bash)
* MenuComplete (works like zsh)

You set the mode with `Set-PSReadLineKeyHandler -Key Tab -Function <mode>`. Descriptions are only displayed when using the `Complete` or `MenuComplete` mode.

Users need PowerShell version 5.0 or above, which comes with Windows 10 and can be downloaded separately for Windows 7 or 8.1. They can then write the completions to a file and source this file from their PowerShell profile, which is referenced by the `$Profile` environment variable. See `Get-Help about_Profiles` for more info about PowerShell profiles.

```
# With descriptions and Mode 'Complete'
$ helm s[tab]
search (search for a keyword in charts) show (show information of a chart) status (displays the status of the named release)
# With descriptions and Mode 'MenuComplete' The description of the current selected value will be displayed below the suggestions.
$ helm s[tab]
search show status
search for a keyword in charts
# Without descriptions
$ helm s[tab]
search show status
```

### Limitations

* The following flag completion annotations are not supported and will be ignored for `powershell`:
* `BashCompFilenameExt` (filtering by file extension)
* `BashCompSubdirsInDir` (filtering by directory)
* The functions corresponding to the above annotations are consequently not supported and will be ignored for `powershell`:
* `FlagOptFilename()` (filtering by file extension)
* `FlagOptDirname()` (filtering by directory)
* Similarly, the following completion directives are not supported and will be ignored for `powershell`:
* `ShellCompDirectiveFilterFileExt` (filtering by file extension)
* `ShellCompDirectiveFilterDirs` (filtering by directory)

0 comments on commit ff91ef2

Please sign in to comment.