Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a small utility method to display a warnings. #16441

Merged
merged 5 commits into from Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/16441.txt
@@ -0,0 +1,3 @@
```release-note:improvement
base: Added a small utility method to display a warning if flags are passed after arguments in a command.
tomhjp marked this conversation as resolved.
Show resolved Hide resolved
```
17 changes: 14 additions & 3 deletions command/base.go
Expand Up @@ -549,6 +549,7 @@ type FlagSets struct {
mainSet *flag.FlagSet
hiddens map[string]struct{}
completions complete.Flags
ui cli.Ui
}

// NewFlagSets creates a new flag sets.
Expand All @@ -564,6 +565,7 @@ func NewFlagSets(ui cli.Ui) *FlagSets {
mainSet: mainSet,
hiddens: make(map[string]struct{}),
completions: complete.Flags{},
ui: ui,
}
}

Expand All @@ -582,8 +584,17 @@ func (f *FlagSets) Completions() complete.Flags {
}

// Parse parses the given flags, returning any errors.
// Warnings, if any, regarding the arguments format are sent to stdout
func (f *FlagSets) Parse(args []string) error {
return f.mainSet.Parse(args)
err := f.mainSet.Parse(args)

var out bytes.Buffer
printArgsWarningIfAny(&out, f.Args())
if out.String() != "" {
f.ui.Warn(out.String())
}
Copy link
Member

Choose a reason for hiding this comment

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

Alternatively, you can have printArgsWarningIfAny return the warning as a string, and output the string if it's non-empty.


return err
}

// Parsed reports whether the command-line flags have been parsed.
Expand All @@ -603,10 +614,10 @@ func (f *FlagSets) Visit(fn func(*flag.Flag)) {
}

// Help builds custom help for this command, grouping by flag set.
func (fs *FlagSets) Help() string {
func (f *FlagSets) Help() string {
var out bytes.Buffer

for _, set := range fs.flagSets {
for _, set := range f.flagSets {
printFlagTitle(&out, set.name+":")
set.VisitAll(func(f *flag.Flag) {
// Skip any hidden flags
Expand Down
13 changes: 13 additions & 0 deletions command/base_helpers.go
Expand Up @@ -292,3 +292,16 @@ func parseFlagFile(raw string) (string, error) {

return raw, nil
}

func printArgsWarningIfAny(w io.Writer, args []string) {
tomhjp marked this conversation as resolved.
Show resolved Hide resolved
var trailingFlags []string
for _, arg := range args {
if strings.HasPrefix(arg, "-") {
trailingFlags = append(trailingFlags, arg)
}
}

if len(trailingFlags) > 0 {
fmt.Fprintf(w, "Flag(s) must be provided before positional argument(s): %s", trailingFlags)
tomhjp marked this conversation as resolved.
Show resolved Hide resolved
}
}
49 changes: 49 additions & 0 deletions command/base_helpers_test.go
@@ -1,10 +1,12 @@
package command

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"testing"
"time"
)
Expand Down Expand Up @@ -209,3 +211,50 @@ func TestParseFlagFile(t *testing.T) {
})
}
}

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

cases := []struct {
args []string
expected string
}{
{
[]string{"a", "b", "c"},
"",
},
{
[]string{"a", "-b"},
"-b",
},
{
[]string{"a", "--b"},
"--b",
},
{
[]string{"a-b", "-c"},
"-c",
},
{
[]string{"a", "-b-c"},
"-b-c",
},
{
[]string{"-a", "b"},
"-a",
},
}

for _, tc := range cases {
tc := tc

t.Run(tc.expected, func(t *testing.T) {
var out bytes.Buffer

printArgsWarningIfAny(&out, tc.args)
if !strings.Contains(out.String(), tc.expected) {
t.Fatalf("expected %s to contain %s", out.String(), tc.expected)
}
})
}
}