mirror of
https://github.com/arl/gitmux.git
synced 2026-09-09 23:16:28 -04:00
Fix flags_without_count option behavior for empty symbols (#136)
The flags_without_count option was not handling empty symbols correctly. Previously, flags with empty symbols were completely hidden regardless of the option value, but according to the intended behavior, they should show counts when flags_without_count=false (default).
This commit is contained in:
parent
70a31330cd
commit
6a169c649f
|
|
@ -86,4 +86,6 @@ tmux:
|
|||
# Add a space between behind & ahead upstream counts.
|
||||
divergence_space: false
|
||||
# Show flags symbols without counts.
|
||||
# When true, shows only symbols (empty symbols show nothing).
|
||||
# When false (default), shows symbols with counts (empty symbols show counts only).
|
||||
flags_without_count: false
|
||||
|
|
|
|||
|
|
@ -296,7 +296,9 @@ This is the list of additional configuration `options`:
|
|||
| `hide_clean` | Hides the clean flag entirely | `false` |
|
||||
| `swap_divergence` | Swaps order of behind & ahead upstream counts | `false` |
|
||||
| `divergence_space` | Add a space between behind & ahead upstream counts | `false` |
|
||||
| `flags_without_count`| Show flags symbols without counts | `false` |
|
||||
| `flags_without_count`| Show flags symbols without counts* | `false` |
|
||||
|
||||
*When `flags_without_count` is true, shows only symbols (empty symbols show nothing). When false (default), shows symbols with counts (empty symbols show counts only).
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -295,21 +295,31 @@ func (f *Formater) currentRef() string {
|
|||
return fmt.Sprintf("%s%s%s", f.Styles.Clear, f.Styles.Branch, branch)
|
||||
}
|
||||
|
||||
// formatFlag formats a flag with or without count based on the flags_without_count option
|
||||
func (f *Formater) formatFlag(style, symbol string, count int) string {
|
||||
if f.Options.FlagsWithoutCount {
|
||||
return fmt.Sprintf("%s%s", style, symbol)
|
||||
// appendFlag appends a flag to the flags slice based on configuration options
|
||||
func (f *Formater) appendFlag(flags []string, style, symbol string, count int) []string {
|
||||
if count == 0 {
|
||||
return flags
|
||||
}
|
||||
return fmt.Sprintf("%s%s%d", style, symbol, count)
|
||||
|
||||
if f.Options.FlagsWithoutCount {
|
||||
// When flags_without_count is true, show symbol only (empty string if symbol is empty)
|
||||
if symbol == "" {
|
||||
return flags
|
||||
}
|
||||
return append(flags, fmt.Sprintf("%s%s", style, symbol))
|
||||
}
|
||||
|
||||
// When flags_without_count is false, show symbol + count, or just count if symbol is empty
|
||||
return append(flags, fmt.Sprintf("%s%s%d", style, symbol, count))
|
||||
}
|
||||
|
||||
func (f *Formater) flags() string {
|
||||
var flags []string
|
||||
if f.st.IsClean {
|
||||
if f.st.NumStashed != 0 && f.Symbols.Stashed != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Stashed, f.Symbols.Stashed, f.st.NumStashed))
|
||||
}
|
||||
// For stashed in clean state, handle empty symbols properly
|
||||
flags = f.appendFlag(flags, f.Styles.Stashed, f.Symbols.Stashed, f.st.NumStashed)
|
||||
|
||||
// Clean flag only shows if symbol is not empty and hide_clean is false
|
||||
if !f.Options.HideClean && f.Symbols.Clean != "" {
|
||||
flags = append(flags, fmt.Sprintf("%s%s", f.Styles.Clean, f.Symbols.Clean))
|
||||
}
|
||||
|
|
@ -319,25 +329,12 @@ func (f *Formater) flags() string {
|
|||
}
|
||||
}
|
||||
|
||||
if f.st.NumStaged != 0 && f.Symbols.Staged != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Staged, f.Symbols.Staged, f.st.NumStaged))
|
||||
}
|
||||
|
||||
if f.st.NumConflicts != 0 && f.Symbols.Conflict != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Conflict, f.Symbols.Conflict, f.st.NumConflicts))
|
||||
}
|
||||
|
||||
if f.st.NumModified != 0 && f.Symbols.Modified != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Modified, f.Symbols.Modified, f.st.NumModified))
|
||||
}
|
||||
|
||||
if f.st.NumStashed != 0 && f.Symbols.Stashed != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Stashed, f.Symbols.Stashed, f.st.NumStashed))
|
||||
}
|
||||
|
||||
if f.st.NumUntracked != 0 && f.Symbols.Untracked != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Untracked, f.Symbols.Untracked, f.st.NumUntracked))
|
||||
}
|
||||
// For all other flags, handle empty symbols properly
|
||||
flags = f.appendFlag(flags, f.Styles.Staged, f.Symbols.Staged, f.st.NumStaged)
|
||||
flags = f.appendFlag(flags, f.Styles.Conflict, f.Symbols.Conflict, f.st.NumConflicts)
|
||||
flags = f.appendFlag(flags, f.Styles.Modified, f.Symbols.Modified, f.st.NumModified)
|
||||
flags = f.appendFlag(flags, f.Styles.Stashed, f.Symbols.Stashed, f.st.NumStashed)
|
||||
flags = f.appendFlag(flags, f.Styles.Untracked, f.Symbols.Untracked, f.st.NumUntracked)
|
||||
|
||||
if len(flags) > 0 {
|
||||
return f.Styles.Clear + strings.Join(flags, " ")
|
||||
|
|
|
|||
|
|
@ -104,6 +104,200 @@ func TestFlags(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFlagsWithoutCountBehavior(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
styles styles
|
||||
symbols symbols
|
||||
options options
|
||||
st *gitstatus.Status
|
||||
want string
|
||||
}{
|
||||
// Case 1: non-empty symbol, count=1, flags_without_count=false
|
||||
{
|
||||
name: "case 1a: non-empty symbol, count=1, flags_without_count=false",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "SymbolStaged",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: false,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 1,
|
||||
},
|
||||
},
|
||||
want: "StyleClearStyleStagedSymbolStaged1",
|
||||
},
|
||||
// Case 1: non-empty symbol, count=1, flags_without_count=true
|
||||
{
|
||||
name: "case 1b: non-empty symbol, count=1, flags_without_count=true",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "SymbolStaged",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: true,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 1,
|
||||
},
|
||||
},
|
||||
want: "StyleClearStyleStagedSymbolStaged",
|
||||
},
|
||||
// Case 2: empty symbol, count=1, flags_without_count=false
|
||||
{
|
||||
name: "case 2a: empty symbol, count=1, flags_without_count=false",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: false,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 1,
|
||||
},
|
||||
},
|
||||
want: "StyleClearStyleStaged1",
|
||||
},
|
||||
// Case 2: empty symbol, count=1, flags_without_count=true
|
||||
{
|
||||
name: "case 2b: empty symbol, count=1, flags_without_count=true",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: true,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 1,
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
// Case 3: count=0, flags_without_count=false
|
||||
{
|
||||
name: "case 3a: count=0, flags_without_count=false",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "SymbolStaged",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: false,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 0,
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
// Case 3: count=0, flags_without_count=true
|
||||
{
|
||||
name: "case 3b: count=0, flags_without_count=true",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "SymbolStaged",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: true,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 0,
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
// Mixed case: multiple flags with different symbol states
|
||||
{
|
||||
name: "mixed flags: some empty symbols, some non-empty, flags_without_count=false",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "", // empty symbol, should show count only
|
||||
Modified: "M", // non-empty symbol, should show symbol+count
|
||||
Stashed: "", // empty symbol, should show count only
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: false,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 2,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 1,
|
||||
NumModified: 3,
|
||||
},
|
||||
},
|
||||
want: "StyleClearStyleStaged1 StyleModM3 StyleStash2",
|
||||
},
|
||||
// Mixed case: multiple flags with different symbol states, flags_without_count=true
|
||||
{
|
||||
name: "mixed flags: some empty symbols, some non-empty, flags_without_count=true",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "", // empty symbol, should show nothing
|
||||
Modified: "M", // non-empty symbol, should show symbol only
|
||||
Stashed: "", // empty symbol, should show nothing
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: true,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 2,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 1,
|
||||
NumModified: 3,
|
||||
},
|
||||
},
|
||||
want: "StyleClearStyleModM",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f := &Formater{
|
||||
Config: Config{Styles: tt.styles, Symbols: tt.symbols, Options: tt.options},
|
||||
st: tt.st,
|
||||
}
|
||||
|
||||
compareStrings(t, tt.want, f.flags())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlagsWithoutCount(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
@ -988,7 +1182,7 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty stashed symbol hides stash count",
|
||||
name: "empty stashed symbol shows stash count (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Modified: "StyleMod",
|
||||
|
|
@ -996,7 +1190,7 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
},
|
||||
symbols: symbols{
|
||||
Modified: "SymbolMod",
|
||||
Stashed: "", // empty symbol should hide this flag
|
||||
Stashed: "", // empty symbol should show count with default flags_without_count=false
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 5,
|
||||
|
|
@ -1004,17 +1198,17 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
NumModified: 2,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleModSymbolMod2",
|
||||
want: "StyleClear" + "StyleModSymbolMod2 StyleStash5",
|
||||
},
|
||||
{
|
||||
name: "empty modified symbol hides modified count",
|
||||
name: "empty modified symbol shows modified count (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Modified: "", // empty symbol should hide this flag
|
||||
Modified: "", // empty symbol should show count with default flags_without_count=false
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
|
|
@ -1023,17 +1217,17 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
NumModified: 2,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStashSymbolStash1",
|
||||
want: "StyleClear" + "StyleMod2 StyleStashSymbolStash1",
|
||||
},
|
||||
{
|
||||
name: "empty staged symbol hides staged count",
|
||||
name: "empty staged symbol shows staged count (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "", // empty symbol should hide this flag
|
||||
Staged: "", // empty symbol should show count with default flags_without_count=false
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
|
|
@ -1042,17 +1236,17 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
NumStaged: 3,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStashSymbolStash1",
|
||||
want: "StyleClear" + "StyleStaged3 StyleStashSymbolStash1",
|
||||
},
|
||||
{
|
||||
name: "empty untracked symbol hides untracked count",
|
||||
name: "empty untracked symbol shows untracked count (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Untracked: "StyleUntracked",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Untracked: "", // empty symbol should hide this flag
|
||||
Untracked: "", // empty symbol should show count with default flags_without_count=false
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
|
|
@ -1061,17 +1255,17 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
NumUntracked: 7,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStashSymbolStash1",
|
||||
want: "StyleClear" + "StyleStashSymbolStash1 StyleUntracked7",
|
||||
},
|
||||
{
|
||||
name: "empty conflict symbol hides conflict count",
|
||||
name: "empty conflict symbol shows conflict count (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Conflict: "StyleConflict",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Conflict: "", // empty symbol should hide this flag
|
||||
Conflict: "", // empty symbol should show count with default flags_without_count=false
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
|
|
@ -1080,7 +1274,7 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
NumConflicts: 3,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStashSymbolStash1",
|
||||
want: "StyleClear" + "StyleConflict3 StyleStashSymbolStash1",
|
||||
},
|
||||
{
|
||||
name: "empty clean symbol hides clean flag",
|
||||
|
|
@ -1100,23 +1294,24 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
want: "StyleClear" + "StyleStashSymbolStash1",
|
||||
},
|
||||
{
|
||||
name: "empty stashed symbol in clean state hides stash count",
|
||||
name: "empty stashed symbol in clean state shows stash count (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Clean: "StyleClean",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Clean: "SymbolClean",
|
||||
Stashed: "", // empty symbol should hide this flag
|
||||
Stashed: "", // empty symbol should show count with default flags_without_count=false
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
IsClean: true,
|
||||
NumStashed: 1,
|
||||
},
|
||||
want: "StyleClear" + "StyleCleanSymbolClean",
|
||||
want: "StyleClear" + "StyleStash1 StyleCleanSymbolClean",
|
||||
},
|
||||
{
|
||||
name: "all symbols empty shows nothing",
|
||||
name: "all symbols empty shows counts (flags_without_count=false default)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Clean: "StyleClean",
|
||||
|
|
@ -1144,7 +1339,7 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
NumUntracked: 4,
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
want: "StyleClear" + "StyleStaged3 StyleConflict1 StyleMod2 StyleStash1 StyleUntracked4",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
|
@ -1159,6 +1354,81 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFlagsWithEmptySymbolsAndFlagsWithoutCount(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
styles styles
|
||||
symbols symbols
|
||||
options options
|
||||
st *gitstatus.Status
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty symbols hide when flags_without_count=true",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Modified: "", // empty symbol should hide with flags_without_count=true
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: true,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumModified: 2,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStashSymbolStash",
|
||||
},
|
||||
{
|
||||
name: "all empty symbols hide when flags_without_count=true",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
Modified: "StyleMod",
|
||||
Conflict: "StyleConflict",
|
||||
Untracked: "StyleUntracked",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "",
|
||||
Modified: "",
|
||||
Conflict: "",
|
||||
Untracked: "",
|
||||
Stashed: "",
|
||||
},
|
||||
options: options{
|
||||
FlagsWithoutCount: true,
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 3,
|
||||
NumModified: 2,
|
||||
NumConflicts: 1,
|
||||
NumUntracked: 4,
|
||||
},
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f := &Formater{
|
||||
Config: Config{Styles: tt.styles, Symbols: tt.symbols, Options: tt.options},
|
||||
st: tt.st,
|
||||
}
|
||||
|
||||
compareStrings(t, tt.want, f.flags())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func compareStrings(t *testing.T, want, got string) {
|
||||
if got != want {
|
||||
t.Errorf(`
|
||||
|
|
|
|||
Loading…
Reference in a new issue