Compare commits

..

No commits in common. "main" and "v1.2.1" have entirely different histories.
main ... v1.2.1

15 changed files with 78 additions and 326 deletions

112
cli.go
View File

@ -14,11 +14,10 @@ type cliParser interface {
getCliArgs(startIndex, endIndex int) (args []string)
PrintVersion(specs []string)
PrintUsage()
FlagIsSet(flag int16) bool
}
type cliOptionParser interface {
parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, optValue string, err error)
parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error)
getTemplate() string
getDefaultValue() string
getBase() *cliOptionBase
@ -26,7 +25,6 @@ type cliOptionParser interface {
isSet() bool
isHidden() bool
requiresValue() bool
finalCheck() (err error)
}
type OptManager interface {
@ -34,39 +32,26 @@ type OptManager interface {
}
type SpecialValueFunc func(manager OptManager, cliValue string, currentValue any) (value any, err error)
type FinalCheckFunc func(currentValue any) (err error)
type OptReference interface {
AddSpecialValue(cliValue string, specialFunc SpecialValueFunc)
OnFinalCheck(checkFunc FinalCheckFunc)
SetHidden(hidden bool)
}
const (
ResetOnEqualSign = int16(1 << iota) // for some option types, like arrays, the equal signs reset to empty the accumulator of values
)
type CliParser struct {
description string
version string
options []cliOptionParser
argSpecs []argSpec
cliArgs []string
flags int16
}
func (cli *CliParser) Init(argv []string, version string, description string, flags ...int16) {
func (cli *CliParser) Init(argv []string, version string, description string) {
cli.version = version
cli.description = description
cli.cliArgs = argv
for _, flag := range flags {
cli.flags |= flag
}
}
func (cli *CliParser) FlagIsSet(flag int16) bool {
return (cli.flags & flag) == flag
}
func (cli *CliParser) GetOption(name string) (ref OptReference) {
var opt cliOptionParser
if strings.HasPrefix(name, "-") {
@ -170,12 +155,16 @@ func (cli *CliParser) addHelpAndVersion() {
}
func (cli *CliParser) parseOptions() (commandArgs []string, err error) {
// var commandArgs []string
func (cli *CliParser) Parse() (err error) {
var arg string
var i int
var args []string
var optionsAllowed bool = true
cli.addHelpAndVersion()
skipNext := false
for i, arg := range cli.cliArgs[1:] {
for i, arg = range cli.cliArgs[1:] {
if skipNext {
skipNext = false
} else {
@ -189,82 +178,43 @@ func (cli *CliParser) parseOptions() (commandArgs []string, err error) {
break
}
} else {
commandArgs = append(commandArgs, arg)
args = append(args, arg)
}
}
}
return
}
func (cli *CliParser) checkOptionValues() (err error) {
for _, opt := range cli.options {
if err = opt.finalCheck(); err != nil {
break
}
}
return
}
func (cli *CliParser) parseCommandArgs(commandArgs []string) (err error) {
var n int
i := 0
// acquire arguments as required by the argSpecs
specIndex := -1
for index, argSpec := range cli.argSpecs {
specIndex = index
if n, err = argSpec.parse(cli, specIndex, commandArgs, i); err != nil {
break
}
i += n
if i >= len(commandArgs) {
break
}
}
// check if there are remaining arg-specs that require a value
if err == nil {
if i < len(commandArgs) {
err = fmt.Errorf("too many arguments: %d allowed", i)
} else {
specIndex++
if specIndex < len(cli.argSpecs) {
// skip all non required args
var argSpec argSpec
var n, specIndex int
i = 0
for specIndex, argSpec = range cli.argSpecs {
if n, err = argSpec.parse(cli, specIndex, args, i); err != nil {
break
}
i += n
if i >= len(args) {
break
}
}
if err == nil {
if i < len(args) {
err = fmt.Errorf("too many arguments: %d allowed", i)
} else {
specIndex++
for _, spec := range cli.argSpecs[specIndex:] {
if !spec.getBase().required {
specIndex++
}
}
}
// return error if there are remaining arg-specs that require a value
if specIndex < len(cli.argSpecs) {
err = errTooFewArguments(len(cli.argSpecs))
if specIndex < len(cli.argSpecs) {
err = errTooFewArguments(len(cli.argSpecs))
}
}
}
}
return
}
func (cli *CliParser) Parse() (err error) {
var commandArgs []string
cli.addHelpAndVersion()
// first parse options and collect command arguments in the args array
if commandArgs, err = cli.parseOptions(); err != nil {
return
}
// do final checks
if err = cli.checkOptionValues(); err != nil {
return
}
// then parse collected arguments
err = cli.parseCommandArgs(commandArgs)
return
}
func (cli *CliParser) checkCompatibility(arg string) (err error) {
var opti cliOptionParser
if opti = cli.findOptionByArg(arg); opti != nil {

View File

@ -85,17 +85,16 @@ where:
<dest> Output destination file
<report> Optional report file
<options>
-V, --verbose Print verbose output (default: "0")
-o, --print-ocr Print the OCR output to stderr
-s, --save-clip Save the image clips as PNG files (alias: save-clips)
-t, --trace Enable trace mode for detailed logging
-p, --page(s) <num>["," ...] Process only the specified pages (comma-separated list)
-c, --config <file> Alternate configuration file
-l, --log(s) <string>["," ...] Logging options (comma-separated list)
--var(s) <key=value>["," ...] Define one or more comma separated variables for the actions context (multiple allowed)
-n, --input-name <string> Input file name when source comes from stdin
-d, --work-dir <dir> Work directory
--attempts <num> Attempts for retrying failed operations (default: "1")
-o, --print-ocr Print the OCR output to stderr
-s, --save-clip Save the image clips as PNG files (alias: save-clips)
-t, --trace Enable trace mode for detailed logging
-p, --page(s) <num>["," ...] Process only the specified pages (comma-separated list)
-c, --config <file> Alternate configuration file
-l, --log(s) <string>["," ...] Logging options (comma-separated list)
-V, --var(s) <key=value>["," ...] Define one or more comma separated variables for the actions context (multiple allowed)
-n, --input-name <string> Input file name when source comes from stdin
-d, --work-dir <dir> Work directory
--attempts <num> Attempts for retrying failed operations (default: "1")
`
var cli CliParser
var gd GlobalData
@ -110,8 +109,7 @@ where:
}
}
func TestParser(t *testing.T) {
const expectedOutput = `Option: verbose, Type: num, Value: 3
Option: print-ocr, Type: bool, Value: true
const expectedOutput = `Option: print-ocr, Type: bool, Value: true
Option: save-clip, Type: bool, Value: false
Option: trace, Type: bool, Value: true
Option: page, Type: num-array, Value: [17 18]
@ -137,7 +135,7 @@ Option: version, Type: n/a, Value: <nil>
if err := cli.Parse(); err == nil {
cli.TraceOptions(tracer)
if sb.String() != expectedOutput {
t.Errorf("Parsed options do not match expected list.\nGot:\n%q\nExpected:\n%q", sb.String(), expectedOutput)
t.Errorf("Parsed options do not match expected.\nGot:\n%q\nExpected:\n%q", sb.String(), expectedOutput)
}
} else {
t.Error(err)
@ -324,16 +322,15 @@ where:
<dest> Output destination file
<report> Optional report file
<options>
-V, --verbose Print verbose output (default: "0")
-o, --print-ocr Print the OCR output to stderr
-t, --trace Enable trace mode for detailed logging
-p, --page(s) <num>["," ...] Process only the specified pages (comma-separated list)
-c, --config <file> Alternate configuration file
-l, --log(s) <string>["," ...] Logging options (comma-separated list)
--var(s) <key=value>["," ...] Define one or more comma separated variables for the actions context (multiple allowed)
-n, --input-name <string> Input file name when source comes from stdin
-d, --work-dir <dir> Work directory
--attempts <num> Attempts for retrying failed operations (default: "1")
-o, --print-ocr Print the OCR output to stderr
-t, --trace Enable trace mode for detailed logging
-p, --page(s) <num>["," ...] Process only the specified pages (comma-separated list)
-c, --config <file> Alternate configuration file
-l, --log(s) <string>["," ...] Logging options (comma-separated list)
-V, --var(s) <key=value>["," ...] Define one or more comma separated variables for the actions context (multiple allowed)
-n, --input-name <string> Input file name when source comes from stdin
-d, --work-dir <dir> Work directory
--attempts <num> Attempts for retrying failed operations (default: "1")
`
var cli CliParser
var gd GlobalData
@ -344,7 +341,7 @@ where:
}
usage := cli.Usage()
if usage != expectedUsage {
t.Errorf("Usage output does not match expected text.\nGot:\n%s\nExpected:\n%s", usage, expectedUsage)
t.Errorf("Usage output does not match expected.\nGot:\n%s\nExpected:\n%s", usage, expectedUsage)
}
}

View File

@ -13,9 +13,7 @@ type cliOptionBase struct {
description string
isArray bool
hidden bool
alreadySeen bool
specialValues map[string]SpecialValueFunc
finalCheckFunc FinalCheckFunc
incompatibleWith []string
}
@ -42,10 +40,6 @@ func (opt *cliOptionBase) SetHidden(hidden bool) {
opt.hidden = hidden
}
func (opt *cliOptionBase) OnFinalCheck(checkFunc FinalCheckFunc) {
opt.finalCheckFunc = checkFunc
}
func (opt *cliOptionBase) AddSpecialValue(cliValue string, specialFunc SpecialValueFunc) {
if opt.specialValues == nil {
opt.specialValues = make(map[string]SpecialValueFunc)
@ -72,9 +66,8 @@ func (opt *cliOptionBase) addIncompatibleOption(names ...string) {
opt.incompatibleWith = append(opt.incompatibleWith, names...)
}
func (opt *cliOptionBase) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
err = fmt.Errorf("unhandled option %q", opt.name)
return
func (opt *cliOptionBase) parse(parser cliParser, valuePtr *string) (err error) {
return fmt.Errorf("unhandled option %q", opt.name)
}
func (opt *cliOptionBase) getDefaultValue() string {
@ -152,14 +145,3 @@ func (opt *cliOptionBase) fetchOptionValue(parser cliParser, argIndex int, value
}
return
}
func (opt *cliOptionBase) finalCheck() (err error) {
return
}
func (opt *cliOptionBase) checkValue(value any) (err error) {
if opt.finalCheckFunc != nil {
err = opt.finalCheckFunc(value)
}
return
}

View File

@ -47,11 +47,11 @@ func (opt *cliOptionBool) getTemplate() (templ string) {
return
}
func (opt *cliOptionBool) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, optValue string, err error) {
func (opt *cliOptionBool) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) {
var boxedValue any
optValue = "true"
value := "true"
if boxedValue, err = opt.getSpecialValue(parser, optValue, opt.targetVar); err == nil {
if boxedValue, err = opt.getSpecialValue(parser, value, opt.targetVar); err == nil {
if opt.targetVar != nil {
if boxedValue != nil {
if val, ok := boxedValue.(bool); ok {
@ -67,11 +67,6 @@ func (opt *cliOptionBool) parse(parser cliParser, argIndex int, valuePtr *string
return
}
func (opt *cliOptionBool) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}
func (cli *CliParser) AddBoolOpt(name, short string, targetVar *bool, description string, aliases ...string) OptReference {
if cli.optionExists(name, short, aliases) {
panic(errOptionAlreadyDefined(name))

View File

@ -23,7 +23,7 @@ func (opt *cliOptionHelp) getTemplate() string {
return opt.makeOptSimpleTemplate(false, false, "")
}
func (opt *cliOptionHelp) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
func (opt *cliOptionHelp) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) {
parser.PrintUsage()
err = io.EOF
return

View File

@ -63,7 +63,8 @@ func parseIntRange(value string) (min int, max int, err error) {
return
}
func (opt *cliOptionIntArray) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, optValue string, err error) {
func (opt *cliOptionIntArray) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) {
var optValue string
if optValue, skipNextArg, err = opt.fetchOptionValue(parser, argIndex, valuePtr); err == nil {
var boxedValue any
if boxedValue, err = opt.getSpecialValue(parser, optValue, opt.targetVar); err == nil {
@ -75,10 +76,6 @@ func (opt *cliOptionIntArray) parse(parser cliParser, argIndex int, valuePtr *st
err = errInvalidOptionValue(opt.name, boxedValue, "num-array")
}
} else {
if !opt.alreadySeen || (valuePtr != nil && parser.FlagIsSet(ResetOnEqualSign)) {
*opt.targetVar = []int{}
opt.alreadySeen = true
}
for value := range strings.SplitSeq(optValue, ",") {
var minRange, maxRange int
if minRange, maxRange, err = parseIntRange(value); err == nil {
@ -97,11 +94,6 @@ func (opt *cliOptionIntArray) parse(parser cliParser, argIndex int, valuePtr *st
return
}
func (opt *cliOptionIntArray) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}
func (cli *CliParser) AddIntArrayOpt(name, short string, targetVar *[]int, defaultValue []int, description string, aliases ...string) OptReference {
aliases = cli.checkAlreadyUsedNames(name, short, aliases)
opt := &cliOptionIntArray{

View File

@ -38,10 +38,11 @@ func (opt *cliOptionInt) getTemplate() string {
return opt.makeOptTemplate(false, intTypeName)
}
func (opt *cliOptionInt) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, optValue string, err error) {
if optValue, skipNextArg, err = opt.fetchOptionValue(parser, argIndex, valuePtr); err == nil {
func (opt *cliOptionInt) 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, optValue, opt.targetVar); err == nil {
if boxedValue, err = opt.getSpecialValue(parser, value, opt.targetVar); err == nil {
if opt.targetVar != nil {
if boxedValue != nil {
if val, ok := boxedValue.(string); ok {
@ -50,17 +51,13 @@ func (opt *cliOptionInt) parse(parser cliParser, argIndex int, valuePtr *string)
err = errInvalidOptionValue(opt.name, boxedValue, "int")
}
} else {
*opt.targetVar, err = strconv.Atoi(optValue)
*opt.targetVar, err = strconv.Atoi(value)
}
}
}
}
return
}
func (opt *cliOptionInt) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}
func (cli *CliParser) AddIntOpt(name, short string, targetVar *int, defaultValue int, description string, aliases ...string) OptReference {
if cli.optionExists(name, short, aliases) {

View File

@ -2,7 +2,7 @@ package cli
func (cli *CliParser) SetOptionValue(name string, value string) (err error) {
if opt := cli.findOptionByArg(name); opt != nil {
_, _, err = opt.parse(cli, -1, &value)
_, err = opt.parse(cli, -1, &value)
} else {
err = errOptionNotFound(name)
}

View File

@ -46,17 +46,12 @@ func (opt *cliOptionMulti) getTemplate() (templ string) {
return
}
func (opt *cliOptionMulti) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
func (opt *cliOptionMulti) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) {
if opt.targetVar != nil {
*opt.targetVar++
}
value = "true"
return
}
func (opt *cliOptionMulti) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}
func (cli *CliParser) AddMultiOpt(name, short string, targetVar *int, defaultValue int, description string, aliases ...string) OptReference {
if cli.optionExists(name, short, aliases) {

View File

@ -43,7 +43,8 @@ func (opt *cliOptionStringArray) getTemplate() string {
// parse retrieves the option value from the parser and updates the target variable.
// It handles comma-separated values and special values if configured.
func (opt *cliOptionStringArray) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
func (opt *cliOptionStringArray) 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 {
@ -54,8 +55,6 @@ func (opt *cliOptionStringArray) parse(parser cliParser, argIndex int, valuePtr
} else {
err = errInvalidOptionValue(opt.name, boxedValue, "array of string")
}
} else if opt.alreadySeen {
*opt.targetVar = append(*opt.targetVar, strings.Split(value, ",")...)
} else {
*opt.targetVar = strings.Split(value, ",")
}
@ -84,8 +83,3 @@ func (cli *CliParser) AddStringArrayOpt(name, short string, targetVar *[]string,
cli.options = append(cli.options, opt)
return opt
}
func (opt *cliOptionStringArray) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}

View File

@ -57,7 +57,8 @@ func (opt *cliOptionStringMap) getTemplate() string {
return opt.makeOptTemplate(true, "key=value")
}
func (opt *cliOptionStringMap) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
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 {
@ -70,7 +71,7 @@ func (opt *cliOptionStringMap) parse(parser cliParser, argIndex int, valuePtr *s
err = errInvalidOptionValue(opt.name, boxedValue, "map of string")
}
} else {
if dict == nil || !opt.alreadySeen {
if dict == nil {
dict = make(map[string]string)
}
for value := range strings.SplitSeq(value, ",") {
@ -89,11 +90,6 @@ func (opt *cliOptionStringMap) parse(parser cliParser, argIndex int, valuePtr *s
return
}
func (opt *cliOptionStringMap) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}
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{

View File

@ -36,7 +36,8 @@ func (opt *cliOptionString) getTemplate() string {
return opt.makeOptTemplate(false, stringTypeName)
}
func (opt *cliOptionString) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
func (opt *cliOptionString) 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 {
@ -55,10 +56,6 @@ func (opt *cliOptionString) parse(parser cliParser, argIndex int, valuePtr *stri
}
return
}
func (opt *cliOptionString) finalCheck() (err error) {
currentValue, _ := opt.getTargetVar()
return opt.getBase().checkValue(currentValue)
}
func (cli *CliParser) AddStringOpt(name, short string, targetVar *string, defaultValue string, description string, aliases ...string) OptReference {
if cli.optionExists(name, short, aliases) {

View File

@ -23,7 +23,7 @@ func (opt *cliOptionVersion) getTemplate() string {
return opt.makeOptSimpleTemplate(false, true, "section")
}
func (opt *cliOptionVersion) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, value string, err error) {
func (opt *cliOptionVersion) parse(parser cliParser, argIndex int, valuePtr *string) (skipNextArg bool, err error) {
var args []string
if valuePtr != nil {
args = []string{*valuePtr}

View File

@ -1,143 +0,0 @@
package cli
import (
"fmt"
"testing"
)
func TestOneOptWithEqual(t *testing.T) {
var cli CliParser
var color string
// Always recover from panic to return error before adding options
defer func() {
if r := recover(); r != nil {
if err := r.(error); err != nil {
t.Error(err)
}
}
}()
// Define options
cli.AddStringOpt("color", "c", &color, "white", "Set color")
args := []string{
"TestOneOptWithEqual",
"--color=blue",
}
cli.Init(args, "1.0.0", "TestOneOptWithEqual description")
if err := cli.Parse(); err != nil {
t.Error(err)
} else if color != "blue" {
t.Errorf("Expected color blue, got %q", color)
}
}
func addBoxOption(cli *CliParser, boxPtr *[]int) {
// Define options
optRef := cli.AddIntArrayOpt("box", "b", boxPtr, []int{1, 2, 3, 4}, "Box spec: Left,Width,Top,Height; provide 4 int values")
optRef.OnFinalCheck(func(currentValue any) (err error) {
if array, ok := currentValue.([]int); ok {
if len(array) != 4 {
err = fmt.Errorf("--box option requires exactly 4 items, %d provided", len(array))
}
} else {
err = fmt.Errorf("wrong datatype for --box option value")
}
return
})
}
func testIntArrayOptOk(t *testing.T, n int, args []string, flags ...int16) {
var box []int
var cli CliParser
t.Logf("Arg set n. %d", n)
addBoxOption(&cli, &box)
cli.Init(args, "1.0.0", "TestIntArrayOpt description", flags...)
if err := cli.Parse(); err != nil {
t.Error(err)
} else if len(box) != 4 {
t.Errorf(`Expected 4 items, got %d`, len(box))
}
}
func testIntArrayOptKo(t *testing.T, n int, args []string, msg string, flags ...int16) {
var box []int
var cli CliParser
t.Logf("Arg set n. %d", n)
addBoxOption(&cli, &box)
cli.Init(args, "1.0.0", "TestIntArrayOpt description", flags...)
if err := cli.Parse(); err == nil {
t.Errorf("Expected error, got nil")
} else if err.Error() != msg {
t.Errorf(`Invalid error: %q; expected: %q`, err.Error(), msg)
}
}
func TestIntArrayOpt(t *testing.T) {
var args []string
// Always recover from panic to return error before adding options
defer func() {
if r := recover(); r != nil {
if err := r.(error); err != nil {
t.Error(err)
}
}
}()
n := 0
n++
args = []string{
"TestIntArrayOpt",
"--box=100,200,150,450",
}
testIntArrayOptOk(t, n, args)
n++
args = []string{
"TestIntArrayOpt",
"--box=100,200,150",
}
testIntArrayOptKo(t, n, args, "--box option requires exactly 4 items, 3 provided")
n++
args = []string{
"TestIntArrayOpt",
"--box", "100,200,150,450",
}
testIntArrayOptOk(t, n, args)
n++
args = []string{
"TestIntArrayOpt",
"--box",
}
testIntArrayOptKo(t, n, args, `option "box" requires a value`)
n++
args = []string{
"TestIntArrayOpt",
"--box", "100,200,150",
"--box", "450",
}
testIntArrayOptOk(t, n, args)
n++
args = []string{
"TestIntArrayOpt",
"--box", "100,200,150",
"--box", "450,12",
}
testIntArrayOptKo(t, n, args, "--box option requires exactly 4 items, 5 provided")
n++
args = []string{
"TestIntArrayOpt",
"--box", "100,200,150",
"--box=100,200,150,450",
}
testIntArrayOptOk(t, n, args, ResetOnEqualSign)
}

View File

@ -105,11 +105,11 @@ func (cli *CliParser) parseArg(arg string, index int) (skipNextArg bool, err err
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)
_, 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)
skipNextArg, err = opt.parse(cli, index, nil)
}
} else {
err = errUnknownOption(dashes + optName)