1340 lines
36 KiB
Go
1340 lines
36 KiB
Go
|
|
package core
|
||
|
|
|
||
|
|
import (
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"os"
|
||
|
|
"reflect"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Command represents a command that may be run by the user
|
||
|
|
type clirCommand struct {
|
||
|
|
name string
|
||
|
|
commandPath string
|
||
|
|
shortdescription string
|
||
|
|
longdescription string
|
||
|
|
subCommands []*clirCommand
|
||
|
|
subCommandsMap map[string]*clirCommand
|
||
|
|
longestSubcommand int
|
||
|
|
actionCallback CliAction
|
||
|
|
app *Cli
|
||
|
|
flags *flag.FlagSet
|
||
|
|
flagCount int
|
||
|
|
helpFlag bool
|
||
|
|
hidden bool
|
||
|
|
positionalArgsMap map[string]reflect.Value
|
||
|
|
sliceSeparator map[string]string
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewCommand creates a new Command.
|
||
|
|
// Description is optional — if omitted, i18n resolves it from the command path.
|
||
|
|
func newClirCommand(name string, description ...string) *clirCommand {
|
||
|
|
desc := ""
|
||
|
|
if len(description) > 0 {
|
||
|
|
desc = description[0]
|
||
|
|
}
|
||
|
|
result := &Command{
|
||
|
|
name: name,
|
||
|
|
shortdescription: desc,
|
||
|
|
subCommandsMap: make(map[string]*clirCommand),
|
||
|
|
hidden: false,
|
||
|
|
positionalArgsMap: make(map[string]reflect.Value),
|
||
|
|
sliceSeparator: make(map[string]string),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Init flagset so flags can be added before Run
|
||
|
|
result.setParentCommandPath("")
|
||
|
|
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) setParentCommandPath(parentCommandPath string) {
|
||
|
|
// Set up command path
|
||
|
|
if parentCommandPath != "" {
|
||
|
|
c.commandPath += parentCommandPath + " "
|
||
|
|
}
|
||
|
|
c.commandPath += c.name
|
||
|
|
|
||
|
|
// Set up flag set
|
||
|
|
c.flags = flag.NewFlagSet(c.commandPath, flag.ContinueOnError)
|
||
|
|
c.BoolFlag("help", "Get help on the '"+strings.ToLower(c.commandPath)+"' command.", &c.helpFlag)
|
||
|
|
|
||
|
|
// result.Flags.Usage = result.PrintHelp
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) inheritFlags(inheritFlags *flag.FlagSet) {
|
||
|
|
// inherit flags
|
||
|
|
inheritFlags.VisitAll(func(f *flag.Flag) {
|
||
|
|
if f.Name != "help" {
|
||
|
|
c.flags.Var(f.Value, f.Name, f.Usage)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) setApp(app *Cli) {
|
||
|
|
c.app = app
|
||
|
|
}
|
||
|
|
|
||
|
|
// parseFlags parses the given flags
|
||
|
|
func (c *clirCommand) parseFlags(args []string) error {
|
||
|
|
// Parse flags
|
||
|
|
// Suppress flag parse errors to stderr
|
||
|
|
|
||
|
|
c.flags.SetOutput(io.Discard)
|
||
|
|
|
||
|
|
// Credit: https://stackoverflow.com/a/74146375
|
||
|
|
var positionalArgs []string
|
||
|
|
for {
|
||
|
|
if err := c.flags.Parse(args); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
// Consume all the flags that were parsed as flags.
|
||
|
|
args = args[len(args)-c.flags.NArg():]
|
||
|
|
if len(args) == 0 {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
// There's at least one flag remaining and it must be a positional arg since
|
||
|
|
// we consumed all args that were parsed as flags. Consume just the first
|
||
|
|
// one, and retry parsing, since subsequent args may be flags.
|
||
|
|
positionalArgs = append(positionalArgs, args[0])
|
||
|
|
args = args[1:]
|
||
|
|
}
|
||
|
|
|
||
|
|
// Parse just the positional args so that flagset.Args()/flagset.NArgs()
|
||
|
|
// return the expected value.
|
||
|
|
// Note: This should never return an error.
|
||
|
|
err := c.flags.Parse(positionalArgs)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
if len(positionalArgs) > 0 {
|
||
|
|
return c.parsePositionalArgs(positionalArgs)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Run - Runs the Command with the given arguments
|
||
|
|
func (c *clirCommand) run(args []string) error {
|
||
|
|
|
||
|
|
// If we have arguments, process them
|
||
|
|
if len(args) > 0 {
|
||
|
|
// Check for subcommand
|
||
|
|
subcommand := c.subCommandsMap[args[0]]
|
||
|
|
if subcommand != nil {
|
||
|
|
return subcommand.run(args[1:])
|
||
|
|
}
|
||
|
|
|
||
|
|
// Parse flags
|
||
|
|
err := c.parseFlags(args)
|
||
|
|
if err != nil {
|
||
|
|
if c.app.errorHandler != nil {
|
||
|
|
return c.app.errorHandler(c.commandPath, err)
|
||
|
|
}
|
||
|
|
return E("cli.Run", fmt.Sprintf("see '%s --help' for usage", c.commandPath), err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Help takes precedence
|
||
|
|
if c.helpFlag {
|
||
|
|
c.PrintHelp()
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Do we have an action?
|
||
|
|
if c.actionCallback != nil {
|
||
|
|
return c.actionCallback()
|
||
|
|
}
|
||
|
|
|
||
|
|
// If we haven't specified a subcommand
|
||
|
|
// check for an app level default command
|
||
|
|
if c.app.defaultCommand != nil {
|
||
|
|
// Prevent recursion!
|
||
|
|
if c.app.defaultCommand != c {
|
||
|
|
// only run default command if no args passed
|
||
|
|
if len(args) == 0 {
|
||
|
|
return c.app.defaultCommand.run(args)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Nothing left we can do
|
||
|
|
c.PrintHelp()
|
||
|
|
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Action - Define an action from this command
|
||
|
|
func (c *clirCommand) Action(callback CliAction) *clirCommand {
|
||
|
|
c.actionCallback = callback
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// PrintHelp - Output the help text for this command
|
||
|
|
func (c *clirCommand) PrintHelp() {
|
||
|
|
c.app.PrintBanner()
|
||
|
|
|
||
|
|
commandTitle := c.commandPath
|
||
|
|
if c.shortdescription != "" {
|
||
|
|
commandTitle += " - " + c.shortdescription
|
||
|
|
}
|
||
|
|
// Ignore root command
|
||
|
|
if c.commandPath != c.name {
|
||
|
|
fmt.Println(commandTitle)
|
||
|
|
}
|
||
|
|
if c.longdescription != "" {
|
||
|
|
fmt.Println(c.longdescription + "\n")
|
||
|
|
}
|
||
|
|
if len(c.subCommands) > 0 {
|
||
|
|
fmt.Println("Available commands:")
|
||
|
|
fmt.Println("")
|
||
|
|
for _, subcommand := range c.subCommands {
|
||
|
|
if subcommand.isHidden() {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
spacer := strings.Repeat(" ", 3+c.longestSubcommand-len(subcommand.name))
|
||
|
|
isDefault := ""
|
||
|
|
if subcommand.isDefaultCommand() {
|
||
|
|
isDefault = "[default]"
|
||
|
|
}
|
||
|
|
fmt.Printf(" %s%s%s %s\n", subcommand.name, spacer, subcommand.shortdescription, isDefault)
|
||
|
|
}
|
||
|
|
fmt.Println("")
|
||
|
|
}
|
||
|
|
if c.flagCount > 0 {
|
||
|
|
fmt.Println("Flags:")
|
||
|
|
fmt.Println()
|
||
|
|
c.flags.SetOutput(os.Stdout)
|
||
|
|
c.flags.PrintDefaults()
|
||
|
|
c.flags.SetOutput(os.Stderr)
|
||
|
|
|
||
|
|
}
|
||
|
|
fmt.Println()
|
||
|
|
}
|
||
|
|
|
||
|
|
// isDefaultCommand returns true if called on the default command
|
||
|
|
func (c *clirCommand) isDefaultCommand() bool {
|
||
|
|
return c.app.defaultCommand == c
|
||
|
|
}
|
||
|
|
|
||
|
|
// isHidden returns true if the command is a hidden command
|
||
|
|
func (c *clirCommand) isHidden() bool {
|
||
|
|
return c.hidden
|
||
|
|
}
|
||
|
|
|
||
|
|
// Hidden hides the command from the Help system
|
||
|
|
func (c *clirCommand) Hidden() {
|
||
|
|
c.hidden = true
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewChildCommand - Creates a new subcommand
|
||
|
|
func (c *clirCommand) NewChildCommand(name string, description ...string) *clirCommand {
|
||
|
|
result := NewCommand(name, description...)
|
||
|
|
c.AddCommand(result)
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// AddCommand - Adds a subcommand
|
||
|
|
func (c *clirCommand) AddCommand(command *clirCommand) {
|
||
|
|
command.setApp(c.app)
|
||
|
|
command.setParentCommandPath(c.commandPath)
|
||
|
|
name := command.name
|
||
|
|
c.subCommands = append(c.subCommands, command)
|
||
|
|
c.subCommandsMap[name] = command
|
||
|
|
if len(name) > c.longestSubcommand {
|
||
|
|
c.longestSubcommand = len(name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewChildCommandInheritFlags - Creates a new subcommand, inherits flags from command
|
||
|
|
func (c *clirCommand) NewChildCommandInheritFlags(name string, description ...string) *clirCommand {
|
||
|
|
result := c.NewChildCommand(name, description...)
|
||
|
|
result.inheritFlags(c.flags)
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) AddFlags(optionStruct any) *clirCommand {
|
||
|
|
// use reflection to determine if this is a pointer to a struct
|
||
|
|
// if not, panic
|
||
|
|
|
||
|
|
t := reflect.TypeOf(optionStruct)
|
||
|
|
|
||
|
|
// Check for a pointer to a struct
|
||
|
|
if t.Kind() != reflect.Ptr {
|
||
|
|
panic("AddFlags() requires a pointer to a struct")
|
||
|
|
}
|
||
|
|
if t.Elem().Kind() != reflect.Struct {
|
||
|
|
panic("AddFlags() requires a pointer to a struct")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Iterate through the fields of the struct reading the struct tags
|
||
|
|
// and adding the flags
|
||
|
|
v := reflect.ValueOf(optionStruct).Elem()
|
||
|
|
for i := 0; i < v.NumField(); i++ {
|
||
|
|
field := v.Field(i)
|
||
|
|
fieldType := t.Elem().Field(i)
|
||
|
|
if !fieldType.IsExported() {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
// If this is an embedded struct, recurse
|
||
|
|
if fieldType.Type.Kind() == reflect.Struct {
|
||
|
|
c.AddFlags(field.Addr().Interface())
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
|
||
|
|
tag := t.Elem().Field(i).Tag
|
||
|
|
name := tag.Get("name")
|
||
|
|
description := tag.Get("description")
|
||
|
|
defaultValue := tag.Get("default")
|
||
|
|
pos := tag.Get("pos")
|
||
|
|
sep := tag.Get("sep")
|
||
|
|
c.positionalArgsMap[pos] = field
|
||
|
|
if sep != "" {
|
||
|
|
c.sliceSeparator[pos] = sep
|
||
|
|
}
|
||
|
|
if name == "" {
|
||
|
|
name = strings.ToLower(t.Elem().Field(i).Name)
|
||
|
|
}
|
||
|
|
switch field.Kind() {
|
||
|
|
case reflect.Bool:
|
||
|
|
var defaultValueBool bool
|
||
|
|
if defaultValue != "" {
|
||
|
|
var err error
|
||
|
|
defaultValueBool, err = strconv.ParseBool(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for bool flag")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
field.SetBool(defaultValueBool)
|
||
|
|
c.BoolFlag(name, description, field.Addr().Interface().(*bool))
|
||
|
|
case reflect.String:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
field.SetString(defaultValue)
|
||
|
|
}
|
||
|
|
c.StringFlag(name, description, field.Addr().Interface().(*string))
|
||
|
|
case reflect.Int:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int flag")
|
||
|
|
}
|
||
|
|
field.SetInt(int64(value))
|
||
|
|
}
|
||
|
|
c.IntFlag(name, description, field.Addr().Interface().(*int))
|
||
|
|
case reflect.Int8:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int8 flag")
|
||
|
|
}
|
||
|
|
field.SetInt(int64(value))
|
||
|
|
}
|
||
|
|
c.Int8Flag(name, description, field.Addr().Interface().(*int8))
|
||
|
|
case reflect.Int16:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int16 flag")
|
||
|
|
}
|
||
|
|
field.SetInt(int64(value))
|
||
|
|
}
|
||
|
|
c.Int16Flag(name, description, field.Addr().Interface().(*int16))
|
||
|
|
case reflect.Int32:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int32 flag")
|
||
|
|
}
|
||
|
|
field.SetInt(int64(value))
|
||
|
|
}
|
||
|
|
c.Int32Flag(name, description, field.Addr().Interface().(*int32))
|
||
|
|
case reflect.Int64:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int64 flag")
|
||
|
|
}
|
||
|
|
field.SetInt(int64(value))
|
||
|
|
}
|
||
|
|
c.Int64Flag(name, description, field.Addr().Interface().(*int64))
|
||
|
|
case reflect.Uint:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint flag")
|
||
|
|
}
|
||
|
|
field.SetUint(uint64(value))
|
||
|
|
}
|
||
|
|
c.UintFlag(name, description, field.Addr().Interface().(*uint))
|
||
|
|
case reflect.Uint8:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint8 flag")
|
||
|
|
}
|
||
|
|
field.SetUint(uint64(value))
|
||
|
|
}
|
||
|
|
c.Uint8Flag(name, description, field.Addr().Interface().(*uint8))
|
||
|
|
case reflect.Uint16:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint16 flag")
|
||
|
|
}
|
||
|
|
field.SetUint(uint64(value))
|
||
|
|
}
|
||
|
|
c.Uint16Flag(name, description, field.Addr().Interface().(*uint16))
|
||
|
|
case reflect.Uint32:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint32 flag")
|
||
|
|
}
|
||
|
|
field.SetUint(uint64(value))
|
||
|
|
}
|
||
|
|
c.Uint32Flag(name, description, field.Addr().Interface().(*uint32))
|
||
|
|
case reflect.Uint64:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.Atoi(defaultValue)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint64 flag")
|
||
|
|
}
|
||
|
|
field.SetUint(uint64(value))
|
||
|
|
}
|
||
|
|
c.UInt64Flag(name, description, field.Addr().Interface().(*uint64))
|
||
|
|
case reflect.Float32:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.ParseFloat(defaultValue, 64)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for float32 flag")
|
||
|
|
}
|
||
|
|
field.SetFloat(value)
|
||
|
|
}
|
||
|
|
c.Float32Flag(name, description, field.Addr().Interface().(*float32))
|
||
|
|
case reflect.Float64:
|
||
|
|
if defaultValue != "" {
|
||
|
|
// set value of field to default value
|
||
|
|
value, err := strconv.ParseFloat(defaultValue, 64)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for float64 flag")
|
||
|
|
}
|
||
|
|
field.SetFloat(value)
|
||
|
|
}
|
||
|
|
c.Float64Flag(name, description, field.Addr().Interface().(*float64))
|
||
|
|
case reflect.Slice:
|
||
|
|
c.addSliceField(field, defaultValue, sep)
|
||
|
|
c.addSliceFlags(name, description, field)
|
||
|
|
default:
|
||
|
|
if pos != "" {
|
||
|
|
fmt.Fprintf(os.Stderr, "WARNING: unsupported type for flag: %s %s\n", fieldType.Type.Kind(), name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) addSliceFlags(name, description string, field reflect.Value) *clirCommand {
|
||
|
|
if field.Kind() != reflect.Slice {
|
||
|
|
panic("addSliceFlags() requires a pointer to a slice")
|
||
|
|
}
|
||
|
|
t := reflect.TypeOf(field.Addr().Interface())
|
||
|
|
if t.Kind() != reflect.Ptr {
|
||
|
|
panic("addSliceFlags() requires a pointer to a slice")
|
||
|
|
}
|
||
|
|
if t.Elem().Kind() != reflect.Slice {
|
||
|
|
panic("addSliceFlags() requires a pointer to a slice")
|
||
|
|
}
|
||
|
|
switch t.Elem().Elem().Kind() {
|
||
|
|
case reflect.Bool:
|
||
|
|
c.BoolsFlag(name, description, field.Addr().Interface().(*[]bool))
|
||
|
|
case reflect.String:
|
||
|
|
c.StringsFlag(name, description, field.Addr().Interface().(*[]string))
|
||
|
|
case reflect.Int:
|
||
|
|
c.IntsFlag(name, description, field.Addr().Interface().(*[]int))
|
||
|
|
case reflect.Int8:
|
||
|
|
c.Int8sFlag(name, description, field.Addr().Interface().(*[]int8))
|
||
|
|
case reflect.Int16:
|
||
|
|
c.Int16sFlag(name, description, field.Addr().Interface().(*[]int16))
|
||
|
|
case reflect.Int32:
|
||
|
|
c.Int32sFlag(name, description, field.Addr().Interface().(*[]int32))
|
||
|
|
case reflect.Int64:
|
||
|
|
c.Int64sFlag(name, description, field.Addr().Interface().(*[]int64))
|
||
|
|
case reflect.Uint:
|
||
|
|
c.UintsFlag(name, description, field.Addr().Interface().(*[]uint))
|
||
|
|
case reflect.Uint8:
|
||
|
|
c.Uint8sFlag(name, description, field.Addr().Interface().(*[]uint8))
|
||
|
|
case reflect.Uint16:
|
||
|
|
c.Uint16sFlag(name, description, field.Addr().Interface().(*[]uint16))
|
||
|
|
case reflect.Uint32:
|
||
|
|
c.Uint32sFlag(name, description, field.Addr().Interface().(*[]uint32))
|
||
|
|
case reflect.Uint64:
|
||
|
|
c.Uint64sFlag(name, description, field.Addr().Interface().(*[]uint64))
|
||
|
|
case reflect.Float32:
|
||
|
|
c.Float32sFlag(name, description, field.Addr().Interface().(*[]float32))
|
||
|
|
case reflect.Float64:
|
||
|
|
c.Float64sFlag(name, description, field.Addr().Interface().(*[]float64))
|
||
|
|
default:
|
||
|
|
panic(fmt.Sprintf("addSliceFlags() not supported slice type %s", t.Elem().Elem().Kind().String()))
|
||
|
|
}
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) addSliceField(field reflect.Value, defaultValue, separator string) *clirCommand {
|
||
|
|
if defaultValue == "" {
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
if field.Kind() != reflect.Slice {
|
||
|
|
panic("addSliceField() requires a pointer to a slice")
|
||
|
|
}
|
||
|
|
t := reflect.TypeOf(field.Addr().Interface())
|
||
|
|
if t.Kind() != reflect.Ptr {
|
||
|
|
panic("addSliceField() requires a pointer to a slice")
|
||
|
|
}
|
||
|
|
if t.Elem().Kind() != reflect.Slice {
|
||
|
|
panic("addSliceField() requires a pointer to a slice")
|
||
|
|
}
|
||
|
|
defaultSlice := []string{defaultValue}
|
||
|
|
if separator != "" {
|
||
|
|
defaultSlice = strings.Split(defaultValue, separator)
|
||
|
|
}
|
||
|
|
switch t.Elem().Elem().Kind() {
|
||
|
|
case reflect.Bool:
|
||
|
|
defaultValues := make([]bool, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.ParseBool(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for bool flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, val)
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.String:
|
||
|
|
field.Set(reflect.ValueOf(defaultSlice))
|
||
|
|
case reflect.Int:
|
||
|
|
defaultValues := make([]int, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, val)
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Int8:
|
||
|
|
defaultValues := make([]int8, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int8 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, int8(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Int16:
|
||
|
|
defaultValues := make([]int16, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int16 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, int16(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Int32:
|
||
|
|
defaultValues := make([]int32, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.ParseInt(value, 10, 32)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int32 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, int32(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Int64:
|
||
|
|
defaultValues := make([]int64, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.ParseInt(value, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for int64 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, val)
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Uint:
|
||
|
|
defaultValues := make([]uint, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, uint(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Uint8:
|
||
|
|
defaultValues := make([]uint8, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint8 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, uint8(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Uint16:
|
||
|
|
defaultValues := make([]uint16, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint16 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, uint16(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Uint32:
|
||
|
|
defaultValues := make([]uint32, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint32 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, uint32(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Uint64:
|
||
|
|
defaultValues := make([]uint64, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for uint64 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, uint64(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Float32:
|
||
|
|
defaultValues := make([]float32, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.ParseFloat(value, 32)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for float32 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, float32(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
case reflect.Float64:
|
||
|
|
defaultValues := make([]float64, 0, len(defaultSlice))
|
||
|
|
for _, value := range defaultSlice {
|
||
|
|
val, err := strconv.ParseFloat(value, 64)
|
||
|
|
if err != nil {
|
||
|
|
panic("Invalid default value for float64 flag")
|
||
|
|
}
|
||
|
|
defaultValues = append(defaultValues, float64(val))
|
||
|
|
}
|
||
|
|
field.Set(reflect.ValueOf(defaultValues))
|
||
|
|
default:
|
||
|
|
panic(fmt.Sprintf("addSliceField() not supported slice type %s", t.Elem().Elem().Kind().String()))
|
||
|
|
}
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// BoolFlag - Adds a boolean flag to the command
|
||
|
|
func (c *clirCommand) BoolFlag(name, description string, variable *bool) *clirCommand {
|
||
|
|
c.flags.BoolVar(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// BoolsFlag - Adds a booleans flag to the command
|
||
|
|
func (c *clirCommand) BoolsFlag(name, description string, variable *[]bool) *clirCommand {
|
||
|
|
c.flags.Var(newBoolsValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// StringFlag - Adds a string flag to the command
|
||
|
|
func (c *clirCommand) StringFlag(name, description string, variable *string) *clirCommand {
|
||
|
|
c.flags.StringVar(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// StringsFlag - Adds a strings flag to the command
|
||
|
|
func (c *clirCommand) StringsFlag(name, description string, variable *[]string) *clirCommand {
|
||
|
|
c.flags.Var(newStringsValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// IntFlag - Adds an int flag to the command
|
||
|
|
func (c *clirCommand) IntFlag(name, description string, variable *int) *clirCommand {
|
||
|
|
c.flags.IntVar(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// IntsFlag - Adds an ints flag to the command
|
||
|
|
func (c *clirCommand) IntsFlag(name, description string, variable *[]int) *clirCommand {
|
||
|
|
c.flags.Var(newIntsValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int8Flag - Adds an int8 flag to the command
|
||
|
|
func (c *clirCommand) Int8Flag(name, description string, variable *int8) *clirCommand {
|
||
|
|
c.flags.Var(newInt8Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int8sFlag - Adds an int8 s flag to the command
|
||
|
|
func (c *clirCommand) Int8sFlag(name, description string, variable *[]int8) *clirCommand {
|
||
|
|
c.flags.Var(newInt8sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int16Flag - Adds an int16 flag to the command
|
||
|
|
func (c *clirCommand) Int16Flag(name, description string, variable *int16) *clirCommand {
|
||
|
|
c.flags.Var(newInt16Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int16sFlag - Adds an int16s flag to the command
|
||
|
|
func (c *clirCommand) Int16sFlag(name, description string, variable *[]int16) *clirCommand {
|
||
|
|
c.flags.Var(newInt16sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int32Flag - Adds an int32 flag to the command
|
||
|
|
func (c *clirCommand) Int32Flag(name, description string, variable *int32) *clirCommand {
|
||
|
|
c.flags.Var(newInt32Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int32sFlag - Adds an int32s flag to the command
|
||
|
|
func (c *clirCommand) Int32sFlag(name, description string, variable *[]int32) *clirCommand {
|
||
|
|
c.flags.Var(newInt32sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int64Flag - Adds an int64 flag to the command
|
||
|
|
func (c *clirCommand) Int64Flag(name, description string, variable *int64) *clirCommand {
|
||
|
|
c.flags.Int64Var(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Int64sFlag - Adds an int64s flag to the command
|
||
|
|
func (c *clirCommand) Int64sFlag(name, description string, variable *[]int64) *clirCommand {
|
||
|
|
c.flags.Var(newInt64sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// UintFlag - Adds an uint flag to the command
|
||
|
|
func (c *clirCommand) UintFlag(name, description string, variable *uint) *clirCommand {
|
||
|
|
c.flags.UintVar(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// UintsFlag - Adds an uints flag to the command
|
||
|
|
func (c *clirCommand) UintsFlag(name, description string, variable *[]uint) *clirCommand {
|
||
|
|
c.flags.Var(newUintsValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint8Flag - Adds an uint8 flag to the command
|
||
|
|
func (c *clirCommand) Uint8Flag(name, description string, variable *uint8) *clirCommand {
|
||
|
|
c.flags.Var(newUint8Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint8sFlag - Adds an uint8 s flag to the command
|
||
|
|
func (c *clirCommand) Uint8sFlag(name, description string, variable *[]uint8) *clirCommand {
|
||
|
|
c.flags.Var(newUint8sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint16Flag - Adds an uint16 flag to the command
|
||
|
|
func (c *clirCommand) Uint16Flag(name, description string, variable *uint16) *clirCommand {
|
||
|
|
c.flags.Var(newUint16Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint16sFlag - Adds an uint16s flag to the command
|
||
|
|
func (c *clirCommand) Uint16sFlag(name, description string, variable *[]uint16) *clirCommand {
|
||
|
|
c.flags.Var(newUint16sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint32Flag - Adds an uint32 flag to the command
|
||
|
|
func (c *clirCommand) Uint32Flag(name, description string, variable *uint32) *clirCommand {
|
||
|
|
c.flags.Var(newUint32Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint32sFlag - Adds an uint32s flag to the command
|
||
|
|
func (c *clirCommand) Uint32sFlag(name, description string, variable *[]uint32) *clirCommand {
|
||
|
|
c.flags.Var(newUint32sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// UInt64Flag - Adds an uint64 flag to the command
|
||
|
|
func (c *clirCommand) UInt64Flag(name, description string, variable *uint64) *clirCommand {
|
||
|
|
c.flags.Uint64Var(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Uint64sFlag - Adds an uint64s flag to the command
|
||
|
|
func (c *clirCommand) Uint64sFlag(name, description string, variable *[]uint64) *clirCommand {
|
||
|
|
c.flags.Var(newUint64sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Float64Flag - Adds a float64 flag to the command
|
||
|
|
func (c *clirCommand) Float64Flag(name, description string, variable *float64) *clirCommand {
|
||
|
|
c.flags.Float64Var(variable, name, *variable, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Float32Flag - Adds a float32 flag to the command
|
||
|
|
func (c *clirCommand) Float32Flag(name, description string, variable *float32) *clirCommand {
|
||
|
|
c.flags.Var(newFloat32Value(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Float32sFlag - Adds a float32s flag to the command
|
||
|
|
func (c *clirCommand) Float32sFlag(name, description string, variable *[]float32) *clirCommand {
|
||
|
|
c.flags.Var(newFloat32sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// Float64sFlag - Adds a float64s flag to the command
|
||
|
|
func (c *clirCommand) Float64sFlag(name, description string, variable *[]float64) *clirCommand {
|
||
|
|
c.flags.Var(newFloat64sValue(*variable, variable), name, description)
|
||
|
|
c.flagCount++
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
type boolsFlagVar []bool
|
||
|
|
|
||
|
|
func (f *boolsFlagVar) String() string { return fmt.Sprint([]bool(*f)) }
|
||
|
|
|
||
|
|
func (f *boolsFlagVar) Set(value string) error {
|
||
|
|
if value == "" {
|
||
|
|
*f = append(*f, false)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
b, err := strconv.ParseBool(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, b)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *boolsFlagVar) IsBoolFlag() bool {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
func newBoolsValue(val []bool, p *[]bool) *boolsFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*boolsFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type stringsFlagVar []string
|
||
|
|
|
||
|
|
func (f *stringsFlagVar) String() string { return fmt.Sprint([]string(*f)) }
|
||
|
|
|
||
|
|
func (f *stringsFlagVar) Set(value string) error {
|
||
|
|
*f = append(*f, value)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newStringsValue(val []string, p *[]string) *stringsFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*stringsFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type intsFlagVar []int
|
||
|
|
|
||
|
|
func (f *intsFlagVar) String() string { return fmt.Sprint([]int(*f)) }
|
||
|
|
|
||
|
|
func (f *intsFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newIntsValue(val []int, p *[]int) *intsFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*intsFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type int8Value int8
|
||
|
|
|
||
|
|
func newInt8Value(val int8, p *int8) *int8Value {
|
||
|
|
*p = val
|
||
|
|
return (*int8Value)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *int8Value) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = int8Value(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *int8Value) String() string { return fmt.Sprint(int8(*f)) }
|
||
|
|
|
||
|
|
type int8sFlagVar []int8
|
||
|
|
|
||
|
|
func (f *int8sFlagVar) String() string { return fmt.Sprint([]int8(*f)) }
|
||
|
|
|
||
|
|
func (f *int8sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, int8(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newInt8sValue(val []int8, p *[]int8) *int8sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*int8sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type int16Value int16
|
||
|
|
|
||
|
|
func newInt16Value(val int16, p *int16) *int16Value {
|
||
|
|
*p = val
|
||
|
|
return (*int16Value)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *int16Value) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = int16Value(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *int16Value) String() string { return fmt.Sprint(int16(*f)) }
|
||
|
|
|
||
|
|
type int16sFlagVar []int16
|
||
|
|
|
||
|
|
func (f *int16sFlagVar) String() string { return fmt.Sprint([]int16(*f)) }
|
||
|
|
|
||
|
|
func (f *int16sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, int16(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newInt16sValue(val []int16, p *[]int16) *int16sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*int16sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type int32Value int32
|
||
|
|
|
||
|
|
func newInt32Value(val int32, p *int32) *int32Value {
|
||
|
|
*p = val
|
||
|
|
return (*int32Value)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *int32Value) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = int32Value(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *int32Value) String() string { return fmt.Sprint(int32(*f)) }
|
||
|
|
|
||
|
|
type int32sFlagVar []int32
|
||
|
|
|
||
|
|
func (f *int32sFlagVar) String() string { return fmt.Sprint([]int32(*f)) }
|
||
|
|
|
||
|
|
func (f *int32sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, int32(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newInt32sValue(val []int32, p *[]int32) *int32sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*int32sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type int64sFlagVar []int64
|
||
|
|
|
||
|
|
func (f *int64sFlagVar) String() string { return fmt.Sprint([]int64(*f)) }
|
||
|
|
|
||
|
|
func (f *int64sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.ParseInt(value, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newInt64sValue(val []int64, p *[]int64) *int64sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*int64sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type uintsFlagVar []uint
|
||
|
|
|
||
|
|
func (f *uintsFlagVar) String() string {
|
||
|
|
return fmt.Sprint([]uint(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uintsFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, uint(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newUintsValue(val []uint, p *[]uint) *uintsFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uintsFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint8FlagVar uint8
|
||
|
|
|
||
|
|
func newUint8Value(val uint8, p *uint8) *uint8FlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint8FlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint8FlagVar) String() string {
|
||
|
|
return fmt.Sprint(uint8(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint8FlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = uint8FlagVar(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint8sFlagVar []uint8
|
||
|
|
|
||
|
|
func (f *uint8sFlagVar) String() string {
|
||
|
|
return fmt.Sprint([]uint8(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint8sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, uint8(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newUint8sValue(val []uint8, p *[]uint8) *uint8sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint8sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint16FlagVar uint16
|
||
|
|
|
||
|
|
func newUint16Value(val uint16, p *uint16) *uint16FlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint16FlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint16FlagVar) String() string {
|
||
|
|
return fmt.Sprint(uint16(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint16FlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = uint16FlagVar(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint16sFlagVar []uint16
|
||
|
|
|
||
|
|
func (f *uint16sFlagVar) String() string {
|
||
|
|
return fmt.Sprint([]uint16(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint16sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, uint16(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newUint16sValue(val []uint16, p *[]uint16) *uint16sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint16sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint32FlagVar uint32
|
||
|
|
|
||
|
|
func newUint32Value(val uint32, p *uint32) *uint32FlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint32FlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint32FlagVar) String() string {
|
||
|
|
return fmt.Sprint(uint32(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint32FlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = uint32FlagVar(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint32sFlagVar []uint32
|
||
|
|
|
||
|
|
func (f *uint32sFlagVar) String() string {
|
||
|
|
return fmt.Sprint([]uint32(*f))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (f *uint32sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.Atoi(value)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, uint32(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newUint32sValue(val []uint32, p *[]uint32) *uint32sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint32sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type uint64sFlagVar []uint64
|
||
|
|
|
||
|
|
func (f *uint64sFlagVar) String() string { return fmt.Sprint([]uint64(*f)) }
|
||
|
|
|
||
|
|
func (f *uint64sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.ParseUint(value, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newUint64sValue(val []uint64, p *[]uint64) *uint64sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*uint64sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type float32sFlagVar []float32
|
||
|
|
|
||
|
|
func (f *float32sFlagVar) String() string { return fmt.Sprint([]float32(*f)) }
|
||
|
|
|
||
|
|
func (f *float32sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.ParseFloat(value, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, float32(i))
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newFloat32sValue(val []float32, p *[]float32) *float32sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*float32sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type float32FlagVar float32
|
||
|
|
|
||
|
|
func (f *float32FlagVar) String() string { return fmt.Sprint(float32(*f)) }
|
||
|
|
|
||
|
|
func (f *float32FlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.ParseFloat(value, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = float32FlagVar(i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newFloat32Value(val float32, p *float32) *float32FlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*float32FlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
type float64sFlagVar []float64
|
||
|
|
|
||
|
|
func (f *float64sFlagVar) String() string { return fmt.Sprint([]float64(*f)) }
|
||
|
|
|
||
|
|
func (f *float64sFlagVar) Set(value string) error {
|
||
|
|
i, err := strconv.ParseFloat(value, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
*f = append(*f, i)
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func newFloat64sValue(val []float64, p *[]float64) *float64sFlagVar {
|
||
|
|
*p = val
|
||
|
|
return (*float64sFlagVar)(p)
|
||
|
|
}
|
||
|
|
|
||
|
|
// LongDescription - Sets the long description for the command
|
||
|
|
func (c *clirCommand) LongDescription(longdescription string) *clirCommand {
|
||
|
|
c.longdescription = longdescription
|
||
|
|
return c
|
||
|
|
}
|
||
|
|
|
||
|
|
// OtherArgs - Returns the non-flag arguments passed to the subcommand. NOTE: This should only be called within the context of an action.
|
||
|
|
func (c *clirCommand) OtherArgs() []string {
|
||
|
|
return c.flags.Args()
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) NewChildCommandFunction(name string, description string, fn any) *clirCommand {
|
||
|
|
result := c.NewChildCommand(name, description)
|
||
|
|
// use reflection to determine if this is a function
|
||
|
|
// if not, panic
|
||
|
|
t := reflect.TypeOf(fn)
|
||
|
|
if t.Kind() != reflect.Func {
|
||
|
|
panic("NewChildCommandFunction '" + name + "' requires a function with the signature 'func(*struct) error'")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check the function has 1 input ant it's a struct pointer
|
||
|
|
fnValue := reflect.ValueOf(fn)
|
||
|
|
if t.NumIn() != 1 {
|
||
|
|
panic("NewChildCommandFunction '" + name + "' requires a function with the signature 'func(*struct) error'")
|
||
|
|
}
|
||
|
|
// Check the input is a struct pointer
|
||
|
|
if t.In(0).Kind() != reflect.Ptr {
|
||
|
|
panic("NewChildCommandFunction '" + name + "' requires a function with the signature 'func(*struct) error'")
|
||
|
|
}
|
||
|
|
if t.In(0).Elem().Kind() != reflect.Struct {
|
||
|
|
panic("NewChildCommandFunction '" + name + "' requires a function with the signature 'func(*struct) error'")
|
||
|
|
}
|
||
|
|
// Check only 1 output and it's an error
|
||
|
|
if t.NumOut() != 1 {
|
||
|
|
panic("NewChildCommandFunction '" + name + "' requires a function with the signature 'func(*struct) error'")
|
||
|
|
}
|
||
|
|
if t.Out(0) != reflect.TypeOf((*error)(nil)).Elem() {
|
||
|
|
panic("NewChildCommandFunction '" + name + "' requires a function with the signature 'func(*struct) error'")
|
||
|
|
}
|
||
|
|
flags := reflect.New(t.In(0).Elem())
|
||
|
|
result.Action(func() error {
|
||
|
|
result := fnValue.Call([]reflect.Value{flags})[0].Interface()
|
||
|
|
if result != nil {
|
||
|
|
return result.(error)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
})
|
||
|
|
result.AddFlags(flags.Interface())
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func (c *clirCommand) parsePositionalArgs(args []string) error {
|
||
|
|
for index, posArg := range args {
|
||
|
|
// Check the map for a field for this arg
|
||
|
|
key := strconv.Itoa(index + 1)
|
||
|
|
field, ok := c.positionalArgsMap[key]
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
fieldType := field.Type()
|
||
|
|
switch fieldType.Kind() {
|
||
|
|
case reflect.Bool:
|
||
|
|
// set value of field to true
|
||
|
|
field.SetBool(true)
|
||
|
|
case reflect.String:
|
||
|
|
field.SetString(posArg)
|
||
|
|
case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
|
||
|
|
value, err := strconv.ParseInt(posArg, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
field.SetInt(value)
|
||
|
|
case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
|
||
|
|
value, err := strconv.ParseUint(posArg, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
field.SetUint(value)
|
||
|
|
case reflect.Float64, reflect.Float32:
|
||
|
|
value, err := strconv.ParseFloat(posArg, 64)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
field.SetFloat(value)
|
||
|
|
case reflect.Slice:
|
||
|
|
c.addSliceField(field, posArg, c.sliceSeparator[key])
|
||
|
|
default:
|
||
|
|
return E("cli.parsePositionalArgs", "unsupported type for positional argument: "+fieldType.Name(), nil)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|