From c924a6cf007f897f02c6a1a0a5ca8381a037d123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20B=C3=B6ttcher?= <34623283+spacesinmotion@users.noreply.github.com> Date: Wed, 7 Aug 2019 16:52:10 +0200 Subject: [PATCH] flag: allow to define flags with abbreviation * flag: allow to check the count of the free args to produce an error * flag: allow to define flags with abbreviation flags could be defined to use a single char as abbreviation like '--output' or '-o' '--help' or '-h' --- vlib/flag/flag.v | 93 ++++++++++++++++++++++++++++++++----------- vlib/flag/flag_test.v | 14 +++++++ 2 files changed, 83 insertions(+), 24 deletions(-) diff --git a/vlib/flag/flag.v b/vlib/flag/flag.v index 7dcb0673b8..63f6ecffb5 100644 --- a/vlib/flag/flag.v +++ b/vlib/flag/flag.v @@ -49,6 +49,7 @@ module flag struct Flag { pub: name string // name as it appears on command line + abbr byte // shortcut usage string // help message val_desc string // something like '' that appears in usage } @@ -94,10 +95,11 @@ pub fn (fs mut FlagParser) skip_executable() { } // private helper to register a flag -fn (fs mut FlagParser) add_flag(n, u, vd string) { +fn (fs mut FlagParser) add_flag(n string, a byte, u, vd string) { fs.flags << Flag{ name: n, - usage: u + abbr: a, + usage: u, val_desc: vd } } @@ -111,10 +113,10 @@ fn (fs mut FlagParser) add_flag(n, u, vd string) { // // - the name, usage are registered // - found arguments and corresponding values are removed from args list -fn (fs mut FlagParser) parse_value(n string) ?string { +fn (fs mut FlagParser) parse_value(n string, ab byte) ?string { c := '--$n' for i, a in fs.args { - if a == c { + if a == c || (a.len == 2 && a[1] == ab) { if fs.args.len > i+1 && fs.args[i+1].left(2) != '--' { val := fs.args[i+1] fs.args.delete(i+1) @@ -138,10 +140,10 @@ fn (fs mut FlagParser) parse_value(n string) ?string { // special: it is allowed to define bool flags without value // -> '--flag' is parsed as true // -> '--flag' is equal to '--flag=true' -fn (fs mut FlagParser) parse_bool_value(n string) ?string { +fn (fs mut FlagParser) parse_bool_value(n string, ab byte) ?string { c := '--$n' for i, a in fs.args { - if a == c { + if a == c || (a.len == 2 && a[1] == ab) { if fs.args.len > i+1 && (fs.args[i+1] in ['true', 'false']) { val := fs.args[i+1] fs.args.delete(i+1) @@ -166,15 +168,41 @@ fn (fs mut FlagParser) parse_bool_value(n string) ?string { // the value is returned (true/false) // else // the default value is returned +// version with abbreviation //TODO error handling for invalid string to bool conversion -pub fn (fs mut FlagParser) bool(n string, v bool, u string) bool { - fs.add_flag(n, u, '') - parsed := fs.parse_bool_value(n) or { +pub fn (fs mut FlagParser) bool_(n string, a byte, v bool, u string) bool { + fs.add_flag(n, a, u, '') + parsed := fs.parse_bool_value(n, a) or { return v } return parsed == 'true' } +// defining and parsing a bool flag +// if defined +// the value is returned (true/false) +// else +// the default value is returned +//TODO error handling for invalid string to bool conversion +pub fn (fs mut FlagParser) bool(n string, v bool, u string) bool { + return fs.bool_(n, `\0`, v, u) +} + +// defining and parsing an int flag +// if defined +// the value is returned (int) +// else +// the default value is returned +// version with abbreviation +//TODO error handling for invalid string to int conversion +pub fn (fs mut FlagParser) int_(n string, a byte, i int, u string) int { + fs.add_flag(n, a, u, '') + parsed := fs.parse_value(n, a) or { + return i + } + return parsed.int() +} + // defining and parsing an int flag // if defined // the value is returned (int) @@ -182,11 +210,22 @@ pub fn (fs mut FlagParser) bool(n string, v bool, u string) bool { // the default value is returned //TODO error handling for invalid string to int conversion pub fn (fs mut FlagParser) int(n string, i int, u string) int { - fs.add_flag(n, u, '') - parsed := fs.parse_value(n) or { - return i + return fs.int_(n, `\0`, i, u) +} + +// defining and parsing a flaot flag +// if defined +// the value is returned (float) +// else +// the default value is returned +// version with abbreviation +//TODO error handling for invalid string to float conversion +pub fn (fs mut FlagParser) float_(n string, a byte, f f32, u string) f32 { + fs.add_flag(n, a, u, '') + parsed := fs.parse_value(n, a) or { + return f } - return parsed.int() + return parsed.f32() } // defining and parsing a flaot flag @@ -196,11 +235,21 @@ pub fn (fs mut FlagParser) int(n string, i int, u string) int { // the default value is returned //TODO error handling for invalid string to float conversion pub fn (fs mut FlagParser) float(n string, f f32, u string) f32 { - fs.add_flag(n, u, '') - parsed := fs.parse_value(n) or { - return f + return fs.float_(n, `\0`, f, u) +} + +// defining and parsing a string flag +// if defined +// the value is returned (string) +// else +// the default value is returned +// version with abbreviation +pub fn (fs mut FlagParser) string_(n string, a byte, v, u string) string { + fs.add_flag(n, a, u, '') + parsed := fs.parse_value(n, a) or { + return v } - return parsed.f32() + return parsed } // defining and parsing a string flag @@ -209,14 +258,9 @@ pub fn (fs mut FlagParser) float(n string, f f32, u string) f32 { // else // the default value is returned pub fn (fs mut FlagParser) string(n, v, u string) string { - fs.add_flag(n, u, '') - parsed := fs.parse_value(n) or { - return v - } - return parsed + return fs.string_(n, `\0`, v, u) } -// add an additional check for free arguments // this will cause an error in finalize() if free args are out of range // (min, ..., max) pub fn (fs mut FlagParser) limit_free_args(min, max int) { @@ -247,7 +291,8 @@ pub fn (fs FlagParser) usage() string { } else { SPACE.right(flag_desc.len) } - use += '$flag_desc$space$f.usage\n' + abbr_desc := if f.abbr == `\0` { '' } else { ' -${tos(f.abbr, 1)}\n' } + use += '$abbr_desc$flag_desc$space$f.usage\n' } } diff --git a/vlib/flag/flag_test.v b/vlib/flag/flag_test.v index d8cd48c830..663275129d 100644 --- a/vlib/flag/flag_test.v +++ b/vlib/flag/flag_test.v @@ -231,3 +231,17 @@ fn test_could_expect_no_free_args() { } assert args.len < 0 // expect an error and need to use args } + +fn test_allow_abreviations() { + mut fp := flag.new_flag_parser(['-v', '-o', 'some_file', '-i', '42', '-f', '2.0']) + + v := fp.bool_('version', `v`, false, '') + o := fp.string_('output', `o`, 'empty', '') + i := fp.int_('count', `i`, 0, '') + f := fp.float_('value', `f`, 0.0, '') + + assert v && o == 'some_file' && i == 42 && f == 2.0 + + u := fp.usage() + assert u.contains(' -v') && u.contains(' -o') && u.contains(' -i') && u.contains(' -f') +}