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

123 lines
2.7 KiB
Go

package cli
import (
"slices"
"strings"
)
// Private functions implementation
func (cli *CliParser) optionExists(name, short string, aliases []string) (exists bool) {
for _, opti := range cli.options {
opt := opti.getBase()
if len(opt.shortAlias) > 0 && opt.shortAlias == short {
exists = true
break
} else if opt.Is(name) {
exists = true
break
} else {
if slices.ContainsFunc(aliases, opt.Is) {
exists = true
break
}
}
}
return
}
func (cli *CliParser) checkAlreadyUsedNames(name, short string, aliases []string) []string {
if plural := makePlural(name); !slices.Contains(aliases, plural) {
aliases = append(aliases, plural)
}
if cli.optionExists(name, short, aliases) {
panic(errOptionAlreadyDefined(name))
}
return aliases
}
func (cli *CliParser) getOptionValue(argIndex int) (value string, present bool) {
if argIndex < len(cli.cliArgs)-2 {
value = cli.cliArgs[1+argIndex+1]
present = true
}
return
}
func (cli *CliParser) getCliArgs(startIndex, endIndex int) (args []string) {
if endIndex < 0 || endIndex > len(cli.cliArgs) {
endIndex = len(cli.cliArgs)
}
if startIndex < 0 {
startIndex = 0
}
if startIndex > endIndex {
startIndex = endIndex
}
args = cli.cliArgs[startIndex:endIndex]
return
}
func (cli *CliParser) findOptionByArg(arg string) (matchingOpt cliOptionParser) {
if strings.HasPrefix(arg, "--") {
for _, opti := range cli.options {
opt := opti.getBase()
if opt.Is(arg[2:]) {
matchingOpt = opti
break
}
}
} else if strings.HasPrefix(arg, "-") {
for _, opti := range cli.options {
opt := opti.getBase()
if opt.shortAlias == arg[1:] {
matchingOpt = opti
break
}
}
}
return
}
func (cli *CliParser) findOptionByName(optName string) (matchingOpt cliOptionParser) {
for _, opti := range cli.options {
opt := opti.getBase()
if opt.Is(optName) {
matchingOpt = opti
break
}
}
return
}
func (cli *CliParser) parseArg(arg string, index int) (skipNextArg bool, err error) {
var opts []string
var name, value, dashes string
var equalPresent bool
name, value, equalPresent = strings.Cut(arg, "=")
if strings.HasPrefix(name, "--") {
opts = []string{name[2:]}
dashes = "--"
} else {
opts = strings.Split(name[1:], "")
dashes = "-"
}
for i, optName := range opts {
if opt := cli.findOptionByArg(dashes + optName); opt != nil {
if equalPresent && i == len(opts)-1 {
_, err = opt.parse(cli, index, &value)
} else if i < len(opts)-1 && opt.requiresValue() {
err = errMissingOptionValue(dashes + optName)
} else {
skipNextArg, err = opt.parse(cli, index, nil)
}
} else {
err = errUnknownOption(dashes + optName)
}
if err != nil {
break
}
}
return
}