Skip to content

Commit

Permalink
feat: git segment branch context color
Browse files Browse the repository at this point in the history
  • Loading branch information
JanDeDobbeleer committed Oct 18, 2020
1 parent 4e27952 commit c418661
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 5 deletions.
10 changes: 10 additions & 0 deletions docs/docs/segment-git.md
Expand Up @@ -68,5 +68,15 @@ Local changes can also shown by default using the following syntax for both the

- working_color: `string` [hex color code][colors] - foreground color for the working area status - defaults to segment foreground
- staging_color: `string` [hex color code][colors] - foreground color for the staging area status - defaults to segment foreground
- status_colors_enabled: `boolean` - color the segment based on the repository status - defaults to `false`
- color_background: `boolean` - color background or foreground - defaults to `true`
- local_changes_color: `string` [hex color code][colors] - segment color when there are local changes - defaults to segment
foreground/background (see `color_background`)
- ahead_and_behind_color: `string` [hex color code][colors] - segment color when the branch is ahead and behind -
defaults to segment foreground/background (see `color_background`)
- behind_color: `string` [hex color code][colors] - segment color when the branch is behind - defaults to segment
foreground/background (see `color_background`)
- ahead_color: `string` [hex color code][colors] - segment color when the branch is ahead - defaults to segment
foreground/background (see `color_background`)

