Skip to content

Commit

Permalink
Add option to disable completion in usage (#25)
Browse files Browse the repository at this point in the history
* Add option to disable completion in usage

For some use-cases or operation systems, it might not be desirable to print usage information. That is why this commit introduces an option to disable completion information.
This addresses issue #20

* Detect completion support automatically

* Improve env handling

* Fix formatting
  • Loading branch information
Jan authored Sep 27, 2020
1 parent 8cff9ee commit 74170b4
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 3 deletions.
8 changes: 7 additions & 1 deletion cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"

Expand Down Expand Up @@ -418,7 +419,7 @@ func (c *SubCmd) Usage() {
}
fmt.Fprintf(w, "\n")
// Print completion options only to the root command.
if c.isRoot {
if c.isRoot && detectCompletionSupport() {
fmt.Fprintln(w, completionUsage(c.name))
}
} else {
Expand Down Expand Up @@ -506,6 +507,11 @@ func copyFlagSet(cfg config, f *compflag.FlagSet) *compflag.FlagSet {
return (*compflag.FlagSet)(cp)
}

func detectCompletionSupport() bool {
shellName := strings.ToLower(filepath.Base(os.Getenv("SHELL")))
return shellName == "bash" || shellName == "fish" || shellName == "zsh"
}

func completionUsage(name string) string {
return fmt.Sprintf(`Bash Completion:
Expand Down
74 changes: 72 additions & 2 deletions cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import (
"bytes"
"flag"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"

"github.com/posener/complete/v2/predict"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

type testCmd struct {
Expand Down Expand Up @@ -145,13 +147,57 @@ func TestSubCmd(t *testing.T) {
}

func TestHelp(t *testing.T) {
t.Parallel()

tests := []struct {
shell string
args []string
want string
}{
{
shell: "/bin/bash",
args: []string{"cmd", "-h"},
want: `Usage: cmd [sub1|sub2]
cmd synopsis
testing command line example
Subcommands:
sub1 a sub command with flags and sub commands
sub2 a sub command without flags and sub commands
Bash Completion:
Install bash completion by running: 'COMP_INSTALL=1 cmd'.
Uninstall by running: 'COMP_UNINSTALL=1 cmd'.
Skip installation prompt with environment variable: 'COMP_YES=1'.
`,
},
{
shell: "/bin/fish",
args: []string{"cmd", "-h"},
want: `Usage: cmd [sub1|sub2]
cmd synopsis
testing command line example
Subcommands:
sub1 a sub command with flags and sub commands
sub2 a sub command without flags and sub commands
Bash Completion:
Install bash completion by running: 'COMP_INSTALL=1 cmd'.
Uninstall by running: 'COMP_UNINSTALL=1 cmd'.
Skip installation prompt with environment variable: 'COMP_YES=1'.
`,
},
{
shell: "/bin/zsh",
args: []string{"cmd", "-h"},
want: `Usage: cmd [sub1|sub2]
Expand All @@ -173,6 +219,23 @@ Skip installation prompt with environment variable: 'COMP_YES=1'.
`,
},
{
shell: "",
args: []string{"cmd", "-h"},
want: `Usage: cmd [sub1|sub2]
cmd synopsis
testing command line example
Subcommands:
sub1 a sub command with flags and sub commands
sub2 a sub command without flags and sub commands
`,
},
{
shell: "/bin/bash",
args: []string{"cmd", "sub1", "-h"},
want: `Usage: cmd sub1 [sub1|sub2]
Expand All @@ -193,6 +256,7 @@ Subcommands:
`,
},
{
shell: "/bin/bash",
args: []string{"cmd", "sub2", "-h"},
want: `Usage: cmd sub2 [flags] [arg]
Expand All @@ -210,6 +274,7 @@ Positional arguments:
`,
},
{
shell: "/bin/bash",
args: []string{"cmd", "sub1", "sub1", "-h"},
want: `Usage: cmd sub1 sub1 [flags] [args...]
Expand All @@ -227,6 +292,7 @@ Flags:
`,
},
{
shell: "/bin/bash",
args: []string{"cmd", "sub1", "sub2", "-h"},
want: `Usage: cmd sub1 sub2 [flags]
Expand All @@ -247,6 +313,10 @@ Flags:

for _, tt := range tests {
t.Run(strings.Join(tt.args, " "), func(t *testing.T) {
previousShell := os.Getenv("SHELL")
defer os.Setenv("SHELL", previousShell)
require.NoError(t, os.Setenv("SHELL", tt.shell))

root := newTestCmd()
err := root.ParseArgs(tt.args...)
assert.Error(t, err)
Expand Down

0 comments on commit 74170b4

Please sign in to comment.