From 850787cd6f1f116035245ca32034ba4c461c64ba Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Thu, 5 Jan 2023 12:46:15 +0100 Subject: [PATCH] refactor(ansi): write inverted colors correctly for transparency --- src/ansi/ansi_writer.go | 27 +++++++++++++++++++++----- src/ansi/ansi_writer_hyperlink_test.go | 4 ++-- src/ansi/ansi_writer_test.go | 4 ++-- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/ansi/ansi_writer.go b/src/ansi/ansi_writer.go index 1c31a688..c6a924b9 100644 --- a/src/ansi/ansi_writer.go +++ b/src/ansi/ansi_writer.go @@ -53,9 +53,10 @@ const ( // Foreground takes the current segment's foreground color Foreground = "foreground" - anchorRegex = `^(?P<(?P[^,>]+)?,?(?P[^>]+)?>)` - colorise = "\x1b[%sm" - transparent = "\x1b[%s;49m\x1b[7m" + anchorRegex = `^(?P<(?P[^,>]+)?,?(?P[^>]+)?>)` + colorise = "\x1b[%sm" + transparent = "\x1b[0m\x1b[%s;49m\x1b[7m" + transparentEnd = "\x1b[27m" AnsiRegex = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))" @@ -87,6 +88,7 @@ type Writer struct { currentForeground Color currentBackground Color runes []rune + transparent bool shell string format string @@ -363,11 +365,15 @@ func (w *Writer) writeSegmentColors() { fg = w.currentForeground } + // always reset inverted + // w.transparent = false + if fg.IsTransparent() && len(w.TerminalBackground) != 0 { background := w.getAnsiFromColorString(w.TerminalBackground, false) w.writeEscapedAnsiString(fmt.Sprintf(colorise, background)) w.writeEscapedAnsiString(fmt.Sprintf(colorise, bg.ToForeground())) } else if fg.IsTransparent() && !bg.IsEmpty() { + w.transparent = true w.writeEscapedAnsiString(fmt.Sprintf(transparent, bg)) } else { if !bg.IsEmpty() && !bg.IsTransparent() { @@ -393,12 +399,16 @@ func (w *Writer) writeColorOverrides(match map[string]string, background string, if position == len(w.runes)-1 { return } - if w.currentBackground != w.background { + if w.currentBackground != w.background || w.transparent { + if w.transparent { + w.writeEscapedAnsiString(transparentEnd) + } w.writeEscapedAnsiString(fmt.Sprintf(colorise, w.background)) } - if w.currentForeground != w.foreground { + if w.currentForeground != w.foreground || w.transparent { w.writeEscapedAnsiString(fmt.Sprintf(colorise, w.foreground)) } + w.transparent = false return } @@ -436,6 +446,7 @@ func (w *Writer) writeColorOverrides(match map[string]string, background string, } if w.currentForeground.IsTransparent() && !w.currentBackground.IsTransparent() { + w.transparent = true w.writeEscapedAnsiString(fmt.Sprintf(transparent, w.currentBackground)) return } @@ -457,6 +468,12 @@ func (w *Writer) writeColorOverrides(match map[string]string, background string, } func (w *Writer) asAnsiColors(background, foreground string) (Color, Color) { + if len(background) == 0 { + background = Background + } + if len(foreground) == 0 { + foreground = Foreground + } background = w.expandKeyword(background) foreground = w.expandKeyword(foreground) inverted := foreground == Transparent && len(background) != 0 diff --git a/src/ansi/ansi_writer_hyperlink_test.go b/src/ansi/ansi_writer_hyperlink_test.go index 01221935..bdd7eaf7 100644 --- a/src/ansi/ansi_writer_hyperlink_test.go +++ b/src/ansi/ansi_writer_hyperlink_test.go @@ -41,9 +41,9 @@ func TestGenerateHyperlinkWithUrl(t *testing.T) { Expected: "\x1b[47m\x1b[30m\x1b]8;;http://www.google.be\x1b\\google\x1b]8;;\x1b\\ \x1b]8;;http://maps.google.be\x1b\\maps (2/2)\x1b]8;;\x1b\\\x1b[0m", }, { - Text: "in \x1b[1mpwsh \x1b[22m ", + Text: "in pwsh ", ShellName: shell.PWSH, - Expected: "\x1b[47m\x1b[30min \x1b[1mpwsh \x1b[22m \x1b[0m", + Expected: "\x1b[47m\x1b[30min \x1b[0m\x1b[30m\x1b[1mpwsh \x1b[22m\x1b[47m \x1b[0m", }, {Text: "[google](http://www.google.be)", ShellName: shell.ZSH, Expected: "%{\x1b[47m%}%{\x1b[30m%}%{\x1b]8;;http://www.google.be\x1b\\%}google%{\x1b]8;;\x1b\\%}%{\x1b[0m%}"}, {Text: "[google](http://www.google.be)", ShellName: shell.PWSH, Expected: "\x1b[47m\x1b[30m\x1b]8;;http://www.google.be\x1b\\google\x1b]8;;\x1b\\\x1b[0m"}, diff --git a/src/ansi/ansi_writer_test.go b/src/ansi/ansi_writer_test.go index e5740102..dd8d9f11 100644 --- a/src/ansi/ansi_writer_test.go +++ b/src/ansi/ansi_writer_test.go @@ -93,7 +93,7 @@ func TestWriteANSIColors(t *testing.T) { { Case: "Inherit no parent foreground", Input: "hello world", - Expected: "\x1b[47m\x1b[30mhello \x1b[47;49m\x1b[7mworld\x1b[0m", + Expected: "\x1b[47m\x1b[30mhello \x1b[0m\x1b[37;49m\x1b[7mworld\x1b[0m", Colors: &cachedColor{Foreground: "black", Background: "white"}, }, { @@ -143,7 +143,7 @@ func TestWriteANSIColors(t *testing.T) { { Case: "Transparent foreground", Input: "test", - Expected: "\x1b[38;2;255;87;51;49m\x1b[7mtest\x1b[0m", + Expected: "\x1b[0m\x1b[38;2;255;87;51;49m\x1b[7mtest\x1b[0m", Colors: &cachedColor{Foreground: Transparent, Background: "#FF5733"}, }, {