[colors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
51 changes: 46 additions & 5 deletions segment_git.go
Expand Up @@ -25,6 +25,7 @@ type gitStatus struct {
added int
modified int
untracked int
changed bool
}

func (s *gitStatus) string(prefix string, color string) string {
Expand Down Expand Up @@ -99,6 +100,16 @@ const (
WorkingColor Property = "working_color"
//StagingColor if set, the color to use on the staging area
StagingColor Property = "staging_color"
//StatusColorsEnabled enables status colors
StatusColorsEnabled Property = "status_colors_enabled"
//LocalChangesColor if set, the color to use when there are local changes
LocalChangesColor Property = "local_changes_color"
//AheadAndBehindColor if set, the color to use when the branch is ahead and behind the remote
AheadAndBehindColor Property = "ahead_and_behind_color"
//BehindColor if set, the color to use when the branch is ahead and behind the remote
BehindColor Property = "behind_color"
//AheadColor if set, the color to use when the branch is ahead and behind the remote
AheadColor Property = "ahead_color"
)

func (g *git) enabled() bool {
Expand All @@ -111,6 +122,10 @@ func (g *git) enabled() bool {

func (g *git) string() string {
g.setGitStatus()
if g.props.getBool(StatusColorsEnabled, false) {
g.SetStatusColor()
}
// g.getGitColor()
buffer := new(bytes.Buffer)
// branchName
if g.repo.upstream != "" && g.props.getBool(DisplayUpstreamIcon, false) {
Expand All @@ -134,13 +149,17 @@ func (g *git) string() string {
} else if g.repo.upstream == "" {
fmt.Fprintf(buffer, " %s", g.props.getString(BranchGoneIcon, "\u2262"))
}
staging := g.repo.staging.string(g.props.getString(LocalStagingIcon, "\uF046"), g.props.getColor(StagingColor, g.props.foreground))
working := g.repo.working.string(g.props.getString(LocalWorkingIcon, "\uF044"), g.props.getColor(WorkingColor, g.props.foreground))
fmt.Fprint(buffer, staging)
if staging != "" && working != "" {
if g.repo.staging.changed {
staging := g.repo.staging.string(g.props.getString(LocalStagingIcon, "\uF046"), g.props.getColor(StagingColor, g.props.foreground))
fmt.Fprint(buffer, staging)
}
if g.repo.staging.changed && g.repo.working.changed {
fmt.Fprint(buffer, g.props.getString(StatusSeparatorIcon, " |"))
}
fmt.Fprint(buffer, working)
if g.repo.working.changed {
working := g.repo.working.string(g.props.getString(LocalWorkingIcon, "\uF044"), g.props.getColor(WorkingColor, g.props.foreground))
fmt.Fprint(buffer, working)
}
if g.props.getBool(DisplayStashCount, false) && g.repo.stashCount != "" {
fmt.Fprintf(buffer, " %s%s", g.props.getString(StashCountIcon, "\uF692"), g.repo.stashCount)
}
Expand Down Expand Up @@ -185,6 +204,27 @@ func (g *git) setGitStatus() {
g.repo.stashCount = g.getStashContext()
}

func (g *git) SetStatusColor() {
if g.props.getBool(ColorBackground, true) {
g.props.background = g.getStatusColor(g.props.background)
} else {
g.props.foreground = g.getStatusColor(g.props.foreground)
}
}

func (g *git) getStatusColor(defaultValue string) string {
if g.repo.staging.changed || g.repo.working.changed {
return g.props.getColor(LocalChangesColor, defaultValue)
} else if g.repo.ahead > 0 && g.repo.behind > 0 {
return g.props.getColor(AheadAndBehindColor, defaultValue)
} else if g.repo.ahead > 0 {
return g.props.getColor(AheadColor, defaultValue)
} else if g.repo.behind > 0 {
return g.props.getColor(BehindColor, defaultValue)
}
return defaultValue
}

func (g *git) getGitCommandOutput(args ...string) string {
args = append([]string{"-c", "core.quotepath=false", "-c", "color.status=false"}, args...)
val, _ := g.env.runCommand("git", args...)
Expand Down Expand Up @@ -287,6 +327,7 @@ func (g *git) parseGitStats(output []string, working bool) *gitStatus {
status.modified++
}
}
status.changed = status.added > 0 || status.deleted > 0 || status.modified > 0 || status.unmerged > 0 || status.untracked > 0
return &status
}

Expand Down
161 changes: 161 additions & 0 deletions segment_git_test.go
Expand Up @@ -309,6 +309,7 @@ func TestParseGitStatsWorking(t *testing.T) {
assert.Equal(t, 1, status.added)
assert.Equal(t, 1, status.deleted)
assert.Equal(t, 2, status.untracked)
assert.True(t, status.changed)
}

func TestParseGitStatsStaging(t *testing.T) {
Expand All @@ -330,6 +331,7 @@ func TestParseGitStatsStaging(t *testing.T) {
assert.Equal(t, 1, status.added)
assert.Equal(t, 2, status.deleted)
assert.Equal(t, 1, status.untracked)
assert.True(t, status.changed)
}

func TestParseGitStatsNoChanges(t *testing.T) {
Expand All @@ -340,6 +342,7 @@ func TestParseGitStatsNoChanges(t *testing.T) {
}
status := g.parseGitStats(output, false)
assert.Equal(t, expected, status)
assert.False(t, status.changed)
}

func TestParseGitStatsInvalidLine(t *testing.T) {
Expand All @@ -351,6 +354,7 @@ func TestParseGitStatsInvalidLine(t *testing.T) {
}
status := g.parseGitStats(output, false)
assert.Equal(t, expected, status)
assert.False(t, status.changed)
}

func bootstrapUpstreamTest(upstream string) *git {
Expand Down Expand Up @@ -397,3 +401,160 @@ func TestGetUpstreamSymbolGit(t *testing.T) {
upstreamIcon := g.getUpstreamSymbol()
assert.Equal(t, "G", upstreamIcon)
}

func TestGetStatusColorLocalChangesStaging(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{
changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}

func TestGetStatusColorLocalChangesWorking(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{},
working: &gitStatus{
changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}

func TestGetStatusColorAheadAndBehind(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{},
working: &gitStatus{},
ahead: 1,
behind: 3,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
AheadAndBehindColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}

func TestGetStatusColorAhead(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{},
working: &gitStatus{},
ahead: 1,
behind: 0,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
AheadColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}

func TestGetStatusColorBehind(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{},
working: &gitStatus{},
ahead: 0,
behind: 5,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
BehindColor: expected,
},
},
}
assert.Equal(t, expected, g.getStatusColor("#fg1111"))
}

func TestGetStatusColorDefault(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{},
working: &gitStatus{},
ahead: 0,
behind: 0,
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
BehindColor: "#BD8BDE",
},
},
}
assert.Equal(t, expected, g.getStatusColor(expected))
}

func TestSetStatusColorBackground(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{
changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: "#BD8BDE",
ColorBackground: false,
},
foreground: "#ffffff",
background: "#111111",
},
}
g.SetStatusColor()
assert.Equal(t, expected, g.props.foreground)
}

func TestSetStatusColorForeground(t *testing.T) {
expected := "#BD8BDE"
repo := &gitRepo{
staging: &gitStatus{
changed: true,
},
}
g := &git{
repo: repo,
props: &properties{
values: map[Property]interface{}{
LocalChangesColor: "#BD8BDE",
ColorBackground: true,
},
foreground: "#ffffff",
background: "#111111",
},
}
g.SetStatusColor()
assert.Equal(t, expected, g.props.background)
}

0 comments on commit c418661

Please sign in to comment.