From d2f2ac523feb0a15de0a187f7a625b0acfdac95d Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Mon, 30 Dec 2019 17:38:32 +0200 Subject: [PATCH] flag: fix displaying of both abbreviated and long options Add tests for the usage screen --- tools/oldv.v | 15 +-- vlib/compiler/preludes/tests_with_stats.v | 1 - vlib/flag/flag.v | 147 +++++++++++----------- vlib/flag/flag_test.v | 3 + 4 files changed, 85 insertions(+), 81 deletions(-) diff --git a/tools/oldv.v b/tools/oldv.v index c1ad516f66..cde2631f13 100644 --- a/tools/oldv.v +++ b/tools/oldv.v @@ -109,18 +109,19 @@ fn main(){ scripting.used_tools_must_exist(['git','cc']) mut context := Context{} mut fp := flag.new_flag_parser(os.args) - fp.application(os.filename(os.executable())) + fp.application(filepath.filename(os.executable())) fp.version( tool_version ) fp.description( tool_description ) fp.arguments_description('VCOMMIT') fp.skip_executable() - show_help:=fp.bool('help', false, 'Show this help screen\n') - context.cmd_to_run = fp.string('command', '', 'Command to run in the old V repo.\n') - context.cleanup = fp.bool('clean', true, 'Clean before running (slower).\n') - context.verbose = fp.bool('verbose', false, 'Be more verbose.\n') + show_help:=fp.bool_('help', `h`, false, 'Show this help screen.') + context.verbose = fp.bool_('verbose', `v`, false, 'Be more verbose.\n') - context.workdir = os.realpath( fp.string('work-dir', os.tmpdir(), 'A writable folder, where the comparison will be done.\n') ) + context.cleanup = fp.bool('clean', true, 'Clean before running (slower).') + context.cmd_to_run = fp.string_('command', `c`, '', 'Command to run in the old V repo.') + + context.workdir = os.realpath( fp.string_('work-dir', `w`, os.tmpdir(), 'A writable folder, where the comparison will be done.\n') ) context.repo_url_v = fp.string('v-repo', remote_repo_url_v, 'The url of the V repository. You can clone it locally too.\n') @@ -129,7 +130,7 @@ fn main(){ flag.SPACE+'beforehand, and then just give the local folder \n'+ flag.SPACE+'path here. That will eliminate the network ops \n'+ flag.SPACE+'done by this tool, which is useful, if you want \n'+ - flag.SPACE+'to script it/run it in a restrictive vps/docker.\n') + flag.SPACE+'to script it/run it in a restrictive vps/docker.') if( show_help ){ println( fp.usage() ) diff --git a/vlib/compiler/preludes/tests_with_stats.v b/vlib/compiler/preludes/tests_with_stats.v index 325f57a176..3a3c46ed55 100644 --- a/vlib/compiler/preludes/tests_with_stats.v +++ b/vlib/compiler/preludes/tests_with_stats.v @@ -8,7 +8,6 @@ module main // / code, instead of in embedded C ... // ///////////////////////////////////////////////////////////////////// import ( - term filepath benchmark ) diff --git a/vlib/flag/flag.v b/vlib/flag/flag.v index 59b84204de..bf1e51f6f0 100644 --- a/vlib/flag/flag.v +++ b/vlib/flag/flag.v @@ -83,18 +83,18 @@ pub fn new_flag_parser(args []string) &FlagParser { } // change the application name to be used in 'usage' output -pub fn (fs mut FlagParser) application(n string) { - fs.application_name = n +pub fn (fs mut FlagParser) application(name string) { + fs.application_name = name } // change the application version to be used in 'usage' output -pub fn (fs mut FlagParser) version(n string) { - fs.application_version = n +pub fn (fs mut FlagParser) version(vers string) { + fs.application_version = vers } // change the application version to be used in 'usage' output -pub fn (fs mut FlagParser) description(n string) { - fs.application_description = n +pub fn (fs mut FlagParser) description(desc string) { + fs.application_description = desc } // in most cases you do not need the first argv for flag parsing @@ -103,12 +103,12 @@ pub fn (fs mut FlagParser) skip_executable() { } // private helper to register a flag -fn (fs mut FlagParser) add_flag(n string, a byte, u, vd string) { +fn (fs mut FlagParser) add_flag(name string, abbr byte, usage string, desc string) { fs.flags << Flag{ - name: n, - abbr: a, - usage: u, - val_desc: vd + name: name, + abbr: abbr, + usage: usage, + val_desc: desc } } @@ -204,10 +204,10 @@ fn (fs mut FlagParser) parse_bool_value(longhand string, shorthand byte) ?string // bool_opt returns an optional that returns the value associated with the flag. // In the situation that the flag was not provided, it returns null. -pub fn (fs mut FlagParser) bool_opt(n string, a byte, u string) ?bool { - fs.add_flag(n, a, u, '') - parsed := fs.parse_bool_value(n, a) or { - return error("parameter '$n' not provided") +pub fn (fs mut FlagParser) bool_opt(name string, abbr byte, usage string) ?bool { + fs.add_flag(name, abbr, usage, '') + parsed := fs.parse_bool_value(name, abbr) or { + return error("parameter '$name' not provided") } return parsed == 'true' } @@ -217,11 +217,11 @@ pub fn (fs mut FlagParser) bool_opt(n string, a byte, u string) ?bool { // the value is returned (true/false) // else // the default value is returned -// version with abbreviation +// version with abbr //TODO error handling for invalid string to bool conversion -pub fn (fs mut FlagParser) bool_(n string, a byte, v bool, u string) bool { - value := fs.bool_opt(n, a, u) or { - return v +pub fn (fs mut FlagParser) bool_(name string, abbr byte, bdefault bool, usage string) bool { + value := fs.bool_opt(name, abbr, usage) or { + return bdefault } return value } @@ -232,15 +232,15 @@ pub fn (fs mut FlagParser) bool_(n string, a byte, v bool, u string) bool { // 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) +pub fn (fs mut FlagParser) bool(name string, v bool, usage string) bool { + return fs.bool_(name, 0, v, usage) } // int_multi returns all instances of values associated with the flags provided // In the case that none were found, it returns an empty array. -pub fn (fs mut FlagParser) int_multi(n string, a byte, u string) []int { - fs.add_flag(n, a, u, '') - parsed := fs.parse_value(n, a) +pub fn (fs mut FlagParser) int_multi(name string, abbr byte, usage string) []int { + fs.add_flag(name, abbr, usage, '') + parsed := fs.parse_value(name, abbr) mut value := []int for val in parsed { value << val.int() @@ -250,11 +250,11 @@ pub fn (fs mut FlagParser) int_multi(n string, a byte, u string) []int { // int_opt returns an optional that returns the value associated with the flag. // In the situation that the flag was not provided, it returns null. -pub fn (fs mut FlagParser) int_opt(n string, a byte, u string) ?int { - fs.add_flag(n, a, u, '') - parsed := fs.parse_value(n, a) +pub fn (fs mut FlagParser) int_opt(name string, abbr byte, usage string) ?int { + fs.add_flag(name, abbr, usage, '') + parsed := fs.parse_value(name, abbr) if parsed.len == 0 { - return error("parameter '$n' not provided") + return error("parameter '$name' not provided") } return parsed[0].int() } @@ -264,11 +264,11 @@ pub fn (fs mut FlagParser) int_opt(n string, a byte, u string) ?int { // the value is returned (int) // else // the default value is returned -// version with abbreviation +// version with abbr //TODO error handling for invalid string to int conversion -pub fn (fs mut FlagParser) int_(n string, a byte, i int, u string) int { - value := fs.int_opt(n, a, u) or { - return i +pub fn (fs mut FlagParser) int_(name string, abbr byte, idefault int, usage string) int { + value := fs.int_opt(name, abbr, usage) or { + return idefault } return value } @@ -279,15 +279,15 @@ pub fn (fs mut FlagParser) int_(n string, a byte, i int, u string) int { // else // 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 { - return fs.int_(n, `\0`, i, u) +pub fn (fs mut FlagParser) int(name string, i int, usage string) int { + return fs.int_(name, 0, i, usage) } // float_multi returns all instances of values associated with the flags provided // In the case that none were found, it returns an empty array. -pub fn (fs mut FlagParser) float_multi(n string, a byte, u string) []f32 { - fs.add_flag(n, a, u, '') - parsed := fs.parse_value(n, a) +pub fn (fs mut FlagParser) float_multi(name string, abbr byte, usage string) []f32 { + fs.add_flag(name, abbr, usage, '') + parsed := fs.parse_value(name, abbr) mut value := []f32 for val in parsed { value << val.f32() @@ -297,11 +297,11 @@ pub fn (fs mut FlagParser) float_multi(n string, a byte, u string) []f32 { // float_opt returns an optional that returns the value associated with the flag. // In the situation that the flag was not provided, it returns null. -pub fn (fs mut FlagParser) float_opt(n string, a byte, u string) ?f32 { - fs.add_flag(n, a, u, '') - parsed := fs.parse_value(n, a) +pub fn (fs mut FlagParser) float_opt(name string, abbr byte, usage string) ?f32 { + fs.add_flag(name, abbr, usage, '') + parsed := fs.parse_value(name, abbr) if parsed.len == 0 { - return error("parameter '$n' not provided") + return error("parameter '$name' not provided") } return parsed[0].f32() } @@ -311,11 +311,11 @@ pub fn (fs mut FlagParser) float_opt(n string, a byte, u string) ?f32 { // the value is returned (float) // else // the default value is returned -// version with abbreviation +// version with abbr //TODO error handling for invalid string to float conversion -pub fn (fs mut FlagParser) float_(n string, a byte, f f32, u string) f32 { - value := fs.float_opt(n, a, u) or { - return f +pub fn (fs mut FlagParser) float_(name string, abbr byte, fdefault f32, usage string) f32 { + value := fs.float_opt(name, abbr, usage) or { + return fdefault } return value } @@ -326,24 +326,24 @@ pub fn (fs mut FlagParser) float_(n string, a byte, f f32, u string) f32 { // else // 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 { - return fs.float_(n, `\0`, f, u) +pub fn (fs mut FlagParser) float(name string, f f32, usage string) f32 { + return fs.float_(name, 0, f, usage) } // string_multi returns all instances of values associated with the flags provided // In the case that none were found, it returns an empty array. -pub fn (fs mut FlagParser) string_multi(n string, a byte, u string) []string { - fs.add_flag(n, a, u, '') - return fs.parse_value(n, a) +pub fn (fs mut FlagParser) string_multi(name string, abbr byte, usage string) []string { + fs.add_flag(name, abbr, usage, '') + return fs.parse_value(name, abbr) } // string_opt returns an optional that returns the value associated with the flag. // In the situation that the flag was not provided, it returns null. -pub fn (fs mut FlagParser) string_opt(n string, a byte, u string) ?string { - fs.add_flag(n, a, u, '') - parsed := fs.parse_value(n, a) +pub fn (fs mut FlagParser) string_opt(name string, abbr byte, usage string) ?string { + fs.add_flag(name, abbr, usage, '') + parsed := fs.parse_value(name, abbr) if parsed.len == 0 { - return error("parameter '$n' not provided") + return error("parameter '$name' not provided") } return parsed[0] } @@ -353,10 +353,10 @@ pub fn (fs mut FlagParser) string_opt(n string, a byte, u string) ?string { // 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 { - value := fs.string_opt(n, a, u) or { - return v +// version with abbr +pub fn (fs mut FlagParser) string_(name string, abbr byte, sdefault string, usage string) string { + value := fs.string_opt(name, abbr, usage) or { + return sdefault } return value } @@ -366,8 +366,8 @@ pub fn (fs mut FlagParser) string_(n string, a byte, v, u string) string { // the value is returned (string) // else // the default value is returned -pub fn (fs mut FlagParser) string(n, v, u string) string { - return fs.string_(n, `\0`, v, u) +pub fn (fs mut FlagParser) string(name string, sdefault string, usage string) string { + return fs.string_(name, 0, sdefault, usage) } pub fn (fs mut FlagParser) limit_free_args_to_at_least(n int) { @@ -448,23 +448,24 @@ pub fn (fs FlagParser) usage() string { if fs.flags.len > 0 { use += 'Options:\n' for f in fs.flags { - longstr := if f.val_desc.contains('bool') { - ', --$f.name' - } else { - ', --$f.name $f.val_desc' + mut onames:=[]string + if f.abbr != 0 { + onames << '-${f.abbr.str()}' } - flag_desc := if f.name.len == 0 { - ', $f.val_desc' - } else { - longstr + if f.name != '' { + if !f.val_desc.contains('') { + onames << '--${f.name} $f.val_desc' + }else{ + onames << '--${f.name}' + } } - space := if flag_desc.len > SPACE.len-2 { - '\n$SPACE' + option_names := ' ' + onames.join(', ') + space := if option_names.len > SPACE.len-2 { + '\n${SPACE}' } else { - SPACE[flag_desc.len..] + SPACE[option_names.len..] } - abbr_desc := if f.abbr == `\0` { '' } else { ' -${tos(f.abbr, 1)}' } - use += '${abbr_desc}${flag_desc}${space}${f.usage}\n' + use += '${option_names}${space}${f.usage}\n' } } diff --git a/vlib/flag/flag_test.v b/vlib/flag/flag_test.v index 99fd52fc6b..689c19d6c8 100644 --- a/vlib/flag/flag_test.v +++ b/vlib/flag/flag_test.v @@ -245,6 +245,9 @@ fn test_allow_abreviations() { u := fp.usage() assert u.contains(' -v') && u.contains(' -o') && u.contains(' -i') && u.contains(' -f') + assert u.contains(' -o, --output ') + assert u.contains(' -i, --count ') + assert u.contains(' -f, --value ') } fn test_allow_kebab_options() {