Skip to content

Commit

Permalink
feat(colors): current color override
Browse files Browse the repository at this point in the history
relates to #1099
  • Loading branch information
JanDeDobbeleer committed Oct 25, 2021
1 parent 224bc0a commit d84b92e
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 20 deletions.
43 changes: 34 additions & 9 deletions src/ansi_color.go
Expand Up @@ -47,6 +47,7 @@ type colorWriter interface {
write(background, foreground, text string)
string() string
reset()
setColors(background, foreground string)
setParentColors(background, foreground string)
}

Expand All @@ -55,7 +56,8 @@ type AnsiColor struct {
builder strings.Builder
ansi *ansiUtils
terminalBackground string
Parent *Color
Colors *Color
ParentColors *Color
}

type Color struct {
Expand All @@ -66,12 +68,23 @@ type Color struct {
const (
// Transparent implies a transparent color
Transparent = "transparent"
// Inherit take the previous segment's color
// Inherit takes the previous segment's color
Inherit = "inherit"
// Background takes the current segment's background color
Background = "background"
// Foreground takes the current segment's foreground color
Foreground = "foreground"
)

func (a *AnsiColor) setColors(background, foreground string) {
a.Colors = &Color{
Background: background,
Foreground: foreground,
}
}

func (a *AnsiColor) setParentColors(background, foreground string) {
a.Parent = &Color{
a.ParentColors = &Color{
Background: background,
Foreground: foreground,
}
Expand Down Expand Up @@ -134,16 +147,28 @@ func (a *AnsiColor) write(background, foreground, text string) {
}

getAnsiColors := func(background, foreground string) (string, string) {
if background == Inherit && a.Parent != nil {
background = a.Parent.Background
if background == Background {
background = a.Colors.Background
}
if background == Foreground {
background = a.Colors.Foreground
}
if foreground == Foreground {
foreground = a.Colors.Foreground
}
if foreground == Background {
foreground = a.Colors.Background
}
if background == Inherit && a.ParentColors != nil {
background = a.ParentColors.Background
}
if background == Inherit && a.Parent == nil {
if background == Inherit && a.ParentColors == nil {
background = Transparent
}
if foreground == Inherit && a.Parent != nil {
foreground = a.Parent.Foreground
if foreground == Inherit && a.ParentColors != nil {
foreground = a.ParentColors.Foreground
}
if foreground == Inherit && a.Parent == nil {
if foreground == Inherit && a.ParentColors == nil {
foreground = Transparent
}
inverted := foreground == Transparent && len(background) != 0
Expand Down
33 changes: 32 additions & 1 deletion src/ansi_color_test.go
Expand Up @@ -147,14 +147,45 @@ func TestWriteANSIColors(t *testing.T) {
Colors: &Color{Foreground: Transparent, Background: "#FF5733"},
TerminalBackground: "#212F3C",
},
{
Case: "Foreground for foreground override",
Input: "<foreground>test</>",
Expected: "\x1b[47m\x1b[30mtest\x1b[0m",
Colors: &Color{Foreground: "black", Background: "white"},
},
{
Case: "Foreground for background override",
Input: "<background>test</>",
Expected: "\x1b[47m\x1b[37mtest\x1b[0m",
Colors: &Color{Foreground: "black", Background: "white"},
},
{
Case: "Foreground for background vice versa override",
Input: "<background,foreground>test</>",
Expected: "\x1b[40m\x1b[37mtest\x1b[0m",
Colors: &Color{Foreground: "black", Background: "white"},
},
{
Case: "Background for background override",
Input: "<,background>test</>",
Expected: "\x1b[47m\x1b[30mtest\x1b[0m",
Colors: &Color{Foreground: "black", Background: "white"},
},
{
Case: "Background for foreground override",
Input: "<,foreground>test</>",
Expected: "\x1b[40m\x1b[30mtest\x1b[0m",
Colors: &Color{Foreground: "black", Background: "white"},
},
}

for _, tc := range cases {
ansi := &ansiUtils{}
ansi.init("pwsh")
renderer := &AnsiColor{
ansi: ansi,
Parent: tc.Parent,
ParentColors: tc.Parent,
Colors: tc.Colors,
terminalBackground: tc.TerminalBackground,
}
renderer.write(tc.Colors.Background, tc.Colors.Foreground, tc.Input)
Expand Down
23 changes: 13 additions & 10 deletions src/block.go
Expand Up @@ -38,6 +38,8 @@ type Block struct {
ansi *ansiUtils
activeSegment *Segment
previousActiveSegment *Segment
activeBackground string
activeForeground string
}

func (b *Block) init(env environmentInfo, writer colorWriter, ansi *ansiUtils) {
Expand Down Expand Up @@ -126,7 +128,7 @@ func (b *Block) getPowerlineColor(foreground bool) string {
return b.previousActiveSegment.background()
}
if b.activeSegment.Style == Diamond && len(b.activeSegment.LeadingDiamond) == 0 {
return b.activeSegment.background()
return b.activeBackground
}
if !foreground && b.activeSegment.Style != Powerline {
return Transparent
Expand All @@ -138,6 +140,9 @@ func (b *Block) getPowerlineColor(foreground bool) string {
}

func (b *Block) renderSegmentText(text string) {
b.activeBackground = b.activeSegment.background()
b.activeForeground = b.activeSegment.foreground()
b.writer.setColors(b.activeBackground, b.activeForeground)
switch b.activeSegment.Style {
case Plain:
b.renderPlainSegment(text)
Expand All @@ -147,11 +152,11 @@ func (b *Block) renderSegmentText(text string) {
b.renderPowerLineSegment(text)
}
b.previousActiveSegment = b.activeSegment
b.writer.setParentColors(b.activeSegment.background(), b.activeSegment.foreground())
b.writer.setParentColors(b.activeBackground, b.activeForeground)
}

func (b *Block) renderPowerLineSegment(text string) {
b.writePowerLineSeparator(b.activeSegment.background(), b.getPowerlineColor(true), false)
b.writePowerLineSeparator(b.activeBackground, b.getPowerlineColor(true), false)
b.renderText(text)
}

Expand All @@ -160,7 +165,7 @@ func (b *Block) renderPlainSegment(text string) {
}

func (b *Block) renderDiamondSegment(text string) {
background := b.activeSegment.background()

This comment has been minimized.

Copy link
@lnu

lnu Oct 27, 2021

Contributor

I have an issue with this change. I have a custom theme and the last diamond segment of the left prompt was rendered like this:
image

and now:
image

If I revert only this line, all tests are successfull and my current theme is still working.

https://gist.github.com/lnu/191c4e726468b0f7ad8899feb2192ee2#file-jandedobbeleer_custom-json

This comment has been minimized.

Copy link
@JanDeDobbeleer

JanDeDobbeleer Oct 27, 2021

Author Owner

@lnu I'm trying to understand why that would change anything. We set that variable here: activeBackground and then immediately go to renderDiamondSegment which should then take the same content. What am I missing?

This comment has been minimized.

Copy link
@lnu

lnu Oct 27, 2021

Contributor

At some point, the color between b.activeSegment.background() is different than b.activebackground. I’ll try to see what happens.

This comment has been minimized.

Copy link
@JanDeDobbeleer

JanDeDobbeleer Oct 27, 2021

Author Owner

But there's nothing in between that point (at least according to what I can see). It's a straight path down. Yet something did change :-)

This comment has been minimized.

Copy link
@lnu

lnu Oct 27, 2021

Contributor

image

This comment has been minimized.

Copy link
@lnu

lnu Oct 27, 2021

Contributor

should we do something like this:
image

?

This comment has been minimized.

Copy link
@JanDeDobbeleer

JanDeDobbeleer Oct 27, 2021

Author Owner

That could also work, it's at the same time and the string is set meaning everything is in place to render the colors.

background := b.activeBackground
if background == Inherit {
background = b.previousActiveSegment.background()
}
Expand All @@ -170,12 +175,10 @@ func (b *Block) renderDiamondSegment(text string) {
}

func (b *Block) renderText(text string) {
bg := b.activeSegment.background()
fg := b.activeSegment.foreground()
defaultValue := " "
b.writer.write(bg, fg, b.activeSegment.getValue(Prefix, defaultValue))
b.writer.write(bg, fg, text)
b.writer.write(bg, fg, b.activeSegment.getValue(Postfix, defaultValue))
b.writer.write(b.activeBackground, b.activeForeground, b.activeSegment.getValue(Prefix, defaultValue))
b.writer.write(b.activeBackground, b.activeForeground, text)
b.writer.write(b.activeBackground, b.activeForeground, b.activeSegment.getValue(Postfix, defaultValue))
}

func (b *Block) debug() (int, []*SegmentTiming) {
Expand Down Expand Up @@ -205,7 +208,7 @@ func (b *Block) debug() (int, []*SegmentTiming) {
b.activeSegment = segment
b.renderSegmentText(segmentTiming.stringValue)
if b.activeSegment.Style == Powerline {
b.writePowerLineSeparator(Transparent, b.activeSegment.background(), true)
b.writePowerLineSeparator(Transparent, b.activeBackground, true)
}
segmentTiming.stringValue = b.writer.string()
b.writer.reset()
Expand Down

0 comments on commit d84b92e

Please sign in to comment.