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)
string() string
reset()
setColors(background, foreground string)
setParentColors(background, foreground string)
}
@ -55,7 +56,8 @@ type AnsiColor struct {
builder strings.Builder
ansi *ansiUtils
terminalBackground string
Parent *Color
Colors *Color
ParentColors *Color
}
type Color struct {
@ -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,
}
@ -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 == 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
}
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

View file

@ -147,6 +147,36 @@ 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 {
@ -154,7 +184,8 @@ func TestWriteANSIColors(t *testing.T) {
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)

View file

@ -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) {
@ -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
@ -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)
@ -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)
}
@ -160,7 +165,7 @@ func (b *Block) renderPlainSegment(text string) {
}
func (b *Block) renderDiamondSegment(text string) {
background := b.activeSegment.background()
background := b.activeBackground
if background == Inherit {
background = b.previousActiveSegment.background()
}
@ -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) {
@ -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()