-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
Proposal Details
The flag package forces lexicographical sorting through sortFlags, which is called by Visit and VisitAll. That makes it hard to keep related flags grouped together in help output unless you track that yourself. For example, if you have paired flags like -no-list/-list or -lower/-upper, there’s no way to keep them next to each other in the help output without PrintDefaults customization.
Developers already express the order they want simply by the order they define their flags. FlagSet discards that insertion order by storing flags only in a map. There's no reason to throw away that order. Adding an optional “insertion order” sort mode would keep the default behavior intact, but give developers a straightforward way to present flags in a logical order when generating help.
This is a small, backward-compatible change: default behavior stays the same, but developers who want predictable, grouped help output can opt in without writing their own tracking layer.
An example implementation
- Add an insertion slice to
FlagSet
type FlagSet struct {
// existing fields...
formal map[string]*Flag
// new: preserve definition order
insertion []*Flag // this could also be a []string of flag names
}- Record insertion order in Var
func (f *FlagSet) Var(value Value, name, usage string) {
// existing logic...
fl := &Flag{Name: name, Usage: usage, Value: value}
f.formal[name] = fl
f.insertion = append(f.insertion, fl)
}3.Add a sort mode and update sortFlags
type SortMode int
const (
SortLexical SortMode = iota
SortInsertion
)
var sortMode = SortLexical
func SetSortMode(m SortMode) { sortMode = m }
// use whatever sort mode the user set
func (f *FlagSet) sortFlags(list []*Flag) []*Flag {
switch sortMode {
case SortInsertion:
return f.insertion
default:
sort.Slice(list, func(i, j int) bool {
return list[i].Name < list[j].Name
})
return list
}
}There are other possible implementations, but this one is simple and maintains backward compatibility. Yes, a developer can manually maintain their own insertion slice and override PrintDefaults, but they shouldn’t have to - FlagSet already knows the order flags were defined, and that information is currently lost. Allowing insertion-order sorting makes builtin help generation more predictable without breaking any existing behavior.