cli/opt-int-array.go
2025-12-11 07:57:48 +01:00

112 lines
2.7 KiB
Go

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
}