Skip to content

Commit e6374a3

Browse files
Removed duplicate entries for WithAlias from UsageString
1 parent 9bfcfb9 commit e6374a3

File tree

3 files changed

+95
-35
lines changed

3 files changed

+95
-35
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v2.0.11
1+
v2.0.12

alias_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,7 @@ func TestWithAlias(t *testing.T) {
8989
figs = figs.WithAlias("two", "x") // Should this overwrite or be ignored?
9090
assert.NoError(t, figs.Parse())
9191
assert.Equal(t, "value1", *figs.String("x")) // Clarify expected behavior
92+
us := figs.UsageString()
93+
assert.NotEmpty(t, us)
9294
})
9395
}

usage.go

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package figtree
22

33
import (
4-
"flag"
54
"fmt"
65
"os"
76
"path/filepath"
7+
"sort"
88
"strings"
99

1010
"golang.org/x/term"
@@ -23,52 +23,110 @@ func (tree *figTree) UsageString() string {
2323
}
2424
}
2525

26+
// First pass: Collect all primary flag names and aliases correctly
27+
// Also calculate maxFlagLen for formatting
28+
type flagInfo struct {
29+
name string
30+
aliases []string
31+
defValue string
32+
usage string
33+
mutagenesis Mutagenesis
34+
isAlias bool // Mark if this is an alias entry itself
35+
originalName string // For aliases, store the original flag name
36+
}
37+
allFlagData := make(map[string]*flagInfo) // Use map to deduplicate and process by main flag name
38+
39+
tree.mu.RLock() // Lock for accessing tree.figs and tree.aliases
40+
41+
// Populate with main flags
42+
for name, fruit := range tree.figs {
43+
f := tree.flagSet.Lookup(name) // Get the flag.Flag object
44+
if f == nil {
45+
continue // Should not happen if figs map is consistent with flagSet
46+
}
47+
48+
info := &flagInfo{
49+
name: f.Name,
50+
defValue: f.DefValue,
51+
usage: f.Usage,
52+
mutagenesis: fruit.Mutagenesis, // Get mutagenesis from figFruit
53+
isAlias: false,
54+
}
55+
allFlagData[name] = info
56+
}
57+
58+
// Add aliases to their primary flags
59+
for alias, originalName := range tree.aliases {
60+
if info, ok := allFlagData[originalName]; ok {
61+
info.aliases = append(info.aliases, alias)
62+
}
63+
}
64+
65+
tree.mu.RUnlock() // Release lock
66+
67+
// Second pass: Re-evaluate maxFlagLen based on combined flag names
2668
maxFlagLen := 0
27-
flag.VisitAll(func(f *flag.Flag) {
28-
flagStr := f.Name
29-
// Handle special cases for default values
30-
defValue := f.DefValue
31-
if defValue == `""` || defValue == "[]" || defValue == "{}" {
32-
defValue = ""
69+
for name := range allFlagData { // Iterate over main flag names only
70+
info := allFlagData[name]
71+
72+
flagStr := info.name
73+
if len(info.aliases) > 0 {
74+
// Sort aliases for consistent output
75+
// Sort is important here because map iteration order is not guaranteed.
76+
// This ensures "-a|-alpha" is always consistent.
77+
sortedAliases := make([]string, len(info.aliases))
78+
copy(sortedAliases, info.aliases)
79+
// Apply tree.mu.RLock() and tree.mu.RUnlock() or sort.Strings outside loop
80+
sort.Strings(sortedAliases) // Needs sort import
81+
82+
flagStr = fmt.Sprintf("%s|-%s", strings.Join(sortedAliases, "|-"), info.name)
3383
}
34-
if defValue != "" {
35-
flagStr = fmt.Sprintf("%s[=%s]", f.Name, defValue)
84+
85+
displayValue := info.defValue
86+
if displayValue == `""` || displayValue == "[]" || displayValue == "{}" {
87+
displayValue = ""
88+
}
89+
if displayValue != "" {
90+
flagStr = fmt.Sprintf("%s[=%s]", flagStr, displayValue)
3691
}
92+
3793
if len(flagStr) > maxFlagLen {
3894
maxFlagLen = len(flagStr)
3995
}
40-
})
96+
}
4197

4298
var sb strings.Builder
4399
_, _ = fmt.Fprintf(&sb, "Usage of %s (powered by figtree %s):\n", filepath.Base(os.Args[0]), Version())
44-
flag.VisitAll(func(f *flag.Flag) {
45-
flagStr := f.Name
46-
defValue := f.DefValue
47-
if defValue == `""` || defValue == "[]" || defValue == "{}" {
48-
defValue = ""
49-
}
50-
if defValue != "" {
51-
flagStr = fmt.Sprintf("%s[=%s]", f.Name, defValue)
52-
}
53100

54-
typeStr := "Unknown"
55-
tree.mu.RLock()
56-
if fig, ok := tree.figs[f.Name]; ok && fig != nil {
57-
typeStr = string(fig.Mutagenesis)
101+
sortedFlagNames := make([]string, 0, len(allFlagData))
102+
for name := range allFlagData {
103+
sortedFlagNames = append(sortedFlagNames, name)
104+
}
105+
sort.Strings(sortedFlagNames)
106+
107+
for _, name := range sortedFlagNames {
108+
info := allFlagData[name]
109+
110+
flagStr := info.name
111+
if len(info.aliases) > 0 {
112+
sortedAliases := make([]string, len(info.aliases))
113+
copy(sortedAliases, info.aliases)
114+
sort.Strings(sortedAliases)
115+
flagStr = fmt.Sprintf("%s|-%s", strings.Join(sortedAliases, "|-"), info.name)
58116
}
59-
tree.mu.RUnlock()
60-
typeField := fmt.Sprintf("[%s]", typeStr)
61-
var aliasList []string
62-
for alias, name := range tree.aliases {
63-
if name == f.Name {
64-
aliasList = append(aliasList, alias)
65-
}
117+
118+
displayValue := info.defValue
119+
if displayValue == `""` || displayValue == "[]" || displayValue == "{}" {
120+
displayValue = ""
66121
}
67-
if len(aliasList) > 0 {
68-
flagStr = fmt.Sprintf("%s|-%s", strings.Join(aliasList, "|-"), flagStr)
122+
if displayValue != "" {
123+
flagStr = fmt.Sprintf("%s[=%s]", flagStr, displayValue)
69124
}
70125

71-
line := fmt.Sprintf(" -%-*s %-8s %s", maxFlagLen, flagStr, typeField, f.Usage)
126+
typeField := fmt.Sprintf("[%s]", info.mutagenesis) // Use Mutagenesis from figFruit
127+
128+
// The f.Usage is the usage string of the main flag.
129+
line := fmt.Sprintf(" -%-*s %-8s %s", maxFlagLen, flagStr, typeField, info.usage)
72130

73131
// Wrap the usage text if it exceeds terminal width
74132
lines := wrapText(line, termWidth, maxFlagLen+8+3+3) // 8 for type field, 3 spaces each side
@@ -81,7 +139,7 @@ func (tree *figTree) UsageString() string {
81139
_, _ = fmt.Fprintf(&sb, "%s%s\n", indent, l)
82140
}
83141
}
84-
})
142+
}
85143

86144
return sb.String()
87145
}

0 commit comments

Comments
 (0)