feat: git segment branch context color

This commit is contained in:
Jan De Dobbeleer 2020-10-18 19:27:20 +02:00 committed by Jan De Dobbeleer
parent 4e27952b3f
commit c41866171d
3 changed files with 217 additions and 5 deletions

View file

@ -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/

View file

@ -25,6 +25,7 @@ type gitStatus struct {
added int
modified int
untracked int
changed bool
}
func (s *gitStatus) string(prefix string, color string) string {
@ -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 {
@ -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) {
@ -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)
}
@ -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...)
@ -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
}

View file

@ -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) {
@ -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) {
@ -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) {
@ -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 {
@ -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)
}