cli

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 18, 2022 License: Apache-2.0 Imports: 10 Imported by: 8

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/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"
	keyWorkers  = "app.child.workers"
	keyDry      = "run.dryRun"
)

// globalFlags captures CLI flags.
//
// In this example, we choose to control over where the flag values are stored.
//
// This is not needed if all configuration is bound to viper.
var globalFlags cliFlags

type (
	cliFlags struct {
		DryRun   bool
		URL      string
		Parallel int
		User     string
		LogLevel string

		Child childFlags
	}

	childFlags struct {
		Workers int
	}
)

// Default values for flags.
func (f cliFlags) Defaults() cliFlags {
	return cliFlags{
		URL:      "https://www.example.com",
		Parallel: 2,
		LogLevel: "info",
		Child: childFlags{
			Workers: 5,
		},
	}
}

// applyDefaults set default values for the config. It is consistent with flag defaults.
func (f cliFlags) applyDefaults(cfg *viper.Viper) {
	cfg.SetDefault(keyURL, globalFlags.Defaults().URL)
	cfg.SetDefault(keyParallel, globalFlags.Defaults().Parallel)
	cfg.SetDefault(keyLog, globalFlags.Defaults().LogLevel)
	cfg.SetDefault(keyWorkers, globalFlags.Defaults().Child.Workers)
}

// root command execution
func rootRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())
	if cfg == nil {
		cli.Die("failed to retrieve config")
	}

	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)),
	)

	fmt.Println(
		"global flags values evaluated by root\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

// child command execution
func childRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	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)),
	)

	fmt.Println(
		"global flags values evaluated by child\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

func emptyRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	fmt.Println("command called:", c.Name())
	fmt.Println("injected config:", cfg.AllSettings())

	return nil
}

// RootCmd illustrates the scaffolding of a command tree with explicit storage of the CLI flags and default values.
func RootCmd() *cli.Command {

	return cli.NewCommand(
		&cobra.Command{
			Use:   "example",
			Short: "examplifies a cobra command",
			Long:  "...",
			RunE:  rootRunFunc,
		},
		cli.WithFlagVar(&globalFlags.DryRun, "dry-run", globalFlags.Defaults().DryRun, "Dry run",
			cli.BindFlagToConfig(keyDry),
		),
		cli.WithFlagVar(&globalFlags.LogLevel, "log-level", globalFlags.Defaults().LogLevel, "Controls logging verbosity",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyLog),
		),
		cli.WithFlagVar(&globalFlags.URL, "url", globalFlags.Defaults().URL, "The URL to connect to",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyURL),
		),
		cli.WithFlagVarP(&globalFlags.Parallel, "parallel", "p", globalFlags.Defaults().Parallel, "Degree of parallelism",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyParallel),
		),

		cli.WithFlagFunc(func(flags *pflag.FlagSet) string {
			const userFlag = "user"
			flags.StringVar(&globalFlags.User, userFlag, globalFlags.Defaults().User, "Originating user")
			return userFlag
		},
			cli.FlagIsPersistent(),
			cli.FlagIsRequired(),
			cli.BindFlagToConfig(keyUser),
		),
		cli.WithSubCommands(
			cli.NewCommand(
				&cobra.Command{
					Use:   "child",
					Short: "sub-command example",
					Long:  "...",
					RunE:  childRunFunc,
				},
				cli.WithFlagVar(&globalFlags.Child.Workers, "workers", globalFlags.Defaults().Child.Workers, "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(globalFlags.applyDefaults)),
	)
}

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

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 (Help)
package main

import (
	"fmt"
	"log"

	"github.com/fredbi/go-cli/cli"
	"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"
	keyWorkers  = "app.child.workers"
	keyDry      = "run.dryRun"
)

// globalFlags captures CLI flags.
//
// In this example, we choose to control over where the flag values are stored.
//
// This is not needed if all configuration is bound to viper.
var globalFlags cliFlags

type (
	cliFlags struct {
		DryRun   bool
		URL      string
		Parallel int
		User     string
		LogLevel string

		Child childFlags
	}

	childFlags struct {
		Workers int
	}
)

// Default values for flags.
func (f cliFlags) Defaults() cliFlags {
	return cliFlags{
		URL:      "https://www.example.com",
		Parallel: 2,
		LogLevel: "info",
		Child: childFlags{
			Workers: 5,
		},
	}
}

// applyDefaults set default values for the config. It is consistent with flag defaults.
func (f cliFlags) applyDefaults(cfg *viper.Viper) {
	cfg.SetDefault(keyURL, globalFlags.Defaults().URL)
	cfg.SetDefault(keyParallel, globalFlags.Defaults().Parallel)
	cfg.SetDefault(keyLog, globalFlags.Defaults().LogLevel)
	cfg.SetDefault(keyWorkers, globalFlags.Defaults().Child.Workers)
}

// root command execution
func rootRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())
	if cfg == nil {
		cli.Die("failed to retrieve config")
	}

	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)),
	)

	fmt.Println(
		"global flags values evaluated by root\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

// child command execution
func childRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	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)),
	)

	fmt.Println(
		"global flags values evaluated by child\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

func emptyRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	fmt.Println("command called:", c.Name())
	fmt.Println("injected config:", cfg.AllSettings())

	return nil
}

