Documentation ¶
Overview ¶
Package enumflag supplements the Golang CLI flag handling packages spf13/cobra and spf13/pflag with enumeration flags.
For instance, users can specify enum flags as “--mode=foo” or “--mode=bar”, where “foo” and “bar” are valid enumeration values. Other values which are not part of the set of allowed enumeration values cannot be set and raise CLI flag errors.
Application programmers then simply deal with enumeration values in form of uints (or ints), liberated from parsing strings and validating enumeration flags.
Example ¶
package main import ( "fmt" "github.com/spf13/cobra" "github.com/thediveo/enumflag/v2" ) // ① Define your new enum flag type. It can be derived from enumflag.Flag, // but it doesn't need to be as long as it satisfies constraints.Integer. type FooMode enumflag.Flag // ② Define the enumeration values for FooMode. const ( Foo FooMode = iota Bar ) // ③ Map enumeration values to their textual representations (value // identifiers). var FooModeIds = map[FooMode][]string{ Foo: {"foo"}, Bar: {"bar"}, } func main() { // ④ Define your enum flag value. var foomode FooMode rootCmd := &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { fmt.Printf("mode is: %d=%q\n", foomode, cmd.PersistentFlags().Lookup("mode").Value.String()) }, } // ⑤ Define the CLI flag parameters for your wrapped enum flag. rootCmd.PersistentFlags().VarP( enumflag.New(&foomode, "mode", FooModeIds, enumflag.EnumCaseInsensitive), "mode", "m", "foos the output; can be 'foo' or 'bar'") // cobra's help will render the default enum value identifier... _ = rootCmd.Help() // parse the CLI args to set our enum flag. rootCmd.SetArgs([]string{"--mode", "bAr"}) _ = rootCmd.Execute() }
Output: Usage: [flags] Flags: -m, --mode mode foos the output; can be 'foo' or 'bar' (default foo) mode is: 1="bar"
Example (External) ¶
package main import ( "fmt" "os" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "github.com/thediveo/enumflag/v2" ) func init() { log.SetOutput(os.Stdout) } func main() { // ①+② skip "define your own enum flag type" and enumeration values, as we // already have a 3rd party one. // ③ Map 3rd party enumeration values to their textual representations var LoglevelIds = map[log.Level][]string{ log.TraceLevel: {"trace"}, log.DebugLevel: {"debug"}, log.InfoLevel: {"info"}, log.WarnLevel: {"warning", "warn"}, log.ErrorLevel: {"error"}, log.FatalLevel: {"fatal"}, log.PanicLevel: {"panic"}, } // ④ Define your enum flag value and set the your logging default value. var loglevel log.Level = log.WarnLevel rootCmd := &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { fmt.Printf("logging level is: %d=%q\n", loglevel, cmd.PersistentFlags().Lookup("log").Value.String()) }, } // ⑤ Define the CLI flag parameters for your wrapped enum flag. rootCmd.PersistentFlags().Var( enumflag.New(&loglevel, "log", LoglevelIds, enumflag.EnumCaseInsensitive), "log", "sets logging level; can be 'trace', 'debug', 'info', 'warn', 'error', 'fatal', 'panic'") _ = rootCmd.Execute() rootCmd.SetArgs([]string{"--log", "debug"}) _ = rootCmd.Execute() }
Output: logging level is: 3="warning" logging level is: 5="debug"
Example (No_default_value) ¶
package main import ( "fmt" "github.com/spf13/cobra" "github.com/thediveo/enumflag/v2" ) // ① Define your new enum flag type. It can be derived from enumflag.Flag, // but it doesn't need to be as long as it satisfies constraints.Integer. type BarMode enumflag.Flag // ② Define the enumeration values for BarMode. const ( NoDefault = iota // optional definition for "no default" zero value Barr BarMode = iota Barz ) // ③ Map enumeration values to their textual representations (value // identifiers). var BarModeIds = map[BarMode][]string{ // ...do NOT include/map the "no default" zero value! Barr: {"barr"}, Barz: {"barz"}, } func main() { // ④ Define your enum flag value. var barmode BarMode rootCmd := &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { fmt.Printf("mode is: %d=%q\n", barmode, cmd.PersistentFlags().Lookup("mode").Value.String()) }, } // ⑤ Define the CLI flag parameters for your wrapped enum flag. rootCmd.PersistentFlags().VarP( enumflag.NewWithoutDefault(&barmode, "mode", BarModeIds, enumflag.EnumCaseInsensitive), "mode", "m", "bars the output; can be 'barr' or 'barz'") // now cobra's help won't render the default enum value identifier anymore... _ = rootCmd.Help() _ = rootCmd.Execute() }
Output: Usage: [flags] Flags: -m, --mode mode bars the output; can be 'barr' or 'barz' mode is: 0=""
Example (Slice) ¶
package main import ( "fmt" "github.com/spf13/cobra" "github.com/thediveo/enumflag/v2" ) // ① Define your new enum flag type. It can be derived from enumflag.Flag, // but it doesn't need to be as long as it satisfies constraints.Integer. type MooMode enumflag.Flag // ② Define the enumeration values for FooMode. const ( Moo MooMode = (iota + 1) * 111 Møø Mimimi ) // ③ Map enumeration values to their textual representations (value // identifiers). var MooModeIds = map[MooMode][]string{ Moo: {"moo"}, Møø: {"møø"}, Mimimi: {"mimimi"}, } func main() { // ④ Define your enum slice flag value. var moomode []MooMode rootCmd := &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { fmt.Printf("mode is: %d=%q\n", moomode, cmd.PersistentFlags().Lookup("mode").Value.String()) }, } // ⑤ Define the CLI flag parameters for your wrapped enum slice flag. rootCmd.PersistentFlags().VarP( enumflag.NewSlice(&moomode, "mode", MooModeIds, enumflag.EnumCaseInsensitive), "mode", "m", "can be any combination of 'moo', 'møø', 'mimimi'") rootCmd.SetArgs([]string{"--mode", "Moo,møø"}) _ = rootCmd.Execute() }
Output: mode is: [111 222]="[moo,møø]"
Index ¶
- type Completor
- type EnumCaseSensitivity
- type EnumFlagValue
- func New[E constraints.Integer](flag *E, typename string, mapping EnumIdentifiers[E], ...) *EnumFlagValue[E]
- func NewSlice[E constraints.Integer](flag *[]E, typename string, mapping EnumIdentifiers[E], ...) *EnumFlagValue[E]
- func NewWithoutDefault[E constraints.Integer](flag *E, typename string, mapping EnumIdentifiers[E], ...) *EnumFlagValue[E]
- type EnumIdentifiers
- type Flag
- type Help
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Completor ¶ added in v2.0.4
type Completor func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
Completor tells cobra how to complete a flag. See also cobra's dynamic flag completion documentation.
type EnumCaseSensitivity ¶
type EnumCaseSensitivity bool
EnumCaseSensitivity specifies whether the textual representations of enum values are considered to be case sensitive, or not.
const ( EnumCaseInsensitive EnumCaseSensitivity = false EnumCaseSensitive EnumCaseSensitivity = true )
Controls whether the textual representations for enum values are case sensitive, or not.
type EnumFlagValue ¶
type EnumFlagValue[E constraints.Integer] struct { // contains filtered or unexported fields }
EnumFlagValue wraps a user-defined enum type value satisfying constraints.Integer or []constraints.Integer. It implements the github.com/spf13/pflag.Value interface, so the user-defined enum type value can directly be used with the fine pflag drop-in package for Golang CLI flags.
func New ¶
func New[E constraints.Integer](flag *E, typename string, mapping EnumIdentifiers[E], sensitivity EnumCaseSensitivity) *EnumFlagValue[E]
New wraps a given enum variable (satisfying constraints.Integer) so that it can be used as a flag Value with github.com/spf13/pflag.Var and github.com/spf13/pflag.VarP. In case no default enum value should be set and therefore no default shown in spf13/cobra, use NewWithoutDefault instead.
func NewSlice ¶
func NewSlice[E constraints.Integer](flag *[]E, typename string, mapping EnumIdentifiers[E], sensitivity EnumCaseSensitivity) *EnumFlagValue[E]
NewSlice wraps a given enum slice variable (satisfying constraints.Integer) so that it can be used as a flag Value with github.com/spf13/pflag.Var and github.com/spf13/pflag.VarP.
func NewWithoutDefault ¶
func NewWithoutDefault[E constraints.Integer](flag *E, typename string, mapping EnumIdentifiers[E], sensitivity EnumCaseSensitivity) *EnumFlagValue[E]
NewWithoutDefault wraps a given enum variable (satisfying constraints.Integer) so that it can be used as a flag Value with github.com/spf13/pflag.Var and github.com/spf13/pflag.VarP. Please note that the zero enum value must not be mapped and thus not be assigned to any enum value textual representation.
spf13/cobra won't show any default value in its help for CLI enum flags created with NewWithoutDefault.
func (*EnumFlagValue[E]) Get ¶
func (e *EnumFlagValue[E]) Get() any
Get returns the current enum value for convenience. Please note that the enum value is either scalar or slice, depending on how the enum flag was created.
func (*EnumFlagValue[E]) RegisterCompletion ¶ added in v2.0.4
RegisterCompletion registers completions for the specified (flag) name, with optional help texts.
func (*EnumFlagValue[E]) Set ¶
func (e *EnumFlagValue[E]) Set(val string) error
Set sets the enum flag to the specified enum value. If the specified value isn't a valid enum value, then the enum flag won't be set and an error is returned instead.
func (*EnumFlagValue[E]) String ¶
func (e *EnumFlagValue[E]) String() string
String returns the textual representation of an enumeration (flag) value. In case multiple textual representations (~identifiers) exist for the same enumeration value, then only the first textual representation is returned, which is considered to be the canonical one.
func (*EnumFlagValue[E]) Type ¶
func (e *EnumFlagValue[E]) Type() string
Type returns the name of the flag value type. The type name is used in error messages.
type EnumIdentifiers ¶
type EnumIdentifiers[E constraints.Integer] map[E][]string
EnumIdentifiers maps enumeration values to their corresponding textual representations (~identifiers). This mapping is a one-to-many mapping in that the same enumeration value may have more than only one associated textual representation (indentifier). If more than one textual representation exists for the same enumeration value, then the first textual representation is considered to be the canonical one.
type Flag ¶
type Flag uint
Flag represents a CLI (enumeration) flag which can take on only a single enumeration value out of a fixed set of enumeration values. Applications using the enumflag package might want to “derive” their enumeration flags from Flag for documentation purposes; for instance:
type MyFoo enumflag.Flag
However, applications don't need to base their own enum types on Flag. The only requirement for user-defined enumeration flags is that they must be (“somewhat”) compatible with the Flag type, or more precise: user-defined enumerations must satisfy constraints.Integer.
type Help ¶ added in v2.0.4
type Help[E constraints.Integer] map[E]string
Help maps enumeration values to their corresponding help descriptions. These descriptions should contain just the description but without any "foo\t" enum value prefix. The reason is that enumflag will automatically register the correct (erm, “complete”) completion text. Please note that it isn't necessary to supply any help texts in order to register enum flag completion.