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

148 lines
3.5 KiB
Go

package cli
import (
"fmt"
"slices"
"strings"
)
type cliOptionBase struct {
name string
shortAlias string
aliases []string
description string
isArray bool
hidden bool
specialValues map[string]SpecialValueFunc
incompatibleWith []string
}
func (opt *cliOptionBase) getBase() *cliOptionBase {
return opt
}
func (opt *cliOptionBase) getTargetVar() (any, string) {
return nil, "n/a"
}
func (opt *cliOptionBase) Is(name string) (result bool) {
if result = opt.name == name; !result && len(opt.aliases) > 0 {
result = slices.Contains(opt.aliases, name)
}
return
}
func (opt *cliOptionBase) isHidden() bool {
return opt.hidden
}
func (opt *cliOptionBase) SetHidden(hidden bool) {
opt.hidden = hidden
}
func (opt *cliOptionBase) AddSpecialValue(cliValue string, specialFunc SpecialValueFunc) {
if opt.specialValues == nil {
opt.specialValues = make(map[string]SpecialValueFunc)
}
opt.specialValues[cliValue] = specialFunc
}
func (opt *cliOptionBase) getSpecialFunc(cliValue string) (specialFunc SpecialValueFunc, exists bool) {
if len(opt.specialValues) > 0 {
specialFunc, exists = opt.specialValues[cliValue]
}
return
}
func (opt *cliOptionBase) isSet() bool {
return false
}
func (opt *cliOptionBase) requiresValue() bool {
return true
}
func (opt *cliOptionBase) addIncompatibleOption(names ...string) {
opt.incompatibleWith = append(opt.incompatibleWith, names...)
}
func (opt *cliOptionBase) parse(parser cliParser, valuePtr *string) (err error) {
return fmt.Errorf("unhandled option %q", opt.name)
}
func (opt *cliOptionBase) getDefaultValue() string {
return ""
}
func pluralSuffix(word string) (suffix string) {
if len(word) > 0 {
if strings.HasSuffix(word, "x") || strings.HasSuffix(word, "s") || strings.HasSuffix(word, "ch") {
suffix = "es"
} else {
suffix = "s"
}
}
return
}
func makePlural(word string) (plural string) {
return word + pluralSuffix(word)
}
func (opt *cliOptionBase) makeOptTemplate(isArray bool, valueType string) (templ string) {
var suffix, multiValue string
if isArray {
suffix = "(" + pluralSuffix(opt.name) + ")"
multiValue = `["," ...]`
}
if opt.shortAlias != "" {
templ = fmt.Sprintf(`-%s, --%s%s <%s>%s`, opt.shortAlias, opt.name, suffix, valueType, multiValue)
} else {
templ = fmt.Sprintf(`--%s%s <%s>%s`, opt.name, suffix, valueType, multiValue)
}
return
}
func (opt *cliOptionBase) makeOptSimpleTemplate(valueRequired, multiValue bool, valueType string) (templ string) {
var valueSpec, dots string
if multiValue {
dots = " ..."
}
if len(valueType) > 0 {
valueSpec = " <" + valueType + ">" + dots
if !valueRequired {
valueSpec = " [" + valueSpec[1:] + "]"
}
}
if opt.shortAlias != "" {
templ = fmt.Sprintf(`-%s, --%s%s`, opt.shortAlias, opt.name, valueSpec)
} else {
templ = fmt.Sprintf(`--%s%s`, opt.name, valueSpec)
}
return
}
func (opt *cliOptionBase) getSpecialValue(parser cliParser, value string, targetVar any) (boxedValue any, err error) {
if specialFunc, exists := opt.getSpecialFunc(value); exists {
manager := parser.(OptManager)
boxedValue, err = specialFunc(manager, value, targetVar)
}
return
}
func (opt *cliOptionBase) fetchOptionValue(parser cliParser, argIndex int, valuePtr *string) (value string, skipNextArg bool, err error) {
if valuePtr != nil {
value = *valuePtr
} else {
if source, optionPresent := parser.getOptionValue(argIndex); optionPresent {
skipNextArg = true
value = source
} else {
err = errMissingOptionValue(opt.name)
}
}
return
}