allow flexible display for output format of git status (#21)

* changes from casonadams:
- added options in cfg file to show or hide remote information
- Consider possibility to choose/reorder/remove the info shown #14 fix
- updated test cases to accomidate changes to code base
- better docs, added second delm option, more flexible formatting
- fixed tests to run on travis CI
- fixed tests to run on travis CI
- adding README info for cfg options in dynamic layout output
- making display output not break if missing, plus making spacing strings more flexible
- adding usage in READ around display features
- fixed typo in README

* changes from salarkhan
- match string exactly, remove regexp
- don't call git, create a synthetic status to compare against
- use "Symbol-Thing" instead of the actual symbols, in case they change
- note that divergence is coupled to remote. maybe these should be split
- add empty test case
- no need to have a test for every single permutation, one example should suffice

* display -> layout

Co-authored-by: Cason Adams <casonadams@gmail.com>
This commit is contained in:
Salar Khan 2020-04-12 23:04:30 -07:00 committed by GitHub
parent a2244005d4
commit 9846b104da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 154 additions and 20 deletions

View file

@ -51,13 +51,13 @@ Add this line to your `.tmux.conf`:
## Customizing
`gitmux` output can be customized via a configuration file in YAML format.
`gitmux` output can be customized via a configuration file in YAML format.
First, save the default configuration to a new file
gitmux -printcfg > .gitmux.conf
Open `.gitmux.conf` and modify it, replacing symbols and colors to suit your needs.
Open `.gitmux.conf` and modify it, replacing symbols and colors to suit your needs.
Ensure the file is valid by adding the `-dbg` flag
gitmux -dbg -cfg .gitmux.conf
@ -66,10 +66,17 @@ Modify the line in `.tmux.conf`, passing the path of the configuration file as a
gitmux -cfg .gitmux.conf
`gitmux` configuration is split into 2 sections:
`gitmux` configuration is split into 3 sections:
- symbols: they are just strings of unicode characters
- styles: they are tmux format strings (`man tmux` for reference)
- layout: is the layout of git components & separators
Example layouts:
```
layout: [branch, '..', remote, ' - ', flags]
layout: [branch]
layout: [flags, ' && ', branch]
```
## Troubleshooting
@ -78,6 +85,7 @@ Please report anything by [filing an issue](https://github.com/arl/gitmux/issues
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

View file

@ -18,6 +18,8 @@ type Config struct {
// Styles contains the tmux style strings for symbols and Git status
// components.
Styles styles
// Layout sets the output format of the Git status.
Layout []string `yaml:",flow"`
}
type symbols struct {
@ -71,6 +73,7 @@ var DefaultCfg = Config{
Stashed: "#[fg=cyan,bold]",
Clean: "#[fg=green,bold]",
},
Layout: []string{"branch", "..", "remote", " - ", "flags"},
}
// A Formater formats git status to a tmux style string.
@ -88,20 +91,31 @@ func (f *Formater) Format(w io.Writer, st *gitstatus.Status) error {
// overall working tree state
if f.st.IsInitial {
fmt.Fprintf(w, "%s%s [no commits yet]", f.Styles.Branch, f.st.LocalBranch)
goto fileCounts
f.flags()
_, err := f.b.WriteTo(w)
return err
}
f.specialState()
f.remote()
fileCounts:
f.flags()
f.format()
_, err := f.b.WriteTo(w)
return err
}
func (f *Formater) format() {
for _, order := range f.Layout {
switch order {
case "branch":
f.specialState()
case "remote":
f.remote()
case "flags":
f.flags()
default:
f.b.WriteString(order)
}
}
}
func (f *Formater) specialState() {
f.clear()
switch f.st.State {
@ -128,7 +142,7 @@ func (f *Formater) specialState() {
func (f *Formater) remote() {
f.clear()
if f.st.RemoteBranch != "" {
fmt.Fprintf(&f.b, "..%s%s", f.Styles.Remote, f.st.RemoteBranch)
fmt.Fprintf(&f.b, "%s%s", f.Styles.Remote, f.st.RemoteBranch)
f.divergence()
}
}
@ -164,7 +178,6 @@ func (f *Formater) divergence() {
func (f *Formater) flags() {
f.clear()
f.b.WriteString(" - ")
if f.st.IsClean {
fmt.Fprintf(&f.b, "%s%s", f.Styles.Clean, f.Symbols.Clean)

View file

@ -1,6 +1,7 @@
package tmux
import (
"os"
"testing"
"github.com/arl/gitstatus"
@ -12,21 +13,23 @@ func TestFormater_flags(t *testing.T) {
name string
styles styles
symbols symbols
layout []string
st *gitstatus.Status
want string
}{
{
name: "clean flag",
styles: styles{
Clean: "CleanStyle",
Clean: "StyleClean",
},
symbols: symbols{
Clean: "CleanSymbol",
Clean: "SymbolClean",
},
layout: []string{"branch", "..", "remote", " - ", "flags"},
st: &gitstatus.Status{
IsClean: true,
},
want: clear + " - CleanStyleCleanSymbol",
want: clear + "StyleCleanSymbolClean",
},
{
name: "mixed flags",
@ -40,6 +43,7 @@ func TestFormater_flags(t *testing.T) {
Stashed: "SymbolStash",
Staged: "SymbolStaged",
},
layout: []string{"branch", "..", "remote", " - ", "flags"},
st: &gitstatus.Status{
NumStashed: 1,
Porcelain: gitstatus.Porcelain{
@ -47,7 +51,7 @@ func TestFormater_flags(t *testing.T) {
NumStaged: 3,
},
},
want: clear + " - StyleStagedSymbolStaged3 StyleModSymbolMod2 StyleStashSymbolStash1",
want: clear + "StyleStagedSymbolStaged3 StyleModSymbolMod2 StyleStashSymbolStash1",
},
{
name: "mixed flags 2",
@ -65,13 +69,13 @@ func TestFormater_flags(t *testing.T) {
NumUntracked: 17,
},
},
want: clear + " - StyleConflictSymbolConflict42 StyleUntrackedSymbolUntracked17",
want: clear + "StyleConflictSymbolConflict42 StyleUntrackedSymbolUntracked17",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
f := &Formater{
Config: Config{Styles: tc.styles, Symbols: tc.symbols},
Config: Config{Styles: tc.styles, Symbols: tc.symbols, Layout: tc.layout},
st: tc.st,
}
f.flags()
@ -156,3 +160,111 @@ func TestFormater_divergence(t *testing.T) {
})
}
}
func TestFormater_Format(t *testing.T) {
tests := []struct {
name string
styles styles
symbols symbols
layout []string
st *gitstatus.Status
want string
}{
{
name: "default format",
styles: styles{
Clean: "StyleClean",
Branch: "StyleBranch",
Modified: "StyleMod",
Remote: "StyleRemote",
},
symbols: symbols{
Branch: "SymbolBranch",
Clean: "SymbolClean",
Modified: "SymbolMod",
},
layout: []string{"branch", "..", "remote", " - ", "flags"},
st: &gitstatus.Status{
Porcelain: gitstatus.Porcelain{
LocalBranch: "Local",
RemoteBranch: "Remote",
NumModified: 2,
},
},
want: clear + "StyleBranchSymbolBranch" + clear + "Local" + ".." + clear + "StyleRemoteRemote" + clear + " - " + clear + "StyleModSymbolMod2",
},
{
name: "branch, different delimiter, flags",
styles: styles{
Branch: "StyleBranch",
Remote: "StyleRemote",
Modified: "StyleMod",
},
symbols: symbols{
Branch: "SymbolBranch",
Ahead: "SymbolAhead",
Modified: "SymbolMod",
},
layout: []string{"branch", " ~~ ", "flags"},
st: &gitstatus.Status{
Porcelain: gitstatus.Porcelain{
LocalBranch: "Local",
RemoteBranch: "Remote",
NumModified: 2,
AheadCount: 1,
},
},
want: clear + "StyleBranchSymbolBranch" + clear + "Local" + " ~~ " + clear + "StyleModSymbolMod2",
},
{
name: "remote only",
styles: styles{
Branch: "StyleBranch",
Remote: "StyleRemote",
},
symbols: symbols{
Branch: "SymbolBranch",
Ahead: "SymbolAhead",
},
layout: []string{"remote"},
st: &gitstatus.Status{
Porcelain: gitstatus.Porcelain{
LocalBranch: "Local",
RemoteBranch: "Remote",
AheadCount: 1,
},
},
want: clear + "StyleRemoteRemote" + clear + " SymbolAhead1",
},
{
name: "empty",
styles: styles{
Branch: "StyleBranch",
Modified: "StyleMod",
},
symbols: symbols{
Branch: "SymbolBranch",
Modified: "SymbolMod",
},
layout: []string{},
st: &gitstatus.Status{
Porcelain: gitstatus.Porcelain{
LocalBranch: "Local",
NumModified: 2,
},
},
want: "",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
f := &Formater{
Config: Config{Styles: tc.styles, Symbols: tc.symbols, Layout: tc.layout},
}
f.Format(os.Stdout, tc.st)
f.format()
require.EqualValues(t, tc.want, f.b.String())
})
}
}

1
go.sum
View file

@ -4,6 +4,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=