% ./server -address=192.168.1.1 -address=192.168.1.2
flag specified twice: -address
The only solution I see is to define a separator in the argument and
to parse myself:
/server -address=192.168.1.1\;192.168.1.2
Is there a feature in the flag package to do it more simply?
No, but it's easy to split the flag value yourself using
strings.Split. I suggest commas rather than semicolons for simpler
typing, too.
If this is important to fix - and I don't think it is - the flag value
for "address" would have to be a slice. It's doable but it's easier
just to split the flag value.
-rob
This feature is enough to make me switch to another option parsing
library for some projects.
If a patch was submitted adding these two functions, what are the
chances that it would be accepted?
StringArray(name string, value []string, usage string) *[]string
StringArrayVar(p *[]string, name string, value []string, usage string)
This assumes, of course, that the patch is good. I'm mostly asking if
the API change would be accepted.
Russ
the -I argument to 8g is one obvious counter-example.
> On Mar 18, 3:30 pm, "Rob 'Commander' Pike" <r...@google.com> wrote:
>> On Mar 18, 2010, at 12:38 PM, Stéphane Bortzmeyer wrote:
>>
>>> A program may accept several values of an argument. Apparently,flag
>>> does not accept it:
>>
>>> % ./server -address=192.168.1.1 -address=192.168.1.2
>>> flagspecified twice: -address
>>
>>> The only solution I see is to define a separator in the argument and
>>> to parse myself:
>>
>>> /server -address=192.168.1.1\;192.168.1.2
>>
>>> Is there a feature in theflagpackage to do it more simply?
>>
>> No, but it's easy to split theflagvalue yourself using
>> strings.Split. I suggest commas rather than semicolons for simpler
>> typing, too.
>>
>> If this is important to fix - and I don't think it is - theflagvalue
>> for "address" would have to be a slice. It's doable but it's easier
>> just to split theflagvalue.
>>
>> -rob
>
> This feature is enough to make me switch to another option parsing
> library for some projects.
Really? It's worth that much trouble to avoid one call to strings.Split?
>
> If a patch was submitted adding these two functions, what are the
> chances that it would be accepted?
> StringArray(name string, value []string, usage string) *[]string
> StringArrayVar(p *[]string, name string, value []string, usage string)
> This assumes, of course, that the patch is good. I'm mostly asking if
> the API change would be accepted.
It would need an explanation for why it's valuable. I haven't seen
one yet.
-rob
strings.Split isn't a great solution if the flag arguments are
being used to pass names that may contain the separator
character (as filenames may contain commas or white space
for example)
e.g. 8g -I "$a" -I "$b"
8g comes from a different era (using the term advisedly) in flag
processing.
-rob
i realise that, but i still think the point is valid. if you want to split an
argument, you either have to ban at least one character or invent
a new quoting rule.
if 8g was invented now using your suggestion above,
then a pathname with a comma would cause a failure.
also this idiom:
CFLAGS=($CFLAGS -I $newdir)
to add another directory to the search path
would be harder to write. then again it probably
fails in most shells anyway if $newdir contains white space.
in rc (ok i know i'm in a minority here) i can easily prepend
a flag to each of several arguments:
dirs = /foo/bar/*.h
cmd '-I='^$h
but reliably concatenating them separated by a comma is harder.
i imagine it might be easier in bash though.
the main difference is that flag arguments starting
with "-" need to be specified as "-flag=value", not "-flag value".
this means that flag parsing is context insensitive.
the implementation allows the use of []type to
get all values for a given flag. if the type implements
Parseable, then its Parse method is called to do the
conversion from string.
here's an example. note that global variables can depend
command-line flags; even the default value of a flag
can depend on a command-line flag!
package main
import (
"fmt"
"flags"
)
type Xs int
// silly parser - count the number of 'x's in the string
func (x Xs) Parse(s string) (interface{}, bool) {
n := Xs(0)
for _, c := range s {
if c == 'x' {
n++
}
}
return n, true
}
var n = flags.IntValue("n", 999, "count of something")
var m = flags.IntValue("m", n, "count of other thing")
var includes = flags.Value("I", []string{}, "includes").([]string)
var xs = flags. Value("x", Xs(0), "xs").(Xs)
var buf = make([]byte, n)
func main() {
flags.Check()
fmt.Printf("n %v; includes %v; xs %v; m %v\n", n, includes, xs, m)
fmt.Printf("args: %v\n", flags.Args)
}
http://codereview.appspot.com/842041
-rob