summaryrefslogtreecommitdiff
path: root/src/pkg/flag
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
committerOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
commit5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch)
treec0650497e988f47be9c6f2324fa692a52dea82e1 /src/pkg/flag
parent80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff)
downloadgolang-upstream/60.tar.gz
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/pkg/flag')
-rw-r--r--src/pkg/flag/Makefile11
-rw-r--r--src/pkg/flag/export_test.go22
-rw-r--r--src/pkg/flag/flag.go705
-rw-r--r--src/pkg/flag/flag_test.go255
4 files changed, 993 insertions, 0 deletions
diff --git a/src/pkg/flag/Makefile b/src/pkg/flag/Makefile
new file mode 100644
index 000000000..3408ca474
--- /dev/null
+++ b/src/pkg/flag/Makefile
@@ -0,0 +1,11 @@
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include ../../Make.inc
+
+TARG=flag
+GOFILES=\
+ flag.go\
+
+include ../../Make.pkg
diff --git a/src/pkg/flag/export_test.go b/src/pkg/flag/export_test.go
new file mode 100644
index 000000000..7b190807a
--- /dev/null
+++ b/src/pkg/flag/export_test.go
@@ -0,0 +1,22 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flag
+
+import "os"
+
+// Additional routines compiled into the package only during testing.
+
+// ResetForTesting clears all flag state and sets the usage function as directed.
+// After calling ResetForTesting, parse errors in flag handling will not
+// exit the program.
+func ResetForTesting(usage func()) {
+ commandLine = NewFlagSet(os.Args[0], ContinueOnError)
+ Usage = usage
+}
+
+// CommandLine returns the default FlagSet.
+func CommandLine() *FlagSet {
+ return commandLine
+}
diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go
new file mode 100644
index 000000000..01bbc3770
--- /dev/null
+++ b/src/pkg/flag/flag.go
@@ -0,0 +1,705 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ Package flag implements command-line flag parsing.
+
+ Usage:
+
+ Define flags using flag.String(), Bool(), Int(), etc. Example:
+ import "flag"
+ var ip *int = flag.Int("flagname", 1234, "help message for flagname")
+ If you like, you can bind the flag to a variable using the Var() functions.
+ var flagvar int
+ func init() {
+ flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
+ }
+ Or you can create custom flags that satisfy the Value interface (with
+ pointer receivers) and couple them to flag parsing by
+ flag.Var(&flagVal, "name", "help message for flagname")
+ For such flags, the default value is just the initial value of the variable.
+
+ After all flags are defined, call
+ flag.Parse()
+ to parse the command line into the defined flags.
+
+ Flags may then be used directly. If you're using the flags themselves,
+ they are all pointers; if you bind to variables, they're values.
+ fmt.Println("ip has value ", *ip);
+ fmt.Println("flagvar has value ", flagvar);
+
+ After parsing, the arguments after the flag are available as the
+ slice flag.Args() or individually as flag.Arg(i).
+ The arguments are indexed from 0 up to flag.NArg().
+
+ Command line flag syntax:
+ -flag
+ -flag=x
+ -flag x // non-boolean flags only
+ One or two minus signs may be used; they are equivalent.
+ The last form is not permitted for boolean flags because the
+ meaning of the command
+ cmd -x *
+ will change if there is a file called 0, false, etc. You must
+ use the -flag=false form to turn off a boolean flag.
+
+ Flag parsing stops just before the first non-flag argument
+ ("-" is a non-flag argument) or after the 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.
+
+ The default set of command-line flags is controlled by
+ top-level functions. The FlagSet type allows one to define
+ independent sets of flags, such as to implement subcommands
+ in a command-line interface. The methods of FlagSet are
+ analogous to the top-level functions for the command-line
+ flag set.
+*/
+package flag
+
+import (
+ "fmt"
+ "os"
+ "sort"
+ "strconv"
+)
+
+// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined.
+var ErrHelp = os.NewError("flag: help requested")
+
+// -- Bool Value
+type boolValue bool
+
+func newBoolValue(val bool, p *bool) *boolValue {
+ *p = val
+ return (*boolValue)(p)
+}
+
+func (b *boolValue) Set(s string) bool {
+ v, err := strconv.Atob(s)
+ *b = boolValue(v)
+ return err == nil
+}
+
+func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
+
+// -- Int Value
+type intValue int
+
+func newIntValue(val int, p *int) *intValue {
+ *p = val
+ return (*intValue)(p)
+}
+
+func (i *intValue) Set(s string) bool {
+ v, err := strconv.Btoi64(s, 0)
+ *i = intValue(v)
+ return err == nil
+}
+
+func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- Int64 Value
+type int64Value int64
+
+func newInt64Value(val int64, p *int64) *int64Value {
+ *p = val
+ return (*int64Value)(p)
+}
+
+func (i *int64Value) Set(s string) bool {
+ v, err := strconv.Btoi64(s, 0)
+ *i = int64Value(v)
+ return err == nil
+}
+
+func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- Uint Value
+type uintValue uint
+
+func newUintValue(val uint, p *uint) *uintValue {
+ *p = val
+ return (*uintValue)(p)
+}
+
+func (i *uintValue) Set(s string) bool {
+ v, err := strconv.Btoui64(s, 0)
+ *i = uintValue(v)
+ return err == nil
+}
+
+func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- uint64 Value
+type uint64Value uint64
+
+func newUint64Value(val uint64, p *uint64) *uint64Value {
+ *p = val
+ return (*uint64Value)(p)
+}
+
+func (i *uint64Value) Set(s string) bool {
+ v, err := strconv.Btoui64(s, 0)
+ *i = uint64Value(v)
+ return err == nil
+}
+
+func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
+
+// -- string Value
+type stringValue string
+
+func newStringValue(val string, p *string) *stringValue {
+ *p = val
+ return (*stringValue)(p)
+}
+
+func (s *stringValue) Set(val string) bool {
+ *s = stringValue(val)
+ return true
+}
+
+func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
+
+// -- Float64 Value
+type float64Value float64
+
+func newFloat64Value(val float64, p *float64) *float64Value {
+ *p = val
+ return (*float64Value)(p)
+}
+
+func (f *float64Value) Set(s string) bool {
+ v, err := strconv.Atof64(s)
+ *f = float64Value(v)
+ return err == nil
+}
+
+func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Value is the interface to the dynamic value stored in a flag.
+// (The default value is represented as a string.)
+type Value interface {
+ String() string
+ Set(string) bool
+}
+
+// ErrorHandling defines how to handle flag parsing errors.
+type ErrorHandling int
+
+const (
+ ContinueOnError ErrorHandling = iota
+ ExitOnError
+ PanicOnError
+)
+
+// A FlagSet represents a set of defined flags.
+type FlagSet struct {
+ // Usage is the function called when an error occurs while parsing flags.
+ // The field is a function (not a method) that may be changed to point to
+ // a custom error handler.
+ Usage func()
+
+ name string
+ actual map[string]*Flag
+ formal map[string]*Flag
+ args []string // arguments after flags
+ exitOnError bool // does the program exit if there's an error?
+ errorHandling ErrorHandling
+}
+
+// A Flag represents the state of a flag.
+type Flag struct {
+ Name string // name as it appears on command line
+ Usage string // help message
+ Value Value // value as set
+ DefValue string // default value (as text); for usage message
+}
+
+// sortFlags returns the flags as a slice in lexicographical sorted order.
+func sortFlags(flags map[string]*Flag) []*Flag {
+ list := make(sort.StringSlice, len(flags))
+ i := 0
+ for _, f := range flags {
+ list[i] = f.Name
+ i++
+ }
+ list.Sort()
+ result := make([]*Flag, len(list))
+ for i, name := range list {
+ result[i] = flags[name]
+ }
+ return result
+}
+
+// VisitAll visits the flags in lexicographical order, calling fn for each.
+// It visits all flags, even those not set.
+func (f *FlagSet) VisitAll(fn func(*Flag)) {
+ for _, flag := range sortFlags(f.formal) {
+ fn(flag)
+ }
+}
+
+// VisitAll visits the command-line flags in lexicographical order, calling
+// fn for each. It visits all flags, even those not set.
+func VisitAll(fn func(*Flag)) {
+ commandLine.VisitAll(fn)
+}
+
+// Visit visits the flags in lexicographical order, calling fn for each.
+// It visits only those flags that have been set.
+func (f *FlagSet) Visit(fn func(*Flag)) {
+ for _, flag := range sortFlags(f.actual) {
+ fn(flag)
+ }
+}
+
+// Visit visits the command-line flags in lexicographical order, calling fn
+// for each. It visits only those flags that have been set.
+func Visit(fn func(*Flag)) {
+ commandLine.Visit(fn)
+}
+
+// Lookup returns the Flag structure of the named flag, returning nil if none exists.
+func (f *FlagSet) Lookup(name string) *Flag {
+ return f.formal[name]
+}
+
+// Lookup returns the Flag structure of the named command-line flag,
+// returning nil if none exists.
+func Lookup(name string) *Flag {
+ return commandLine.formal[name]
+}
+
+// Set sets the value of the named flag. It returns true if the set succeeded; false if
+// there is no such flag defined.
+func (f *FlagSet) Set(name, value string) bool {
+ flag, ok := f.formal[name]
+ if !ok {
+ return false
+ }
+ ok = flag.Value.Set(value)
+ if !ok {
+ return false
+ }
+ f.actual[name] = flag
+ return true
+}
+
+// Set sets the value of the named command-line flag. It returns true if the
+// set succeeded; false if there is no such flag defined.
+func Set(name, value string) bool {
+ return commandLine.Set(name, value)
+}
+
+// PrintDefaults prints to standard error the default values of all defined flags in the set.
+func (f *FlagSet) PrintDefaults() {
+ f.VisitAll(func(f *Flag) {
+ format := " -%s=%s: %s\n"
+ if _, ok := f.Value.(*stringValue); ok {
+ // put quotes on the value
+ format = " -%s=%q: %s\n"
+ }
+ fmt.Fprintf(os.Stderr, format, f.Name, f.DefValue, f.Usage)
+ })
+}
+
+// PrintDefaults prints to standard error the default values of all defined command-line flags.
+func PrintDefaults() {
+ commandLine.PrintDefaults()
+}
+
+// defaultUsage is the default function to print a usage message.
+func defaultUsage(f *FlagSet) {
+ fmt.Fprintf(os.Stderr, "Usage of %s:\n", f.name)
+ f.PrintDefaults()
+}
+
+// Usage prints to standard error a usage message documenting all defined command-line flags.
+// The function is a variable that may be changed to point to a custom function.
+var Usage = func() {
+ defaultUsage(commandLine)
+}
+
+// NFlag returns the number of flags that have been set.
+func (f *FlagSet) NFlag() int { return len(f.actual) }
+
+// NFlag returns the number of command-line flags that have been set.
+func NFlag() int { return len(commandLine.actual) }
+
+// Arg returns the i'th argument. Arg(0) is the first remaining argument
+// after flags have been processed.
+func (f *FlagSet) Arg(i int) string {
+ if i < 0 || i >= len(f.args) {
+ return ""
+ }
+ return f.args[i]
+}
+
+// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
+// after flags have been processed.
+func Arg(i int) string {
+ return commandLine.Arg(i)
+}
+
+// NArg is the number of arguments remaining after flags have been processed.
+func (f *FlagSet) NArg() int { return len(f.args) }
+
+// NArg is the number of arguments remaining after flags have been processed.
+func NArg() int { return len(commandLine.args) }
+
+// Args returns the non-flag arguments.
+func (f *FlagSet) Args() []string { return f.args }
+
+// Args returns the non-flag command-line arguments.
+func Args() []string { return commandLine.args }
+
+// BoolVar defines a bool flag with specified name, default value, and usage string.
+// The argument p points to a bool variable in which to store the value of the flag.
+func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
+ f.Var(newBoolValue(value, p), name, usage)
+}
+
+// BoolVar defines a bool flag with specified name, default value, and usage string.
+// The argument p points to a bool variable in which to store the value of the flag.
+func BoolVar(p *bool, name string, value bool, usage string) {
+ commandLine.Var(newBoolValue(value, p), name, usage)
+}
+
+// Bool defines a bool flag with specified name, default value, and usage string.
+// The return value is the address of a bool variable that stores the value of the flag.
+func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
+ p := new(bool)
+ f.BoolVar(p, name, value, usage)
+ return p
+}
+
+// Bool defines a bool flag with specified name, default value, and usage string.
+// The return value is the address of a bool variable that stores the value of the flag.
+func Bool(name string, value bool, usage string) *bool {
+ return commandLine.Bool(name, value, usage)
+}
+
+// IntVar defines an int flag with specified name, default value, and usage string.
+// The argument p points to an int variable in which to store the value of the flag.
+func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
+ f.Var(newIntValue(value, p), name, usage)
+}
+
+// IntVar defines an int flag with specified name, default value, and usage string.
+// The argument p points to an int variable in which to store the value of the flag.
+func IntVar(p *int, name string, value int, usage string) {
+ commandLine.Var(newIntValue(value, p), name, usage)
+}
+
+// Int defines an int flag with specified name, default value, and usage string.
+// The return value is the address of an int variable that stores the value of the flag.
+func (f *FlagSet) Int(name string, value int, usage string) *int {
+ p := new(int)
+ f.IntVar(p, name, value, usage)
+ return p
+}
+
+// Int defines an int flag with specified name, default value, and usage string.
+// The return value is the address of an int variable that stores the value of the flag.
+func Int(name string, value int, usage string) *int {
+ return commandLine.Int(name, value, usage)
+}
+
+// Int64Var defines an int64 flag with specified name, default value, and usage string.
+// The argument p points to an int64 variable in which to store the value of the flag.
+func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
+ f.Var(newInt64Value(value, p), name, usage)
+}
+
+// Int64Var defines an int64 flag with specified name, default value, and usage string.
+// The argument p points to an int64 variable in which to store the value of the flag.
+func Int64Var(p *int64, name string, value int64, usage string) {
+ commandLine.Var(newInt64Value(value, p), name, usage)
+}
+
+// Int64 defines an int64 flag with specified name, default value, and usage string.
+// The return value is the address of an int64 variable that stores the value of the flag.
+func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
+ p := new(int64)
+ f.Int64Var(p, name, value, usage)
+ return p
+}
+
+// Int64 defines an int64 flag with specified name, default value, and usage string.
+// The return value is the address of an int64 variable that stores the value of the flag.
+func Int64(name string, value int64, usage string) *int64 {
+ return commandLine.Int64(name, value, usage)
+}
+
+// UintVar defines a uint flag with specified name, default value, and usage string.
+// The argument p points to a uint variable in which to store the value of the flag.
+func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
+ f.Var(newUintValue(value, p), name, usage)
+}
+
+// UintVar defines a uint flag with specified name, default value, and usage string.
+// The argument p points to a uint variable in which to store the value of the flag.
+func UintVar(p *uint, name string, value uint, usage string) {
+ commandLine.Var(newUintValue(value, p), name, usage)
+}
+
+// Uint defines a uint flag with specified name, default value, and usage string.
+// The return value is the address of a uint variable that stores the value of the flag.
+func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
+ p := new(uint)
+ f.UintVar(p, name, value, usage)
+ return p
+}
+
+// Uint defines a uint flag with specified name, default value, and usage string.
+// The return value is the address of a uint variable that stores the value of the flag.
+func Uint(name string, value uint, usage string) *uint {
+ return commandLine.Uint(name, value, usage)
+}
+
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
+// The argument p points to a uint64 variable in which to store the value of the flag.
+func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
+ f.Var(newUint64Value(value, p), name, usage)
+}
+
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
+// The argument p points to a uint64 variable in which to store the value of the flag.
+func Uint64Var(p *uint64, name string, value uint64, usage string) {
+ commandLine.Var(newUint64Value(value, p), name, usage)
+}
+
+// Uint64 defines a uint64 flag with specified name, default value, and usage string.
+// The return value is the address of a uint64 variable that stores the value of the flag.
+func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
+ p := new(uint64)
+ f.Uint64Var(p, name, value, usage)
+ return p
+}
+
+// Uint64 defines a uint64 flag with specified name, default value, and usage string.
+// The return value is the address of a uint64 variable that stores the value of the flag.
+func Uint64(name string, value uint64, usage string) *uint64 {
+ return commandLine.Uint64(name, value, usage)
+}
+
+// StringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a string variable in which to store the value of the flag.
+func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
+ f.Var(newStringValue(value, p), name, usage)
+}
+
+// StringVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a string variable in which to store the value of the flag.
+func StringVar(p *string, name string, value string, usage string) {
+ commandLine.Var(newStringValue(value, p), name, usage)
+}
+
+// String defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a string variable that stores the value of the flag.
+func (f *FlagSet) String(name string, value string, usage string) *string {
+ p := new(string)
+ f.StringVar(p, name, value, usage)
+ return p
+}
+
+// String defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a string variable that stores the value of the flag.
+func String(name string, value string, usage string) *string {
+ return commandLine.String(name, value, usage)
+}
+
+// Float64Var defines a float64 flag with specified name, default value, and usage string.
+// The argument p points to a float64 variable in which to store the value of the flag.
+func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
+ f.Var(newFloat64Value(value, p), name, usage)
+}
+
+// Float64Var defines a float64 flag with specified name, default value, and usage string.
+// The argument p points to a float64 variable in which to store the value of the flag.
+func Float64Var(p *float64, name string, value float64, usage string) {
+ commandLine.Var(newFloat64Value(value, p), name, usage)
+}
+
+// Float64 defines a float64 flag with specified name, default value, and usage string.
+// The return value is the address of a float64 variable that stores the value of the flag.
+func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
+ p := new(float64)
+ f.Float64Var(p, name, value, usage)
+ return p
+}
+
+// Float64 defines an int flag with specified name, default value, and usage string.
+// The return value is the address of a float64 variable that stores the value of the flag.
+func Float64(name string, value float64, usage string) *float64 {
+ return commandLine.Float64(name, value, usage)
+}
+
+// Var defines a flag with the specified name and usage string. The type and
+// value of the flag are represented by the first argument, of type Value, which
+// typically holds a user-defined implementation of Value. For instance, the
+// caller could create a flag that turns a comma-separated string into a slice
+// of strings by giving the slice the methods of Value; in particular, Set would
+// decompose the comma-separated string into the slice.
+func (f *FlagSet) Var(value Value, name string, usage string) {
+ // Remember the default value as a string; it won't change.
+ flag := &Flag{name, usage, value, value.String()}
+ _, alreadythere := f.formal[name]
+ if alreadythere {
+ fmt.Fprintf(os.Stderr, "%s flag redefined: %s\n", f.name, name)
+ panic("flag redefinition") // Happens only if flags are declared with identical names
+ }
+ f.formal[name] = flag
+}
+
+// Var defines a flag with the specified name and usage string. The type and
+// value of the flag are represented by the first argument, of type Value, which
+// typically holds a user-defined implementation of Value. For instance, the
+// caller could create a flag that turns a comma-separated string into a slice
+// of strings by giving the slice the methods of Value; in particular, Set would
+// decompose the comma-separated string into the slice.
+func Var(value Value, name string, usage string) {
+ commandLine.Var(value, name, usage)
+}
+
+// failf prints to standard error a formatted error and usage message and
+// returns the error.
+func (f *FlagSet) failf(format string, a ...interface{}) os.Error {
+ err := fmt.Errorf(format, a...)
+ fmt.Fprintln(os.Stderr, err)
+ f.usage()
+ return err
+}
+
+// usage calls the Usage method for the flag set, or the usage function if
+// the flag set is commandLine.
+func (f *FlagSet) usage() {
+ if f == commandLine {
+ Usage()
+ } else {
+ f.Usage()
+ }
+}
+
+// parseOne parses one flag. It returns whether a flag was seen.
+func (f *FlagSet) parseOne() (bool, os.Error) {
+ if len(f.args) == 0 {
+ return false, nil
+ }
+ s := f.args[0]
+ if len(s) == 0 || s[0] != '-' || len(s) == 1 {
+ return false, nil
+ }
+ num_minuses := 1
+ if s[1] == '-' {
+ num_minuses++
+ if len(s) == 2 { // "--" terminates the flags
+ f.args = f.args[1:]
+ return false, nil
+ }
+ }
+ name := s[num_minuses:]
+ if len(name) == 0 || name[0] == '-' || name[0] == '=' {
+ return false, f.failf("bad flag syntax: %s", s)
+ }
+
+ // it's a flag. does it have an argument?
+ f.args = f.args[1:]
+ has_value := false
+ value := ""
+ 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
+ }
+ }
+ m := f.formal
+ flag, alreadythere := m[name] // BUG
+ if !alreadythere {
+ if name == "help" || name == "h" { // special case for nice help message.
+ f.usage()
+ return false, ErrHelp
+ }
+ return false, f.failf("flag provided but not defined: -%s", name)
+ }
+ if fv, ok := flag.Value.(*boolValue); ok { // special case: doesn't need an arg
+ if has_value {
+ if !fv.Set(value) {
+ f.failf("invalid boolean value %q for flag: -%s", value, name)
+ }
+ } else {
+ fv.Set("true")
+ }
+ } else {
+ // It must have a value, which might be the next argument.
+ if !has_value && len(f.args) > 0 {
+ // value is the next arg
+ has_value = true
+ value, f.args = f.args[0], f.args[1:]
+ }
+ if !has_value {
+ return false, f.failf("flag needs an argument: -%s", name)
+ }
+ ok = flag.Value.Set(value)
+ if !ok {
+ return false, f.failf("invalid value %q for flag: -%s", value, name)
+ }
+ }
+ f.actual[name] = flag
+ return true, nil
+}
+
+// Parse parses flag definitions from the argument list, which should not
+// include the command name. Must be called after all flags in the FlagSet
+// are defined and before flags are accessed by the program.
+// The return value will be ErrHelp if -help was set but not defined.
+func (f *FlagSet) Parse(arguments []string) os.Error {
+ f.args = arguments
+ for {
+ seen, err := f.parseOne()
+ if seen {
+ continue
+ }
+ if err == nil {
+ break
+ }
+ switch f.errorHandling {
+ case ContinueOnError:
+ return err
+ case ExitOnError:
+ os.Exit(2)
+ case PanicOnError:
+ panic(err)
+ }
+ }
+ return nil
+}
+
+// Parse parses the command-line flags from os.Args[1:]. Must be called
+// after all flags are defined and before flags are accessed by the program.
+func Parse() {
+ // Ignore errors; commandLine is set for ExitOnError.
+ commandLine.Parse(os.Args[1:])
+}
+
+// The default set of command-line flags, parsed from os.Args.
+var commandLine = NewFlagSet(os.Args[0], ExitOnError)
+
+// NewFlagSet returns a new, empty flag set with the specified name and
+// error handling property.
+func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
+ f := &FlagSet{
+ name: name,
+ actual: make(map[string]*Flag),
+ formal: make(map[string]*Flag),
+ errorHandling: errorHandling,
+ }
+ f.Usage = func() { defaultUsage(f) }
+ return f
+}
diff --git a/src/pkg/flag/flag_test.go b/src/pkg/flag/flag_test.go
new file mode 100644
index 000000000..63d0a9fc8
--- /dev/null
+++ b/src/pkg/flag/flag_test.go
@@ -0,0 +1,255 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package flag_test
+
+import (
+ . "flag"
+ "fmt"
+ "os"
+ "sort"
+ "testing"
+)
+
+var (
+ test_bool = Bool("test_bool", false, "bool value")
+ test_int = Int("test_int", 0, "int value")
+ test_int64 = Int64("test_int64", 0, "int64 value")
+ test_uint = Uint("test_uint", 0, "uint value")
+ test_uint64 = Uint64("test_uint64", 0, "uint64 value")
+ test_string = String("test_string", "0", "string value")
+ test_float64 = Float64("test_float64", 0, "float64 value")
+)
+
+func boolString(s string) string {
+ if s == "0" {
+ return "false"
+ }
+ return "true"
+}
+
+func TestEverything(t *testing.T) {
+ m := make(map[string]*Flag)
+ desired := "0"
+ visitor := func(f *Flag) {
+ if len(f.Name) > 5 && f.Name[0:5] == "test_" {
+ m[f.Name] = f
+ ok := false
+ switch {
+ case f.Value.String() == desired:
+ ok = true
+ case f.Name == "test_bool" && f.Value.String() == boolString(desired):
+ ok = true
+ }
+ if !ok {
+ t.Error("Visit: bad value", f.Value.String(), "for", f.Name)
+ }
+ }
+ }
+ VisitAll(visitor)
+ if len(m) != 7 {
+ t.Error("VisitAll misses some flags")
+ for k, v := range m {
+ t.Log(k, *v)
+ }
+ }
+ m = make(map[string]*Flag)
+ Visit(visitor)
+ if len(m) != 0 {
+ t.Errorf("Visit sees unset flags")
+ for k, v := range m {
+ t.Log(k, *v)
+ }
+ }
+ // Now set all flags
+ Set("test_bool", "true")
+ Set("test_int", "1")
+ Set("test_int64", "1")
+ Set("test_uint", "1")
+ Set("test_uint64", "1")
+ Set("test_string", "1")
+ Set("test_float64", "1")
+ desired = "1"
+ Visit(visitor)
+ if len(m) != 7 {
+ t.Error("Visit fails after set")
+ for k, v := range m {
+ t.Log(k, *v)
+ }
+ }
+ // Now test they're visited in sort order.
+ var flagNames []string
+ Visit(func(f *Flag) { flagNames = append(flagNames, f.Name) })
+ if !sort.StringsAreSorted(flagNames) {
+ t.Errorf("flag names not sorted: %v", flagNames)
+ }
+}
+
+func TestUsage(t *testing.T) {
+ called := false
+ ResetForTesting(func() { called = true })
+ if CommandLine().Parse([]string{"-x"}) == nil {
+ t.Error("parse did not fail for unknown flag")
+ }
+ if !called {
+ t.Error("did not call Usage for unknown flag")
+ }
+}
+
+func testParse(f *FlagSet, t *testing.T) {
+ boolFlag := f.Bool("bool", false, "bool value")
+ bool2Flag := f.Bool("bool2", false, "bool2 value")
+ intFlag := f.Int("int", 0, "int value")
+ int64Flag := f.Int64("int64", 0, "int64 value")
+ uintFlag := f.Uint("uint", 0, "uint value")
+ uint64Flag := f.Uint64("uint64", 0, "uint64 value")
+ stringFlag := f.String("string", "0", "string value")
+ float64Flag := f.Float64("float64", 0, "float64 value")
+ extra := "one-extra-argument"
+ args := []string{
+ "-bool",
+ "-bool2=true",
+ "--int", "22",
+ "--int64", "0x23",
+ "-uint", "24",
+ "--uint64", "25",
+ "-string", "hello",
+ "-float64", "2718e28",
+ extra,
+ }
+ if err := f.Parse(args); err != nil {
+ t.Fatal(err)
+ }
+ if *boolFlag != true {
+ t.Error("bool flag should be true, is ", *boolFlag)
+ }
+ if *bool2Flag != true {
+ t.Error("bool2 flag should be true, is ", *bool2Flag)
+ }
+ if *intFlag != 22 {
+ t.Error("int flag should be 22, is ", *intFlag)
+ }
+ if *int64Flag != 0x23 {
+ t.Error("int64 flag should be 0x23, is ", *int64Flag)
+ }
+ if *uintFlag != 24 {
+ t.Error("uint flag should be 24, is ", *uintFlag)
+ }
+ if *uint64Flag != 25 {
+ t.Error("uint64 flag should be 25, is ", *uint64Flag)
+ }
+ if *stringFlag != "hello" {
+ t.Error("string flag should be `hello`, is ", *stringFlag)
+ }
+ if *float64Flag != 2718e28 {
+ t.Error("float64 flag should be 2718e28, is ", *float64Flag)
+ }
+ if len(f.Args()) != 1 {
+ t.Error("expected one argument, got", len(f.Args()))
+ } else if f.Args()[0] != extra {
+ t.Errorf("expected argument %q got %q", extra, f.Args()[0])
+ }
+}
+
+func TestParse(t *testing.T) {
+ ResetForTesting(func() { t.Error("bad parse") })
+ testParse(CommandLine(), t)
+}
+
+func TestFlagSetParse(t *testing.T) {
+ testParse(NewFlagSet("test", ContinueOnError), t)
+}
+
+// Declare a user-defined flag type.
+type flagVar []string
+
+func (f *flagVar) String() string {
+ return fmt.Sprint([]string(*f))
+}
+
+func (f *flagVar) Set(value string) bool {
+ *f = append(*f, value)
+ return true
+}
+
+func TestUserDefined(t *testing.T) {
+ flags := NewFlagSet("test", ContinueOnError)
+ var v flagVar
+ flags.Var(&v, "v", "usage")
+ if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil {
+ t.Error(err)
+ }
+ if len(v) != 3 {
+ t.Fatal("expected 3 args; got ", len(v))
+ }
+ expect := "[1 2 3]"
+ if v.String() != expect {
+ t.Errorf("expected value %q got %q", expect, v.String())
+ }
+}
+
+// This tests that one can reset the flags. This still works but not well, and is
+// superseded by FlagSet.
+func TestChangingArgs(t *testing.T) {
+ ResetForTesting(func() { t.Fatal("bad parse") })
+ oldArgs := os.Args
+ defer func() { os.Args = oldArgs }()
+ os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
+ before := Bool("before", false, "")
+ if err := CommandLine().Parse(os.Args[1:]); err != nil {
+ t.Fatal(err)
+ }
+ cmd := Arg(0)
+ os.Args = Args()
+ after := Bool("after", false, "")
+ Parse()
+ args := Args()
+
+ if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" {
+ t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args)
+ }
+}
+
+// Test that -help invokes the usage message and returns ErrHelp.
+func TestHelp(t *testing.T) {
+ var helpCalled = false
+ fs := NewFlagSet("help test", ContinueOnError)
+ fs.Usage = func() { helpCalled = true }
+ var flag bool
+ fs.BoolVar(&flag, "flag", false, "regular flag")
+ // Regular flag invocation should work
+ err := fs.Parse([]string{"-flag=true"})
+ if err != nil {
+ t.Fatal("expected no error; got ", err)
+ }
+ if !flag {
+ t.Error("flag was not set by -flag")
+ }
+ if helpCalled {
+ t.Error("help called for regular flag")
+ helpCalled = false // reset for next test
+ }
+ // Help flag should work as expected.
+ err = fs.Parse([]string{"-help"})
+ if err == nil {
+ t.Fatal("error expected")
+ }
+ if err != ErrHelp {
+ t.Fatal("expected ErrHelp; got ", err)
+ }
+ if !helpCalled {
+ t.Fatal("help was not called")
+ }
+ // If we define a help flag, that should override.
+ var help bool
+ fs.BoolVar(&help, "help", false, "help flag")
+ helpCalled = false
+ err = fs.Parse([]string{"-help"})
+ if err != nil {
+ t.Fatal("expected no error for defined -help; got ", err)
+ }
+ if helpCalled {
+ t.Fatal("help was called; should not have been for defined help flag")
+ }
+}