cli: simplify flag parsing (#21392)

This commit is contained in:
Turiiya 2024-05-01 20:07:25 +02:00 committed by GitHub
parent 3ec1994b32
commit 7170f9da36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 38 additions and 30 deletions

View File

@ -248,16 +248,16 @@ fn (mut cmd Command) add_default_commands() {
} }
fn (mut cmd Command) parse_flags() { fn (mut cmd Command) parse_flags() {
for { for cmd.args.len > 0 {
if cmd.args.len < 1 || !cmd.args[0].starts_with('-') { if !cmd.args[0].starts_with('-') {
break return
} }
mut found := false mut found := false
for i in 0 .. cmd.flags.len { for mut flag in cmd.flags {
mut flag := &cmd.flags[i] if flag.matches(cmd.args[0], cmd.posix_mode) {
if flag.matches(cmd.args, cmd.posix_mode) {
found = true found = true
flag.found = true flag.found = true
// Eat flag and its values, continue with reduced args.
cmd.args = flag.parse(cmd.args, cmd.posix_mode) or { cmd.args = flag.parse(cmd.args, cmd.posix_mode) or {
eprintln_exit('Failed to parse flag `${cmd.args[0]}`: ${err}') eprintln_exit('Failed to parse flag `${cmd.args[0]}`: ${err}')
} }

View File

@ -94,44 +94,54 @@ fn test_if_flag_gets_set_with_long_arg() {
cmd.parse(['command', '--flag', 'value']) cmd.parse(['command', '--flag', 'value'])
} }
fn flag_should_have_value_of_42(cmd cli.Command) ! { fn assert_flags(cmd cli.Command) ! {
flag := cmd.flags.get_string('flag')! flag := cmd.flags.get_string('flag')!
assert flag == 'value' assert flag == 'value'
value := cmd.flags.get_int('value')! value := cmd.flags.get_int('value')!
assert value == 42 assert value == 42
flag2 := cmd.flags.get_string('flag-2')!
assert flag2 == 'value-2'
} }
fn test_if_multiple_flags_get_set() { fn test_if_multiple_flags_get_set() {
mut cmd := cli.Command{ mut cmd := cli.Command{
name: 'command' name: 'command'
execute: flag_should_have_value_of_42 execute: assert_flags
} }
cmd.add_flag(cli.Flag{ cmd.add_flag(cli.Flag{
flag: .string flag: .string
name: 'flag' name: 'flag'
}) })
cmd.add_flag(cli.Flag{
flag: .string
name: 'flag-2'
})
cmd.add_flag(cli.Flag{ cmd.add_flag(cli.Flag{
flag: .int flag: .int
name: 'value' name: 'value'
}) })
cmd.parse(['command', '-flag', 'value', '-value', '42']) cmd.parse(['command', '-flag=value', '-value', '42', '-flag-2', 'value-2'])
} }
fn test_if_required_flags_get_set() { fn test_if_required_flags_get_set() {
mut cmd := cli.Command{ mut cmd := cli.Command{
name: 'command' name: 'command'
execute: flag_should_have_value_of_42 execute: assert_flags
} }
cmd.add_flag(cli.Flag{ cmd.add_flag(cli.Flag{
flag: .string flag: .string
name: 'flag' name: 'flag'
}) })
cmd.add_flag(cli.Flag{
flag: .string
name: 'flag-2'
})
cmd.add_flag(cli.Flag{ cmd.add_flag(cli.Flag{
flag: .int flag: .int
name: 'value' name: 'value'
required: true required: true
}) })
cmd.parse(['command', '-flag', 'value', '-value', '42']) cmd.parse(['command', '-flag', 'value', '-value', '42', '-flag-2', 'value-2'])
} }
fn flag_is_set_in_subcommand(cmd cli.Command) ! { fn flag_is_set_in_subcommand(cmd cli.Command) ! {

View File

@ -213,31 +213,29 @@ pub fn (flags []Flag) get_strings(name string) ![]string {
// parse parses flag values from arguments and return // parse parses flag values from arguments and return
// an array of arguments with all consumed elements removed. // an array of arguments with all consumed elements removed.
pub fn (mut flag Flag) parse(args []string, posix_mode bool) ![]string { pub fn (mut flag Flag) parse(args []string, posix_mode bool) ![]string {
if flag.matches(args, posix_mode) { return match true {
if flag.flag == .bool { !flag.matches(args[0], posix_mode) {
new_args := flag.parse_bool(args)! args
return new_args
} else {
if flag.value.len > 0 && flag.flag != .int_array && flag.flag != .float_array
&& flag.flag != .string_array {
return error('The argument `${flag.name}` accept only one value!')
} }
flag.flag == .bool {
new_args := flag.parse_raw(args)! flag.parse_bool(args)!
return new_args }
flag.value.len > 0 && flag.flag !in [.int_array, .float_array, .string_array] {
error('The argument `${flag.name}` accept only one value!')
}
else {
flag.parse_raw(args)!
} }
} else {
return args
} }
} }
// matches returns `true` if first arg in `args` matches this flag. // matches returns `true` if first arg in `args` matches this flag.
fn (mut flag Flag) matches(args []string, posix_mode bool) bool { fn (mut flag Flag) matches(arg string, posix_mode bool) bool {
prefix := if posix_mode { '--' } else { '-' } prefix := if posix_mode { '--' } else { '-' }
return (flag.name != '' && args[0] == '${prefix}${flag.name}') return (flag.name != '' && arg == '${prefix}${flag.name}')
|| (flag.name != '' && args[0].starts_with('${prefix}${flag.name}=')) || (flag.name != '' && arg.starts_with('${prefix}${flag.name}='))
|| (flag.abbrev != '' && args[0] == '-${flag.abbrev}') || (flag.abbrev != '' && arg == '-${flag.abbrev}')
|| (flag.abbrev != '' && args[0].starts_with('-${flag.abbrev}=')) || (flag.abbrev != '' && arg.starts_with('-${flag.abbrev}='))
} }
fn (mut flag Flag) parse_raw(args []string) ![]string { fn (mut flag Flag) parse_raw(args []string) ![]string {