// RootCmd illustrates the scaffolding of a command tree with explicit storage of the CLI flags and default values.
func RootCmd() *cli.Command {

	return cli.NewCommand(
		&cobra.Command{
			Use:   "example",
			Short: "examplifies a cobra command",
			Long:  "...",
			RunE:  rootRunFunc,
		},
		cli.WithFlagVar(&globalFlags.DryRun, "dry-run", globalFlags.Defaults().DryRun, "Dry run",
			cli.BindFlagToConfig(keyDry),
		),
		cli.WithFlagVar(&globalFlags.LogLevel, "log-level", globalFlags.Defaults().LogLevel, "Controls logging verbosity",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyLog),
		),
		cli.WithFlagVar(&globalFlags.URL, "url", globalFlags.Defaults().URL, "The URL to connect to",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyURL),
		),
		cli.WithFlagVarP(&globalFlags.Parallel, "parallel", "p", globalFlags.Defaults().Parallel, "Degree of parallelism",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyParallel),
		),

		cli.WithFlagFunc(func(flags *pflag.FlagSet) string {
			const userFlag = "user"
			flags.StringVar(&globalFlags.User, userFlag, globalFlags.Defaults().User, "Originating user")
			return userFlag
		},
			cli.FlagIsPersistent(),
			cli.FlagIsRequired(),
			cli.BindFlagToConfig(keyUser),
		),
		cli.WithSubCommands(
			cli.NewCommand(
				&cobra.Command{
					Use:   "child",
					Short: "sub-command example",
					Long:  "...",
					RunE:  childRunFunc,
				},
				cli.WithFlagVar(&globalFlags.Child.Workers, "workers", globalFlags.Defaults().Child.Workers, "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(globalFlags.applyDefaults)),
	)
}

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/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"
	keyWorkers  = "app.child.workers"
	keyDry      = "run.dryRun"
)

// globalFlags captures CLI flags.
//
// In this example, we choose to control over where the flag values are stored.
//
// This is not needed if all configuration is bound to viper.
var globalFlags cliFlags

type (
	cliFlags struct {
		DryRun   bool
		URL      string
		Parallel int
		User     string
		LogLevel string

		Child childFlags
	}

	childFlags struct {
		Workers int
	}
)

// Default values for flags.
func (f cliFlags) Defaults() cliFlags {
	return cliFlags{
		URL:      "https://www.example.com",
		Parallel: 2,
		LogLevel: "info",
		Child: childFlags{
			Workers: 5,
		},
	}
}

// applyDefaults set default values for the config. It is consistent with flag defaults.
func (f cliFlags) applyDefaults(cfg *viper.Viper) {
	cfg.SetDefault(keyURL, globalFlags.Defaults().URL)
	cfg.SetDefault(keyParallel, globalFlags.Defaults().Parallel)
	cfg.SetDefault(keyLog, globalFlags.Defaults().LogLevel)
	cfg.SetDefault(keyWorkers, globalFlags.Defaults().Child.Workers)
}

// root command execution
func rootRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())
	if cfg == nil {
		cli.Die("failed to retrieve config")
	}

	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)),
	)

	fmt.Println(
		"global flags values evaluated by root\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

// child command execution
func childRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	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)),
	)

	fmt.Println(
		"global flags values evaluated by child\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

func emptyRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	fmt.Println("command called:", c.Name())
	fmt.Println("injected config:", cfg.AllSettings())

	return nil
}

// RootCmd illustrates the scaffolding of a command tree with explicit storage of the CLI flags and default values.
func RootCmd() *cli.Command {

	return cli.NewCommand(
		&cobra.Command{
			Use:   "example",
			Short: "examplifies a cobra command",
			Long:  "...",
			RunE:  rootRunFunc,
		},
		cli.WithFlagVar(&globalFlags.DryRun, "dry-run", globalFlags.Defaults().DryRun, "Dry run",
			cli.BindFlagToConfig(keyDry),
		),
		cli.WithFlagVar(&globalFlags.LogLevel, "log-level", globalFlags.Defaults().LogLevel, "Controls logging verbosity",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyLog),
		),
		cli.WithFlagVar(&globalFlags.URL, "url", globalFlags.Defaults().URL, "The URL to connect to",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyURL),
		),
		cli.WithFlagVarP(&globalFlags.Parallel, "parallel", "p", globalFlags.Defaults().Parallel, "Degree of parallelism",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyParallel),
		),

		cli.WithFlagFunc(func(flags *pflag.FlagSet) string {
			const userFlag = "user"
			flags.StringVar(&globalFlags.User, userFlag, globalFlags.Defaults().User, "Originating user")
			return userFlag
		},
			cli.FlagIsPersistent(),
			cli.FlagIsRequired(),
			cli.BindFlagToConfig(keyUser),
		),
		cli.WithSubCommands(
			cli.NewCommand(
				&cobra.Command{
					Use:   "child",
					Short: "sub-command example",
					Long:  "...",
					RunE:  childRunFunc,
				},
				cli.WithFlagVar(&globalFlags.Child.Workers, "workers", globalFlags.Defaults().Child.Workers, "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(globalFlags.applyDefaults)),
	)
}

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/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"
	keyWorkers  = "app.child.workers"
	keyDry      = "run.dryRun"
)

// globalFlags captures CLI flags.
//
// In this example, we choose to control over where the flag values are stored.
//
// This is not needed if all configuration is bound to viper.
var globalFlags cliFlags

type (
	cliFlags struct {
		DryRun   bool
		URL      string
		Parallel int
		User     string
		LogLevel string

		Child childFlags
	}

	childFlags struct {
		Workers int
	}
)

// Default values for flags.
func (f cliFlags) Defaults() cliFlags {
	return cliFlags{
		URL:      "https://www.example.com",
		Parallel: 2,
		LogLevel: "info",
		Child: childFlags{
			Workers: 5,
		},
	}
}

// applyDefaults set default values for the config. It is consistent with flag defaults.
func (f cliFlags) applyDefaults(cfg *viper.Viper) {
	cfg.SetDefault(keyURL, globalFlags.Defaults().URL)
	cfg.SetDefault(keyParallel, globalFlags.Defaults().Parallel)
	cfg.SetDefault(keyLog, globalFlags.Defaults().LogLevel)
	cfg.SetDefault(keyWorkers, globalFlags.Defaults().Child.Workers)
}

// root command execution
func rootRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())
	if cfg == nil {
		cli.Die("failed to retrieve config")
	}

	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)),
	)

	fmt.Println(
		"global flags values evaluated by root\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

// child command execution
func childRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	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)),
	)

	fmt.Println(
		"global flags values evaluated by child\n",
		fmt.Sprintf("%#v", globalFlags),
	)

	return nil
}

func emptyRunFunc(c *cobra.Command, _ []string) error {
	cfg := cli.ConfigFromContext(c.Context())

	fmt.Println("command called:", c.Name())
	fmt.Println("injected config:", cfg.AllSettings())

	return nil
}

