package cli import ( "flag" "io" "testing") // Trailing flags (`tx9 delete mybox --force`) were silently ignored when// commands called fs.Parse directly — stdlib flag stops at the first// positional. parseFlagsAnywhere reorders so both spellings work.func TestParseFlagsAnywhere(t *testing.T) { cases := []struct { name string args []string wantForce bool wantPath string wantPos []string }{ {"flag before positional", []string{"--force", "mybox"}, true, "", []string{"mybox"}}, {"flag after positional", []string{"mybox", "--force"}, true, "", []string{"mybox"}}, {"value flag after positional", []string{"mybox", "--path", "/tmp/x"}, false, "/tmp/x", []string{"mybox"}}, {"value flag equals form", []string{"mybox", "--path=/tmp/y"}, false, "/tmp/y", []string{"mybox"}}, {"double dash stops parsing", []string{"mybox", "--", "--force"}, false, "", []string{"mybox", "--force"}}, {"no flags", []string{"mybox"}, false, "", []string{"mybox"}}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { fs := flag.NewFlagSet("test", flag.ContinueOnError) fs.SetOutput(io.Discard) force := fs.Bool("force", false, "") path := fs.String("path", "", "") if err := parseFlagsAnywhere(fs, tc.args); err != nil { t.Fatalf("parse: %v", err) } if *force != tc.wantForce { t.Errorf("force = %v, want %v", *force, tc.wantForce) } if *path != tc.wantPath { t.Errorf("path = %q, want %q", *path, tc.wantPath) } if got := fs.Args(); len(got) != len(tc.wantPos) { t.Fatalf("positionals = %v, want %v", got, tc.wantPos) } else { for i := range got { if got[i] != tc.wantPos[i] { t.Errorf("positional[%d] = %q, want %q", i, got[i], tc.wantPos[i]) } } } }) }}
package cli
import (
"flag"
"io"
"testing"
)
// Trailing flags (`tx9 delete mybox --force`) were silently ignored when
// commands called fs.Parse directly — stdlib flag stops at the first
// positional. parseFlagsAnywhere reorders so both spellings work.
func TestParseFlagsAnywhere(t *testing.T) {
cases := []struct {
name string
args []string
wantForce bool
wantPath string
wantPos []string
}{
{"flag before positional", []string{"--force", "mybox"}, true, "", []string{"mybox"}},
{"flag after positional", []string{"mybox", "--force"}, true, "", []string{"mybox"}},
{"value flag after positional", []string{"mybox", "--path", "/tmp/x"}, false, "/tmp/x", []string{"mybox"}},
{"value flag equals form", []string{"mybox", "--path=/tmp/y"}, false, "/tmp/y", []string{"mybox"}},
{"double dash stops parsing", []string{"mybox", "--", "--force"}, false, "", []string{"mybox", "--force"}},
{"no flags", []string{"mybox"}, false, "", []string{"mybox"}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
fs := flag.NewFlagSet("test", flag.ContinueOnError)
fs.SetOutput(io.Discard)
force := fs.Bool("force", false, "")
path := fs.String("path", "", "")
if err := parseFlagsAnywhere(fs, tc.args); err != nil {
t.Fatalf("parse: %v", err)
}
if *force != tc.wantForce {
t.Errorf("force = %v, want %v", *force, tc.wantForce)
}
if *path != tc.wantPath {
t.Errorf("path = %q, want %q", *path, tc.wantPath)
}
if got := fs.Args(); len(got) != len(tc.wantPos) {
t.Fatalf("positionals = %v, want %v", got, tc.wantPos)
} else {
for i := range got {
if got[i] != tc.wantPos[i] {
t.Errorf("positional[%d] = %q, want %q", i, got[i], tc.wantPos[i])
}
}
}
})
}
}