feat(colors): current color override

relates to #1099
This commit is contained in:
Jan De Dobbeleer 2021-10-25 19:22:58 +02:00 committed by Jan De Dobbeleer
parent 224bc0a5b2
commit d84b92ef13
3 changed files with 79 additions and 20 deletions

View file

@ -47,6 +47,7 @@ type colorWriter interface {
write(background, foreground, text string) write(background, foreground, text string)
string() string string() string
reset() reset()
setColors(background, foreground string)
setParentColors(background, foreground string) setParentColors(background, foreground string)
} }
@ -55,7 +56,8 @@ type AnsiColor struct {
builder strings.Builder builder strings.Builder
ansi *ansiUtils ansi *ansiUtils
terminalBackground string terminalBackground string
Parent *Color Colors *Color
ParentColors *Color
} }
type Color struct { type Color struct {
@ -66,12 +68,23 @@ type Color struct {
const ( const (
// Transparent implies a transparent color // Transparent implies a transparent color
Transparent = "transparent" Transparent = "transparent"
// Inherit take the previous segment's color // Inherit takes the previous segment's color
Inherit = "inherit" 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) { func (a *AnsiColor) setParentColors(background, foreground string) {
a.Parent = &Color{ a.ParentColors = &Color{
Background: background, Background: background,
Foreground: foreground, Foreground: foreground,
} }
@ -134,16 +147,28 @@ func (a *AnsiColor) write(background, foreground, text string) {
} }
getAnsiColors := func(background, foreground string) (string, string) { getAnsiColors := func(background, foreground string) (string, string) {
if background == Inherit && a.Parent != nil { if background == Background {
background = a.Parent.Background background = a.Colors.Background
} }
if background == Inherit && a.Parent == nil { 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.ParentColors == nil {
background = Transparent background = Transparent
} }
if foreground == Inherit && a.Parent != nil { if foreground == Inherit && a.ParentColors != nil {
foreground = a.Parent.Foreground foreground = a.ParentColors.Foreground
} }
if foreground == Inherit && a.Parent == nil { if foreground == Inherit && a.ParentColors == nil {
foreground = Transparent foreground = Transparent
} }
inverted := foreground == Transparent && len(background) != 0 inverted := foreground == Transparent && len(background) != 0

View file

@ -147,6 +147,36 @@ func TestWriteANSIColors(t *testing.T) {
Colors: &Color{Foreground: Transparent, Background: "#FF5733"}, Colors: &Color{Foreground: Transparent, Background: "#FF5733"},
TerminalBackground: "#212F3C", 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 { for _, tc := range cases {
@ -154,7 +184,8 @@ func TestWriteANSIColors(t *testing.T) {
ansi.init("pwsh") ansi.init("pwsh")
renderer := &AnsiColor{ renderer := &AnsiColor{
ansi: ansi, ansi: ansi,
Parent: tc.Parent, ParentColors: tc.Parent,
Colors: tc.Colors,
terminalBackground: tc.TerminalBackground, terminalBackground: tc.TerminalBackground,
} }
renderer.write(tc.Colors.Background, tc.Colors.Foreground, tc.Input) renderer.write(tc.Colors.Background, tc.Colors.Foreground, tc.Input)

View file

@ -38,6 +38,8 @@ type Block struct {
ansi *ansiUtils ansi *ansiUtils
activeSegment *Segment activeSegment *Segment
previousActiveSegment *Segment previousActiveSegment *Segment
activeBackground string
activeForeground string
} }
func (b *Block) init(env environmentInfo, writer colorWriter, ansi *ansiUtils) { func (b *Block) init(env environmentInfo, writer colorWriter, ansi *ansiUtils) {
@ -126,7 +128,7 @@ func (b *Block) getPowerlineColor(foreground bool) string {
return b.previousActiveSegment.background() return b.previousActiveSegment.background()
} }
if b.activeSegment.Style == Diamond && len(b.activeSegment.LeadingDiamond) == 0 { if b.activeSegment.Style == Diamond && len(b.activeSegment.LeadingDiamond) == 0 {
return b.activeSegment.background() return b.activeBackground
} }
if !foreground && b.activeSegment.Style != Powerline { if !foreground && b.activeSegment.Style != Powerline {
return Transparent return Transparent
@ -138,6 +140,9 @@ func (b *Block) getPowerlineColor(foreground bool) string {
} }
func (b *Block) renderSegmentText(text 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 { switch b.activeSegment.Style {
case Plain: case Plain:
b.renderPlainSegment(text) b.renderPlainSegment(text)
@ -147,11 +152,11 @@ func (b *Block) renderSegmentText(text string) {
b.renderPowerLineSegment(text) b.renderPowerLineSegment(text)
} }
b.previousActiveSegment = b.activeSegment 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) { 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) b.renderText(text)
} }
@ -160,7 +165,7 @@ func (b *Block) renderPlainSegment(text string) {
} }
func (b *Block) renderDiamondSegment(text string) { func (b *Block) renderDiamondSegment(text string) {
background := b.activeSegment.background() background := b.activeBackground
if background == Inherit { if background == Inherit {
background = b.previousActiveSegment.background() background = b.previousActiveSegment.background()
} }
@ -170,12 +175,10 @@ func (b *Block) renderDiamondSegment(text string) {
} }
func (b *Block) renderText(text string) { func (b *Block) renderText(text string) {
bg := b.activeSegment.background()
fg := b.activeSegment.foreground()
defaultValue := " " defaultValue := " "
b.writer.write(bg, fg, b.activeSegment.getValue(Prefix, defaultValue)) b.writer.write(b.activeBackground, b.activeForeground, b.activeSegment.getValue(Prefix, defaultValue))
b.writer.write(bg, fg, text) b.writer.write(b.activeBackground, b.activeForeground, text)
b.writer.write(bg, fg, b.activeSegment.getValue(Postfix, defaultValue)) b.writer.write(b.activeBackground, b.activeForeground, b.activeSegment.getValue(Postfix, defaultValue))
} }
func (b *Block) debug() (int, []*SegmentTiming) { func (b *Block) debug() (int, []*SegmentTiming) {
@ -205,7 +208,7 @@ func (b *Block) debug() (int, []*SegmentTiming) {
b.activeSegment = segment b.activeSegment = segment
b.renderSegmentText(segmentTiming.stringValue) b.renderSegmentText(segmentTiming.stringValue)
if b.activeSegment.Style == Powerline { if b.activeSegment.Style == Powerline {
b.writePowerLineSeparator(Transparent, b.activeSegment.background(), true) b.writePowerLineSeparator(Transparent, b.activeBackground, true)
} }
segmentTiming.stringValue = b.writer.string() segmentTiming.stringValue = b.writer.string()
b.writer.reset() b.writer.reset()