// RootCmd illustrates the scaffolding of a command tree with explicit storage of the CLI flags and default values.
func RootCmd() *cli.Command {

	return cli.NewCommand(
		&cobra.Command{
			Use:   "example",
			Short: "examplifies a cobra command",
			Long:  "...",
			RunE:  rootRunFunc,
		},
		cli.WithFlagVar(&globalFlags.DryRun, "dry-run", globalFlags.Defaults().DryRun, "Dry run",
			cli.BindFlagToConfig(keyDry),
		),
		cli.WithFlagVar(&globalFlags.LogLevel, "log-level", globalFlags.Defaults().LogLevel, "Controls logging verbosity",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyLog),
		),
		cli.WithFlagVar(&globalFlags.URL, "url", globalFlags.Defaults().URL, "The URL to connect to",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyURL),
		),
		cli.WithFlagVarP(&globalFlags.Parallel, "parallel", "p", globalFlags.Defaults().Parallel, "Degree of parallelism",
			cli.FlagIsPersistent(),
			cli.BindFlagToConfig(keyParallel),
		),

		cli.WithFlagFunc(func(flags *pflag.FlagSet) string {
			const userFlag = "user"
			flags.StringVar(&globalFlags.User, userFlag, globalFlags.Defaults().User, "Originating user")
			return userFlag
		},
			cli.FlagIsPersistent(),
			cli.FlagIsRequired(),
			cli.BindFlagToConfig(keyUser),
		),
		cli.WithSubCommands(
			cli.NewCommand(
				&cobra.Command{
					Use:   "child",
					Short: "sub-command example",
					Long:  "...",
					RunE:  childRunFunc,
				},
				cli.WithFlagVar(&globalFlags.Child.Workers, "workers", globalFlags.Defaults().Child.Workers, "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(globalFlags.applyDefaults)),
	)
}

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

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

Index

Examples

Constants

This section is empty.

Variables

View Source
var (

	// ConfigEnv defines the environment variable used by the Config() function
	// to find the current environment.
	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

func Config(defaulters ...func(*viper.Viper)) *viper.Viper

Config calls ConfigForEnv, with the current environment resolved from the variable "CONFIG_ENV".

func ConfigForEnv

func ConfigForEnv(env string, defaulters ...func(*viper.Viper)) *viper.Viper

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.

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 ConfigFromContext

func ConfigFromContext(ctx context.Context) *viper.Viper

ConfigFromContext retrieves a configuration registry from the context.

func ContextWithConfig

func ContextWithConfig(ctx context.Context, cfg *viper.Viper) context.Context

ContextWithConfig puts a configuration registry in the context.

func Die

func Die(format string, args ...any)

Die exits the current process with some final croak.

This wraps log.Fatal for convenient testing.

func Must

func Must(err error)

Must panic on error.

func MustBindFromFlagSet

func MustBindFromFlagSet(cfg *viper.Viper, key, flagName string, flags *pflag.FlagSet)

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 set is nil or if the requested flag has not been registered in the flag set yet.

func MustBindPFlag

func MustBindPFlag(cfg *viper.Viper, key string, flag *pflag.Flag)

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 SetConfigOptions

func SetConfigOptions(opts ...config.Option)

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.

func SetDie

func SetDie(fatalFunc func(string, ...any))

SetDie alters the package level log.Fatalf implementation.

This should be used for testing only.

Types

type Command

type Command struct {
	*cobra.Command
	// contains filtered or unexported fields
}

Command wraps a *cobra.Command with some options to register and bind flags more easily.

func NewCommand

func NewCommand(cmd *cobra.Command, opts ...Option) *Command

NewCommand builds a new Command wrapping a *cobra.Command.

func (*Command) AddCommand

func (c *Command) AddCommand(subs ...*Command)

AddCommand adds child command(s).

func (*Command) BindFlags

func (c *Command) BindFlags()

BindFlags binds the command-line flags marked as such to the configuration registry.

This applies recursively to all sub-commands.

It doesn't perform anything if no flags or no config are set for the command (use the options WithFlagVar() and WithConfig())

func (*Command) Commands

func (c *Command) Commands() []*Command

Commands returns the child commands.

func (*Command) Config

func (c *Command) Config() *viper.Viper

Config returns the viper config registry shared by the command tree.

func (*Command) ExecuteContext

func (c *Command) ExecuteContext(ctx context.Context) error

ExecuteContext wraps cobra.Command.ExecuteContext() by ensuring the config is in the context.

func (*Command) ExecuteWithArgs

func (c *Command) ExecuteWithArgs(args ...string) error

ExecuteWithArgs is a convenience wrapper to execute a command with preset args.

This is primarily intended for testing commands.

func (*Command) RegisterFlags

func (c *Command) RegisterFlags()

Register command-line flags for this command.

func (*Command) String

func (c *Command) String() string

String provides a short text representation of the command subtree.

type FlagOption

type FlagOption func(*flagOption)

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 WithConfig

func WithConfig(cfg *viper.Viper) Option

WithConfig adds a viper.Viper configuration to the command tree.

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 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

func WithSubCommands(subs ...*Command) Option

WithSubCommands adds child commands.

type RegisterFunc

type RegisterFunc func(*pflag.FlagSet) string

RegisterFunc registers a flag to a provided pflag.FlagSet and returns the flag name.

Directories

Path Synopsis
Package gflag exposes generic types to deal with flags.
Package gflag exposes generic types to deal with flags.
extensions
Package extensions provides extensions to the github.com/spf13/pflag package.
Package extensions provides extensions to the github.com/spf13/pflag package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL