Skip to content
This repository was archived by the owner on Jan 2, 2026. It is now read-only.

Commit 3b65b9b

Browse files
committed
Allow ... to denote unlimited args list
1 parent 57eada9 commit 3b65b9b

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

cli/parsing.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ func usageFrom(path string) (string, cobra.PositionalArgs, error) {
7979

8080
var required, optional int
8181
for _, i := range parts[1:] {
82+
if i == "..." {
83+
continue
84+
}
8285
if strings.HasPrefix(i, "[") && strings.HasSuffix(i, "]") {
8386
logrus.Debug("Found optional arg: ", i)
8487
optional++
@@ -87,7 +90,10 @@ func usageFrom(path string) (string, cobra.PositionalArgs, error) {
8790
required++
8891
}
8992
}
90-
93+
if parts[len(parts)-1] == "..." {
94+
logrus.Debug("Minimum of ", required, " arguments set")
95+
return match[1], cobra.MinimumNArgs(required), nil
96+
}
9197
logrus.Debug("Arg range of ", required, " and ", required+optional, " set")
9298
return match[1], cobra.RangeArgs(required, required+optional), nil
9399
}

cli/parsing_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,48 @@ func TestUsageFrom(t *testing.T) {
108108
assert.Error(t, v(&cobra.Command{}, []string{"first", "second", "third"}))
109109
},
110110
},
111+
{
112+
"unlimited arguments, mixed",
113+
"#\n# usage: blah foo [bar] ...\n#\n",
114+
func(t *testing.T, name string, actual string) {
115+
assert.Equal(t, "blah foo [bar] ...", actual)
116+
},
117+
func(t *testing.T, v cobra.PositionalArgs) {
118+
assert.Error(t, v(&cobra.Command{}, []string{}))
119+
assert.NoError(t, v(&cobra.Command{}, []string{"first"}))
120+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second"}))
121+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second", "third"}))
122+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second", "third", "fourth"}))
123+
},
124+
},
125+
{
126+
"unlimited arguments, required",
127+
"#\n# usage: blah foo bar ...\n#\n",
128+
func(t *testing.T, name string, actual string) {
129+
assert.Equal(t, "blah foo bar ...", actual)
130+
},
131+
func(t *testing.T, v cobra.PositionalArgs) {
132+
assert.Error(t, v(&cobra.Command{}, []string{}))
133+
assert.Error(t, v(&cobra.Command{}, []string{"first"}))
134+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second"}))
135+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second", "third"}))
136+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second", "third", "fourth"}))
137+
},
138+
},
139+
{
140+
"unlimited arguments, optional",
141+
"#\n# usage: blah [bar] ...\n#\n",
142+
func(t *testing.T, name string, actual string) {
143+
assert.Equal(t, "blah [bar] ...", actual)
144+
},
145+
func(t *testing.T, v cobra.PositionalArgs) {
146+
assert.NoError(t, v(&cobra.Command{}, []string{}))
147+
assert.NoError(t, v(&cobra.Command{}, []string{"first"}))
148+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second"}))
149+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second", "third"}))
150+
assert.NoError(t, v(&cobra.Command{}, []string{"first", "second", "third", "fourth"}))
151+
},
152+
},
111153
{
112154
"missing",
113155
"#\n#\n#\n",

0 commit comments

Comments
 (0)