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 }