From ff730b4eb0a58b50e9e14efbf42f7b2c7c3e4dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20B=C3=B6ttcher?= Date: Mon, 5 Aug 2019 07:50:24 +0200 Subject: [PATCH] flag: allow to check the count of the free args to produce an error --- vlib/flag/flag.v | 28 +++++++++++++++++++++++++++- vlib/flag/flag_test.v | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/vlib/flag/flag.v b/vlib/flag/flag.v index 27dbeeb7d2..7dcb0673b8 100644 --- a/vlib/flag/flag.v +++ b/vlib/flag/flag.v @@ -62,11 +62,15 @@ pub mut: application_name string application_version string application_description string + + min_free_args int + max_free_args int } // create a new flag set for parsing command line arguments +// TODO use INT_MAX some how pub fn new_flag_parser(args []string) &FlagParser { - return &FlagParser{args:args} + return &FlagParser{args:args, max_free_args: 4048} } // change the application name to be used in 'usage' output @@ -212,6 +216,17 @@ pub fn (fs mut FlagParser) string(n, v, u string) string { return parsed } +// 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) { + if min > max { + panic('flag.limit_free_args expect min < max, got $min >= $max') + } + fs.min_free_args = min + fs.max_free_args = max +} + const ( // used for formating usage message SPACE = ' ' @@ -259,5 +274,16 @@ pub fn (fs FlagParser) finalize() ?[]string { return error('Unknown argument \'${a.right(2)}\'') } } + if fs.args.len < fs.min_free_args { + return error('Expect at least ${fs.min_free_args} arguments') + } + if fs.args.len >= fs.max_free_args { + if fs.max_free_args > 0 { + return error('Expect at most ${fs.max_free_args} arguments') + } else { + return error('Expect no arguments') + } + } return fs.args } + diff --git a/vlib/flag/flag_test.v b/vlib/flag/flag_test.v index 2b45ebd2dc..d8cd48c830 100644 --- a/vlib/flag/flag_test.v +++ b/vlib/flag/flag_test.v @@ -191,3 +191,43 @@ fn test_if_no_options_given_usage_message_does_not_contain_options() { assert !fp.usage().contains('options:') } + +fn test_free_args_could_be_limited() { + mut fp1 := flag.new_flag_parser(['a', 'b', 'c']) + fp1.limit_free_args(1, 4) + args := fp1.finalize() or { + assert false + return + } + assert args[0] == 'a' && args[1] == 'b' && args[2] == 'c' +} + +fn test_error_for_to_few_free_args() { + mut fp1 := flag.new_flag_parser(['a', 'b', 'c']) + fp1.limit_free_args(5, 6) + args := fp1.finalize() or { + assert err == 'Expect at least 5 arguments' + return + } + assert args.len < 0 // expect an error and need to use args +} + +fn test_error_for_to_much_free_args() { + mut fp1 := flag.new_flag_parser(['a', 'b', 'c']) + fp1.limit_free_args(1, 2) + args := fp1.finalize() or { + assert err == 'Expect at most 2 arguments' + return + } + assert args.len < 0 // expect an error and need to use args +} + +fn test_could_expect_no_free_args() { + mut fp1 := flag.new_flag_parser(['a']) + fp1.limit_free_args(0, 0) + args := fp1.finalize() or { + assert err == 'Expect no arguments' + return + } + assert args.len < 0 // expect an error and need to use args +}