diff --git a/README.md b/README.md index 78b982d..ea2a255 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,30 @@ - **shell-agnostic**. Does not rely on shell-features so works with all of them - **customizable**. Colors, symbols and layout are configurable +--- + +- [Prerequisites](#prerequisites) +- [Installing](#installing) + - [Binary release](#binary-release) + - [Homebrew (tap) macOS and linux, amd64 and arm64](#homebrew-tap-macos-and-linux-amd64-and-arm64) + - [AUR](#aur) + - [From source](#from-source) +- [Getting started](#getting-started) +- [Customizing](#customizing) + - [Symbols](#symbols) + - [Styles](#styles) + - [Layout components](#layout-components) + - [Additional options](#additional-options) +- [Troubleshooting](#troubleshooting) + - [Gitmux takes too long to refresh?](#gitmux-takes-too-long-to-refresh) +- [Contributing](#contributing) +- [License: MIT](#license-mit) + + ## Prerequisites -Works with all decently recent [tmux](https://github.com/tmux/tmux) versions. +Works with all reasonably recent [tmux](https://github.com/tmux/tmux) versions (2.1+) ## Installing @@ -92,18 +112,22 @@ tmux: untracked: '… ' stashed: '⚑ ' clean: ✔ + insertions: Σ + deletions: Δ styles: clear: '#[fg=default]' state: '#[fg=red,bold]' branch: '#[fg=white,bold]' remote: '#[fg=cyan]' + divergence: '#[fg=default]' staged: '#[fg=green,bold]' conflict: '#[fg=red,bold]' modified: '#[fg=red,bold]' untracked: '#[fg=magenta,bold]' stashed: '#[fg=cyan,bold]' clean: '#[fg=green,bold]' - divergence: '#[fg=default]' + insertions: '#[fg=green]' + deletions: '#[fg=red]' layout: [branch, .., remote-branch, divergence, ' - ', flags] options: branch_max_len: 0 @@ -112,11 +136,11 @@ tmux: First, save the default configuration to a new file: - gitmux -printcfg > .gitmux.conf + gitmux -printcfg > $HOME/.gitmux.conf -Modify the line in `.tmux.conf`, passing the path of the configuration file as argument to `gitmux` via the `-cfg` flag +Modify the line you've added to `.tmux.conf`, passing the path of the configuration file as argument to `gitmux` via the `-cfg` flag - set -g status-right '#(gitmux -cfg .gitmux.conf "#{pane_current_path}")' + set -g status-right '#(gitmux -cfg $HOME/.gitmux.conf "#{pane_current_path}")' Open `.gitmux.conf` and modify it, replacing symbols, styles and layout to suit your needs. @@ -135,16 +159,18 @@ The `symbols` section describes the symbols `gitmux` prints for the various comp ```yaml symbols: - branch: '⎇ ' # Shown before a branch - hashprefix: ':' # Shown before a Git hash (in 'detached HEAD' state) - ahead: ↑· # Shown before the 'ahead count' when local and remote branch diverge - behind: ↓· # Shown before the 'behind count' when local/remote branch diverge - staged: '● ' # Shown before the 'staged' files count - conflict: '✖ ' # Shown before the 'conflicts' count - modified: '✚ ' # Shown before the 'modified' files count - untracked: '… ' # Shown before the 'untracked' files count - stashed: '⚑ ' # Shown before the 'stash' count - clean: ✔ # Shown when the working tree is clean (empty staging area) + branch: '⎇ ' # Shown before a branch + hashprefix: ':' # Shown before a Git hash (in 'detached HEAD' state) + ahead: ↑· # Shown before the 'ahead count' when local and remote branch diverge + behind: ↓· # Shown before the 'behind count' when local/remote branch diverge + staged: '● ' # Shown before the 'staged' files count + conflict: '✖ ' # Shown before the 'conflicts' count + modified: '✚ ' # Shown before the 'modified' files count + untracked: '… ' # Shown before the 'untracked' files count + stashed: '⚑ ' # Shown before the 'stash' count + insertions: Σ # Shown before the count of insertied lines (stats sections). + deletions: Δ # Shown before the count of deletions lines (stats sections). + clean: ✔ # Shown when the working tree is clean (empty staging area) ``` @@ -165,6 +191,8 @@ See [`tmux` styles reference](https://man7.org/linux/man-pages/man1/tmux.1.html# modified: '#[fg=red,bold]' # Style of the 'modified' files count untracked: '#[fg=magenta,bold]' # Style of the 'modified' files count stashed: '#[fg=cyan,bold]' # Style of the 'stash' entries count + insertions: '#[fg=green]' # Style of the 'inserted lines' count + deletions: '#[fg=red]' # Style of the 'deleted lines' count clean: '#[fg=green,bold]' # Style of the 'clean' symbol ``` @@ -203,9 +231,11 @@ This is the list of the possible components of the `layout`: | `divergence` | divergence local/remote branch, if any | `↓·2↑·1` | | `remote` | alias for `remote-branch` followed by `divergence` | `origin/main ↓·2↑·1` | | `flags` | Symbols representing the working tree state | `✚ 1 ⚑ 1 … 2` | +| `stats` | Insertions/deletions (lines). Disabled by deafult | `Σ56 Δ21` | | any string `foo` | Any other string is directly shown | `foo` | + Some example layouts: - default layout: @@ -214,7 +244,7 @@ Some example layouts: layout: [branch, .., remote-branch, divergence, " - ", flags] ``` - - some more minimal layouts: + - some examples layouts: ```yaml layout: [branch, divergence, " - ", flags] @@ -222,6 +252,9 @@ layout: [branch, divergence, " - ", flags] ```yaml layout: [flags, " ", branch] ``` +```yaml +layout: [branch, "|", flags, "|", stats] +``` ### Additional options diff --git a/config_test.go b/config_test.go index c96133d..1ec1ebc 100644 --- a/config_test.go +++ b/config_test.go @@ -26,6 +26,7 @@ func TestScripts(t *testing.T) { return nil }, UpdateScripts: *updateGolden, + TestWork: true, } if err := gotooltest.Setup(¶ms); err != nil { t.Errorf("gotooltest.Setup error: %v", err) diff --git a/go.mod b/go.mod index 0702f24..e094452 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,16 @@ module github.com/arl/gitmux -go 1.15 +go 1.20 require ( - github.com/arl/gitstatus v0.5.1 - github.com/rogpeppe/go-internal v1.8.1 - github.com/stretchr/testify v1.7.0 // indirect + github.com/arl/gitstatus v0.6.0 + github.com/rogpeppe/go-internal v1.9.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) + +require ( + github.com/kr/pretty v0.1.0 // indirect + github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e // indirect + github.com/stretchr/testify v1.7.0 // indirect + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect +) diff --git a/go.sum b/go.sum index d1b3ff2..5d3ad05 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/arl/gitstatus v0.5.1 h1:1PkVmVGXpmY0ibzJv4HDw8brFUoKHLVmEmKBN+XIAmU= -github.com/arl/gitstatus v0.5.1/go.mod h1:/lYgp44CnFS2PqmWUuE6mDArpIJizmpE6j5XgzBZ/AI= +github.com/arl/gitstatus v0.6.0 h1:y6DOdk20wHDKRZaQ5cuYNTrwRts8TXAOs8nxxpfrQts= +github.com/arl/gitstatus v0.6.0/go.mod h1:qDNPAKa1vROZfzauCeHLxF4mciRLcluP+d2/a+bcxFo= 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/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -11,17 +11,15 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgc github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 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/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab h1:628ME69lBm9C6JY2wXhAph/yjN3jezx1z7BIDLUwxjo= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/testdata/default.output.txt b/testdata/default.output.txt index a265e29..bfefa48 100644 --- a/testdata/default.output.txt +++ b/testdata/default.output.txt @@ -33,7 +33,7 @@ cmp output output.golden -- .gitignore -- .gitignore -gopath +.gopath gitmux gitmux.exe .tmp diff --git a/tmux/formater.go b/tmux/formater.go index 18aa275..75404a2 100644 --- a/tmux/formater.go +++ b/tmux/formater.go @@ -37,20 +37,29 @@ type symbols struct { Untracked string // Untracked is the string shown before the count of untracked files. Stashed string // Stashed is the string shown before the count of stash entries. Clean string // Clean is the string shown when the working tree is clean. + + Insertions string // Insertions is the string shown before the count of inserted lines. + Deletions string // Deletions is the string shown before the count of deleted lines. } type styles struct { - Clear string // Clear is the style string that clears all styles. - State string // State is the style string printed before eventual special state. - Branch string // Branch is the style string printed before the local branch. - Remote string // Remote is the style string printed before the upstream branch. - Staged string // Staged is the style string printed before the staged files count. - Conflict string // Conflict is the style string printed before the conflict count. - Modified string // Modified is the style string printed before the modified files count. - Untracked string // Untracked is the style string printed before the untracked files count. - Stashed string // Stashed is the style string printed before the stash entries count. - Clean string // Clean is the style string printed before the clean symbols. + Clear string // Clear is the style string that clears all styles. + + State string // State is the style string printed before eventual special state. + Branch string // Branch is the style string printed before the local branch. + Remote string // Remote is the style string printed before the upstream branch. + Divergence string // Divergence is the style string printed before divergence count/symbols. + + Staged string // Staged is the style string printed before the staged files count. + Conflict string // Conflict is the style string printed before the conflict count. + Modified string // Modified is the style string printed before the modified files count. + Untracked string // Untracked is the style string printed before the untracked files count. + Stashed string // Stashed is the style string printed before the stash entries count. + Clean string // Clean is the style string printed before the clean symbols. + + Insertions string // Insertions is the style string printed before the count of inserted lines. + Deletions string // Deletions is the style string printed before the count of deleted lines. } const ( @@ -94,6 +103,9 @@ var DefaultCfg = Config{ Ahead: "↑·", Behind: "↓·", HashPrefix: ":", + + Insertions: "Σ", + Deletions: "Δ", }, Styles: styles{ Clear: "#[fg=default]", @@ -107,6 +119,8 @@ var DefaultCfg = Config{ Untracked: "#[fg=magenta,bold]", Stashed: "#[fg=cyan,bold]", Clean: "#[fg=green,bold]", + Insertions: "#[fg=green]", + Deletions: "#[fg=red]", }, Layout: []string{"branch", "..", "remote-branch", "divergence", " - ", "flags"}, Options: options{ @@ -190,6 +204,8 @@ func (f *Formater) format() { f.divergence() case "flags": f.flags() + case "stats": + f.stats() default: f.clear() f.b.WriteString(item) @@ -312,3 +328,20 @@ func (f *Formater) flags() { f.b.WriteString(strings.Join(flags, " ")) } } + +func (f *Formater) stats() { + stats := make([]string, 0, 2) + + if f.st.Insertions != 0 { + stats = append(stats, fmt.Sprintf("%s%s%d", f.Styles.Insertions, f.Symbols.Insertions, f.st.Insertions)) + } + + if f.st.Deletions != 0 { + stats = append(stats, fmt.Sprintf("%s%s%d", f.Styles.Deletions, f.Symbols.Deletions, f.st.Deletions)) + } + + if len(stats) != 0 { + f.clear() + f.b.WriteString(strings.Join(stats, " ")) + } +} diff --git a/tmux/formater_test.go b/tmux/formater_test.go index d041303..def5120 100644 --- a/tmux/formater_test.go +++ b/tmux/formater_test.go @@ -523,3 +523,60 @@ func TestFormat(t *testing.T) { }) } } + +func Test_stats(t *testing.T) { + tests := []struct { + name string + layout []string + insertions, deletions int + want string + }{ + { + name: "nothing", + want: "", + }, + { + name: "insertions", + insertions: 12, + want: "StyleClear" + "StyleInsertionsSymbolInsertions12", + }, + { + name: "deletions", + deletions: 12, + want: "StyleClear" + "StyleDeletionsSymbolDeletions12", + }, + { + name: "insertions and deletions", + insertions: 1, + deletions: 2, + want: "StyleClear" + "StyleInsertionsSymbolInsertions1" + " " + "StyleDeletionsSymbolDeletions2", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := &Formater{ + Config: Config{ + Styles: styles{ + Clear: "StyleClear", + Deletions: "StyleDeletions", + Insertions: "StyleInsertions", + }, + Symbols: symbols{ + Deletions: "SymbolDeletions", + Insertions: "SymbolInsertions", + }, + Layout: []string{"stats"}, + }, + st: &gitstatus.Status{ + Insertions: tt.insertions, + Deletions: tt.deletions, + }, + } + f.stats() + + if got := f.b.String(); got != tt.want { + t.Errorf("got:\n%s\n\nwant:\n%s\n", got, tt.want) + } + }) + } +}