Skip to content

Commit cff5dbb

Browse files
committed
shorthand flags + cleanup
1 parent 5ae2c90 commit cff5dbb

File tree

7 files changed

+67
-48
lines changed

7 files changed

+67
-48
lines changed

command.go

+20-12
Original file line numberDiff line numberDiff line change
@@ -620,14 +620,7 @@ func (inv *Invocation) with(fn func(*Invocation)) *Invocation {
620620
}
621621

622622
func (inv *Invocation) flagHandler(word string) bool {
623-
opt := inv.Command.Options.ByFlag(word[2:])
624-
if opt != nil && opt.CompletionHandler != nil {
625-
for _, e := range opt.CompletionHandler(inv) {
626-
fmt.Fprintf(inv.Stdout, "%s\n", e)
627-
}
628-
return true
629-
}
630-
return false
623+
return inv.doFlagCompletion("", word)
631624
}
632625

633626
func (inv *Invocation) equalsFlagHandler(word string) bool {
@@ -638,11 +631,26 @@ func (inv *Invocation) equalsFlagHandler(word string) bool {
638631
} else {
639632
inv.CurWord = ""
640633
}
641-
outPrefix := word + "="
634+
prefix := word + "="
635+
return inv.doFlagCompletion(prefix, word)
636+
}
637+
638+
func (inv *Invocation) doFlagCompletion(prefix, word string) bool {
642639
opt := inv.Command.Options.ByFlag(word[2:])
643-
if opt != nil && opt.CompletionHandler != nil {
644-
for _, e := range opt.CompletionHandler(inv) {
645-
fmt.Fprintf(inv.Stdout, "%s%s\n", outPrefix, e)
640+
if opt == nil {
641+
return false
642+
}
643+
if opt.CompletionHandler != nil {
644+
completions := opt.CompletionHandler(inv)
645+
for _, completion := range completions {
646+
fmt.Fprintf(inv.Stdout, "%s%s\n", prefix, completion)
647+
}
648+
return true
649+
}
650+
val, ok := opt.Value.(*Enum)
651+
if ok {
652+
for _, choice := range val.Choices {
653+
fmt.Fprintf(inv.Stdout, "%s%s\n", prefix, choice)
646654
}
647655
return true
648656
}

command_test.go

+15-13
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,16 @@ func SampleCommand(t *testing.T) *serpent.Command {
6464
Short: "Example with required flags",
6565
Options: serpent.OptionSet{
6666
serpent.Option{
67-
Name: "req-bool",
68-
Flag: "req-bool",
69-
Value: serpent.BoolOf(&reqBool),
70-
Required: true,
67+
Name: "req-bool",
68+
Flag: "req-bool",
69+
FlagShorthand: "b",
70+
Value: serpent.BoolOf(&reqBool),
71+
Required: true,
7172
},
7273
serpent.Option{
73-
Name: "req-string",
74-
Flag: "req-string",
74+
Name: "req-string",
75+
Flag: "req-string",
76+
FlagShorthand: "s",
7577
Value: serpent.Validate(serpent.StringOf(&reqStr), func(value *serpent.String) error {
7678
ok := strings.Contains(value.String(), " ")
7779
if !ok {
@@ -82,15 +84,15 @@ func SampleCommand(t *testing.T) *serpent.Command {
8284
Required: true,
8385
},
8486
serpent.Option{
85-
Name: "req-enum",
86-
Flag: "req-enum",
87-
Value: serpent.EnumOf(&enumStr, enumChoices...),
88-
CompletionHandler: completion.EnumHandler(enumChoices...),
87+
Name: "req-enum",
88+
Flag: "req-enum",
89+
Value: serpent.EnumOf(&enumStr, enumChoices...),
8990
},
9091
serpent.Option{
91-
Name: "req-array",
92-
Flag: "req-array",
93-
Value: serpent.StringArrayOf(&reqArr),
92+
Name: "req-array",
93+
Flag: "req-array",
94+
FlagShorthand: "a",
95+
Value: serpent.StringArrayOf(&reqArr),
9496
},
9597
},
9698
HelpHandler: func(i *serpent.Invocation) error {

completion/all.go

-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ func ShellOptions(choice *string) *serpent.Enum {
3030
return serpent.EnumOf(choice, BashShell, FishShell, ZShell, Powershell)
3131
}
3232

33-
func ShellHandler() serpent.CompletionHandlerFunc {
34-
return EnumHandler(BashShell, FishShell, ZShell, Powershell)
35-
}
36-
3733
func GetCompletion(writer io.Writer, shell string, cmdName string) error {
3834
fn, ok := shellCompletionByName[shell]
3935
if !ok {

completion/handlers.go

-6
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,6 @@ import (
99
"github.com/coder/serpent"
1010
)
1111

12-
func EnumHandler(choices ...string) serpent.CompletionHandlerFunc {
13-
return func(inv *serpent.Invocation) []string {
14-
return choices
15-
}
16-
}
17-
1812
// FileHandler returns a handler that completes files, using the
1913
// given filter func, which may be nil.
2014
func FileHandler(filter func(info os.FileInfo) bool) serpent.CompletionHandlerFunc {

completion_test.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ func TestCompletion(t *testing.T) {
2525
require.Equal(t, "altfile\nfile\nrequired-flag\ntoupper\n--prefix\n--verbose\n", io.Stdout.String())
2626
})
2727

28+
t.Run("SubcommandNoPartial", func(t *testing.T) {
29+
t.Parallel()
30+
i := cmd().Invoke("f")
31+
i.Environ.Set(serpent.CompletionModeEnv, "1")
32+
io := fakeIO(i)
33+
err := i.Run()
34+
require.NoError(t, err)
35+
require.Equal(t, "altfile\nfile\nrequired-flag\ntoupper\n--prefix\n--verbose\n", io.Stdout.String())
36+
})
37+
2838
t.Run("SubcommandComplete", func(t *testing.T) {
2939
t.Parallel()
3040
i := cmd().Invoke("required-flag")
@@ -47,7 +57,17 @@ func TestCompletion(t *testing.T) {
4757

4858
t.Run("FlagExhaustive", func(t *testing.T) {
4959
t.Parallel()
50-
i := cmd().Invoke("required-flag", "--req-bool", "--req-string", "foo bar", "--req-array", "asdf")
60+
i := cmd().Invoke("required-flag", "--req-bool", "--req-string", "foo bar", "--req-array", "asdf", "--req-array", "qwerty")
61+
i.Environ.Set(serpent.CompletionModeEnv, "1")
62+
io := fakeIO(i)
63+
err := i.Run()
64+
require.NoError(t, err)
65+
require.Equal(t, "--req-array\n--req-enum\n", io.Stdout.String())
66+
})
67+
68+
t.Run("FlagShorthand", func(t *testing.T) {
69+
t.Parallel()
70+
i := cmd().Invoke("required-flag", "-b", "-s", "foo bar", "-a", "asdf")
5171
i.Environ.Set(serpent.CompletionModeEnv, "1")
5272
io := fakeIO(i)
5373
err := i.Run()
@@ -74,6 +94,7 @@ func TestCompletion(t *testing.T) {
7494
require.NoError(t, err)
7595
require.Equal(t, "--req-enum=foo\n--req-enum=bar\n--req-enum=qux\n", io.Stdout.String())
7696
})
97+
7798
}
7899

79100
func TestFileCompletion(t *testing.T) {

example/completetest/main.go

+9-11
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,11 @@ func InstallCommand() *serpent.Command {
2626
},
2727
Options: serpent.OptionSet{
2828
{
29-
Flag: "shell",
30-
FlagShorthand: "s",
31-
Default: defaultShell,
32-
Description: "The shell to generate a completion script for.",
33-
Value: completion.ShellOptions(&shell),
34-
CompletionHandler: completion.ShellHandler(),
29+
Flag: "shell",
30+
FlagShorthand: "s",
31+
Default: defaultShell,
32+
Description: "The shell to generate a completion script for.",
33+
Value: completion.ShellOptions(&shell),
3534
},
3635
},
3736
}
@@ -99,11 +98,10 @@ func main() {
9998
Description: "Print the file.",
10099
},
101100
{
102-
Name: "type",
103-
Value: serpent.EnumOf(&fileType, "binary", "text"),
104-
Flag: "type",
105-
Description: "The type of file.",
106-
CompletionHandler: completion.EnumHandler("binary", "text"),
101+
Name: "type",
102+
Value: serpent.EnumOf(&fileType, "binary", "text"),
103+
Flag: "type",
104+
Description: "The type of file.",
107105
},
108106
{
109107
Name: "extra",

option.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ func (optSet OptionSet) ByName(name string) *Option {
349349
func (optSet OptionSet) ByFlag(flag string) *Option {
350350
for i := range optSet {
351351
opt := &optSet[i]
352-
if opt.Flag == flag {
352+
if opt.Flag == flag || opt.FlagShorthand == flag {
353353
return opt
354354
}
355355
}

0 commit comments

Comments
 (0)