flag: fix Flag.free(), workaround -autofree limitations
parent
a593ff930f
commit
b335d47b72
179
vlib/flag/flag.v
179
vlib/flag/flag.v
|
@ -10,6 +10,15 @@ pub:
|
|||
// and also the default value, when the flag is not given
|
||||
}
|
||||
|
||||
[unsafe]
|
||||
fn (mut f Flag) free() {
|
||||
unsafe {
|
||||
f.name.free()
|
||||
f.usage.free()
|
||||
f.val_desc.free()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (f Flag) str() string {
|
||||
return '' + ' flag:\n' + ' name: $f.name\n' + ' abbr: $f.abbr\n' +
|
||||
' usag: $f.usage\n' + ' desc: $f.val_desc'
|
||||
|
@ -41,8 +50,16 @@ pub mut:
|
|||
[unsafe]
|
||||
fn (mut f FlagParser) free() {
|
||||
unsafe {
|
||||
for a in f.args {
|
||||
a.free()
|
||||
}
|
||||
f.args.free()
|
||||
//
|
||||
for flag in f.flags {
|
||||
flag.free()
|
||||
}
|
||||
f.flags.free()
|
||||
//
|
||||
f.application_name.free()
|
||||
f.application_version.free()
|
||||
f.application_description.free()
|
||||
|
@ -105,10 +122,17 @@ fn (mut fs FlagParser) add_flag(name string, abbr byte, usage string, desc strin
|
|||
//
|
||||
// - the name, usage are registered
|
||||
// - found arguments and corresponding values are removed from args list
|
||||
[manualfree]
|
||||
fn (mut fs FlagParser) parse_value(longhand string, shorthand byte) []string {
|
||||
full := '--$longhand'
|
||||
defer {
|
||||
unsafe { full.free() }
|
||||
}
|
||||
mut found_entries := []string{}
|
||||
mut to_delete := []int{}
|
||||
defer {
|
||||
unsafe { to_delete.free() }
|
||||
}
|
||||
mut should_skip_one := false
|
||||
for i, arg in fs.args {
|
||||
if should_skip_one {
|
||||
|
@ -127,10 +151,15 @@ fn (mut fs FlagParser) parse_value(longhand string, shorthand byte) []string {
|
|||
return []
|
||||
}
|
||||
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.
|
||||
return []
|
||||
if nextarg.len > 2 {
|
||||
nextarg_rest := nextarg[..2]
|
||||
if nextarg_rest == '--' {
|
||||
// It could be end of input (--) or another argument (--abc).
|
||||
// Both are invalid so die.
|
||||
unsafe { nextarg_rest.free() }
|
||||
return []
|
||||
}
|
||||
unsafe { nextarg_rest.free() }
|
||||
}
|
||||
found_entries << fs.args[i + 1]
|
||||
to_delete << i
|
||||
|
@ -158,39 +187,41 @@ fn (mut fs FlagParser) parse_value(longhand string, shorthand byte) []string {
|
|||
// -> '--flag' is parsed as true
|
||||
// -> '--flag' is equal to '--flag=true'
|
||||
fn (mut fs FlagParser) parse_bool_value(longhand string, shorthand byte) ?string {
|
||||
full := '--$longhand'
|
||||
for i, arg in fs.args {
|
||||
if arg == '--' {
|
||||
// End of input. We're done.
|
||||
break
|
||||
}
|
||||
if arg.len == 0 {
|
||||
continue
|
||||
}
|
||||
if arg[0] != `-` {
|
||||
continue
|
||||
}
|
||||
if (arg.len == 2 && arg[0] == `-` && arg[1] == shorthand) || arg == full {
|
||||
if fs.args.len > i + 1 && (fs.args[i + 1] in ['true', 'false']) {
|
||||
val := fs.args[i + 1]
|
||||
fs.args.delete(i + 1)
|
||||
{
|
||||
full := '--$longhand'
|
||||
for i, arg in fs.args {
|
||||
if arg == '--' {
|
||||
// End of input. We're done.
|
||||
break
|
||||
}
|
||||
if arg.len == 0 {
|
||||
continue
|
||||
}
|
||||
if arg[0] != `-` {
|
||||
continue
|
||||
}
|
||||
if (arg.len == 2 && arg[0] == `-` && arg[1] == shorthand) || arg == full {
|
||||
if fs.args.len > i + 1 && (fs.args[i + 1] in ['true', 'false']) {
|
||||
val := fs.args[i + 1]
|
||||
fs.args.delete(i + 1)
|
||||
fs.args.delete(i)
|
||||
return val
|
||||
} else {
|
||||
fs.args.delete(i)
|
||||
return 'true'
|
||||
}
|
||||
}
|
||||
if arg.len > full.len + 1 && arg[..full.len + 1] == '$full=' {
|
||||
// Flag abc=true
|
||||
val := arg[full.len + 1..]
|
||||
fs.args.delete(i)
|
||||
return val
|
||||
} else {
|
||||
fs.args.delete(i)
|
||||
}
|
||||
if arg.len > 1 && arg[0] == `-` && arg[1] != `-` && arg.index_byte(shorthand) != -1 {
|
||||
// -abc is equivalent to -a -b -c
|
||||
return 'true'
|
||||
}
|
||||
}
|
||||
if arg.len > full.len + 1 && arg[..full.len + 1] == '$full=' {
|
||||
// Flag abc=true
|
||||
val := arg[full.len + 1..]
|
||||
fs.args.delete(i)
|
||||
return val
|
||||
}
|
||||
if arg.len > 1 && arg[0] == `-` && arg[1] != `-` && arg.index_byte(shorthand) != -1 {
|
||||
// -abc is equivalent to -a -b -c
|
||||
return 'true'
|
||||
}
|
||||
}
|
||||
return error("parameter '$longhand' not found")
|
||||
}
|
||||
|
@ -198,9 +229,15 @@ fn (mut fs 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 (mut fs 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'
|
||||
mut res := false
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<bool>')
|
||||
parsed := fs.parse_bool_value(name, abbr) or {
|
||||
return error("parameter '$name' not provided")
|
||||
}
|
||||
res = parsed == 'true'
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// defining and parsing a bool flag
|
||||
|
@ -230,12 +267,17 @@ pub fn (mut fs FlagParser) int_multi(name string, abbr byte, usage 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 (mut fs 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 '$name' not provided")
|
||||
mut res := 0
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<int>')
|
||||
parsed := fs.parse_value(name, abbr)
|
||||
if parsed.len == 0 {
|
||||
return error("parameter '$name' not provided")
|
||||
}
|
||||
parsed0 := parsed[0]
|
||||
res = parsed0.int()
|
||||
}
|
||||
return parsed[0].int()
|
||||
return res
|
||||
}
|
||||
|
||||
// defining and parsing an int flag
|
||||
|
@ -265,12 +307,16 @@ pub fn (mut fs FlagParser) float_multi(name string, abbr byte, usage string) []f
|
|||
// 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 (mut fs FlagParser) float_opt(name string, abbr byte, usage string) ?f64 {
|
||||
fs.add_flag(name, abbr, usage, '<float>')
|
||||
parsed := fs.parse_value(name, abbr)
|
||||
if parsed.len == 0 {
|
||||
return error("parameter '$name' not provided")
|
||||
mut res := 0.0
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<float>')
|
||||
parsed := fs.parse_value(name, abbr)
|
||||
if parsed.len == 0 {
|
||||
return error("parameter '$name' not provided")
|
||||
}
|
||||
res = parsed[0].f64()
|
||||
}
|
||||
return parsed[0].f64()
|
||||
return res
|
||||
}
|
||||
|
||||
// defining and parsing a float flag
|
||||
|
@ -295,12 +341,16 @@ pub fn (mut fs FlagParser) string_multi(name string, abbr byte, usage string) []
|
|||
// 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 (mut fs 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 '$name' not provided")
|
||||
mut res := ''
|
||||
{
|
||||
fs.add_flag(name, abbr, usage, '<string>')
|
||||
parsed := fs.parse_value(name, abbr)
|
||||
if parsed.len == 0 {
|
||||
return error("parameter '$name' not provided")
|
||||
}
|
||||
res = parsed[0]
|
||||
}
|
||||
return parsed[0]
|
||||
return res
|
||||
}
|
||||
|
||||
// defining and parsing a string flag
|
||||
|
@ -358,22 +408,23 @@ pub fn (fs FlagParser) usage() string {
|
|||
if no_arguments {
|
||||
adesc = ''
|
||||
}
|
||||
mut use := ''
|
||||
mut use := []string{}
|
||||
if fs.application_version != '' {
|
||||
use += '$fs.application_name $fs.application_version\n'
|
||||
use += '$flag.underline\n'
|
||||
use << '$fs.application_name $fs.application_version'
|
||||
use << '$flag.underline'
|
||||
}
|
||||
use += 'Usage: $fs.application_name [options] $adesc\n'
|
||||
use += '\n'
|
||||
use << 'Usage: $fs.application_name [options] $adesc'
|
||||
use << ''
|
||||
if fs.application_description != '' {
|
||||
use += 'Description:\n'
|
||||
use += '$fs.application_description'
|
||||
use += '\n\n'
|
||||
use << 'Description: $fs.application_description'
|
||||
use << ''
|
||||
use << ''
|
||||
}
|
||||
// show a message about the [ARGS]:
|
||||
if positive_min_arg || positive_max_arg || no_arguments {
|
||||
if no_arguments {
|
||||
use += 'This application does not expect any arguments\n\n'
|
||||
use << 'This application does not expect any arguments'
|
||||
use << ''
|
||||
} else {
|
||||
mut s := []string{}
|
||||
if positive_min_arg {
|
||||
|
@ -386,11 +437,12 @@ pub fn (fs FlagParser) usage() string {
|
|||
s = ['exactly $fs.min_free_args']
|
||||
}
|
||||
sargs := s.join(' and ')
|
||||
use += 'The arguments should be $sargs in number.\n\n'
|
||||
use << 'The arguments should be $sargs in number.'
|
||||
use << ''
|
||||
}
|
||||
}
|
||||
if fs.flags.len > 0 {
|
||||
use += 'Options:\n'
|
||||
use << 'Options:'
|
||||
for f in fs.flags {
|
||||
mut onames := []string{}
|
||||
if f.abbr != 0 {
|
||||
|
@ -410,10 +462,11 @@ pub fn (fs FlagParser) usage() string {
|
|||
} else {
|
||||
xspace = flag.space[option_names.len..]
|
||||
}
|
||||
use += '$option_names$xspace$f.usage\n'
|
||||
fdesc := '$option_names$xspace$f.usage'
|
||||
use << fdesc
|
||||
}
|
||||
}
|
||||
return use.replace('- ,', ' ')
|
||||
return use.join('\n').replace('- ,', ' ')
|
||||
}
|
||||
|
||||
// finalize - return all remaining arguments (non options).
|
||||
|
|
Loading…
Reference in New Issue