mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-03-05 20:49:04 -08:00
refactor: color logic performance
This commit is contained in:
parent
fa782250dd
commit
b3f537cb76
|
@ -67,6 +67,9 @@ const (
|
||||||
// This can include a valid hex color in the format `#FFFFFF`,
|
// This can include a valid hex color in the format `#FFFFFF`,
|
||||||
// but also a name of one of the first 16 ANSI colors like `lightBlue`.
|
// but also a name of one of the first 16 ANSI colors like `lightBlue`.
|
||||||
func (a *AnsiColor) getAnsiFromColorString(colorString string, isBackground bool) string {
|
func (a *AnsiColor) getAnsiFromColorString(colorString string, isBackground bool) string {
|
||||||
|
if colorString == Transparent || len(colorString) == 0 {
|
||||||
|
return colorString
|
||||||
|
}
|
||||||
colorFromName, err := getColorFromName(colorString, isBackground)
|
colorFromName, err := getColorFromName(colorString, isBackground)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return colorFromName
|
return colorFromName
|
||||||
|
@ -83,27 +86,26 @@ func (a *AnsiColor) writeColoredText(background, foreground, text string) {
|
||||||
if text == "" {
|
if text == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if foreground == Transparent && background != "" && a.terminalBackground != "" {
|
// default to white fg if empty, empty backgrond is supported
|
||||||
bgAnsiColor := a.getAnsiFromColorString(background, true)
|
if len(foreground) == 0 {
|
||||||
|
foreground = a.getAnsiFromColorString("white", false)
|
||||||
|
}
|
||||||
|
if foreground == Transparent && len(background) != 0 && len(a.terminalBackground) != 0 {
|
||||||
fgAnsiColor := a.getAnsiFromColorString(a.terminalBackground, false)
|
fgAnsiColor := a.getAnsiFromColorString(a.terminalBackground, false)
|
||||||
coloredText := fmt.Sprintf(a.ansi.colorFull, bgAnsiColor, fgAnsiColor, text)
|
coloredText := fmt.Sprintf(a.ansi.colorFull, background, fgAnsiColor, text)
|
||||||
a.builder.WriteString(coloredText)
|
a.builder.WriteString(coloredText)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if foreground == Transparent && background != "" {
|
if foreground == Transparent && len(background) != 0 {
|
||||||
ansiColor := a.getAnsiFromColorString(background, false)
|
coloredText := fmt.Sprintf(a.ansi.colorTransparent, background, text)
|
||||||
coloredText := fmt.Sprintf(a.ansi.colorTransparent, ansiColor, text)
|
|
||||||
a.builder.WriteString(coloredText)
|
a.builder.WriteString(coloredText)
|
||||||
return
|
return
|
||||||
} else if background == "" || background == Transparent {
|
} else if len(background) == 0 || background == Transparent {
|
||||||
ansiColor := a.getAnsiFromColorString(foreground, false)
|
coloredText := fmt.Sprintf(a.ansi.colorSingle, foreground, text)
|
||||||
coloredText := fmt.Sprintf(a.ansi.colorSingle, ansiColor, text)
|
|
||||||
a.builder.WriteString(coloredText)
|
a.builder.WriteString(coloredText)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bgAnsiColor := a.getAnsiFromColorString(background, true)
|
coloredText := fmt.Sprintf(a.ansi.colorFull, background, foreground, text)
|
||||||
fgAnsiColor := a.getAnsiFromColorString(foreground, false)
|
|
||||||
coloredText := fmt.Sprintf(a.ansi.colorFull, bgAnsiColor, fgAnsiColor, text)
|
|
||||||
a.builder.WriteString(coloredText)
|
a.builder.WriteString(coloredText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +118,16 @@ func (a *AnsiColor) write(background, foreground, text string) {
|
||||||
if len(text) == 0 {
|
if len(text) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAnsiColors := func(background, foreground string) (string, string) {
|
||||||
|
inverted := foreground == Transparent && len(background) != 0
|
||||||
|
background = a.getAnsiFromColorString(background, !inverted)
|
||||||
|
foreground = a.getAnsiFromColorString(foreground, false)
|
||||||
|
return background, foreground
|
||||||
|
}
|
||||||
|
|
||||||
|
bgAnsi, fgAnsi := getAnsiColors(background, foreground)
|
||||||
|
|
||||||
text = a.ansi.escapeText(text)
|
text = a.ansi.escapeText(text)
|
||||||
text = a.ansi.formatText(text)
|
text = a.ansi.formatText(text)
|
||||||
text = a.ansi.generateHyperlink(text)
|
text = a.ansi.generateHyperlink(text)
|
||||||
|
@ -123,29 +135,27 @@ func (a *AnsiColor) write(background, foreground, text string) {
|
||||||
// first we match for any potentially valid colors enclosed in <>
|
// first we match for any potentially valid colors enclosed in <>
|
||||||
match := findAllNamedRegexMatch(`<(?P<foreground>[^,>]+)?,?(?P<background>[^>]+)?>(?P<content>[^<]*)<\/>`, text)
|
match := findAllNamedRegexMatch(`<(?P<foreground>[^,>]+)?,?(?P<background>[^>]+)?>(?P<content>[^<]*)<\/>`, text)
|
||||||
for i := range match {
|
for i := range match {
|
||||||
extractedForegroundColor := match[i]["foreground"]
|
fg := match[i]["foreground"]
|
||||||
extractedBackgroundColor := match[i]["background"]
|
bg := match[i]["background"]
|
||||||
if col := a.getAnsiFromColorString(extractedForegroundColor, false); col == "" && extractedForegroundColor != Transparent && len(extractedBackgroundColor) == 0 {
|
if fg == Transparent && len(bg) == 0 {
|
||||||
continue // we skip invalid colors
|
bg = background
|
||||||
}
|
}
|
||||||
if col := a.getAnsiFromColorString(extractedBackgroundColor, false); col == "" && extractedBackgroundColor != Transparent && len(extractedForegroundColor) == 0 {
|
bg, fg = getAnsiColors(bg, fg)
|
||||||
continue // we skip invalid colors
|
// set colors if they are empty
|
||||||
|
if len(bg) == 0 {
|
||||||
|
bg = bgAnsi
|
||||||
}
|
}
|
||||||
// reuse function colors if only one was specified
|
if len(fg) == 0 {
|
||||||
if len(extractedBackgroundColor) == 0 {
|
fg = fgAnsi
|
||||||
extractedBackgroundColor = background
|
|
||||||
}
|
|
||||||
if len(extractedForegroundColor) == 0 {
|
|
||||||
extractedForegroundColor = foreground
|
|
||||||
}
|
}
|
||||||
escapedTextSegment := match[i]["text"]
|
escapedTextSegment := match[i]["text"]
|
||||||
innerText := match[i]["content"]
|
innerText := match[i]["content"]
|
||||||
textBeforeColorOverride := strings.Split(text, escapedTextSegment)[0]
|
textBeforeColorOverride := strings.Split(text, escapedTextSegment)[0]
|
||||||
text = a.writeAndRemoveText(background, foreground, textBeforeColorOverride, textBeforeColorOverride, text)
|
text = a.writeAndRemoveText(bgAnsi, fgAnsi, textBeforeColorOverride, textBeforeColorOverride, text)
|
||||||
text = a.writeAndRemoveText(extractedBackgroundColor, extractedForegroundColor, innerText, escapedTextSegment, text)
|
text = a.writeAndRemoveText(bg, fg, innerText, escapedTextSegment, text)
|
||||||
}
|
}
|
||||||
// color the remaining part of text with background and foreground
|
// color the remaining part of text with background and foreground
|
||||||
a.writeColoredText(background, foreground, text)
|
a.writeColoredText(bgAnsi, fgAnsi, text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AnsiColor) string() string {
|
func (a *AnsiColor) string() string {
|
||||||
|
|
|
@ -133,7 +133,7 @@ func TestWriteColorInvalid(t *testing.T) {
|
||||||
}
|
}
|
||||||
text := "This is white, <invalid>this is orange</>, white again"
|
text := "This is white, <invalid>this is orange</>, white again"
|
||||||
renderer.write("#193549", "invalid", text)
|
renderer.write("#193549", "invalid", text)
|
||||||
assert.Contains(t, renderer.string(), "<invalid>")
|
assert.NotContains(t, renderer.string(), "<invalid>")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetAnsiFromColorStringBg(t *testing.T) {
|
func TestGetAnsiFromColorStringBg(t *testing.T) {
|
||||||
|
|
10
src/block.go
10
src/block.go
|
@ -82,17 +82,19 @@ func (b *Block) setStringValues() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) foreground() string {
|
func (b *Block) foreground() string {
|
||||||
if b.previousActiveSegment != nil && b.activeSegment.foreground() == Inherit {
|
color := b.activeSegment.foreground()
|
||||||
|
if b.previousActiveSegment != nil && color == Inherit {
|
||||||
return b.previousActiveSegment.foreground()
|
return b.previousActiveSegment.foreground()
|
||||||
}
|
}
|
||||||
return b.activeSegment.foreground()
|
return color
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) background() string {
|
func (b *Block) background() string {
|
||||||
if b.previousActiveSegment != nil && b.activeSegment.background() == Inherit {
|
color := b.activeSegment.background()
|
||||||
|
if b.previousActiveSegment != nil && color == Inherit {
|
||||||
return b.previousActiveSegment.background()
|
return b.previousActiveSegment.background()
|
||||||
}
|
}
|
||||||
return b.activeSegment.background()
|
return color
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Block) renderSegments() string {
|
func (b *Block) renderSegments() string {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
|
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
|
||||||
|
"final_space": true,
|
||||||
"blocks": [
|
"blocks": [
|
||||||
{
|
{
|
||||||
"type": "prompt",
|
"type": "prompt",
|
||||||
|
@ -176,16 +177,6 @@
|
||||||
"text": "\u276F",
|
"text": "\u276F",
|
||||||
"postfix": ""
|
"postfix": ""
|
||||||
}
|
}
|
||||||
},
|
|
||||||
{
|
|
||||||
"type":"text",
|
|
||||||
"style": "plain",
|
|
||||||
"foreground": "transparent",
|
|
||||||
"properties": {
|
|
||||||
"prefix": "",
|
|
||||||
"text": " ",
|
|
||||||
"postfix": ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue