flag: visit the flags in sorted order, for better messages.
Fixes #1601.
R=rsc
CC=golang-dev
https://golang.org/cl/4249070
diff --git a/src/pkg/flag/flag.go b/src/pkg/flag/flag.go
index 0483425..6c9f3a8 100644
--- a/src/pkg/flag/flag.go
+++ b/src/pkg/flag/flag.go
@@ -68,6 +68,7 @@
import (
"fmt"
"os"
+ "sort"
"strconv"
)
@@ -205,16 +206,34 @@
var flags *allFlags
-// VisitAll visits the flags, calling fn for each. It visits all flags, even those not set.
+// sortFlags returns the flags as a slice in lexicographical sorted order.
+func sortFlags(flags map[string]*Flag) []*Flag {
+ list := make(sort.StringArray, 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 VisitAll(fn func(*Flag)) {
- for _, f := range flags.formal {
+ for _, f := range sortFlags(flags.formal) {
fn(f)
}
}
-// Visit visits the flags, calling fn for each. It visits only those flags that have been set.
+// Visit visits the flags in lexicographical order, calling fn for each.
+// It visits only those flags that have been set.
func Visit(fn func(*Flag)) {
- for _, f := range flags.actual {
+ for _, f := range sortFlags(flags.actual) {
fn(f)
}
}
diff --git a/src/pkg/flag/flag_test.go b/src/pkg/flag/flag_test.go
index 30a21e6..1e47d12 100644
--- a/src/pkg/flag/flag_test.go
+++ b/src/pkg/flag/flag_test.go
@@ -8,6 +8,7 @@
. "flag"
"fmt"
"os"
+ "sort"
"testing"
)
@@ -77,6 +78,12 @@
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) {