Skip to content

Commit 3a591bf

Browse files
committed
equals flags
1 parent 6db6e6c commit 3a591bf

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

command.go

+43-10
Original file line numberDiff line numberDiff line change
@@ -464,19 +464,22 @@ func (inv *Invocation) run(state *runState) error {
464464
defer cancel()
465465
inv = inv.WithContext(ctx)
466466

467+
// Outputted completions are not filtered based on the word under the cursor, as every shell we support does this already.
468+
// We only look at the current word to figure out handler to run, or what directory to inspect.
467469
if inv.IsCompletionMode() {
468470
prev, cur := inv.GetCurWords()
469471
inv.CurWord = cur
470-
if prev != "" {
471-
// If the previous word is a flag, we use it's handler
472-
if strings.HasPrefix(prev, "--") {
473-
opt := inv.Command.Options.ByFlag(prev[2:])
474-
if opt != nil && opt.CompletionHandler != nil {
475-
for _, e := range opt.CompletionHandler(inv) {
476-
fmt.Fprintf(inv.Stdout, "%s\n", e)
477-
}
478-
return nil
479-
}
472+
// If the current word is a flag set using `=`, use it's handler
473+
if strings.HasPrefix(cur, "--") && strings.Contains(cur, "=") {
474+
if inv.equalsFlagHandler(cur) {
475+
return nil
476+
}
477+
}
478+
// If the previous word is a flag, then we're writing it's value
479+
// and we should check it's handler
480+
if strings.HasPrefix(prev, "--") {
481+
if inv.flagHandler(prev) {
482+
return nil
480483
}
481484
}
482485
if inv.Command.Name() == inv.CurWord {
@@ -616,6 +619,36 @@ func (inv *Invocation) with(fn func(*Invocation)) *Invocation {
616619
return &i2
617620
}
618621

622+
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
631+
}
632+
633+
func (inv *Invocation) equalsFlagHandler(word string) bool {
634+
words := strings.Split(word, "=")
635+
word = words[0]
636+
if len(words) > 1 {
637+
inv.CurWord = words[1]
638+
} else {
639+
inv.CurWord = ""
640+
}
641+
outPrefix := word + "="
642+
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)
646+
}
647+
return true
648+
}
649+
return false
650+
}
651+
619652
// MiddlewareFunc returns the next handler in the chain,
620653
// or nil if there are no more.
621654
type MiddlewareFunc func(next HandlerFunc) HandlerFunc

completion_test.go

+10
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ func TestCompletion(t *testing.T) {
6565
require.NoError(t, err)
6666
require.Equal(t, "foo\nbar\nqux\n", io.Stdout.String())
6767
})
68+
69+
t.Run("EnumEqualsOK", func(t *testing.T) {
70+
t.Parallel()
71+
i := cmd().Invoke("required-flag", "--req-enum", "--req-enum=")
72+
i.Environ.Set(serpent.CompletionModeEnv, "1")
73+
io := fakeIO(i)
74+
err := i.Run()
75+
require.NoError(t, err)
76+
require.Equal(t, "--req-enum=foo\n--req-enum=bar\n--req-enum=qux\n", io.Stdout.String())
77+
})
6878
}
6979

7080
func TestFileCompletion(t *testing.T) {

0 commit comments

Comments
 (0)