Documentation ¶
Overview ¶
Package cli exposes helpers to build command-line binaries with cobra and viper.
Example (ChildCmd) ¶
Example_childCmd runs a child command.
package main import ( "fmt" "log" "github.com/fredbi/go-cli/cli" "github.com/fredbi/go-cli/cli/injectable" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" ) // config key mappings const ( keyLog = "app.log.level" keyURL = "app.url" keyParallel = "app.parallel" keyUser = "app.user" keyDry = "run.dryRun" keyWorkers = "app.child.workers" ) // root command execution func rootRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "example called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("log level config: %s\n", cfg.GetString(keyLog)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), ) return nil } // child command execution func childRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "subcommand called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), fmt.Sprintf("workers config: %s\n", cfg.GetString(keyWorkers)), ) return nil } // noop command execution func emptyRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println("command called:", c.Name()) fmt.Println("injected config:", cfg.AllSettings()) return nil } // nolint: dupl // RootCmd illustrates the scaffolding of a command tree without any explicit storage of the CLI flags and default values. // // TODO: binding a flag to the config should trigger a SetDefault in the config. Problem: should be done before loading, // HENCE config loader should be lazy. // TODO: explicit BindEnv for env variables (default is auto) => done with Config pkg. Provide example. func RootCmd() *cli.Command { return cli.NewCommand( &cobra.Command{ Use: "example", Short: "examplifies a cobra command", Long: "...", RunE: rootRunFunc, }, cli.WithFlag("dry-run", false, "Dry run"), cli.WithFlag("log-level", "info", "Controls logging verbosity", cli.FlagIsPersistent(), ), cli.WithFlag("url", "https://www.example.com", "The URL to connect to", cli.FlagIsPersistent(), ), cli.WithFlagP("parallel", "p", 2, "Degree of parallelism", cli.FlagIsPersistent(), ), cli.WithFlagFunc(func(flags *pflag.FlagSet) string { const userFlag = "user" flags.String(userFlag, "", "Originating user") return userFlag }, cli.FlagIsPersistent(), cli.FlagIsRequired(), ), cli.WithBindPersistentFlagsToConfig(map[string]string{ "log-level": keyLog, "url": keyURL, "parallel": keyParallel, "user": keyUser, }), cli.WithBindFlagsToConfig(map[string]string{ "dry-run": keyDry, }), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "child", Short: "sub-command example", Long: "...", RunE: childRunFunc, }, cli.WithFlag("workers", 5, "Number of workers threads", cli.FlagIsRequired(), cli.BindFlagToConfig(keyWorkers), ), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "grandchild", Short: "sub-sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), ), cli.NewCommand( &cobra.Command{ Use: "version", Short: "another sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), cli.WithConfig(cli.Config()), ) } func main() { rootCmd := RootCmd() if err := rootCmd.ExecuteWithArgs( "child", "--parallel", "20", "--url", "https://www.zorg.com", "--user", "zorg", "--workers", "12", ); err != nil { log.Fatal("executing:", err) } fmt.Println("done") }
Output: subcommand called URL config: https://www.zorg.com parallel config: 20 user config: zorg workers config: 12 done
Example (Defaults) ¶
package main import ( "fmt" "log" "github.com/fredbi/go-cli/cli" "github.com/fredbi/go-cli/cli/injectable" "github.com/spf13/cobra" "github.com/spf13/viper" ) func main() { if err := RootCmdWithDefaults(). ExecuteWithArgs("defaults"); err != nil { log.Fatal("executing:", err) } } func RootCmdWithDefaults() *cli.Command { return cli.NewCommand( &cobra.Command{ Use: "defaults", Short: "examplifies a cobra command with defaults settings", Long: "this command shows how config defaults can be set from flags, and supplemented with non-flag defaults", RunE: rootWithDefaultsRunFunc, }, cli.WithFlag("log-level", "info", "Controls logging verbosity", cli.FlagIsPersistent(), cli.BindFlagToConfig(keyLog), ), cli.WithConfig(cli.Config(func(v *viper.Viper) { v.SetDefault("nonFlagKey", 10.345) })), cli.WithAutoVersion(), ) } func rootWithDefaultsRunFunc(cmd *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(cmd.Context(), viper.New) fmt.Println(cfg.AllSettings()) return nil }
Output: map[app:map[log:map[level:info]] nonflagkey:10.345]
Example (GlobalChildCmd) ¶
Example_childCmd runs a child command.
rootCmd := RootCmdWithGlobal() if err := rootCmd.ExecuteWithArgs( "child", "--parallel", "20", "--url", "https://www.zorg.com", "--user", "zorg", "--workers", "12", ); err != nil { log.Fatal("executing:", err) } fmt.Println("done")
Output: subcommand called URL config: https://www.zorg.com parallel config: 20 user config: zorg workers config: 12 global flags values evaluated by child cli_test.cliFlags{DryRun:false, URL:"https://www.zorg.com", Parallel:20, User:"zorg", LogLevel:"info", Child:cli_test.childFlags{Workers:12}} done
Example (GlobalRootCmd) ¶
rootCmd := RootCmdWithGlobal() rootCmd.SetArgs([]string{ "--dry-run", "--log-level", "debug", "--parallel", "15", "--user", "fred", }, ) if err := rootCmd.Execute(); err != nil { log.Fatal("executing:", err) } fmt.Println("done")
Output: example called URL config: https://www.example.com log level config: debug parallel config: 15 user config: fred global flags values evaluated by root cli_test.cliFlags{DryRun:true, URL:"https://www.example.com", Parallel:15, User:"fred", LogLevel:"debug", Child:cli_test.childFlags{Workers:5}} done
Example (Help) ¶
package main import ( "fmt" "log" "github.com/fredbi/go-cli/cli" "github.com/fredbi/go-cli/cli/injectable" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" ) // config key mappings const ( keyLog = "app.log.level" keyURL = "app.url" keyParallel = "app.parallel" keyUser = "app.user" keyDry = "run.dryRun" keyWorkers = "app.child.workers" ) // root command execution func rootRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "example called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("log level config: %s\n", cfg.GetString(keyLog)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), ) return nil } // child command execution func childRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "subcommand called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), fmt.Sprintf("workers config: %s\n", cfg.GetString(keyWorkers)), ) return nil } // noop command execution func emptyRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println("command called:", c.Name()) fmt.Println("injected config:", cfg.AllSettings()) return nil } // nolint: dupl // RootCmd illustrates the scaffolding of a command tree without any explicit storage of the CLI flags and default values. // // TODO: binding a flag to the config should trigger a SetDefault in the config. Problem: should be done before loading, // HENCE config loader should be lazy. // TODO: explicit BindEnv for env variables (default is auto) => done with Config pkg. Provide example. func RootCmd() *cli.Command { return cli.NewCommand( &cobra.Command{ Use: "example", Short: "examplifies a cobra command", Long: "...", RunE: rootRunFunc, }, cli.WithFlag("dry-run", false, "Dry run"), cli.WithFlag("log-level", "info", "Controls logging verbosity", cli.FlagIsPersistent(), ), cli.WithFlag("url", "https://www.example.com", "The URL to connect to", cli.FlagIsPersistent(), ), cli.WithFlagP("parallel", "p", 2, "Degree of parallelism", cli.FlagIsPersistent(), ), cli.WithFlagFunc(func(flags *pflag.FlagSet) string { const userFlag = "user" flags.String(userFlag, "", "Originating user") return userFlag }, cli.FlagIsPersistent(), cli.FlagIsRequired(), ), cli.WithBindPersistentFlagsToConfig(map[string]string{ "log-level": keyLog, "url": keyURL, "parallel": keyParallel, "user": keyUser, }), cli.WithBindFlagsToConfig(map[string]string{ "dry-run": keyDry, }), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "child", Short: "sub-command example", Long: "...", RunE: childRunFunc, }, cli.WithFlag("workers", 5, "Number of workers threads", cli.FlagIsRequired(), cli.BindFlagToConfig(keyWorkers), ), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "grandchild", Short: "sub-sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), ), cli.NewCommand( &cobra.Command{ Use: "version", Short: "another sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), cli.WithConfig(cli.Config()), ) } func main() { rootCmd := RootCmd() rootCmd.SetArgs([]string{ "--help", }) if err := rootCmd.Execute(); err != nil { log.Fatal("executing:", err) } fmt.Println("done") }
Output: ... Usage: example [flags] example [command] Available Commands: child sub-command example completion Generate the autocompletion script for the specified shell help Help about any command version another sub-command example Flags: --dry-run Dry run -h, --help help for example --log-level string Controls logging verbosity (default "info") -p, --parallel int Degree of parallelism (default 2) --url string The URL to connect to (default "https://www.example.com") --user string Originating user Use "example [command] --help" for more information about a command. done
Example (PrintCmd) ¶
Example_printCmd prints out the tree structure of the root command.
package main import ( "fmt" "github.com/fredbi/go-cli/cli" "github.com/fredbi/go-cli/cli/injectable" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" ) // config key mappings const ( keyLog = "app.log.level" keyURL = "app.url" keyParallel = "app.parallel" keyUser = "app.user" keyDry = "run.dryRun" keyWorkers = "app.child.workers" ) // root command execution func rootRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "example called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("log level config: %s\n", cfg.GetString(keyLog)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), ) return nil } // child command execution func childRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "subcommand called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), fmt.Sprintf("workers config: %s\n", cfg.GetString(keyWorkers)), ) return nil } // noop command execution func emptyRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println("command called:", c.Name()) fmt.Println("injected config:", cfg.AllSettings()) return nil } // nolint: dupl // RootCmd illustrates the scaffolding of a command tree without any explicit storage of the CLI flags and default values. // // TODO: binding a flag to the config should trigger a SetDefault in the config. Problem: should be done before loading, // HENCE config loader should be lazy. // TODO: explicit BindEnv for env variables (default is auto) => done with Config pkg. Provide example. func RootCmd() *cli.Command { return cli.NewCommand( &cobra.Command{ Use: "example", Short: "examplifies a cobra command", Long: "...", RunE: rootRunFunc, }, cli.WithFlag("dry-run", false, "Dry run"), cli.WithFlag("log-level", "info", "Controls logging verbosity", cli.FlagIsPersistent(), ), cli.WithFlag("url", "https://www.example.com", "The URL to connect to", cli.FlagIsPersistent(), ), cli.WithFlagP("parallel", "p", 2, "Degree of parallelism", cli.FlagIsPersistent(), ), cli.WithFlagFunc(func(flags *pflag.FlagSet) string { const userFlag = "user" flags.String(userFlag, "", "Originating user") return userFlag }, cli.FlagIsPersistent(), cli.FlagIsRequired(), ), cli.WithBindPersistentFlagsToConfig(map[string]string{ "log-level": keyLog, "url": keyURL, "parallel": keyParallel, "user": keyUser, }), cli.WithBindFlagsToConfig(map[string]string{ "dry-run": keyDry, }), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "child", Short: "sub-command example", Long: "...", RunE: childRunFunc, }, cli.WithFlag("workers", 5, "Number of workers threads", cli.FlagIsRequired(), cli.BindFlagToConfig(keyWorkers), ), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "grandchild", Short: "sub-sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), ), cli.NewCommand( &cobra.Command{ Use: "version", Short: "another sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), cli.WithConfig(cli.Config()), ) } func main() { rootCmd := RootCmd() fmt.Println(rootCmd.String()) }
Output: example child grandchild version
Example (RootCmd) ¶
Example_rootCmd runs the root command.
package main import ( "fmt" "log" "github.com/fredbi/go-cli/cli" "github.com/fredbi/go-cli/cli/injectable" "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" ) // config key mappings const ( keyLog = "app.log.level" keyURL = "app.url" keyParallel = "app.parallel" keyUser = "app.user" keyDry = "run.dryRun" keyWorkers = "app.child.workers" ) // root command execution func rootRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "example called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("log level config: %s\n", cfg.GetString(keyLog)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), ) return nil } // child command execution func childRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println( "subcommand called\n", fmt.Sprintf("URL config: %s\n", cfg.GetString(keyURL)), fmt.Sprintf("parallel config: %d\n", cfg.GetInt(keyParallel)), fmt.Sprintf("user config: %s\n", cfg.GetString(keyUser)), fmt.Sprintf("workers config: %s\n", cfg.GetString(keyWorkers)), ) return nil } // noop command execution func emptyRunFunc(c *cobra.Command, _ []string) error { cfg := injectable.ConfigFromContext(c.Context(), viper.New) fmt.Println("command called:", c.Name()) fmt.Println("injected config:", cfg.AllSettings()) return nil } // nolint: dupl // RootCmd illustrates the scaffolding of a command tree without any explicit storage of the CLI flags and default values. // // TODO: binding a flag to the config should trigger a SetDefault in the config. Problem: should be done before loading, // HENCE config loader should be lazy. // TODO: explicit BindEnv for env variables (default is auto) => done with Config pkg. Provide example. func RootCmd() *cli.Command { return cli.NewCommand( &cobra.Command{ Use: "example", Short: "examplifies a cobra command", Long: "...", RunE: rootRunFunc, }, cli.WithFlag("dry-run", false, "Dry run"), cli.WithFlag("log-level", "info", "Controls logging verbosity", cli.FlagIsPersistent(), ), cli.WithFlag("url", "https://www.example.com", "The URL to connect to", cli.FlagIsPersistent(), ), cli.WithFlagP("parallel", "p", 2, "Degree of parallelism", cli.FlagIsPersistent(), ), cli.WithFlagFunc(func(flags *pflag.FlagSet) string { const userFlag = "user" flags.String(userFlag, "", "Originating user") return userFlag }, cli.FlagIsPersistent(), cli.FlagIsRequired(), ), cli.WithBindPersistentFlagsToConfig(map[string]string{ "log-level": keyLog, "url": keyURL, "parallel": keyParallel, "user": keyUser, }), cli.WithBindFlagsToConfig(map[string]string{ "dry-run": keyDry, }), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "child", Short: "sub-command example", Long: "...", RunE: childRunFunc, }, cli.WithFlag("workers", 5, "Number of workers threads", cli.FlagIsRequired(), cli.BindFlagToConfig(keyWorkers), ), cli.WithSubCommands( cli.NewCommand( &cobra.Command{ Use: "grandchild", Short: "sub-sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), ), cli.NewCommand( &cobra.Command{ Use: "version", Short: "another sub-command example", Long: "...", RunE: emptyRunFunc, }, ), ), cli.WithConfig(cli.Config()), ) } func main() { rootCmd := RootCmd() rootCmd.SetArgs([]string{ "--dry-run", "--log-level", "debug", "--parallel", "15", "--user", "fred", }, ) if err := rootCmd.Execute(); err != nil { log.Fatal("executing:", err) } fmt.Println("done") }
Output: example called URL config: https://www.example.com log level config: debug parallel config: 15 user config: fred done
Index ¶
- Variables
- func Config(defaulters ...func(*viper.Viper)) *viper.Viper
- func ConfigForEnv(env string, defaulters ...func(*viper.Viper)) *viper.Viper
- func ConfigForEnvWithOptions(env string, opts []config.Option, defaulters ...func(*viper.Viper)) *viper.Viper
- func Die(format string, args ...any)
- func Must(err error)
- func MustBindFromFlagSet(cfg *viper.Viper, key, flagName string, flags *pflag.FlagSet)
- func MustBindPFlag(cfg *viper.Viper, key string, flag *pflag.Flag)
- func MustOrDie(msg string, err error)
- func SetConfigOptions(opts ...config.Option)
- func SetDie(fatalFunc func(string, ...any))
- type Command
- func (c *Command) AddCommand(subs ...*Command)
- func (c *Command) Commands() []*Command
- func (c *Command) Config() *viper.Viper
- func (c *Command) Execute() error
- func (c *Command) ExecuteContext(ctx context.Context) error
- func (c *Command) ExecuteWithArgs(args ...string) error
- func (c *Command) String() string
- type FlagOption
- type Option
- func WithAutoVersion() Option
- func WithBindFlagsToConfig(bindings map[string]string) Option
- func WithBindPersistentFlagsToConfig(bindings map[string]string) Option
- func WithCobraOptions(setters ...func(*cobra.Command)) Option
- func WithConfig(cfg *viper.Viper) Option
- func WithFlag[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name string, defaultValue T, usage string, opts ...FlagOption) Option
- func WithFlagFunc(regFunc RegisterFunc, opts ...FlagOption) Option
- func WithFlagP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name, shorthand string, defaultValue T, usage string, opts ...FlagOption) Option
- func WithFlagVar[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *T, name string, defaultValue T, usage string, opts ...FlagOption) Option
- func WithFlagVarP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *T, name, shorthand string, defaultValue T, usage string, ...) Option
- func WithInjectables(injectables ...injectable.ContextInjectable) Option
- func WithSliceFlag[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name string, defaultValue []T, usage string, opts ...FlagOption) Option
- func WithSliceFlagP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name, shorthand string, defaultValue []T, usage string, opts ...FlagOption) Option
- func WithSliceFlagVar[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *[]T, name string, defaultValue []T, usage string, opts ...FlagOption) Option
- func WithSliceFlagVarP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *[]T, name, shorthand string, defaultValue []T, usage string, ...) Option
- func WithSubCommands(subs ...*Command) Option
- func WithVersion(versionFunc func() string) Option
- type RegisterFunc
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ConfigEnv defines the environment variable used by the Config() function // to find the current environment (i.e. a deployment context such as "dev", "prod", etc.). ConfigEnv = "CONFIG_ENV" // ConfigDebugEnv defines the environment variable used to instruct the config loader // to dump all config keys for debugging. ConfigDebugEnv = "DEBUG_CONFIG" )
Functions ¶
func Config ¶
Config calls ConfigForEnv, with the current environment resolved from the variable "CONFIG_ENV".
NOTE: users of this package may override the `ConfigEnv` variable to use a different environment variable.
func ConfigForEnv ¶
ConfigForEnv loads and merge a set of config files for a given environment and applies some default values.
It assumes that config files follow the conventions defined by "github.com/fredbi/go-cli/config".
It dies upon failure.
Defaulters a applied after loading the config.
Environment variable settings:
- If the environment variable "DEBUG_CONFIG" is set, the loaded settings are dumped to standard output as JSON.
- The environment variable "CONFIG_DIR" defines the folder where the root configuration is located.
func ConfigForEnvWithOptions ¶ added in v0.1.1
func ConfigForEnvWithOptions(env string, opts []config.Option, defaulters ...func(*viper.Viper)) *viper.Viper
ConfigForEnvWithOptions loads and merge a set of config files for a given environment and applies some default values.
This function accepts some config.Options to control where and how the configuration files should be loaded.
func Die ¶
Die exits the current process with some final croak. By default, Die is a wrapper around log.Fatalf.
Use SetDie to alter this behavior (e.g. for mocking).
SetDie(nil) will make Die(format, args...) equivalent to panic(fmt.Sprintf(format, args...)).
This wraps log.Fatalf, essentially for testing purpose.
func MustBindFromFlagSet ¶
MustBindFromFlagSet binds a key in a *viper.Viper registry to command-line flag found in a flag set (*pflag.FlagSet).
Dies on error. This happens if the flag to be set is nil or if the requested flag has not been registered in the flag set yet.
func MustBindPFlag ¶
MustBindPlag binds a key in a *viper.Viper registry to a command-line flag (*pflag.Flag).
Dies on error. This happens if the flag is nil.
func MustOrDie ¶ added in v0.1.8
MustOrDie dies on error.
Croaks a message like log.Fatalf(msg + ": %v", err)
func SetConfigOptions ¶
SetConfigOption defines package-level defaults for config options, when using ConfigForEnv or Config.
By default, this package doesn't set any particular option and uses all defaults from the config package.
Types ¶
type Command ¶
Command wraps a *cobra.Command with some options to register and bind flags with a functional style.
func NewCommand ¶
NewCommand builds a new Command wrapping a *cobra.Command.
func (*Command) AddCommand ¶
AddCommand adds child command(s).
func (*Command) Execute ¶ added in v0.3.0
Execute the command, with a default context.Background().
It ensures that all injectables are in the context.
func (*Command) ExecuteContext ¶
ExecuteContext wraps cobra.Command.ExecuteContext().
It ensures that all injectables are in the context.
func (*Command) ExecuteWithArgs ¶
ExecuteWithArgs is a convenience wrapper to execute a command with preset args.
This is primarily intended for testing commands.
type FlagOption ¶
type FlagOption func(*flagOption)
FlagOption provides optional behavior to the CLI flags inlined in a Command definition.
func BindFlagToConfig ¶
func BindFlagToConfig(key string) FlagOption
BindFlagToConfig declares the flag as bound to a configuration key in the viper registry.
func FlagIsPersistent ¶ added in v0.1.1
func FlagIsPersistent() FlagOption
FlagIsPersistent declares the flag as persistent for the command.
func FlagIsRequired ¶
func FlagIsRequired() FlagOption
FlagIsRequired declares the flag as required for the command.
type Option ¶
type Option func(*options)
Option configures a Command.
func WithAutoVersion ¶ added in v0.1.3
func WithAutoVersion() Option
WithAutoVersion wires a "--version" flag using version.Resolve().
This collects versioning from package-level variables set at build time OR go module metadata.
func WithBindFlagsToConfig ¶ added in v0.1.3
WithBindFlagsToConfig binds all (non persistent) flags in the provided map to a config key.
The map is like map[string][string]{"flag-name": "viper-key"}
func WithBindPersistentFlagsToConfig ¶ added in v0.1.3
WithBindPersistentFlagsToConfig binds all persistent flags in the provided map to a config key.
The map is like map[string][string]{"flag-name": "viper-key"}
func WithCobraOptions ¶ added in v0.4.0
WithCobraOptions adds any setter that takes the cobra command as input.
This is useful to add some of the many setters available to the cobra API (e.g. SetHelpCommand(), SetHelpCommandGroupId() etc).
func WithConfig ¶
WithConfig adds a viper.Viper configuration to the command tree.
The config can be retrieved from the context of the command, using injectable.ConfigFromContext().
func WithFlag ¶
func WithFlag[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name string, defaultValue T, usage string, opts ...FlagOption) Option
WithFlag declares a flag of any type supported by gflag, with some options.
The pointer to the flag value is allocated automatically.
func WithFlagFunc ¶
func WithFlagFunc(regFunc RegisterFunc, opts ...FlagOption) Option
WithFlagFunc declares a command flag using a RegisterFunc function and some flag options.
func WithFlagP ¶
func WithFlagP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name, shorthand string, defaultValue T, usage string, opts ...FlagOption) Option
WithFlagP declares a flag of any type supported by gflag, with a shorthand name and some options.
The pointer to the flag value is allocated automatically.
func WithFlagVar ¶ added in v0.1.1
func WithFlagVar[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *T, name string, defaultValue T, usage string, opts ...FlagOption) Option
WithFlagVar declares a flag of any type supported by gflag, with some options.
The pointer to the flag value is provided explicitly.
func WithFlagVarP ¶ added in v0.1.1
func WithFlagVarP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *T, name, shorthand string, defaultValue T, usage string, opts ...FlagOption) Option
WithFlagVarP declares a flag of any type supported by gflag, with a shorthand name and some options.
The pointer to the flag value is provided explicitly.
func WithInjectables ¶ added in v0.1.2
func WithInjectables(injectables ...injectable.ContextInjectable) Option
WithInjectables adds dependencies to be injected in the context of the command.
For each injectable, its Context() method will be called in the specified order to enrich the context of the command.
NOTE: the config registry is a special dependency because it may bind to CLI flags.
Configuration may be injected directly with the more explicit WithConfig() method.
Example ¶
package main import ( "errors" "fmt" "log" "log/slog" "os" "github.com/fredbi/go-cli/cli" "github.com/fredbi/go-cli/cli/injectable" "github.com/spf13/cobra" ) func RootCmdWithDep() *cli.Command { return cli.NewCommand( &cobra.Command{ Use: "inject", Short: "examplifies a cobra command with dependency injection", Long: "in this example, we inject a logger in the context of the command (from log/slog)", RunE: rootWithDepRunFunc, }, cli.WithFlag("log-level", "info", "Controls logging verbosity", cli.FlagIsPersistent(), ), cli.WithInjectables( // injectables know how to be retrieved from context injectable.NewSLogger(slog.New(slog.NewJSONHandler(os.Stderr, nil))), ), ) } func rootWithDepRunFunc(cmd *cobra.Command, _ []string) error { // retrieve injected dependencies from the context of the command ctx := cmd.Context() logger := injectable.SLoggerFromContext(ctx).With("command", "root") if logger == nil { return errors.New("no logger provided") } fmt.Println("print log on stderr") logger.Info("structured log entry") return nil } func main() { rootCmd := RootCmdWithDep() rootCmd.SetArgs([]string{ "inject", "log-level", "info", }) if err := rootCmd.Execute(); err != nil { log.Fatal("executing:", err) } }
Output: print log on stderr
func WithSliceFlag ¶
func WithSliceFlag[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name string, defaultValue []T, usage string, opts ...FlagOption) Option
WithSliceFlag declares a flag of any slice type supported by gflag, with some options.
The pointer to the flag value is allocated automatically.
func WithSliceFlagP ¶
func WithSliceFlagP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](name, shorthand string, defaultValue []T, usage string, opts ...FlagOption) Option
WithSliceFlagP declares a flag of any slice type supported by gflag, with a shorthand name and some options.
The pointer to the flag value is allocated automatically.
func WithSliceFlagVar ¶ added in v0.1.1
func WithSliceFlagVar[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *[]T, name string, defaultValue []T, usage string, opts ...FlagOption) Option
WithSliceFlagVar declares a flag of any slice type supported by gflag, with some options.
The pointer to the flag value is provided explicitly.
func WithSliceFlagVarP ¶ added in v0.1.1
func WithSliceFlagVarP[T gflag.FlaggablePrimitives | gflag.FlaggableTypes](addr *[]T, name, shorthand string, defaultValue []T, usage string, opts ...FlagOption) Option
WithSliceFlagVarP declares a flag of any slice type supported by gflag, with a shorthand name and some options.
func WithSubCommands ¶
WithSubCommands adds child commands.
func WithVersion ¶ added in v0.1.3
WithVersion wires a "--version" flag from a function evaluated at command construction time.
type RegisterFunc ¶
RegisterFunc registers a flag to a provided pflag.FlagSet and returns the flag name.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
cli-utils
|
|
resolve
Package resolve provides a shorthand resolution for command context, config and logger as a one-liner.
|
Package resolve provides a shorthand resolution for command context, config and logger as a one-liner. |
version
Package version provides a built-in versioning based on the version of your go modules.
|
Package version provides a built-in versioning based on the version of your go modules. |
wait
Package wait exposes utilities to synchronize containers based on file or network port.
|
Package wait exposes utilities to synchronize containers based on file or network port. |