flag: fix displaying of both abbreviated and long options

Add tests for the usage screen
pull/3280/head
Delyan Angelov 2019-12-30 17:38:32 +02:00 committed by Alexander Medvednikov
parent d07953b0f0
commit d2f2ac523f
4 changed files with 85 additions and 81 deletions

View File

@ -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() )

View File

@ -8,7 +8,6 @@ module main
// / code, instead of in embedded C ...
// /////////////////////////////////////////////////////////////////////
import (
term
filepath
benchmark
)

View File

@ -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, '<bool>')
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, '<bool>')
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, '<multiple ints>')
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, '<multiple ints>')
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, '<int>')
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, '<int>')
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, '<multiple floats>')
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, '<multiple floats>')
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, '<float>')
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, '<float>')
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, '<multiple floats>')
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, '<multiple floats>')
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, '<string>')
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, '<string>')
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('<bool>') {
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'
}
}

View File

@ -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 <string>')
assert u.contains(' -i, --count <int>')
assert u.contains(' -f, --value <float>')
}
fn test_allow_kebab_options() {