mirror of
https://github.com/arl/gitmux.git
synced 2026-09-10 07:26:18 -04:00
Implement hide_flag_count_if_empty_symbol option with tests and documentation
Co-authored-by: arl <476650+arl@users.noreply.github.com>
This commit is contained in:
parent
ae95b7469d
commit
b5ecc964fc
|
|
@ -87,3 +87,5 @@ tmux:
|
|||
divergence_space: false
|
||||
# Show flags symbols without counts.
|
||||
flags_without_count: false
|
||||
# Hide flag count when symbol is empty (default false shows count only).
|
||||
hide_flag_count_if_empty_symbol: false
|
||||
|
|
|
|||
19
README.md
19
README.md
|
|
@ -288,15 +288,16 @@ layout: [branch, "|", flags, "|", stats]
|
|||
|
||||
This is the list of additional configuration `options`:
|
||||
|
||||
| Option | Description | Default |
|
||||
| :------------------- | :------------------------------------------------------------------------------ | :----------------: |
|
||||
| `branch_max_len` | Maximum displayed length for local and remote branch names | `0` (no limit) |
|
||||
| `branch_trim` | Trim left, right or from the center of the branch (`right`, `left` or `center`) | `right` (trailing) |
|
||||
| `ellipsis` | Character to show branch name has been truncated | `…` |
|
||||
| `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` |
|
||||
| Option | Description | Default |
|
||||
| :------------------------------ | :------------------------------------------------------------------------------ | :----------------: |
|
||||
| `branch_max_len` | Maximum displayed length for local and remote branch names | `0` (no limit) |
|
||||
| `branch_trim` | Trim left, right or from the center of the branch (`right`, `left` or `center`) | `right` (trailing) |
|
||||
| `ellipsis` | Character to show branch name has been truncated | `…` |
|
||||
| `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` |
|
||||
| `hide_flag_count_if_empty_symbol` | Hide flag count when symbol is empty (false shows count only) | `false` |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -88,13 +88,14 @@ func (d *direction) UnmarshalYAML(value *yaml.Node) error {
|
|||
}
|
||||
|
||||
type options struct {
|
||||
BranchMaxLen int `yaml:"branch_max_len"`
|
||||
BranchTrim direction `yaml:"branch_trim"`
|
||||
Ellipsis string `yaml:"ellipsis"`
|
||||
HideClean bool `yaml:"hide_clean"`
|
||||
DivergenceSpace bool `yaml:"divergence_space"`
|
||||
SwapDivergence bool `yaml:"swap_divergence"`
|
||||
FlagsWithoutCount bool `yaml:"flags_without_count"`
|
||||
BranchMaxLen int `yaml:"branch_max_len"`
|
||||
BranchTrim direction `yaml:"branch_trim"`
|
||||
Ellipsis string `yaml:"ellipsis"`
|
||||
HideClean bool `yaml:"hide_clean"`
|
||||
DivergenceSpace bool `yaml:"divergence_space"`
|
||||
SwapDivergence bool `yaml:"swap_divergence"`
|
||||
FlagsWithoutCount bool `yaml:"flags_without_count"`
|
||||
HideFlagCountIfEmptySymbol bool `yaml:"hide_flag_count_if_empty_symbol"`
|
||||
}
|
||||
|
||||
// A Formater formats git status to a tmux style string.
|
||||
|
|
@ -297,6 +298,15 @@ func (f *Formater) currentRef() string {
|
|||
|
||||
// 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 {
|
||||
// Handle empty symbol case based on hide_flag_count_if_empty_symbol option
|
||||
if symbol == "" {
|
||||
if f.Options.HideFlagCountIfEmptySymbol {
|
||||
return "" // Hide both symbol and count
|
||||
}
|
||||
// Show just the count without symbol
|
||||
return fmt.Sprintf("%s%d", style, count)
|
||||
}
|
||||
|
||||
if f.Options.FlagsWithoutCount {
|
||||
return fmt.Sprintf("%s%s", style, symbol)
|
||||
}
|
||||
|
|
@ -306,12 +316,21 @@ func (f *Formater) formatFlag(style, symbol string, count int) string {
|
|||
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))
|
||||
if f.st.NumStashed != 0 {
|
||||
flag := f.formatFlag(f.Styles.Stashed, f.Symbols.Stashed, f.st.NumStashed)
|
||||
if flag != "" {
|
||||
flags = append(flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
if !f.Options.HideClean && f.Symbols.Clean != "" {
|
||||
flags = append(flags, fmt.Sprintf("%s%s", f.Styles.Clean, f.Symbols.Clean))
|
||||
if !f.Options.HideClean {
|
||||
// Handle clean symbol separately since it doesn't have a count
|
||||
if f.Symbols.Clean != "" {
|
||||
flags = append(flags, fmt.Sprintf("%s%s", f.Styles.Clean, f.Symbols.Clean))
|
||||
} else if !f.Options.HideFlagCountIfEmptySymbol {
|
||||
// When symbol is empty but we don't want to hide, there's no count to show for clean flag
|
||||
// so we just skip it (nothing meaningful to display)
|
||||
}
|
||||
}
|
||||
|
||||
if len(flags) != 0 {
|
||||
|
|
@ -319,24 +338,39 @@ 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.NumStaged != 0 {
|
||||
flag := f.formatFlag(f.Styles.Staged, f.Symbols.Staged, f.st.NumStaged)
|
||||
if flag != "" {
|
||||
flags = append(flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
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.NumConflicts != 0 {
|
||||
flag := f.formatFlag(f.Styles.Conflict, f.Symbols.Conflict, f.st.NumConflicts)
|
||||
if flag != "" {
|
||||
flags = append(flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
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.NumModified != 0 {
|
||||
flag := f.formatFlag(f.Styles.Modified, f.Symbols.Modified, f.st.NumModified)
|
||||
if flag != "" {
|
||||
flags = append(flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
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.NumStashed != 0 {
|
||||
flag := f.formatFlag(f.Styles.Stashed, f.Symbols.Stashed, f.st.NumStashed)
|
||||
if flag != "" {
|
||||
flags = append(flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
if f.st.NumUntracked != 0 && f.Symbols.Untracked != "" {
|
||||
flags = append(flags, f.formatFlag(f.Styles.Untracked, f.Symbols.Untracked, f.st.NumUntracked))
|
||||
if f.st.NumUntracked != 0 {
|
||||
flag := f.formatFlag(f.Styles.Untracked, f.Symbols.Untracked, f.st.NumUntracked)
|
||||
if flag != "" {
|
||||
flags = append(flags, flag)
|
||||
}
|
||||
}
|
||||
|
||||
if len(flags) > 0 {
|
||||
|
|
|
|||
|
|
@ -984,6 +984,7 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
name string
|
||||
styles styles
|
||||
symbols symbols
|
||||
options options
|
||||
st *gitstatus.Status
|
||||
want string
|
||||
}{
|
||||
|
|
@ -998,6 +999,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Modified: "SymbolMod",
|
||||
Stashed: "", // empty symbol should hide this flag
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 5,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
|
|
@ -1017,6 +1021,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Modified: "", // empty symbol should hide this flag
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
|
|
@ -1036,6 +1043,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Staged: "", // empty symbol should hide this flag
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
|
|
@ -1055,6 +1065,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Untracked: "", // empty symbol should hide this flag
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
|
|
@ -1074,6 +1087,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Conflict: "", // empty symbol should hide this flag
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
|
|
@ -1093,6 +1109,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Clean: "", // empty symbol should hide this flag
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
IsClean: true,
|
||||
NumStashed: 1,
|
||||
|
|
@ -1109,6 +1128,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Clean: "SymbolClean",
|
||||
Stashed: "", // empty symbol should hide this flag
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
IsClean: true,
|
||||
NumStashed: 1,
|
||||
|
|
@ -1134,6 +1156,9 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
Untracked: "",
|
||||
Stashed: "",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: true, // Use old behavior for this test
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
IsClean: false,
|
||||
NumStashed: 1,
|
||||
|
|
@ -1150,7 +1175,122 @@ func TestFlagsWithEmptySymbols(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f := &Formater{
|
||||
Config: Config{Styles: tt.styles, Symbols: tt.symbols},
|
||||
Config: Config{Styles: tt.styles, Symbols: tt.symbols, Options: tt.options},
|
||||
st: tt.st,
|
||||
}
|
||||
|
||||
compareStrings(t, tt.want, f.flags())
|
||||
})
|
||||
}
|
||||
}
|
||||
func TestFlagsWithEmptySymbolsNewBehavior(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
styles styles
|
||||
symbols symbols
|
||||
options options
|
||||
st *gitstatus.Status
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty stashed symbol shows count only (new behavior)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Modified: "SymbolMod",
|
||||
Stashed: "", // empty symbol should show count only
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: false, // Use new behavior
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 5,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumModified: 2,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleModSymbolMod2 StyleStash5",
|
||||
},
|
||||
{
|
||||
name: "empty modified symbol shows count only (new behavior)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Modified: "", // empty symbol should show count only
|
||||
Stashed: "SymbolStash",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: false, // Use new behavior
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumModified: 2,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleMod2 StyleStashSymbolStash1",
|
||||
},
|
||||
{
|
||||
name: "multiple empty symbols show counts only (new behavior)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
Modified: "StyleMod",
|
||||
Untracked: "StyleUntracked",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "", // empty symbols should show counts only
|
||||
Modified: "",
|
||||
Untracked: "",
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: false, // Use new behavior
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 3,
|
||||
NumModified: 2,
|
||||
NumUntracked: 4,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStaged3 StyleMod2 StyleUntracked4",
|
||||
},
|
||||
{
|
||||
name: "mixed symbols and empty symbols (new behavior)",
|
||||
styles: styles{
|
||||
Clear: "StyleClear",
|
||||
Staged: "StyleStaged",
|
||||
Modified: "StyleMod",
|
||||
Stashed: "StyleStash",
|
||||
},
|
||||
symbols: symbols{
|
||||
Staged: "SymbolStaged", // normal symbol
|
||||
Modified: "", // empty symbol should show count only
|
||||
Stashed: "SymbolStash", // normal symbol
|
||||
},
|
||||
options: options{
|
||||
HideFlagCountIfEmptySymbol: false, // Use new behavior
|
||||
},
|
||||
st: &gitstatus.Status{
|
||||
NumStashed: 1,
|
||||
Porcelain: gitstatus.Porcelain{
|
||||
NumStaged: 3,
|
||||
NumModified: 2,
|
||||
},
|
||||
},
|
||||
want: "StyleClear" + "StyleStagedSymbolStaged3 StyleMod2 StyleStashSymbolStash1",
|
||||
},
|
||||
}
|
||||
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,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue