flag: handle `--` as a parsing stop, and pass everything after it in .finalise() (#10703)
parent
47bf64473c
commit
f62b6b37f0
|
@ -40,8 +40,9 @@ fn (mut f Flag) free() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (f Flag) str() string {
|
pub fn (f Flag) str() string {
|
||||||
return '' + ' flag:\n' + ' name: $f.name\n' + ' abbr: $f.abbr\n' +
|
return '' + ' flag:\n' + ' name: $f.name\n' +
|
||||||
' usag: $f.usage\n' + ' desc: $f.val_desc'
|
' abbr: `$f.abbr.ascii_str()`\n' + ' usag: $f.usage\n' +
|
||||||
|
' desc: $f.val_desc'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (af []Flag) str() string {
|
pub fn (af []Flag) str() string {
|
||||||
|
@ -56,8 +57,12 @@ pub fn (af []Flag) str() string {
|
||||||
|
|
||||||
//
|
//
|
||||||
pub struct FlagParser {
|
pub struct FlagParser {
|
||||||
|
pub:
|
||||||
|
original_args []string // the original arguments to be parsed
|
||||||
|
idx_dashdash int // the index of a `--`, -1 if there is not any
|
||||||
|
all_after_dashdash []string // all options after `--` are ignored, and will be passed to the application unmodified
|
||||||
pub mut:
|
pub mut:
|
||||||
args []string // the arguments to be parsed
|
args []string // the current list of processed args
|
||||||
max_free_args int
|
max_free_args int
|
||||||
flags []Flag // registered flags
|
flags []Flag // registered flags
|
||||||
application_name string
|
application_name string
|
||||||
|
@ -96,10 +101,22 @@ pub const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// create a new flag set for parsing command line arguments
|
// create a new flag set for parsing command line arguments
|
||||||
// TODO use INT_MAX some how
|
|
||||||
pub fn new_flag_parser(args []string) &FlagParser {
|
pub fn new_flag_parser(args []string) &FlagParser {
|
||||||
|
original_args := args.clone()
|
||||||
|
idx_dashdash := args.index('--')
|
||||||
|
mut all_before_dashdash := args.clone()
|
||||||
|
mut all_after_dashdash := []string{}
|
||||||
|
if idx_dashdash >= 0 {
|
||||||
|
all_before_dashdash.trim(idx_dashdash)
|
||||||
|
if idx_dashdash < original_args.len {
|
||||||
|
all_after_dashdash = original_args[idx_dashdash + 1..]
|
||||||
|
}
|
||||||
|
}
|
||||||
return &FlagParser{
|
return &FlagParser{
|
||||||
args: args.clone()
|
original_args: original_args
|
||||||
|
idx_dashdash: idx_dashdash
|
||||||
|
all_after_dashdash: all_after_dashdash
|
||||||
|
args: all_before_dashdash
|
||||||
max_free_args: flag.max_args_number
|
max_free_args: flag.max_args_number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,10 +185,6 @@ fn (mut fs FlagParser) parse_value(longhand string, shorthand byte) []string {
|
||||||
should_skip_one = false
|
should_skip_one = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if arg == '--' {
|
|
||||||
// End of input. We're done here.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if arg[0] != `-` {
|
if arg[0] != `-` {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -219,10 +232,6 @@ fn (mut fs FlagParser) parse_bool_value(longhand string, shorthand byte) ?string
|
||||||
{
|
{
|
||||||
full := '--$longhand'
|
full := '--$longhand'
|
||||||
for i, arg in fs.args {
|
for i, arg in fs.args {
|
||||||
if arg == '--' {
|
|
||||||
// End of input. We're done.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if arg.len == 0 {
|
if arg.len == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -504,8 +513,9 @@ pub fn (fs FlagParser) usage() string {
|
||||||
// defined on the command line. If additional flags are found, i.e.
|
// defined on the command line. If additional flags are found, i.e.
|
||||||
// (things starting with '--' or '-'), it returns an error.
|
// (things starting with '--' or '-'), it returns an error.
|
||||||
pub fn (fs FlagParser) finalize() ?[]string {
|
pub fn (fs FlagParser) finalize() ?[]string {
|
||||||
|
mut remaining := fs.args.clone()
|
||||||
if !fs.allow_unknown_args {
|
if !fs.allow_unknown_args {
|
||||||
for a in fs.args {
|
for a in remaining {
|
||||||
if (a.len >= 2 && a[..2] == '--') || (a.len == 2 && a[0] == `-`) {
|
if (a.len >= 2 && a[..2] == '--') || (a.len == 2 && a[0] == `-`) {
|
||||||
return IError(&UnkownFlagError{
|
return IError(&UnkownFlagError{
|
||||||
msg: 'Unknown flag `$a`'
|
msg: 'Unknown flag `$a`'
|
||||||
|
@ -513,20 +523,21 @@ pub fn (fs FlagParser) finalize() ?[]string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fs.args.len < fs.min_free_args && fs.min_free_args > 0 {
|
if remaining.len < fs.min_free_args && fs.min_free_args > 0 {
|
||||||
return IError(&MinimumArgsCountError{
|
return IError(&MinimumArgsCountError{
|
||||||
msg: 'Expected at least $fs.min_free_args arguments, but given $fs.args.len'
|
msg: 'Expected at least $fs.min_free_args arguments, but given $remaining.len'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if fs.args.len > fs.max_free_args && fs.max_free_args > 0 {
|
if remaining.len > fs.max_free_args && fs.max_free_args > 0 {
|
||||||
return IError(&MaximumArgsCountError{
|
return IError(&MaximumArgsCountError{
|
||||||
msg: 'Expected at most $fs.max_free_args arguments, but given $fs.args.len'
|
msg: 'Expected at most $fs.max_free_args arguments, but given $remaining.len'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if fs.args.len > 0 && fs.max_free_args == 0 && fs.min_free_args == 0 {
|
if remaining.len > 0 && fs.max_free_args == 0 && fs.min_free_args == 0 {
|
||||||
return IError(&NoArgsExpectedError{
|
return IError(&NoArgsExpectedError{
|
||||||
msg: 'Expected no arguments, but given $fs.args.len'
|
msg: 'Expected no arguments, but given $remaining.len'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return fs.args
|
remaining << fs.all_after_dashdash
|
||||||
|
return remaining
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,3 +382,26 @@ fn test_optional_flags() {
|
||||||
b := fp.string_opt('another-flag', `b`, '') or { 'some_default_value' }
|
b := fp.string_opt('another-flag', `b`, '') or { 'some_default_value' }
|
||||||
assert b == 'some_default_value'
|
assert b == 'some_default_value'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_dashdash_acts_as_parser_full_stop() ? {
|
||||||
|
mut fp := flag.new_flag_parser(['-b', '5', '--', '-d', '-x', '-b', '4', '-a', '-c', 'hello',
|
||||||
|
'some', 'other', 'parameters'])
|
||||||
|
a := fp.bool_opt('a-bool-flag', `a`, '') or { false }
|
||||||
|
b := fp.int_opt('an-int-flag', `b`, '') or { -1 }
|
||||||
|
c := fp.string_opt('a-string-flag', `c`, '') or { 'default' }
|
||||||
|
assert a == false
|
||||||
|
assert b == 5
|
||||||
|
assert c == 'default'
|
||||||
|
args := fp.finalize() ?
|
||||||
|
assert args.len > 0
|
||||||
|
assert args[0] != '--'
|
||||||
|
assert args == ['-d', '-x', '-b', '4', '-a', '-c', 'hello', 'some', 'other', 'parameters']
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_dashdash_acts_as_parser_full_stop_dashdash_at_end() ? {
|
||||||
|
mut fp := flag.new_flag_parser(['-b', '5', '-b', '4', 'other', 'params', '--'])
|
||||||
|
b := fp.int_multi('an-int-flag', `b`, '')
|
||||||
|
assert b == [5, 4]
|
||||||
|
args := fp.finalize() ?
|
||||||
|
assert args.len > 0
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue