Option types: bool int, int-array, string, string-array, string-map, file, dir
109 lines
2.5 KiB
Go
109 lines
2.5 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
stringMapTypeName = "map-string"
|
|
)
|
|
|
|
type cliOptionStringMap struct {
|
|
cliOptionBase
|
|
defaultValue map[string]string
|
|
targetVar *map[string]string
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) init() {
|
|
opt.isArray = true
|
|
if opt.targetVar != nil {
|
|
*opt.targetVar = opt.defaultValue
|
|
}
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) getTargetVar() (any, string) {
|
|
var value map[string]string
|
|
if opt.targetVar != nil {
|
|
value = *opt.targetVar
|
|
}
|
|
return value, stringMapTypeName
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) getBase() *cliOptionBase {
|
|
return &opt.cliOptionBase
|
|
}
|
|
|
|
func MapJoin[T any](m map[string]T, kvSep, itemSep string) string {
|
|
var sb strings.Builder
|
|
for key, value := range m {
|
|
if sb.Len() > 0 {
|
|
sb.WriteString(itemSep)
|
|
}
|
|
fmt.Fprintf(&sb, "%q%s%v", key, kvSep, value)
|
|
}
|
|
return sb.String()
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) requiresValue() bool {
|
|
return opt.targetVar != nil
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) getDefaultValue() string {
|
|
return MapJoin(opt.defaultValue, ",", "=")
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) getTemplate() string {
|
|
return opt.makeOptTemplate(true, "key=value")
|
|
}
|
|
|
|
func (opt *cliOptionStringMap) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) {
|
|
var value string
|
|
if value, skipNextArg, err = opt.fetchOptionValue(parser, argIndex, valuePtr); err == nil {
|
|
var boxedValue any
|
|
if boxedValue, err = opt.getSpecialValue(parser, value, opt.targetVar); err == nil {
|
|
if opt.targetVar != nil {
|
|
dict := *opt.targetVar
|
|
if boxedValue != nil {
|
|
if val, ok := boxedValue.(map[string]string); ok {
|
|
dict = val
|
|
} else {
|
|
err = errInvalidOptionValue(opt.name, boxedValue, "map of string")
|
|
}
|
|
} else {
|
|
if dict == nil {
|
|
dict = make(map[string]string)
|
|
}
|
|
for value := range strings.SplitSeq(value, ",") {
|
|
if k, v, sepExists := strings.Cut(value, "="); sepExists {
|
|
dict[k] = v
|
|
} else {
|
|
dict[k] = ""
|
|
}
|
|
}
|
|
}
|
|
*opt.targetVar = dict
|
|
}
|
|
}
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
func (cli *CliParser) AddStringMapOpt(name, short string, targetVar *map[string]string, defaultValue map[string]string, description string, aliases ...string) OptReference {
|
|
aliases = cli.checkAlreadyUsedNames(name, short, aliases)
|
|
opt := &cliOptionStringMap{
|
|
cliOptionBase: cliOptionBase{
|
|
name: name,
|
|
shortAlias: short,
|
|
aliases: aliases,
|
|
description: description,
|
|
isArray: true,
|
|
},
|
|
targetVar: targetVar,
|
|
defaultValue: defaultValue,
|
|
}
|
|
cli.options = append(cli.options, opt)
|
|
return opt
|
|
}
|