feat: add persistent CLI flag helpers
All checks were successful
Security Scan / security (push) Successful in 17s

This commit is contained in:
Virgil 2026-04-01 09:43:59 +00:00
parent 4c072f9463
commit d84d8cc838
3 changed files with 131 additions and 0 deletions

View file

@ -85,6 +85,11 @@ Persistent flags are inherited by all subcommands:
```go
cli.PersistentStringFlag(parentCmd, &dbPath, "db", "d", "", "Database path")
cli.PersistentBoolFlag(parentCmd, &debug, "debug", "", false, "Debug mode")
cli.PersistentIntFlag(parentCmd, &retries, "retries", "r", 3, "Retry count")
cli.PersistentInt64Flag(parentCmd, &seed, "seed", "", 0, "Seed value")
cli.PersistentFloat64Flag(parentCmd, &ratio, "ratio", "", 1.0, "Scaling ratio")
cli.PersistentDurationFlag(parentCmd, &timeout, "timeout", "t", 30*time.Second, "Timeout")
cli.PersistentStringSliceFlag(parentCmd, &tags, "tag", "", nil, "Tags")
```
## Args Validation

View file

@ -195,6 +195,51 @@ func PersistentBoolFlag(cmd *Command, ptr *bool, name, short string, def bool, u
}
}
// PersistentIntFlag adds a persistent integer flag (inherited by subcommands).
func PersistentIntFlag(cmd *Command, ptr *int, name, short string, def int, usage string) {
if short != "" {
cmd.PersistentFlags().IntVarP(ptr, name, short, def, usage)
} else {
cmd.PersistentFlags().IntVar(ptr, name, def, usage)
}
}
// PersistentInt64Flag adds a persistent int64 flag (inherited by subcommands).
func PersistentInt64Flag(cmd *Command, ptr *int64, name, short string, def int64, usage string) {
if short != "" {
cmd.PersistentFlags().Int64VarP(ptr, name, short, def, usage)
} else {
cmd.PersistentFlags().Int64Var(ptr, name, def, usage)
}
}
// PersistentFloat64Flag adds a persistent float64 flag (inherited by subcommands).
func PersistentFloat64Flag(cmd *Command, ptr *float64, name, short string, def float64, usage string) {
if short != "" {
cmd.PersistentFlags().Float64VarP(ptr, name, short, def, usage)
} else {
cmd.PersistentFlags().Float64Var(ptr, name, def, usage)
}
}
// PersistentDurationFlag adds a persistent time.Duration flag (inherited by subcommands).
func PersistentDurationFlag(cmd *Command, ptr *time.Duration, name, short string, def time.Duration, usage string) {
if short != "" {
cmd.PersistentFlags().DurationVarP(ptr, name, short, def, usage)
} else {
cmd.PersistentFlags().DurationVar(ptr, name, def, usage)
}
}
// PersistentStringSliceFlag adds a persistent string slice flag (inherited by subcommands).
func PersistentStringSliceFlag(cmd *Command, ptr *[]string, name, short string, def []string, usage string) {
if short != "" {
cmd.PersistentFlags().StringSliceVarP(ptr, name, short, def, usage)
} else {
cmd.PersistentFlags().StringSliceVar(ptr, name, def, usage)
}
}
// ─────────────────────────────────────────────────────────────────────────────
// Command Configuration
// ─────────────────────────────────────────────────────────────────────────────

81
pkg/cli/command_test.go Normal file
View file

@ -0,0 +1,81 @@
package cli
import (
"testing"
"time"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestPersistentFlagHelpers_Good(t *testing.T) {
t.Run("persistent flags inherit through subcommands", func(t *testing.T) {
parent := NewGroup("parent", "Parent", "")
var (
str string
b bool
i int
i64 int64
f64 float64
dur time.Duration
slice []string
)
PersistentStringFlag(parent, &str, "name", "n", "default", "Name")
PersistentBoolFlag(parent, &b, "debug", "d", false, "Debug")
PersistentIntFlag(parent, &i, "count", "c", 1, "Count")
PersistentInt64Flag(parent, &i64, "seed", "", 2, "Seed")
PersistentFloat64Flag(parent, &f64, "ratio", "", 3.5, "Ratio")
PersistentDurationFlag(parent, &dur, "timeout", "t", 4*time.Second, "Timeout")
PersistentStringSliceFlag(parent, &slice, "tag", "", nil, "Tags")
child := NewCommand("child", "Child", "", func(_ *Command, _ []string) error {
assert.Equal(t, "override", str)
assert.True(t, b)
assert.Equal(t, 9, i)
assert.Equal(t, int64(42), i64)
assert.InDelta(t, 7.25, f64, 1e-9)
assert.Equal(t, 15*time.Second, dur)
assert.Equal(t, []string{"alpha", "beta"}, slice)
return nil
})
parent.AddCommand(child)
parent.SetArgs([]string{
"child",
"--name", "override",
"--debug",
"--count", "9",
"--seed", "42",
"--ratio", "7.25",
"--timeout", "15s",
"--tag", "alpha",
"--tag", "beta",
})
require.NoError(t, parent.Execute())
})
t.Run("persistent helpers use short flags when provided", func(t *testing.T) {
parent := NewGroup("parent", "Parent", "")
var value int
PersistentIntFlag(parent, &value, "count", "c", 1, "Count")
var seen bool
child := &cobra.Command{
Use: "child",
RunE: func(_ *cobra.Command, _ []string) error {
seen = true
assert.Equal(t, 5, value)
return nil
},
}
parent.AddCommand(child)
parent.SetArgs([]string{"child", "-c", "5"})
require.NoError(t, parent.Execute())
assert.True(t, seen)
})
}