cli: add flag/cmd sorting + get_all_found (#5615)

pull/5620/head
Tim Basel 2020-07-02 11:10:03 +02:00 committed by GitHub
parent 6cbc0e84f0
commit 703b060d09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 95 additions and 32 deletions

View File

@ -15,6 +15,9 @@ pub mut:
disable_version bool disable_version bool
disable_flags bool disable_flags bool
sort_flags bool = true
sort_commands bool = true
parent &Command = nil() parent &Command = nil()
commands []Command commands []Command
flags []Flag flags []Flag
@ -49,6 +52,13 @@ pub fn (mut cmd Command) parse(args []string) {
} }
cmd.add_default_commands() cmd.add_default_commands()
if cmd.sort_flags {
cmd.flags.sort()
}
if cmd.sort_commands {
cmd.commands.sort()
}
cmd.args = args[1..] cmd.args = args[1..]
for i in 0..cmd.commands.len { for i in 0..cmd.commands.len {
cmd.commands[i].parent = cmd cmd.commands[i].parent = cmd
@ -88,6 +98,7 @@ fn (mut cmd Command) parse_flags() {
mut flag := &cmd.flags[i] mut flag := &cmd.flags[i]
if flag.matches(cmd.args) { if flag.matches(cmd.args) {
found = true found = true
flag.found = true
cmd.args = flag.parse(cmd.args) or { cmd.args = flag.parse(cmd.args) or {
println('failed to parse flag ${cmd.args[0]}: ${err}') println('failed to parse flag ${cmd.args[0]}: ${err}')
exit(1) exit(1)
@ -127,8 +138,7 @@ fn (mut cmd Command) parse_commands() {
if int(cmd.execute) == 0 { if int(cmd.execute) == 0 {
if !cmd.disable_help { if !cmd.disable_help {
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
execute := help_cmd.execute help_cmd.execute(help_cmd)
execute(help_cmd)
} }
} else { } else {
cmd.check_required_flags() cmd.check_required_flags()
@ -153,8 +163,7 @@ fn (mut cmd Command) check_help_flag() {
help_flag := cmd.flags.get_bool('help') or { return } // ignore error and handle command normally help_flag := cmd.flags.get_bool('help') or { return } // ignore error and handle command normally
if help_flag { if help_flag {
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
execute := help_cmd.execute help_cmd.execute(help_cmd)
execute(help_cmd)
exit(0) exit(0)
} }
} }
@ -168,8 +177,7 @@ fn (mut cmd Command) check_version_flag() {
version_flag := cmd.flags.get_bool('version') or { return } // ignore error and handle command normally version_flag := cmd.flags.get_bool('version') or { return } // ignore error and handle command normally
if version_flag { if version_flag {
version_cmd := cmd.commands.get('version') or { return } // ignore error and handle command normally version_cmd := cmd.commands.get('version') or { return } // ignore error and handle command normally
execute := version_cmd.execute version_cmd.execute(version_cmd)
execute(version_cmd)
exit(0) exit(0)
} }
} }
@ -185,6 +193,15 @@ fn (mut cmd Command) check_required_flags() {
} }
} }
fn (cmds []Command) get(name string) ?Command {
for cmd in cmds {
if cmd.name == name {
return cmd
}
}
return error('command \'${name}\' not found.')
}
fn (cmds []Command) contains(name string) bool { fn (cmds []Command) contains(name string) bool {
for cmd in cmds { for cmd in cmds {
if cmd.name == name { if cmd.name == name {
@ -194,11 +211,8 @@ fn (cmds []Command) contains(name string) bool {
return false return false
} }
fn (cmds []Command) get(name string) ?Command { fn (mut cmds []Command) sort() {
for cmd in cmds { cmds.sort_with_compare(fn(a &Command, b &Command) int {
if cmd.name == name { return compare_strings(&a.name, &b.name)
return cmd })
}
}
return error('command \'${name}\' not found.')
} }

View File

@ -15,14 +15,24 @@ pub mut:
description string description string
global bool global bool
required bool required bool
value string value string
mut:
found bool
}
pub fn (flags []Flag) get_all_found() []Flag {
return flags.filter(it.found)
}
pub fn (flag Flag) get_bool() ?bool {
if flag.flag != .bool { return error('invalid flag type') }
return flag.value == 'true'
} }
pub fn (flags []Flag) get_bool(name string) ?bool { pub fn (flags []Flag) get_bool(name string) ?bool {
flag := flags.get(name) or { return error(err) } flag := flags.get(name) or { return error(err) }
if flag.flag != .bool { return error('invalid flag type') } return flag.get_bool()
return flag.value == 'true'
} }
pub fn (flags []Flag) get_bool_or(name string, or_value bool) bool { pub fn (flags []Flag) get_bool_or(name string, or_value bool) bool {
@ -30,34 +40,46 @@ pub fn (flags []Flag) get_bool_or(name string, or_value bool) bool {
return value return value
} }
pub fn (flags []Flag) get_int(name string) ?int { pub fn (flag Flag) get_int() ?int {
flag := flags.get(name) or { return error(err) }
if flag.flag != .int { return error('invalid flag type') } if flag.flag != .int { return error('invalid flag type') }
return flag.value.int() return flag.value.int()
} }
pub fn (flags []Flag) get_int(name string) ?int {
flag := flags.get(name) or { return error(err) }
return flag.get_int()
}
pub fn (flags []Flag) get_int_or(name string, or_value int) int { pub fn (flags []Flag) get_int_or(name string, or_value int) int {
value := flags.get_int(name) or { return or_value } value := flags.get_int(name) or { return or_value }
return value return value
} }
pub fn (flags []Flag) get_float(name string) ?f32 { pub fn (flag Flag) get_float() ?f64 {
flag := flags.get(name) or { return error(err) }
if flag.flag != .float { return error('invalid flag type') } if flag.flag != .float { return error('invalid flag type') }
return flag.value.f32() return flag.value.f64()
} }
pub fn (flags []Flag) get_float_or(name string, or_value f32) f32 { pub fn (flags []Flag) get_float(name string) ?f64 {
flag := flags.get(name) or { return error(err) }
return flag.get_float()
}
pub fn (flags []Flag) get_float_or(name string, or_value f64) f64 {
value := flags.get_float(name) or { return or_value } value := flags.get_float(name) or { return or_value }
return value return value
} }
pub fn (flags []Flag) get_string(name string) ?string { pub fn (flag Flag) get_string() ?string {
flag := flags.get(name) or { return error(err) }
if flag.flag != .string { return error('invalid flag type') } if flag.flag != .string { return error('invalid flag type') }
return flag.value return flag.value
} }
pub fn (flags []Flag) get_string(name string) ?string {
flag := flags.get(name) or { return error(err) }
return flag.get_string()
}
pub fn (flags []Flag) get_string_or(name string, or_value string) string { pub fn (flags []Flag) get_string_or(name string, or_value string) string {
value := flags.get_string(name) or { return or_value } value := flags.get_string(name) or { return or_value }
return value return value
@ -81,8 +103,10 @@ fn (mut flag Flag) parse(args []string) ?[]string {
// check if first arg matches flag // check if first arg matches flag
fn (mut flag Flag) matches(args []string) bool { fn (mut flag Flag) matches(args []string) bool {
return return
(flag.name != '' && args[0].starts_with('--${flag.name}')) || (flag.name != '' && args[0] == '--${flag.name}') ||
(flag.abbrev != '' && args[0].starts_with('-${flag.abbrev}')) (flag.name != '' && args[0].starts_with('--${flag.name}=')) ||
(flag.abbrev != '' && args[0] == '-${flag.abbrev}') ||
(flag.abbrev != '' && args[0].starts_with('-${flag.abbrev}='))
} }
fn (mut flag Flag) parse_raw(args []string) ?[]string { fn (mut flag Flag) parse_raw(args []string) ?[]string {
@ -127,3 +151,9 @@ fn (flags []Flag) contains(name string) bool {
} }
return false return false
} }
fn (mut flags []Flag) sort() {
flags.sort_with_compare(fn(a &Flag, b &Flag) int {
return compare_strings(&a.name, &b.name)
})
}

View File

@ -18,15 +18,27 @@ fn test_if_bool_flag_parses() {
flag: .bool, flag: .bool,
name: 'flag', name: 'flag',
} }
mut value := false
flag.parse(['--flag']) or { panic(err) } flag.parse(['--flag']) or { panic(err) }
assert flag.value == 'true' value = flag.get_bool() or { panic(err) }
assert value == true
flag.parse(['--flag', 'true']) or { panic(err) } flag.parse(['--flag', 'true']) or { panic(err) }
assert flag.value == 'true' value = flag.get_bool() or { panic(err) }
assert value == true
flag.parse(['--flag=true']) or { panic(err) } flag.parse(['--flag=true']) or { panic(err) }
assert flag.value == 'true' value = flag.get_bool() or { panic(err) }
assert value == true
flag.parse(['--flag', 'false']) or { panic(err) }
value = flag.get_bool() or { panic(err) }
assert value == false
flag.parse(['--flag=false']) or { panic(err) }
value = flag.get_bool() or { panic(err) }
assert value == false
} }
fn test_if_int_flag_parses() { fn test_if_int_flag_parses() {
@ -34,12 +46,15 @@ fn test_if_int_flag_parses() {
flag: .int, flag: .int,
name: 'flag', name: 'flag',
} }
mut value := 0
flag.parse(['--flag', '42']) or { panic(err) } flag.parse(['--flag', '42']) or { panic(err) }
assert flag.value.int() == 42 value = flag.get_int() or { panic(err) }
assert value == 42
flag.parse(['--flag=42']) or { panic(err) } flag.parse(['--flag=42']) or { panic(err) }
assert flag.value.int() == 42 value = flag.get_int() or { panic(err) }
assert value == 42
} }
fn test_if_float_flag_parses() { fn test_if_float_flag_parses() {
@ -47,10 +62,14 @@ fn test_if_float_flag_parses() {
flag: .float, flag: .float,
name: 'flag', name: 'flag',
} }
mut value := f64(0)
flag.parse(['--flag', '3.14159']) or { panic(err) } flag.parse(['--flag', '3.14159']) or { panic(err) }
assert flag.value.f64() == 3.14159 value = flag.get_float() or { panic(err) }
assert value == 3.14159
flag.parse(['--flag=3.14159']) or { panic(err) } flag.parse(['--flag=3.14159']) or { panic(err) }
assert flag.value.f64() == 3.14159 assert flag.value.f64() == 3.14159
value = flag.get_float() or { panic(err) }
assert value == 3.14159
} }