package cli import ( "strconv" "strings" ) const ( intArrayTypeName = "num-array" ) type cliOptionIntArray struct { cliOptionBase defaultValue []int targetVar *[]int } func (opt *cliOptionIntArray) init() { if opt.targetVar != nil { *opt.targetVar = opt.defaultValue } } func (opt *cliOptionIntArray) getTargetVar() (any, string) { var value []int if opt.targetVar != nil { value = *opt.targetVar } return value, intArrayTypeName } func (opt *cliOptionIntArray) requiresValue() bool { return opt.targetVar != nil } func (opt *cliOptionIntArray) getDefaultValue() string { def := make([]string, len(opt.defaultValue)) for i, v := range opt.defaultValue { def[i] = strconv.Itoa(v) } return strings.Join(def, ",") } func (opt *cliOptionIntArray) getTemplate() string { return opt.makeOptTemplate(true, "num") } func parseIntRange(value string) (min int, max int, err error) { var dashPresent bool var minStr, maxStr string minStr, maxStr, dashPresent = strings.Cut(value, "-") if dashPresent { if min, err = strconv.Atoi(minStr); err == nil { if max, err = strconv.Atoi(maxStr); err == nil { if min > max { err = errInvalidOptionValue("", value, "invalid range") } } } } else if min, err = strconv.Atoi(value); err == nil { max = min } return } func (opt *cliOptionIntArray) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) { var optValue string if optValue, skipNextArg, err = opt.fetchOptionValue(parser, argIndex, valuePtr); err == nil { var boxedValue any if boxedValue, err = opt.getSpecialValue(parser, optValue, opt.targetVar); err == nil { if opt.targetVar != nil { if boxedValue != nil { if val, ok := boxedValue.([]int); ok { *opt.targetVar = val } else { err = errInvalidOptionValue(opt.name, boxedValue, "array of int") } } else { for value := range strings.SplitSeq(optValue, ",") { var minRange, maxRange int if minRange, maxRange, err = parseIntRange(value); err == nil { for i := minRange; i <= maxRange; i++ { *opt.targetVar = append(*opt.targetVar, i) } } else { break } } } } } } return } func (cli *CliParser) AddIntArrayOpt(name, short string, targetVar *[]int, defaultValue []int, description string, aliases ...string) OptReference { aliases = cli.checkAlreadyUsedNames(name, short, aliases) opt := &cliOptionIntArray{ cliOptionBase: cliOptionBase{ name: name, shortAlias: short, aliases: aliases, description: description, isArray: true, }, targetVar: targetVar, defaultValue: defaultValue, } cli.options = append(cli.options, opt) return opt }