mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
flag: implement *_opt() and *_multi()
It's very often that someone will need to process values that were not provided separately (eg. generating a complex default value like in V). This commit allows the user to call the *_opt() functions instead of forcing them to provide some magical default values. * flag: Implement int_multi(), float_multi() and string_multi() These 3 functions are useful when the application expects a flag to be repeated more than once. A sample would be: v -cflags someflag -cflags secondflag This feature exposes the raw array that the flag parser internally keeps and allow the application to parse it however they want instead of dropping everything except the first element. * flag: Add documentation Add comments describing what *_opt() and *_multi() do.
This commit is contained in:
parent
d1714c4a2a
commit
dadf147382
442
vlib/flag/flag.v
442
vlib/flag/flag.v
@ -46,70 +46,70 @@ module flag
|
|||||||
|
|
||||||
// data object storing information about a defined flag
|
// data object storing information about a defined flag
|
||||||
pub struct Flag {
|
pub struct Flag {
|
||||||
pub:
|
pub:
|
||||||
name string // name as it appears on command line
|
name string // name as it appears on command line
|
||||||
abbr byte // shortcut
|
abbr byte // shortcut
|
||||||
usage string // help message
|
usage string // help message
|
||||||
val_desc string // something like '<arg>' that appears in usage,
|
val_desc string // something like '<arg>' that appears in usage,
|
||||||
// and also the default value, when the flag is not given
|
// and also the default value, when the flag is not given
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
pub struct FlagParser {
|
pub struct FlagParser {
|
||||||
pub mut:
|
pub mut:
|
||||||
args []string // the arguments to be parsed
|
args []string // the arguments to be parsed
|
||||||
flags []Flag // registered flags
|
flags []Flag // registered flags
|
||||||
|
|
||||||
application_name string
|
application_name string
|
||||||
application_version string
|
application_version string
|
||||||
application_description string
|
application_description string
|
||||||
|
|
||||||
min_free_args int
|
min_free_args int
|
||||||
max_free_args int
|
max_free_args int
|
||||||
args_description string
|
args_description string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
// used for formating usage message
|
// used for formating usage message
|
||||||
SPACE = ' '
|
SPACE = ' '
|
||||||
UNDERLINE = '-----------------------------------------------'
|
UNDERLINE = '-----------------------------------------------'
|
||||||
MAX_ARGS_NUMBER = 4048
|
MAX_ARGS_NUMBER = 4048
|
||||||
)
|
)
|
||||||
|
|
||||||
// create a new flag set for parsing command line arguments
|
// create a new flag set for parsing command line arguments
|
||||||
// TODO use INT_MAX some how
|
// TODO use INT_MAX some how
|
||||||
pub fn new_flag_parser(args []string) &FlagParser {
|
pub fn new_flag_parser(args []string) &FlagParser {
|
||||||
return &FlagParser{args:args, max_free_args: MAX_ARGS_NUMBER}
|
return &FlagParser{args:args, max_free_args: MAX_ARGS_NUMBER}
|
||||||
}
|
}
|
||||||
|
|
||||||
// change the application name to be used in 'usage' output
|
// change the application name to be used in 'usage' output
|
||||||
pub fn (fs mut FlagParser) application(n string) {
|
pub fn (fs mut FlagParser) application(n string) {
|
||||||
fs.application_name = n
|
fs.application_name = n
|
||||||
}
|
}
|
||||||
|
|
||||||
// change the application version to be used in 'usage' output
|
// change the application version to be used in 'usage' output
|
||||||
pub fn (fs mut FlagParser) version(n string) {
|
pub fn (fs mut FlagParser) version(n string) {
|
||||||
fs.application_version = n
|
fs.application_version = n
|
||||||
}
|
}
|
||||||
|
|
||||||
// change the application version to be used in 'usage' output
|
// change the application version to be used in 'usage' output
|
||||||
pub fn (fs mut FlagParser) description(n string) {
|
pub fn (fs mut FlagParser) description(n string) {
|
||||||
fs.application_description = n
|
fs.application_description = n
|
||||||
}
|
}
|
||||||
|
|
||||||
// in most cases you do not need the first argv for flag parsing
|
// in most cases you do not need the first argv for flag parsing
|
||||||
pub fn (fs mut FlagParser) skip_executable() {
|
pub fn (fs mut FlagParser) skip_executable() {
|
||||||
fs.args.delete(0)
|
fs.args.delete(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// private helper to register a flag
|
// 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(n string, a byte, u, vd string) {
|
||||||
fs.flags << Flag{
|
fs.flags << Flag{
|
||||||
name: n,
|
name: n,
|
||||||
abbr: a,
|
abbr: a,
|
||||||
usage: u,
|
usage: u,
|
||||||
val_desc: vd
|
val_desc: vd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private: general parsing a single argument
|
// private: general parsing a single argument
|
||||||
@ -121,24 +121,47 @@ fn (fs mut FlagParser) add_flag(n string, a byte, u, vd string) {
|
|||||||
//
|
//
|
||||||
// - the name, usage are registered
|
// - the name, usage are registered
|
||||||
// - found arguments and corresponding values are removed from args list
|
// - found arguments and corresponding values are removed from args list
|
||||||
fn (fs mut FlagParser) parse_value(n string, ab byte) ?string {
|
fn (fs mut FlagParser) parse_value(longhand string, shorthand byte) []string {
|
||||||
c := '--$n'
|
full := '--$longhand'
|
||||||
for i, a in fs.args {
|
mut found_entries := []string
|
||||||
if a == c || (a.len == 2 && a[1] == ab) {
|
mut to_delete := []int
|
||||||
if i+1 > fs.args.len { panic('Missing argument for \'$n\'') }
|
mut should_skip_one := false
|
||||||
nextarg := fs.args[i+1]
|
for i, arg in fs.args {
|
||||||
if nextarg.limit(2) == '--' { panic('Missing argument for \'$n\'') }
|
if should_skip_one {
|
||||||
val := fs.args[i+1]
|
should_skip_one = false
|
||||||
fs.args.delete(i+1)
|
continue
|
||||||
fs.args.delete(i)
|
}
|
||||||
return val
|
if arg == '--' {
|
||||||
} else if a.len > c.len && c == a[..c.len] && a[c.len..c.len+1] == '=' {
|
//End of input. We're done here.
|
||||||
val := a[c.len+1..]
|
break
|
||||||
fs.args.delete(i)
|
}
|
||||||
return val
|
if arg == full || (arg[0] == `-` && arg[1] == shorthand && arg.len == 2) {
|
||||||
}
|
if i+1 > fs.args.len {
|
||||||
}
|
panic("Missing argument for '$longhand'")
|
||||||
return error('parameter \'$n\' not found')
|
}
|
||||||
|
nextarg := fs.args[i+1]
|
||||||
|
if nextarg.len > 2 && nextarg[..2] == '--' {
|
||||||
|
//It could be end of input (--) or another argument (--abc).
|
||||||
|
//Both are invalid so die.
|
||||||
|
panic("Missing argument for '$longhand'")
|
||||||
|
}
|
||||||
|
found_entries << fs.args[i+1]
|
||||||
|
to_delete << i
|
||||||
|
to_delete << i+1
|
||||||
|
should_skip_one = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if arg.len > full.len+1 && arg[..full.len+1] == '$full=' {
|
||||||
|
found_entries << arg[full.len+1..]
|
||||||
|
to_delete << i
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, del in to_delete {
|
||||||
|
//i entrys are deleted so it's shifted left i times.
|
||||||
|
fs.args.delete(del - i)
|
||||||
|
}
|
||||||
|
return found_entries
|
||||||
}
|
}
|
||||||
|
|
||||||
// special parsing for bool values
|
// special parsing for bool values
|
||||||
@ -147,27 +170,46 @@ fn (fs mut FlagParser) parse_value(n string, ab byte) ?string {
|
|||||||
// special: it is allowed to define bool flags without value
|
// special: it is allowed to define bool flags without value
|
||||||
// -> '--flag' is parsed as true
|
// -> '--flag' is parsed as true
|
||||||
// -> '--flag' is equal to '--flag=true'
|
// -> '--flag' is equal to '--flag=true'
|
||||||
fn (fs mut FlagParser) parse_bool_value(n string, ab byte) ?string {
|
fn (fs mut FlagParser) parse_bool_value(longhand string, shorthand byte) ?string {
|
||||||
c := '--$n'
|
full := '--$longhand'
|
||||||
for i, a in fs.args {
|
for i, arg in fs.args {
|
||||||
if a == c || (a.len == 2 && a[1] == ab) {
|
if arg == '--' {
|
||||||
if fs.args.len > i+1 && (fs.args[i+1] in ['true', 'false']) {
|
//End of input. We're done.
|
||||||
val := fs.args[i+1]
|
break
|
||||||
fs.args.delete(i+1)
|
}
|
||||||
fs.args.delete(i)
|
if arg == full || (arg[0] == `-` && arg[1] == shorthand && arg.len == 2) {
|
||||||
return val
|
if fs.args.len > i+1 && (fs.args[i+1] in ['true', 'false']) {
|
||||||
} else {
|
val := fs.args[i+1]
|
||||||
val := 'true'
|
fs.args.delete(i+1)
|
||||||
fs.args.delete(i)
|
fs.args.delete(i)
|
||||||
return val
|
return val
|
||||||
}
|
} else {
|
||||||
} else if a.len > c.len && c == a[..c.len] && a[c.len..c.len+1] == '=' {
|
fs.args.delete(i)
|
||||||
val := a[c.len+1..]
|
return 'true'
|
||||||
fs.args.delete(i)
|
}
|
||||||
return val
|
}
|
||||||
}
|
if arg.len > full.len+1 && arg[..full.len+1] == '$full=' {
|
||||||
}
|
// Flag abc=true
|
||||||
return error('parameter \'$n\' not found')
|
val := arg[full.len+1..]
|
||||||
|
fs.args.delete(i)
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
if arg[0] == `-` && arg.index_byte(shorthand) != -1 {
|
||||||
|
// -abc is equivalent to -a -b -c
|
||||||
|
return 'true'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error("parameter '$longhand' not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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")
|
||||||
|
}
|
||||||
|
return parsed == 'true'
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing a bool flag
|
// defining and parsing a bool flag
|
||||||
@ -178,11 +220,10 @@ fn (fs mut FlagParser) parse_bool_value(n string, ab byte) ?string {
|
|||||||
// version with abbreviation
|
// version with abbreviation
|
||||||
//TODO error handling for invalid string to bool conversion
|
//TODO error handling for invalid string to bool conversion
|
||||||
pub fn (fs mut FlagParser) bool_(n string, a byte, v bool, u string) bool {
|
pub fn (fs mut FlagParser) bool_(n string, a byte, v bool, u string) bool {
|
||||||
fs.add_flag(n, a, u, '<bool>:'+v.str())
|
value := fs.bool_opt(n, a, u) or {
|
||||||
parsed := fs.parse_bool_value(n, a) or {
|
return v
|
||||||
return v
|
}
|
||||||
}
|
return value
|
||||||
return parsed == 'true'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing a bool flag
|
// defining and parsing a bool flag
|
||||||
@ -192,7 +233,30 @@ pub fn (fs mut FlagParser) bool_(n string, a byte, v bool, u string) bool {
|
|||||||
// the default value is returned
|
// the default value is returned
|
||||||
//TODO error handling for invalid string to bool conversion
|
//TODO error handling for invalid string to bool conversion
|
||||||
pub fn (fs mut FlagParser) bool(n string, v bool, u string) bool {
|
pub fn (fs mut FlagParser) bool(n string, v bool, u string) bool {
|
||||||
return fs.bool_(n, `\0`, v, u)
|
return fs.bool_(n, `\0`, v, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
mut value := []int
|
||||||
|
for val in parsed {
|
||||||
|
value << val.int()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
if parsed.len == 0 {
|
||||||
|
return error("parameter '$n' not provided")
|
||||||
|
}
|
||||||
|
return parsed[0].int()
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing an int flag
|
// defining and parsing an int flag
|
||||||
@ -203,11 +267,10 @@ pub fn (fs mut FlagParser) bool(n string, v bool, u string) bool {
|
|||||||
// version with abbreviation
|
// version with abbreviation
|
||||||
//TODO error handling for invalid string to int conversion
|
//TODO error handling for invalid string to int conversion
|
||||||
pub fn (fs mut FlagParser) int_(n string, a byte, i int, u string) int {
|
pub fn (fs mut FlagParser) int_(n string, a byte, i int, u string) int {
|
||||||
fs.add_flag(n, a, u, '<int>:$i')
|
value := fs.int_opt(n, a, u) or {
|
||||||
parsed := fs.parse_value(n, a) or {
|
return i
|
||||||
return i
|
}
|
||||||
}
|
return value
|
||||||
return parsed.int()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing an int flag
|
// defining and parsing an int flag
|
||||||
@ -217,7 +280,30 @@ pub fn (fs mut FlagParser) int_(n string, a byte, i int, u string) int {
|
|||||||
// the default value is returned
|
// the default value is returned
|
||||||
//TODO error handling for invalid string to int conversion
|
//TODO error handling for invalid string to int conversion
|
||||||
pub fn (fs mut FlagParser) int(n string, i int, u string) int {
|
pub fn (fs mut FlagParser) int(n string, i int, u string) int {
|
||||||
return fs.int_(n, `\0`, i, u)
|
return fs.int_(n, `\0`, i, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
mut value := []f32
|
||||||
|
for val in parsed {
|
||||||
|
value << val.f32()
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
if parsed.len == 0 {
|
||||||
|
return error("parameter '$n' not provided")
|
||||||
|
}
|
||||||
|
return parsed[0].f32()
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing a float flag
|
// defining and parsing a float flag
|
||||||
@ -228,11 +314,10 @@ pub fn (fs mut FlagParser) int(n string, i int, u string) int {
|
|||||||
// version with abbreviation
|
// version with abbreviation
|
||||||
//TODO error handling for invalid string to float conversion
|
//TODO error handling for invalid string to float conversion
|
||||||
pub fn (fs mut FlagParser) float_(n string, a byte, f f32, u string) f32 {
|
pub fn (fs mut FlagParser) float_(n string, a byte, f f32, u string) f32 {
|
||||||
fs.add_flag(n, a, u, '<float>:$f')
|
value := fs.float_opt(n, a, u) or {
|
||||||
parsed := fs.parse_value(n, a) or {
|
return f
|
||||||
return f
|
}
|
||||||
}
|
return value
|
||||||
return parsed.f32()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing a float flag
|
// defining and parsing a float flag
|
||||||
@ -242,7 +327,25 @@ pub fn (fs mut FlagParser) float_(n string, a byte, f f32, u string) f32 {
|
|||||||
// the default value is returned
|
// the default value is returned
|
||||||
//TODO error handling for invalid string to float conversion
|
//TODO error handling for invalid string to float conversion
|
||||||
pub fn (fs mut FlagParser) float(n string, f f32, u string) f32 {
|
pub fn (fs mut FlagParser) float(n string, f f32, u string) f32 {
|
||||||
return fs.float_(n, `\0`, f, u)
|
return fs.float_(n, `\0`, f, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
if parsed.len == 0 {
|
||||||
|
return error("parameter '$n' not provided")
|
||||||
|
}
|
||||||
|
return parsed[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing a string flag
|
// defining and parsing a string flag
|
||||||
@ -252,11 +355,10 @@ pub fn (fs mut FlagParser) float(n string, f f32, u string) f32 {
|
|||||||
// the default value is returned
|
// the default value is returned
|
||||||
// version with abbreviation
|
// version with abbreviation
|
||||||
pub fn (fs mut FlagParser) string_(n string, a byte, v, u string) string {
|
pub fn (fs mut FlagParser) string_(n string, a byte, v, u string) string {
|
||||||
fs.add_flag(n, a, u, '<string>:$v')
|
value := fs.string_opt(n, a, u) or {
|
||||||
parsed := fs.parse_value(n, a) or {
|
return v
|
||||||
return v
|
}
|
||||||
}
|
return value
|
||||||
return parsed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// defining and parsing a string flag
|
// defining and parsing a string flag
|
||||||
@ -265,97 +367,97 @@ pub fn (fs mut FlagParser) string_(n string, a byte, v, u string) string {
|
|||||||
// else
|
// else
|
||||||
// the default value is returned
|
// the default value is returned
|
||||||
pub fn (fs mut FlagParser) string(n, v, u string) string {
|
pub fn (fs mut FlagParser) string(n, v, u string) string {
|
||||||
return fs.string_(n, `\0`, v, u)
|
return fs.string_(n, `\0`, v, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (fs mut FlagParser) limit_free_args_to_at_least(n int) {
|
pub fn (fs mut FlagParser) limit_free_args_to_at_least(n int) {
|
||||||
if n > MAX_ARGS_NUMBER {
|
if n > MAX_ARGS_NUMBER {
|
||||||
panic('flag.limit_free_args_to_at_least expect n to be smaller than $MAX_ARGS_NUMBER')
|
panic('flag.limit_free_args_to_at_least expect n to be smaller than $MAX_ARGS_NUMBER')
|
||||||
}
|
}
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
panic('flag.limit_free_args_to_at_least expect n to be a positive number')
|
panic('flag.limit_free_args_to_at_least expect n to be a positive number')
|
||||||
}
|
}
|
||||||
fs.min_free_args = n
|
fs.min_free_args = n
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (fs mut FlagParser) limit_free_args_to_exactly(n int) {
|
pub fn (fs mut FlagParser) limit_free_args_to_exactly(n int) {
|
||||||
if n > MAX_ARGS_NUMBER {
|
if n > MAX_ARGS_NUMBER {
|
||||||
panic('flag.limit_free_args_to_exactly expect n to be smaller than $MAX_ARGS_NUMBER')
|
panic('flag.limit_free_args_to_exactly expect n to be smaller than $MAX_ARGS_NUMBER')
|
||||||
}
|
}
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
panic('flag.limit_free_args_to_exactly expect n to be a non negative number')
|
panic('flag.limit_free_args_to_exactly expect n to be a non negative number')
|
||||||
}
|
}
|
||||||
fs.min_free_args = n
|
fs.min_free_args = n
|
||||||
fs.max_free_args = n
|
fs.max_free_args = n
|
||||||
}
|
}
|
||||||
|
|
||||||
// this will cause an error in finalize() if free args are out of range
|
// this will cause an error in finalize() if free args are out of range
|
||||||
// (min, ..., max)
|
// (min, ..., max)
|
||||||
pub fn (fs mut FlagParser) limit_free_args(min, max int) {
|
pub fn (fs mut FlagParser) limit_free_args(min, max int) {
|
||||||
if min > max {
|
if min > max {
|
||||||
panic('flag.limit_free_args expect min < max, got $min >= $max')
|
panic('flag.limit_free_args expect min < max, got $min >= $max')
|
||||||
}
|
}
|
||||||
fs.min_free_args = min
|
fs.min_free_args = min
|
||||||
fs.max_free_args = max
|
fs.max_free_args = max
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (fs mut FlagParser) arguments_description(description string){
|
pub fn (fs mut FlagParser) arguments_description(description string){
|
||||||
fs.args_description = description
|
fs.args_description = description
|
||||||
}
|
}
|
||||||
|
|
||||||
// collect all given information and
|
// collect all given information and
|
||||||
pub fn (fs FlagParser) usage() string {
|
pub fn (fs FlagParser) usage() string {
|
||||||
|
|
||||||
positive_min_arg := ( fs.min_free_args > 0 )
|
positive_min_arg := ( fs.min_free_args > 0 )
|
||||||
positive_max_arg := ( fs.max_free_args > 0 && fs.max_free_args != MAX_ARGS_NUMBER )
|
positive_max_arg := ( fs.max_free_args > 0 && fs.max_free_args != MAX_ARGS_NUMBER )
|
||||||
no_arguments := ( fs.min_free_args == 0 && fs.max_free_args == 0 )
|
no_arguments := ( fs.min_free_args == 0 && fs.max_free_args == 0 )
|
||||||
|
|
||||||
mut adesc := if fs.args_description.len > 0 { fs.args_description } else { '[ARGS]' }
|
mut adesc := if fs.args_description.len > 0 { fs.args_description } else { '[ARGS]' }
|
||||||
if no_arguments { adesc = '' }
|
if no_arguments { adesc = '' }
|
||||||
|
|
||||||
mut use := ''
|
mut use := ''
|
||||||
use += '$fs.application_name $fs.application_version\n'
|
use += '$fs.application_name $fs.application_version\n'
|
||||||
use += '$UNDERLINE\n'
|
use += '$UNDERLINE\n'
|
||||||
use += 'Usage: ${fs.application_name} [options] $adesc\n'
|
use += 'Usage: ${fs.application_name} [options] $adesc\n'
|
||||||
use += '\n'
|
use += '\n'
|
||||||
if fs.application_description != '' {
|
if fs.application_description != '' {
|
||||||
use += 'Description:\n'
|
use += 'Description:\n'
|
||||||
use += '$fs.application_description'
|
use += '$fs.application_description'
|
||||||
use += '\n\n'
|
use += '\n\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
// show a message about the [ARGS]:
|
// show a message about the [ARGS]:
|
||||||
if positive_min_arg || positive_max_arg || no_arguments {
|
if positive_min_arg || positive_max_arg || no_arguments {
|
||||||
if no_arguments {
|
if no_arguments {
|
||||||
use += 'This application does not expect any arguments\n\n'
|
use += 'This application does not expect any arguments\n\n'
|
||||||
goto end_of_arguments_handling
|
goto end_of_arguments_handling
|
||||||
}
|
}
|
||||||
mut s:= []string
|
mut s:= []string
|
||||||
if positive_min_arg { s << 'at least $fs.min_free_args' }
|
if positive_min_arg { s << 'at least $fs.min_free_args' }
|
||||||
if positive_max_arg { s << 'at most $fs.max_free_args' }
|
if positive_max_arg { s << 'at most $fs.max_free_args' }
|
||||||
if positive_min_arg && positive_max_arg && fs.min_free_args == fs.max_free_args {
|
if positive_min_arg && positive_max_arg && fs.min_free_args == fs.max_free_args {
|
||||||
s = ['exactly $fs.min_free_args']
|
s = ['exactly $fs.min_free_args']
|
||||||
}
|
}
|
||||||
sargs := s.join(' and ')
|
sargs := s.join(' and ')
|
||||||
use += 'The arguments should be $sargs in number.\n\n'
|
use += 'The arguments should be $sargs in number.\n\n'
|
||||||
}
|
}
|
||||||
end_of_arguments_handling:
|
end_of_arguments_handling:
|
||||||
|
|
||||||
if fs.flags.len > 0 {
|
if fs.flags.len > 0 {
|
||||||
use += 'Options:\n'
|
use += 'Options:\n'
|
||||||
for f in fs.flags {
|
for f in fs.flags {
|
||||||
flag_desc := ' --$f.name $f.val_desc'
|
flag_desc := ' --$f.name $f.val_desc'
|
||||||
space := if flag_desc.len > SPACE.len-2 {
|
space := if flag_desc.len > SPACE.len-2 {
|
||||||
'\n$SPACE'
|
'\n$SPACE'
|
||||||
} else {
|
} else {
|
||||||
SPACE[flag_desc.len..]
|
SPACE[flag_desc.len..]
|
||||||
}
|
}
|
||||||
abbr_desc := if f.abbr == `\0` { '' } else { ' -${tos(f.abbr, 1)}\n' }
|
abbr_desc := if f.abbr == `\0` { '' } else { ' -${tos(f.abbr, 1)}\n' }
|
||||||
use += '${abbr_desc}${flag_desc}${space}${f.usage}\n'
|
use += '${abbr_desc}${flag_desc}${space}${f.usage}\n'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return use
|
return use
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalize argument parsing -> call after all arguments are defined
|
// finalize argument parsing -> call after all arguments are defined
|
||||||
@ -366,20 +468,20 @@ pub fn (fs FlagParser) usage() string {
|
|||||||
// if additional flag are found (things starting with '--') an error is returned
|
// if additional flag are found (things starting with '--') an error is returned
|
||||||
// error handling is up to the application developer
|
// error handling is up to the application developer
|
||||||
pub fn (fs FlagParser) finalize() ?[]string {
|
pub fn (fs FlagParser) finalize() ?[]string {
|
||||||
for a in fs.args {
|
for a in fs.args {
|
||||||
if a.len >= 2 && a[..2] == '--' {
|
if a.len >= 2 && a[..2] == '--' {
|
||||||
return error('Unknown argument \'${a[2..]}\'')
|
return error('Unknown argument \'${a[2..]}\'')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fs.args.len < fs.min_free_args && fs.min_free_args > 0 {
|
if fs.args.len < fs.min_free_args && fs.min_free_args > 0 {
|
||||||
return error('Expected at least ${fs.min_free_args} arguments, but given $fs.args.len')
|
return error('Expected at least ${fs.min_free_args} arguments, but given $fs.args.len')
|
||||||
}
|
}
|
||||||
if fs.args.len > fs.max_free_args && fs.max_free_args > 0 {
|
if fs.args.len > fs.max_free_args && fs.max_free_args > 0 {
|
||||||
return error('Expected at most ${fs.max_free_args} arguments, but given $fs.args.len')
|
return error('Expected at most ${fs.max_free_args} arguments, but given $fs.args.len')
|
||||||
}
|
}
|
||||||
if fs.args.len > 0 && fs.max_free_args == 0 && fs.min_free_args == 0 {
|
if fs.args.len > 0 && fs.max_free_args == 0 && fs.min_free_args == 0 {
|
||||||
return error('Expected no arguments, but given $fs.args.len')
|
return error('Expected no arguments, but given $fs.args.len')
|
||||||
}
|
}
|
||||||
return fs.args
|
return fs.args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,266 +1,319 @@
|
|||||||
|
|
||||||
import flag
|
import flag
|
||||||
|
|
||||||
fn test_if_flag_not_given_return_default_values() {
|
fn test_if_flag_not_given_return_default_values() {
|
||||||
mut fp := flag.new_flag_parser([])
|
mut fp := flag.new_flag_parser([])
|
||||||
|
|
||||||
assert false == fp.bool('a_bool', false, '')
|
assert false == fp.bool('a_bool', false, '')
|
||||||
&& 42 == fp.int('an_int', 42, '')
|
&& 42 == fp.int('an_int', 42, '')
|
||||||
&& 1.0 == fp.float('a_float', 1.0, '')
|
&& 1.0 == fp.float('a_float', 1.0, '')
|
||||||
&& 'stuff' == fp.string('a_string', 'stuff', '')
|
&& 'stuff' == fp.string('a_string', 'stuff', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn test_could_define_application_name_and_version() {
|
fn test_could_define_application_name_and_version() {
|
||||||
mut fp := flag.new_flag_parser([])
|
mut fp := flag.new_flag_parser([])
|
||||||
fp.application('test app')
|
fp.application('test app')
|
||||||
fp.version('0.0.42')
|
fp.version('0.0.42')
|
||||||
fp.description('some text')
|
fp.description('some text')
|
||||||
|
|
||||||
assert fp.application_name == 'test app'
|
assert fp.application_name == 'test app'
|
||||||
&& fp.application_version == '0.0.42'
|
&& fp.application_version == '0.0.42'
|
||||||
&& fp.application_description == 'some text'
|
&& fp.application_description == 'some text'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_bool_flags_do_not_need_an_value() {
|
fn test_bool_flags_do_not_need_an_value() {
|
||||||
mut fp := flag.new_flag_parser(['--a_bool'])
|
mut fp := flag.new_flag_parser(['--a_bool'])
|
||||||
|
|
||||||
assert true == fp.bool('a_bool', false, '')
|
assert true == fp.bool('a_bool', false, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_flags_could_be_defined_with_eq() {
|
fn test_flags_could_be_defined_with_eq() {
|
||||||
mut fp := flag.new_flag_parser([
|
mut fp := flag.new_flag_parser([
|
||||||
'--an_int=42',
|
'--an_int=42',
|
||||||
'--a_float=2.0',
|
'--a_float=2.0',
|
||||||
'--bool_without',
|
'--bool_without',
|
||||||
'--a_string=stuff',
|
'--a_string=stuff',
|
||||||
'--a_bool=true'])
|
'--a_bool=true'])
|
||||||
|
|
||||||
assert 42 == fp.int('an_int', 666, '')
|
assert 42 == fp.int('an_int', 666, '')
|
||||||
&& true == fp.bool('a_bool', false, '')
|
&& true == fp.bool('a_bool', false, '')
|
||||||
&& true == fp.bool('bool_without', false, '')
|
&& true == fp.bool('bool_without', false, '')
|
||||||
&& 2.0 == fp.float('a_float', 1.0, '')
|
&& 2.0 == fp.float('a_float', 1.0, '')
|
||||||
&& 'stuff' == fp.string('a_string', 'not_stuff', '')
|
&& 'stuff' == fp.string('a_string', 'not_stuff', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_values_could_be_defined_without_eq() {
|
fn test_values_could_be_defined_without_eq() {
|
||||||
mut fp := flag.new_flag_parser([
|
mut fp := flag.new_flag_parser([
|
||||||
'--an_int', '42',
|
'--an_int', '42',
|
||||||
'--a_float', '2.0',
|
'--a_float', '2.0',
|
||||||
'--bool_without',
|
'--bool_without',
|
||||||
'--a_string', 'stuff',
|
'--a_string', 'stuff',
|
||||||
'--a_bool', 'true'])
|
'--a_bool', 'true'])
|
||||||
|
|
||||||
assert 42 == fp.int('an_int', 666, '')
|
assert 42 == fp.int('an_int', 666, '')
|
||||||
&& true == fp.bool('a_bool', false, '')
|
&& true == fp.bool('a_bool', false, '')
|
||||||
&& true == fp.bool('bool_without', false, '')
|
&& true == fp.bool('bool_without', false, '')
|
||||||
&& 2.0 == fp.float('a_float', 1.0, '')
|
&& 2.0 == fp.float('a_float', 1.0, '')
|
||||||
&& 'stuff' == fp.string('a_string', 'not_stuff', '')
|
&& 'stuff' == fp.string('a_string', 'not_stuff', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_values_could_be_defined_mixed() {
|
fn test_values_could_be_defined_mixed() {
|
||||||
mut fp := flag.new_flag_parser([
|
mut fp := flag.new_flag_parser([
|
||||||
'--an_int', '42',
|
'--an_int', '42',
|
||||||
'--a_float=2.0',
|
'--a_float=2.0',
|
||||||
'--bool_without',
|
'--bool_without',
|
||||||
'--a_string', 'stuff',
|
'--a_string', 'stuff',
|
||||||
'--a_bool=true'])
|
'--a_bool=true'])
|
||||||
|
|
||||||
assert 42 == fp.int('an_int', 666, '')
|
assert 42 == fp.int('an_int', 666, '')
|
||||||
&& true == fp.bool('a_bool', false, '')
|
&& true == fp.bool('a_bool', false, '')
|
||||||
&& true == fp.bool('bool_without', false, '')
|
&& true == fp.bool('bool_without', false, '')
|
||||||
&& 2.0 == fp.float('a_float', 1.0, '')
|
&& 2.0 == fp.float('a_float', 1.0, '')
|
||||||
&& 'stuff' == fp.string('a_string', 'not_stuff', '')
|
&& 'stuff' == fp.string('a_string', 'not_stuff', '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_beaware_for_argument_names_with_same_prefix() {
|
fn test_beaware_for_argument_names_with_same_prefix() {
|
||||||
mut fp := flag.new_flag_parser([
|
mut fp := flag.new_flag_parser([
|
||||||
'--short', '5',
|
'--short', '5',
|
||||||
'--shorter=7'
|
'--shorter=7'
|
||||||
])
|
])
|
||||||
|
|
||||||
assert 5 == fp.int('short', 666, '')
|
assert 5 == fp.int('short', 666, '')
|
||||||
&& 7 == fp.int('shorter', 666, '')
|
&& 7 == fp.int('shorter', 666, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_beaware_for_argument_names_with_same_prefix_inverse() {
|
fn test_beaware_for_argument_names_with_same_prefix_inverse() {
|
||||||
mut fp := flag.new_flag_parser([
|
mut fp := flag.new_flag_parser([
|
||||||
'--shorter=7',
|
'--shorter=7',
|
||||||
'--short', '5',
|
'--short', '5',
|
||||||
])
|
])
|
||||||
|
|
||||||
assert 5 == fp.int('short', 666, '')
|
assert 5 == fp.int('short', 666, '')
|
||||||
&& 7 == fp.int('shorter', 666, '')
|
&& 7 == fp.int('shorter', 666, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_allow_to_skip_executable_path() {
|
fn test_allow_to_skip_executable_path() {
|
||||||
mut fp := flag.new_flag_parser(['./path/to/execuable'])
|
mut fp := flag.new_flag_parser(['./path/to/execuable'])
|
||||||
|
|
||||||
fp.skip_executable()
|
fp.skip_executable()
|
||||||
|
|
||||||
args := fp.finalize() or {
|
args := fp.finalize() or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert !args.contains('./path/to/execuable')
|
assert !args.contains('./path/to/execuable')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_none_flag_arguments_are_allowed() {
|
fn test_none_flag_arguments_are_allowed() {
|
||||||
mut fp := flag.new_flag_parser([
|
mut fp := flag.new_flag_parser([
|
||||||
'file1', '--an_int=2', 'file2', 'file3', '--bool_without', 'file4', '--outfile', 'outfile'])
|
'file1', '--an_int=2', 'file2', 'file3', '--bool_without', 'file4', '--outfile', 'outfile'])
|
||||||
|
|
||||||
assert 2 == fp.int('an_int', 666, '')
|
assert 2 == fp.int('an_int', 666, '')
|
||||||
&& 'outfile' == fp.string('outfile', 'bad', '')
|
&& 'outfile' == fp.string('outfile', 'bad', '')
|
||||||
&& true == fp.bool('bool_without', false, '')
|
&& true == fp.bool('bool_without', false, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_finalize_returns_none_flag_arguments_ordered() {
|
fn test_finalize_returns_none_flag_arguments_ordered() {
|
||||||
mut fp := flag.new_flag_parser(['d', 'b', 'x', 'a', '--outfile', 'outfile'])
|
mut fp := flag.new_flag_parser(['d', 'b', 'x', 'a', '--outfile', 'outfile'])
|
||||||
fp.string('outfile', 'bad', '')
|
fp.string('outfile', 'bad', '')
|
||||||
|
|
||||||
finalized := fp.finalize() or {
|
finalized := fp.finalize() or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expected := ['d', 'b', 'x', 'a']
|
expected := ['d', 'b', 'x', 'a']
|
||||||
mut all_as_expected := true
|
mut all_as_expected := true
|
||||||
for i, v in finalized {
|
for i, v in finalized {
|
||||||
all_as_expected = all_as_expected && v == expected[i]
|
all_as_expected = all_as_expected && v == expected[i]
|
||||||
}
|
}
|
||||||
assert all_as_expected
|
assert all_as_expected
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_finalize_returns_error_for_unknown_flags() {
|
fn test_finalize_returns_error_for_unknown_flags() {
|
||||||
mut fp := flag.new_flag_parser(['--known', '--unknown'])
|
mut fp := flag.new_flag_parser(['--known', '--unknown'])
|
||||||
|
|
||||||
fp.bool('known', false, '')
|
fp.bool('known', false, '')
|
||||||
|
|
||||||
finalized := fp.finalize() or {
|
finalized := fp.finalize() or {
|
||||||
assert err == 'Unknown argument \'unknown\''
|
assert err == 'Unknown argument \'unknown\''
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert finalized.len < 0 // expect error to be returned
|
assert finalized.len < 0 // expect error to be returned
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_allow_to_build_usage_message() {
|
fn test_allow_to_build_usage_message() {
|
||||||
mut fp := flag.new_flag_parser([])
|
mut fp := flag.new_flag_parser([])
|
||||||
fp.limit_free_args(1, 4)
|
fp.limit_free_args(1, 4)
|
||||||
fp.application('flag_tool')
|
fp.application('flag_tool')
|
||||||
fp.version('v0.0.0')
|
fp.version('v0.0.0')
|
||||||
fp.description('some short information about this tool')
|
fp.description('some short information about this tool')
|
||||||
|
|
||||||
fp.int('an_int', 666, 'some int to define')
|
fp.int('an_int', 666, 'some int to define')
|
||||||
fp.bool('a_bool', false, 'some bool to define')
|
fp.bool('a_bool', false, 'some bool to define')
|
||||||
fp.bool('bool_without_but_really_big', false, 'this should appear on the next line')
|
fp.bool('bool_without_but_really_big', false, 'this should appear on the next line')
|
||||||
fp.float('a_float', 1.0, 'some float as well')
|
fp.float('a_float', 1.0, 'some float as well')
|
||||||
fp.string('a_string', 'not_stuff', 'your credit card number')
|
fp.string('a_string', 'not_stuff', 'your credit card number')
|
||||||
|
|
||||||
usage := fp.usage()
|
usage := fp.usage()
|
||||||
mut all_strings_found := true
|
mut all_strings_found := true
|
||||||
for s in ['flag_tool', 'v0.0.0',
|
for s in ['flag_tool', 'v0.0.0',
|
||||||
'an_int <int>', 'a_bool', 'bool_without', 'a_float <float>', 'a_string <string>:not_stuff',
|
'an_int <int>', 'a_bool', 'bool_without', 'a_float <float>', 'a_string <string>',
|
||||||
'some int to define',
|
'some int to define',
|
||||||
'some bool to define',
|
'some bool to define',
|
||||||
'this should appear on the next line',
|
'this should appear on the next line',
|
||||||
'some float as well',
|
'some float as well',
|
||||||
'your credit card number',
|
'your credit card number',
|
||||||
'The arguments should be at least 1 and at most 4 in number.',
|
'The arguments should be at least 1 and at most 4 in number.',
|
||||||
'Usage', 'Options:', 'Description:',
|
'Usage', 'Options:', 'Description:',
|
||||||
'some short information about this tool'] {
|
'some short information about this tool'] {
|
||||||
if !usage.contains(s) {
|
if !usage.contains(s) {
|
||||||
eprintln(' missing \'$s\' in usage message')
|
eprintln(' missing \'$s\' in usage message')
|
||||||
all_strings_found = false
|
all_strings_found = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert all_strings_found
|
assert all_strings_found
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_if_no_description_given_usage_message_does_not_contain_descpription() {
|
fn test_if_no_description_given_usage_message_does_not_contain_descpription() {
|
||||||
mut fp := flag.new_flag_parser([])
|
mut fp := flag.new_flag_parser([])
|
||||||
fp.application('flag_tool')
|
fp.application('flag_tool')
|
||||||
fp.version('v0.0.0')
|
fp.version('v0.0.0')
|
||||||
|
|
||||||
fp.bool('a_bool', false, '')
|
fp.bool('a_bool', false, '')
|
||||||
|
|
||||||
assert !fp.usage().contains('Description:')
|
assert !fp.usage().contains('Description:')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_if_no_options_given_usage_message_does_not_contain_options() {
|
fn test_if_no_options_given_usage_message_does_not_contain_options() {
|
||||||
mut fp := flag.new_flag_parser([])
|
mut fp := flag.new_flag_parser([])
|
||||||
fp.application('flag_tool')
|
fp.application('flag_tool')
|
||||||
fp.version('v0.0.0')
|
fp.version('v0.0.0')
|
||||||
|
|
||||||
assert !fp.usage().contains('Options:')
|
assert !fp.usage().contains('Options:')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_free_args_could_be_limited() {
|
fn test_free_args_could_be_limited() {
|
||||||
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
||||||
fp1.limit_free_args(1, 4)
|
fp1.limit_free_args(1, 4)
|
||||||
args := fp1.finalize() or {
|
args := fp1.finalize() or {
|
||||||
assert false
|
assert false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert args[0] == 'a' && args[1] == 'b' && args[2] == 'c'
|
assert args[0] == 'a' && args[1] == 'b' && args[2] == 'c'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_error_for_to_few_free_args() {
|
fn test_error_for_to_few_free_args() {
|
||||||
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
||||||
fp1.limit_free_args(5, 6)
|
fp1.limit_free_args(5, 6)
|
||||||
args := fp1.finalize() or {
|
args := fp1.finalize() or {
|
||||||
assert err.starts_with('Expected at least 5 arguments')
|
assert err.starts_with('Expected at least 5 arguments')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert args.len < 0 // expect an error and need to use args
|
assert args.len < 0 // expect an error and need to use args
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_error_for_to_much_free_args() {
|
fn test_error_for_to_much_free_args() {
|
||||||
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
mut fp1 := flag.new_flag_parser(['a', 'b', 'c'])
|
||||||
fp1.limit_free_args(1, 2)
|
fp1.limit_free_args(1, 2)
|
||||||
args := fp1.finalize() or {
|
args := fp1.finalize() or {
|
||||||
assert err.starts_with('Expected at most 2 arguments')
|
assert err.starts_with('Expected at most 2 arguments')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert args.len < 0 // expect an error and need to use args
|
assert args.len < 0 // expect an error and need to use args
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_could_expect_no_free_args() {
|
fn test_could_expect_no_free_args() {
|
||||||
mut fp1 := flag.new_flag_parser(['a'])
|
mut fp1 := flag.new_flag_parser(['a'])
|
||||||
fp1.limit_free_args(0, 0)
|
fp1.limit_free_args(0, 0)
|
||||||
args := fp1.finalize() or {
|
args := fp1.finalize() or {
|
||||||
assert err.starts_with('Expected no arguments')
|
assert err.starts_with('Expected no arguments')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert args.len < 0 // expect an error and need to use args
|
assert args.len < 0 // expect an error and need to use args
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_allow_abreviations() {
|
fn test_allow_abreviations() {
|
||||||
mut fp := flag.new_flag_parser(['-v', '-o', 'some_file', '-i', '42', '-f', '2.0'])
|
mut fp := flag.new_flag_parser(['-v', '-o', 'some_file', '-i', '42', '-f', '2.0'])
|
||||||
|
|
||||||
v := fp.bool_('version', `v`, false, '')
|
v := fp.bool_('version', `v`, false, '')
|
||||||
o := fp.string_('output', `o`, 'empty', '')
|
o := fp.string_('output', `o`, 'empty', '')
|
||||||
i := fp.int_('count', `i`, 0, '')
|
i := fp.int_('count', `i`, 0, '')
|
||||||
f := fp.float_('value', `f`, 0.0, '')
|
f := fp.float_('value', `f`, 0.0, '')
|
||||||
|
|
||||||
assert v && o == 'some_file' && i == 42 && f == 2.0
|
assert v && o == 'some_file' && i == 42 && f == 2.0
|
||||||
|
|
||||||
u := fp.usage()
|
u := fp.usage()
|
||||||
assert u.contains(' -v') && u.contains(' -o') && u.contains(' -i') && u.contains(' -f')
|
assert u.contains(' -v') && u.contains(' -o') && u.contains(' -i') && u.contains(' -f')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_allow_kebab_options() {
|
fn test_allow_kebab_options() {
|
||||||
default_value := 'this_is_the_default_value_of_long_option'
|
default_value := 'this_is_the_default_value_of_long_option'
|
||||||
long_option_value := 'this_is_a_long_option_value_as_argument'
|
long_option_value := 'this_is_a_long_option_value_as_argument'
|
||||||
|
|
||||||
mut fp := flag.new_flag_parser(['--my-long-flag', 'true', '--my-long-option', long_option_value ])
|
mut fp := flag.new_flag_parser(['--my-long-flag', 'true', '--my-long-option', long_option_value ])
|
||||||
|
|
||||||
my_flag := fp.bool('my-long-flag', false, 'flag with long-kebab-name')
|
my_flag := fp.bool('my-long-flag', false, 'flag with long-kebab-name')
|
||||||
my_option := fp.string('my-long-option', default_value, 'string with long-kebab-name')
|
my_option := fp.string('my-long-option', default_value, 'string with long-kebab-name')
|
||||||
|
|
||||||
assert my_flag == true
|
assert my_flag == true
|
||||||
assert my_option == long_option_value
|
assert my_option == long_option_value
|
||||||
|
|
||||||
u := fp.usage()
|
u := fp.usage()
|
||||||
assert u.contains(' --my-long-flag')
|
assert u.contains(' --my-long-flag')
|
||||||
assert u.contains(' --my-long-option')
|
assert u.contains(' --my-long-option')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_not_provided_option_is_not_returned() {
|
||||||
|
mut fp := flag.new_flag_parser([])
|
||||||
|
fp.bool_opt('some-flag', `a`, '') or {
|
||||||
|
fp.int_opt('some-flag', `a`, '') or {
|
||||||
|
fp.float_opt('some-flag', `a`, '') or {
|
||||||
|
fp.string_opt('some-flag', `a`, '') or {
|
||||||
|
//Everything should not return
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If we reach here, one of them returned a value.
|
||||||
|
assert false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_provided_option_is_returned() {
|
||||||
|
mut fp := flag.new_flag_parser(['-a', '-b', '3', '-c', 'hello', '-d', '3.14'])
|
||||||
|
a := fp.bool_opt('some-flag', `a`, '') or {
|
||||||
|
panic('bool_opt did not return a bool')
|
||||||
|
}
|
||||||
|
b := fp.int_opt('some-flag', `b`, '') or {
|
||||||
|
panic('int_opt did not return an int')
|
||||||
|
}
|
||||||
|
c := fp.string_opt('some-flag', `c`, '') or {
|
||||||
|
panic('string_opt did not return a string')
|
||||||
|
}
|
||||||
|
d := fp.float_opt('some-flag', `d`, '') or {
|
||||||
|
panic('float_opt did not return a float')
|
||||||
|
}
|
||||||
|
assert a && b == 3 && c == 'hello' && d == 3.14
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_multiple_arguments() {
|
||||||
|
mut fp := flag.new_flag_parser([
|
||||||
|
'-a', '2', '-a', '3', '-a', '5',
|
||||||
|
'-b', 'a', '-b', 'c', '-b', 'b',
|
||||||
|
'-c', '1.23', '-c', '2.34', '-c', '3.45'
|
||||||
|
])
|
||||||
|
|
||||||
|
//TODO Move to array comparison once it's implemented
|
||||||
|
//assert fp.int_multi('some-flag', `a`, '') == [2, 3, 5] &&
|
||||||
|
// fp.string_multi('some-flag', `b`, '') == ['a', 'c', 'b'] &&
|
||||||
|
// fp.float_multi('some-flag', `c`, '') == [1.23, 2.34, 3.45]
|
||||||
|
|
||||||
|
a := fp.int_multi('some-flag', `a`, '')
|
||||||
|
b := fp.string_multi('some-flag', `b`, '')
|
||||||
|
c := fp.float_multi('some-flag', `c`, '')
|
||||||
|
assert a.len == 3 && b.len == 3 && c.len == 3
|
||||||
|
assert a[0] == 2 && a[1] == 3 && a[2] == 5
|
||||||
|
assert b[0] == 'a' && b[1] == 'c' && b[2] == 'b'
|
||||||
|
assert c[0] == 1.23 && c[1] == 2.34 && c[2] == 3.45
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user