Option types: bool int, int-array, string, string-array, string-map, file, dir
123 lines
2.7 KiB
Go
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
|
|
}
|