Skip to content

Commit fa9b636

Browse files
authored
Support aliases for flags (#409)
Aliases are currently only supported for sub-commands, but they're useful for flags as well. E.g., when migrating from an old flag name to a new flag name, while still supporting the old value.
1 parent 30e8461 commit fa9b636

File tree

5 files changed

+50
-4
lines changed

5 files changed

+50
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ Both can coexist with standard Tag parsing.
566566
| `default:"1"` | On a command, make it the default. |
567567
| `default:"withargs"` | On a command, make it the default and allow args/flags from that command |
568568
| `short:"X"` | Short name, if flag. |
569-
| `aliases:"X,Y"` | One or more aliases (for cmd). |
569+
| `aliases:"X,Y"` | One or more aliases (for cmd or flag). |
570570
| `required:""` | If present, flag/arg is required. |
571571
| `optional:""` | If present, flag/arg is optional. |
572572
| `hidden:""` | If present, command or flag is hidden. |

build.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv
296296
return failField(v, ft, "duplicate flag --%s", value.Name)
297297
}
298298
seenFlags["--"+value.Name] = true
299+
for _, alias := range tag.Aliases {
300+
aliasFlag := "--" + alias
301+
if seenFlags[aliasFlag] {
302+
return failField(v, ft, "duplicate flag %s", aliasFlag)
303+
}
304+
seenFlags[aliasFlag] = true
305+
}
299306
if tag.Short != 0 {
300307
if seenFlags["-"+string(tag.Short)] {
301308
return failField(v, ft, "duplicate short flag -%c", tag.Short)
@@ -304,6 +311,7 @@ func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv
304311
}
305312
flag := &Flag{
306313
Value: value,
314+
Aliases: tag.Aliases,
307315
Short: tag.Short,
308316
PlaceHolder: tag.PlaceHolder,
309317
Envs: tag.Envs,

context.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -684,15 +684,24 @@ func flipBoolValue(value reflect.Value) error {
684684

685685
func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
686686
candidates := []string{}
687+
687688
for _, flag := range flags {
688689
long := "--" + flag.Name
689-
short := "-" + string(flag.Short)
690-
neg := "--no-" + flag.Name
690+
matched := long == match
691691
candidates = append(candidates, long)
692692
if flag.Short != 0 {
693+
short := "-" + string(flag.Short)
694+
matched = matched || (short == match)
693695
candidates = append(candidates, short)
694696
}
695-
if short != match && long != match && !(match == neg && flag.Tag.Negatable) {
697+
for _, alias := range flag.Aliases {
698+
alias = "--" + alias
699+
matched = matched || (alias == match)
700+
candidates = append(candidates, alias)
701+
}
702+
703+
neg := "--no-" + flag.Name
704+
if !matched && !(match == neg && flag.Tag.Negatable) {
696705
continue
697706
}
698707
// Found a matching flag.

kong_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,16 @@ func TestShort(t *testing.T) {
518518
assert.Equal(t, "hello", cli.String)
519519
}
520520

521+
func TestAlias(t *testing.T) {
522+
var cli struct {
523+
String string `aliases:"str"`
524+
}
525+
app := mustNew(t, &cli)
526+
_, err := app.Parse([]string{"--str", "hello"})
527+
assert.NoError(t, err)
528+
assert.Equal(t, "hello", cli.String)
529+
}
530+
521531
func TestDuplicateFlagChoosesLast(t *testing.T) {
522532
var cli struct {
523533
Flag int
@@ -1321,6 +1331,24 @@ func TestDuplicateShortflags(t *testing.T) {
13211331
assert.EqualError(t, err, "<anonymous struct>.Flag2: duplicate short flag -t")
13221332
}
13231333

1334+
func TestDuplicateAliases(t *testing.T) {
1335+
cli1 := struct {
1336+
Flag1 string `aliases:"flag"`
1337+
Flag2 string `aliases:"flag"`
1338+
}{}
1339+
_, err := kong.New(&cli1)
1340+
assert.EqualError(t, err, "<anonymous struct>.Flag2: duplicate flag --flag")
1341+
}
1342+
1343+
func TestDuplicateAliasLong(t *testing.T) {
1344+
cli2 := struct {
1345+
Flag string ``
1346+
Flag2 string `aliases:"flag"` // duplicates Flag
1347+
}{}
1348+
_, err := kong.New(&cli2)
1349+
assert.EqualError(t, err, "<anonymous struct>.Flag2: duplicate flag --flag")
1350+
}
1351+
13241352
func TestDuplicateNestedShortFlags(t *testing.T) {
13251353
cli := struct {
13261354
Flag1 bool `short:"t"`

model.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ type Flag struct {
397397
Xor []string
398398
PlaceHolder string
399399
Envs []string
400+
Aliases []string
400401
Short rune
401402
Hidden bool
402403
Negated bool

0 commit comments

Comments
 (0)