aboutsummaryrefslogtreecommitdiff
path: root/flag.go
diff options
context:
space:
mode:
Diffstat (limited to 'flag.go')
-rw-r--r--flag.go118
1 files changed, 51 insertions, 67 deletions
diff --git a/flag.go b/flag.go
index 42f2308..06edf20 100644
--- a/flag.go
+++ b/flag.go
@@ -64,29 +64,27 @@
Command line flag syntax:
--flag // boolean flags only
--flag=x
- --flag x // non-boolean flags only
- The last form is not permitted for boolean flags because the
- meaning of the command
- cmd --flag *
- will change if there is a file called 0, false, etc. You must
- use the --flag=false form to turn off a boolean flag.
Unlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags.
- -f // f must be boolean
- -abc // all flags must be boolean
- -abcn=1234
- -abcn 1234 // n must be non-boolean
- -abcn1234 // n must be non-boolean
- -Ifile // I must be non-boolean
+ // boolean flags
+ -f
+ -abc
+ // non-boolean flags
+ -n 1234
+ -Ifile
+ // mixed
+ -abcs "hello"
+ -abcn1234
Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.
Integer flags accept 1234, 0664, 0x1234 and may be negative.
- Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False.
+ Boolean flags (in their long form) accept 1, 0, t, f, true, false,
+ TRUE, FALSE, True, False.
Duration flags accept any input valid for time.ParseDuration.
The default set of command-line flags is controlled by
@@ -105,6 +103,7 @@ import (
"os"
"sort"
"strconv"
+ "strings"
"time"
)
@@ -902,6 +901,19 @@ func (f *FlagSet) usage() {
}
}
+func (f *FlagSet) setFlag(flag *Flag, value string, origArg string) error {
+ if err := flag.Value.Set(value); err != nil {
+ return f.failf("invalid argument %q for %s: %v", value, origArg, err)
+ }
+ // mark as visited for Visit()
+ if f.actual == nil {
+ f.actual = make(map[string]*Flag)
+ }
+ f.actual[flag.Name] = flag
+
+ return nil
+}
+
func (f *FlagSet) parseArgs(args []string) error {
for len(args) > 0 {
s := args[0]
@@ -911,9 +923,6 @@ func (f *FlagSet) parseArgs(args []string) error {
continue
}
- var flag *Flag = nil
- has_value := false
- value := ""
if s[1] == '-' {
if len(s) == 2 { // "--" terminates the flags
f.args = append(f.args, args...)
@@ -923,17 +932,10 @@ func (f *FlagSet) parseArgs(args []string) error {
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
return f.failf("bad flag syntax: %s", s)
}
- // check for = argument to flag
- for i := 1; i < len(name); i++ { // equals cannot be first
- if name[i] == '=' {
- value = name[i+1:]
- has_value = true
- name = name[0:i]
- break
- }
- }
+ split := strings.SplitN(name, "=", 2)
+ name = split[0]
m := f.formal
- _, alreadythere := m[name] // BUG
+ flag, alreadythere := m[name] // BUG
if !alreadythere {
if name == "help" { // special case for nice help message.
f.usage()
@@ -941,12 +943,21 @@ func (f *FlagSet) parseArgs(args []string) error {
}
return f.failf("unknown flag: --%s", name)
}
- flag = m[name]
+ if len(split) == 1 {
+ if _, ok := flag.Value.(*boolValue); !ok {
+ return f.failf("flag needs an argument: %s", s)
+ }
+ f.setFlag(flag, "true", s)
+ } else {
+ if err := f.setFlag(flag, split[1], s); err != nil {
+ return err
+ }
+ }
} else {
shorthands := s[1:]
for i := 0; i < len(shorthands); i++ {
c := shorthands[i]
- _, alreadythere := f.shorthands[c]
+ flag, alreadythere := f.shorthands[c]
if !alreadythere {
if c == 'h' { // special case for nice help message.
f.usage()
@@ -954,53 +965,26 @@ func (f *FlagSet) parseArgs(args []string) error {
}
return f.failf("unknown shorthand flag: %q in -%s", c, shorthands)
}
- flag = f.shorthands[c]
- if i == len(shorthands)-1 {
- break
+ if _, ok := flag.Value.(*boolValue); ok {
+ f.setFlag(flag, "true", s)
+ continue
}
- if shorthands[i+1] == '=' {
- value = shorthands[i+2:]
- has_value = true
+ if i < len(shorthands)-1 {
+ if err := f.setFlag(flag, shorthands[i+1:], s); err != nil {
+ return err
+ }
break
}
- if fv, ok := flag.Value.(*boolValue); ok {
- fv.Set("true")
- } else {
- value = shorthands[i+1:]
- has_value = true
- break
+ if len(args) == 0 {
+ return f.failf("flag needs an argument: %q in -%s", c, shorthands)
}
- }
- }
-
- // we have a flag, possibly with included =value argument
- if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
- if has_value {
- if err := fv.Set(value); err != nil {
- f.failf("invalid boolean value %q for %s: %v", value, s, err)
+ if err := f.setFlag(flag, args[0], s); err != nil {
+ return err
}
- } else {
- fv.Set("true")
- }
- } else {
- // It must have a value, which might be the next argument.
- if !has_value && len(args) > 0 {
- // value is the next arg
- has_value = true
- value = args[0]
args = args[1:]
+ break // should be unnecessary
}
- if !has_value {
- return f.failf("flag needs an argument: %s", s)
- }
- if err := flag.Value.Set(value); err != nil {
- return f.failf("invalid value %q for %s: %v", value, s, err)
- }
- }
- if f.actual == nil {
- f.actual = make(map[string]*Flag)
}
- f.actual[flag.Name] = flag
}
return nil
}