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.
This commit is contained in:
committed by
GitHub
parent
30e84613fe
commit
fa9b636997
@@ -566,7 +566,7 @@ Both can coexist with standard Tag parsing.
|
||||
| `default:"1"` | On a command, make it the default. |
|
||||
| `default:"withargs"` | On a command, make it the default and allow args/flags from that command |
|
||||
| `short:"X"` | Short name, if flag. |
|
||||
| `aliases:"X,Y"` | One or more aliases (for cmd). |
|
||||
| `aliases:"X,Y"` | One or more aliases (for cmd or flag). |
|
||||
| `required:""` | If present, flag/arg is required. |
|
||||
| `optional:""` | If present, flag/arg is optional. |
|
||||
| `hidden:""` | If present, command or flag is hidden. |
|
||||
|
||||
@@ -296,6 +296,13 @@ func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv
|
||||
return failField(v, ft, "duplicate flag --%s", value.Name)
|
||||
}
|
||||
seenFlags["--"+value.Name] = true
|
||||
for _, alias := range tag.Aliases {
|
||||
aliasFlag := "--" + alias
|
||||
if seenFlags[aliasFlag] {
|
||||
return failField(v, ft, "duplicate flag %s", aliasFlag)
|
||||
}
|
||||
seenFlags[aliasFlag] = true
|
||||
}
|
||||
if tag.Short != 0 {
|
||||
if seenFlags["-"+string(tag.Short)] {
|
||||
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
|
||||
}
|
||||
flag := &Flag{
|
||||
Value: value,
|
||||
Aliases: tag.Aliases,
|
||||
Short: tag.Short,
|
||||
PlaceHolder: tag.PlaceHolder,
|
||||
Envs: tag.Envs,
|
||||
|
||||
+12
-3
@@ -684,15 +684,24 @@ func flipBoolValue(value reflect.Value) error {
|
||||
|
||||
func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
|
||||
candidates := []string{}
|
||||
|
||||
for _, flag := range flags {
|
||||
long := "--" + flag.Name
|
||||
short := "-" + string(flag.Short)
|
||||
neg := "--no-" + flag.Name
|
||||
matched := long == match
|
||||
candidates = append(candidates, long)
|
||||
if flag.Short != 0 {
|
||||
short := "-" + string(flag.Short)
|
||||
matched = matched || (short == match)
|
||||
candidates = append(candidates, short)
|
||||
}
|
||||
if short != match && long != match && !(match == neg && flag.Tag.Negatable) {
|
||||
for _, alias := range flag.Aliases {
|
||||
alias = "--" + alias
|
||||
matched = matched || (alias == match)
|
||||
candidates = append(candidates, alias)
|
||||
}
|
||||
|
||||
neg := "--no-" + flag.Name
|
||||
if !matched && !(match == neg && flag.Tag.Negatable) {
|
||||
continue
|
||||
}
|
||||
// Found a matching flag.
|
||||
|
||||
@@ -518,6 +518,16 @@ func TestShort(t *testing.T) {
|
||||
assert.Equal(t, "hello", cli.String)
|
||||
}
|
||||
|
||||
func TestAlias(t *testing.T) {
|
||||
var cli struct {
|
||||
String string `aliases:"str"`
|
||||
}
|
||||
app := mustNew(t, &cli)
|
||||
_, err := app.Parse([]string{"--str", "hello"})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", cli.String)
|
||||
}
|
||||
|
||||
func TestDuplicateFlagChoosesLast(t *testing.T) {
|
||||
var cli struct {
|
||||
Flag int
|
||||
@@ -1321,6 +1331,24 @@ func TestDuplicateShortflags(t *testing.T) {
|
||||
assert.EqualError(t, err, "<anonymous struct>.Flag2: duplicate short flag -t")
|
||||
}
|
||||
|
||||
func TestDuplicateAliases(t *testing.T) {
|
||||
cli1 := struct {
|
||||
Flag1 string `aliases:"flag"`
|
||||
Flag2 string `aliases:"flag"`
|
||||
}{}
|
||||
_, err := kong.New(&cli1)
|
||||
assert.EqualError(t, err, "<anonymous struct>.Flag2: duplicate flag --flag")
|
||||
}
|
||||
|
||||
func TestDuplicateAliasLong(t *testing.T) {
|
||||
cli2 := struct {
|
||||
Flag string ``
|
||||
Flag2 string `aliases:"flag"` // duplicates Flag
|
||||
}{}
|
||||
_, err := kong.New(&cli2)
|
||||
assert.EqualError(t, err, "<anonymous struct>.Flag2: duplicate flag --flag")
|
||||
}
|
||||
|
||||
func TestDuplicateNestedShortFlags(t *testing.T) {
|
||||
cli := struct {
|
||||
Flag1 bool `short:"t"`
|
||||
|
||||
Reference in New Issue
Block a user