Documentation ¶
Overview ¶
Package bflags implements binding for command flags or command line arguments to an object. Binding happens through tags annotations on struct types using the `cmd` tag Syntax Tag are specified using 'cmd' followed by either 'flag' or 'arg': flag, name, usage, shorthand, persistent, required, hidden arg, name, usage, order sample: flag `cmd:"flag,id,content id,i,true,true,false"` arg `cmd:"arg,id,content id,0"` Assuming a string value, the above flag tag is read as (using cobra): cmd.PersistentFlags().StringP("id", "i", "", "content id") cmd.MarkPersistentFlagRequired("id") In case the flag is not persistent and not required, it reads as: cmd.Flags().StringP("id", "i", "", "content id") Note that flag names are case-sensitive The default value is the value of the tagged field. In the example below the field Ip of myInput is initialized with net.IPv4(127, 0, 0, 1) before being bound. This makes the flag --ip having a default value of 127.0.0.1. For `arg` tags, the order (starting at 0) must be specified for all or none of the fields in the struct. The library also supports specifying a 'meta' tag, followed by a comma separated list of values that are attached as a slice of strings to the 'Annotations' field of the resulting FlagBond: `meta:"value1,value2"` Even though not a frequent usage, the bound flags can be retrieved after binding: var c *cobra.Command _ = Bind(c, &MyStruct{}) flags, _ := GetCmdFlagSet(c) args, _ := GetCmdArgSet(c) Example type SimpleTaggedStruct struct { Stringval string `cmd:"flag"` Ids id.ID `cmd:"flag,ids,content ids,i,true,true"` Id id.ID `cmd:"arg,id,content id,0"` QId id.ID Ignore string } Complete Usage Sample using go generics. This example takes advantage of go generics to bind the input to the command flags and sets the RunE function of the command. type myInput struct { Ip net.IP `cmd:"flag,ip,node ip,q"` Path string `cmd:"arg"` } func Execute() error { cmd, err := bflags.BindRunE( &myInput{ Ip: net.IPv4(127, 0, 0, 1), Path: "/tmp", }, &cobra.Command{ Use: "sample /path", Short: "run sample", }, func(in *myInput) error { bb, err := json.Marshal(in) if err != nil { return err } fmt.Printf("sample - input %s\n", string(bb)) return nil }, nil) if err != nil { return err } err = cmd.Execute() return err } func main() { if err := Execute(); err != nil { fmt.Println(err) os.Exit(1) } } Complete Usage Sample. Same example as above but not using go generics. type myInput struct { Ip net.IP `cmd:"flag,ip,node ip,q"` Path string `cmd:"arg"` } func InitFlagsSample() (*cobra.Command, error) { var cmdFlagsSample = &cobra.Command{ Use: "sample /path", Short: "run sample", RunE: runSample, } // &myInput instance 'my' here represents the default values of all // flags bound to it my := &myInput{ Ip: net.IPv4(127, 0, 0, 1), Path: "/tmp", } err := bflags.Bind(cmdFlagsSample, my) // this is equivalent to // cmdFlagsSample.Flags().IPVarP(&my.Ip, "ip", "q", my.Ip, "node ip") // additionally if the flag was required // _ = cmdFlagsSample.MarkFlagRequired("ip") // or hidden: // cmdFlagsSample.Flag("ip").Hidden = true if err != nil { return nil, err } return cmdFlagsSample, nil } func runSample(cmd *cobra.Command, args []string) error { // this is required to bind args parameters to the 'arg' fields of the input m, err := bflags.SetArgs(cmd, args) if err != nil { return err } my, ok := m.(*myInput) if !ok { return errors.E("runSample", "wrong input", m) } bb, err := json.Marshal(my) if err != nil { return err } fmt.Printf("sample - input %s\n", string(string(bb))) return nil } func Execute() error { cmd, err := InitFlagsSample() if err != nil { return err } err = cmd.Execute() return err } func main() { if err := Execute(); err != nil { fmt.Println(err) os.Exit(1) } } Binding to specific 'custom' types Binding to specific types is supported through the Flagger interface. With an instance fl of Flagger, call bflags.BindCustom(cmd, fl, v) See `TestCustomFlag` for a sample implementation. Struct implementing flag.Value **Pointer** values to those structs can be used as flags. Example: // workersConfig implements pflag.Value type workersConfig struct { QueueSize int Workers int } func (u *workersConfig) String() string { bb, err := json.Marshal(u) if err != nil { return err.Error() } return string(bb) } func (u *workersConfig) Set(s string) error { return json.Unmarshal([]byte(s), u) } func (u *workersConfig) Type() string { return "workers" } type TestFlagValueStruct struct { // **pointer** ! Workers *workersConfig `cmd:"flag"` } func TestEncodeFlagValue(t *testing.T) { c := &cobra.Command{ Use: "dontUse", } sts := &TestFlagValueStruct{ Workers: &workersConfig{}, } err := Bind(c, sts) require.NoError(t, err) pf := assertFlag(t, c, "Workers") require.Equal(t, &workersConfig{}, sts.Workers) err = pf.Value.Set(`{"QueueSize":50,"Workers":5}`) require.NoError(t, err) wc := &workersConfig{ QueueSize: 50, Workers: 5, } require.Equal(t, wc, sts.Workers) } NOTES * inner structs - even anonymous - can be used for bindings BUT the inner struct needs to be initialized otherwise an error is raised since no binding would occur for its fields.
Index ¶
- func AddTemplateFunc(name string, tmplFunc interface{})
- func AddToCmdCtx(cmd *cobra.Command, name string, v interface{}) bool
- func Bind(c *cobra.Command, v interface{}) error
- func BindCustom(c *cobra.Command, f Flagger, v interface{}) error
- func BindRunE[T any](input *T, cmd *cobra.Command, runE func(*T) error, f Flagger) (*cobra.Command, error)
- func ConfigureCommandHelp(c *cobra.Command)
- func ConfigureHelpFuncs()
- func GetCmdCtx(cmd *cobra.Command) (interface{}, bool)
- func GetCmdInput(cmd *cobra.Command) (interface{}, bool)
- func GetFlagArgSet(c *cobra.Command) map[string]string
- func GetFromCmdCtx(cmd *cobra.Command, name string) (interface{}, bool)
- func SetArgs(c *cobra.Command, args []string) (interface{}, error)
- func SetCmdCtx(cmd *cobra.Command, v interface{})
- func SetupCmdArgs(cmd *cobra.Command, args []string, typ reflect.Type) (interface{}, error)
- type ArgSet
- type Binder
- type CmdFlags
- func (s CmdFlags) ConfigureCmd(cmd *cobra.Command, custom Flagger) error
- func (s CmdFlags) Flagset(cmd *cobra.Command, name string) (*flag.FlagSet, error)
- func (s CmdFlags) Get(name string) (*FlagBond, bool)
- func (s CmdFlags) GetBool(cmd *cobra.Command, name cmdFlag) (bool, error)
- func (s CmdFlags) GetDuration(cmd *cobra.Command, name cmdFlag) (time.Duration, error)
- func (s CmdFlags) GetFloat32(cmd *cobra.Command, name cmdFlag) (float32, error)
- func (s CmdFlags) GetFloat64(cmd *cobra.Command, name cmdFlag) (float64, error)
- func (s CmdFlags) GetIP(cmd *cobra.Command, name cmdFlag) (net.IP, error)
- func (s CmdFlags) GetInt(cmd *cobra.Command, name cmdFlag) (int, error)
- func (s CmdFlags) GetInt64(cmd *cobra.Command, name cmdFlag) (int64, error)
- func (s CmdFlags) GetString(cmd *cobra.Command, name cmdFlag) (string, error)
- func (s CmdFlags) GetUint(cmd *cobra.Command, name cmdFlag) (uint, error)
- func (s CmdFlags) GetUint64(cmd *cobra.Command, name cmdFlag) (uint64, error)
- func (s CmdFlags) Set(string) error
- func (s CmdFlags) String() string
- func (s CmdFlags) Type() string
- func (s CmdFlags) Validate() error
- type FlagBond
- type Flagged
- type Flagger
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AddTemplateFunc ¶ added in v1.0.3
func AddTemplateFunc(name string, tmplFunc interface{})
AddTemplateFunc adds a template function that's available to Usage and Help template generation. Also adds the function to the cobra template functions.
func Bind ¶
Bind binds the flags retrieved in tags of the given struct v as flags or args of the given command. c the command
v expected to be a struct.
Tag are specified using 'cmd' followed by either 'flag' or 'arg':
`cmd:"flag,id,content id, i,true,true,true"` `cmd:"arg,id,content id,0"`
are read as:
flag: name, usage, shorthand, persistent, required, hidden arg: name, usage, order
Attributes with default value on the right side of the expression can be omitted:
`cmd:"flag,id,content id, i"`
A 'meta' tag can be added to convey annotations with the bound tag:
`cmd:"flag,config,file name,c" meta:"file,non-empty"`
func BindCustom ¶
BindCustom is like Bind and allows a custom Flagger
func BindRunE ¶ added in v1.0.3
func BindRunE[T any](input *T, cmd *cobra.Command, runE func(*T) error, f Flagger) (*cobra.Command, error)
BindRunE binds the input parameter to the given command and sets the runE parameter function as the function invoked by the RunE function of the cobra command. _Example_
type testOpts struct { Password string `cmd:"flag,password,password for the user's key,x"` NoCert bool `cmd:"flag,no-cert,don't add certificate to the ssh-agent"` Domains []string `cmd:"arg,domains,name of the ssh domains,0"` done bool } cmd, err := BindRunE( &testOpts{}, &cobra.Command{ Use: "test <domains>", Short: "explanation short", Args: cobra.MinimumNArgs(1), Example: "test a b", }, func(opts *testOpts) error { return opts.run() }, nil) if err != nil { panic(err) } ... use cmd
func ConfigureCommandHelp ¶ added in v1.0.3
func ConfigureHelpFuncs ¶ added in v1.0.3
func ConfigureHelpFuncs()
func GetCmdInput ¶
func GetFlagArgSet ¶ added in v1.0.3
GetFlagArgSet returns a map[string]string of flags and args that were set for the given command. This function has to be called after SetArgs.
func SetArgs ¶
SetArgs sets the args to the 'arg' fields of the value previously bound as the input of the command. The input must have previously been bound to the command like so:
input := &MyStruct{} err := bflags.BindCustom(cmd, elvflags.Flags, input)
The input is returned if no error occurred.
func SetupCmdArgs ¶
SetupCmdArgs configures and returns the input struct bound to the provided command with the given arguments. * If the typ parameter is not nil the type of the input is verified * if the input has a function 'Validate() error', the function is called The input must have previously been bound to the command like so:
input := &MyStruct{} err := bflags.BindCustom(cmd, elvflags.Flags, input)
The input is returned if no error occurred.
Types ¶
type ArgSet ¶
type ArgSet struct {
Flags []*FlagBond
}
func (*ArgSet) ArgUsages ¶
ArgUsages returns a string containing the usage information for all flags in the ArgSet
type Binder ¶ added in v1.0.3
Binder is a utility for fluently building trees of commands with bindings. Example:
root := NewBinderC( &cobra.Command{ Use: "test", Short: "root command", }). AddCommand( NewBinder( &testOpts{}, &cobra.Command{ Use: "a <domains>", Example: "test a x", }, func(opts *testOpts) error { return opts.run() }, nil), NewBinder( &testOpts{}, &cobra.Command{ Use: "b <domains>", Example: "test b y", }, func(opts *testOpts) error { return opts.run() }, nil)) if root.Error != nil { panic(root.Error) } ... use root.Command
func NewBinder ¶ added in v1.0.3
NewBinder returns a Binder initialized by running BindRunE with the given parameters
func NewBinderC ¶ added in v1.0.3
NewBinderC constructs a new Binder with just a Command. This is useful for commands that are only parents of other commands, like the root command.
func (*Binder) AddCommand ¶ added in v1.0.3
AddCommand adds the commands of the given Binder instances to the command of this Binder or append their error to the Error of this Binder if they have errors.
type CmdFlags ¶
type CmdFlags map[cmdFlag]*FlagBond
func (CmdFlags) ConfigureCmd ¶
func (CmdFlags) GetDuration ¶
func (CmdFlags) GetFloat32 ¶
func (CmdFlags) GetFloat64 ¶
type FlagBond ¶
type FlagBond struct { Name cmdFlag // name of the flag Shorthand string // one letter shorthand or the empty string for none Value interface{} // the default value (use zero value for no default) Usage string // usage string : must not be empty Required bool // true if the flag is required Persistent bool // true: the flag is available to the command as well as every command under the command Hidden bool // true to set the flag as hidden ArgOrder int // for flags used to bind args CsvSlice bool // true for flags with comma separated string representation Annotations []string // annotations found as 'meta' tag // contains filtered or unexported fields }