From 477d442f1806704070bb370fcb0aefc7da188e94 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Fri, 9 Jul 2021 22:08:01 +0300 Subject: [PATCH] flag: add overridable --help and --version by default --- vlib/flag/default_flag_options_test.v | 35 +++++++++++++++++++ vlib/flag/flag.v | 33 ++++++++++++++++- .../simplest_flag_program.dashdash.help.out | 1 + ...simplest_flag_program.dashdash.version.out | 1 + .../testdata/simplest_flag_program.help.out | 7 ++++ vlib/flag/testdata/simplest_flag_program.out | 1 + vlib/flag/testdata/simplest_flag_program.v | 14 ++++++++ .../simplest_flag_program.version.out | 1 + 8 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 vlib/flag/default_flag_options_test.v create mode 100644 vlib/flag/testdata/simplest_flag_program.dashdash.help.out create mode 100644 vlib/flag/testdata/simplest_flag_program.dashdash.version.out create mode 100644 vlib/flag/testdata/simplest_flag_program.help.out create mode 100644 vlib/flag/testdata/simplest_flag_program.out create mode 100644 vlib/flag/testdata/simplest_flag_program.v create mode 100644 vlib/flag/testdata/simplest_flag_program.version.out diff --git a/vlib/flag/default_flag_options_test.v b/vlib/flag/default_flag_options_test.v new file mode 100644 index 0000000000..fb0a423a6a --- /dev/null +++ b/vlib/flag/default_flag_options_test.v @@ -0,0 +1,35 @@ +import os + +const source = 'vlib/flag/testdata/simplest_flag_program.v' + +const simple_flag_app_executable = os.real_path(os.join_path(os.cache_dir(), 'simple_flag_app.exe')) + +fn testsuite_begin() { + os.chdir(@VMODROOT) + os.rm(simple_flag_app_executable) or {} + res := os.execute('${@VEXE} -o $simple_flag_app_executable $source') + assert res.exit_code == 0 + assert os.execute(simple_flag_app_executable).exit_code == 0 +} + +fn testsuite_end() { + os.rm(simple_flag_app_executable) or {} + assert true +} + +fn check_program(opts string, extension string) { + result := source.replace('.v', extension) + res := os.execute('$simple_flag_app_executable $opts') + lines := os.read_lines(result) or { panic(err) } + assert res.exit_code == 0 + assert res.output.split_into_lines() == lines +} + +fn test_default_builtin_flag_options() { + check_program('', '.out') + check_program(' -- --help', '.dashdash.help.out') + check_program(' -- --version', '.dashdash.version.out') + check_program(' -h', '.help.out') + check_program(' --help', '.help.out') + check_program(' --version', '.version.out') +} diff --git a/vlib/flag/flag.v b/vlib/flag/flag.v index 102dd1f3f5..bb3c472d6b 100644 --- a/vlib/flag/flag.v +++ b/vlib/flag/flag.v @@ -62,6 +62,8 @@ pub: idx_dashdash int // the index of a `--`, -1 if there is not any all_after_dashdash []string // all options after `--` are ignored, and will be passed to the application unmodified pub mut: + default_help_label string = 'display this help and exit' + default_version_label string = 'output version information and exit' args []string // the current list of processed args max_free_args int flags []Flag // registered flags @@ -507,12 +509,41 @@ pub fn (fs FlagParser) usage() string { return use.join('\n').replace('- ,', ' ') } +fn (mut fs FlagParser) find_existing_flag(fname string) ?Flag { + for f in fs.flags { + if f.name == fname { + return f + } + } + return error('no such flag') +} + +fn (mut fs FlagParser) handle_builtin_options() { + mut show_version := false + mut show_help := false + fs.find_existing_flag('help') or { + show_help = fs.bool('help', `h`, false, fs.default_help_label) + } + fs.find_existing_flag('version') or { + show_version = fs.bool('version', 0, false, fs.default_version_label) + } + if show_help { + println(fs.usage()) + exit(0) + } + if show_version { + println('$fs.application_name $fs.application_version') + exit(0) + } +} + // finalize - return all remaining arguments (non options). // Call .finalize() after all arguments are defined. // The remaining arguments are returned in the same order they are // defined on the command line. If additional flags are found, i.e. // (things starting with '--' or '-'), it returns an error. -pub fn (fs FlagParser) finalize() ?[]string { +pub fn (mut fs FlagParser) finalize() ?[]string { + fs.handle_builtin_options() mut remaining := fs.args.clone() if !fs.allow_unknown_args { for a in remaining { diff --git a/vlib/flag/testdata/simplest_flag_program.dashdash.help.out b/vlib/flag/testdata/simplest_flag_program.dashdash.help.out new file mode 100644 index 0000000000..2529e9f57c --- /dev/null +++ b/vlib/flag/testdata/simplest_flag_program.dashdash.help.out @@ -0,0 +1 @@ +[vlib/flag/testdata/simplest_flag_program.v:13] rest_of_args: ['--help'] diff --git a/vlib/flag/testdata/simplest_flag_program.dashdash.version.out b/vlib/flag/testdata/simplest_flag_program.dashdash.version.out new file mode 100644 index 0000000000..b0b4d65efe --- /dev/null +++ b/vlib/flag/testdata/simplest_flag_program.dashdash.version.out @@ -0,0 +1 @@ +[vlib/flag/testdata/simplest_flag_program.v:13] rest_of_args: ['--version'] diff --git a/vlib/flag/testdata/simplest_flag_program.help.out b/vlib/flag/testdata/simplest_flag_program.help.out new file mode 100644 index 0000000000..9b5ab9e441 --- /dev/null +++ b/vlib/flag/testdata/simplest_flag_program.help.out @@ -0,0 +1,7 @@ +abc 0.0.1 +----------------------------------------------- +Usage: abc [options] [ARGS] + +Options: + -h, --help display this help and exit + --version output version information and exit diff --git a/vlib/flag/testdata/simplest_flag_program.out b/vlib/flag/testdata/simplest_flag_program.out new file mode 100644 index 0000000000..02b7cea388 --- /dev/null +++ b/vlib/flag/testdata/simplest_flag_program.out @@ -0,0 +1 @@ +[vlib/flag/testdata/simplest_flag_program.v:13] rest_of_args: [] diff --git a/vlib/flag/testdata/simplest_flag_program.v b/vlib/flag/testdata/simplest_flag_program.v new file mode 100644 index 0000000000..cee2ff7d3a --- /dev/null +++ b/vlib/flag/testdata/simplest_flag_program.v @@ -0,0 +1,14 @@ +import os +import flag + +fn main() { + mut fp := flag.new_flag_parser(os.args) + fp.application('abc') + fp.version('0.0.1') + fp.skip_executable() + rest_of_args := fp.finalize() or { + eprintln(err) + exit(1) + } + dump(rest_of_args) +} diff --git a/vlib/flag/testdata/simplest_flag_program.version.out b/vlib/flag/testdata/simplest_flag_program.version.out new file mode 100644 index 0000000000..de52cb026f --- /dev/null +++ b/vlib/flag/testdata/simplest_flag_program.version.out @@ -0,0 +1 @@ +abc 0.0.1