feat: add inline background color syntax

This commit is contained in:
Spencer Hedrick 2020-11-21 02:27:29 -08:00 committed by Jan De Dobbeleer
parent c0fd060c89
commit 56778276b2
3 changed files with 77 additions and 8 deletions

View file

@ -200,8 +200,8 @@ segment's configuration will not render it when in that location. The engine wil
#### Colors #### Colors
You have the ability to override the foreground color for text in any property that accepts it. The syntax is custom but You have the ability to override the foreground and/or background color for text in any property that accepts it. The syntax is custom but
should be rather straighforward: `<#ffffff>this is white</> <#FF479C>but this is pink</>`. Anything between the color start should be rather straighforward: `<#ffffff,#000000>this is white with black background</> <#FF479C>but this is pink</>`. Anything between the color start
`<#FF479C>` and end `</>` will be colored accordingly. `<#FF479C>` and end `</>` will be colored accordingly.
For example, if you want `prefix` to print a colored bracket which isn't the same as the segment's `foreground`, you can For example, if you want `prefix` to print a colored bracket which isn't the same as the segment's `foreground`, you can
@ -211,6 +211,18 @@ do so like this:
"prefix": "<#CB4B16>┏[</>", "prefix": "<#CB4B16>┏[</>",
``` ```
If you also wanted to change the background color in the previous command, you would do so like this:
```json
"prefix": "<#CB4B16,#FFFFFF>┏[</>",
```
To change *only* the background color, just omit the first color from the above string:
```json
"prefix": "<,#FFFFFF>┏[</>",
```
Oh my Posh mainly supports three different color types being Oh my Posh mainly supports three different color types being
* Typical [hex colors][hexcolors] (for example `#CB4B16`). * Typical [hex colors][hexcolors] (for example `#CB4B16`).

View file

@ -146,19 +146,32 @@ func (r *Renderer) writeAndRemoveText(background, foreground, text, textToRemove
} }
func (r *Renderer) write(background, foreground, text string) { func (r *Renderer) write(background, foreground, text string) {
// first we match for any potentially valid color enclosed in <> // first we match for any potentially valid colors enclosed in <>
rex := regexp.MustCompile(`<([#A-Za-z0-9]+)>(.*?)<\/>`) rex := regexp.MustCompile(`<([#A-Za-z0-9]+)?(?:,([#A-Za-z0-9]+))?>(.*?)<\/>`)
match := rex.FindAllStringSubmatch(text, -1) match := rex.FindAllStringSubmatch(text, -1)
for i := range match { for i := range match {
extractedColor := match[i][1] extractedForegroundColor := match[i][1]
if col := r.getAnsiFromColorString(extractedColor, false); col == "" && extractedColor != Transparent { extractedBackgroundColor := match[i][2]
if col := r.getAnsiFromColorString(extractedForegroundColor, false); col == "" && extractedForegroundColor != Transparent && len(extractedBackgroundColor) == 0 {
continue // we skip invalid colors continue // we skip invalid colors
} }
if col := r.getAnsiFromColorString(extractedBackgroundColor, false); col == "" && extractedBackgroundColor != Transparent && len(extractedForegroundColor) == 0 {
continue // we skip invalid colors
}
// reuse function colors if only one was specified
if len(extractedBackgroundColor) == 0 {
extractedBackgroundColor = background
}
if len(extractedForegroundColor) == 0 {
extractedForegroundColor = foreground
}
escapedTextSegment := match[i][0] escapedTextSegment := match[i][0]
innerText := match[i][2] innerText := match[i][3]
textBeforeColorOverride := strings.Split(text, escapedTextSegment)[0] textBeforeColorOverride := strings.Split(text, escapedTextSegment)[0]
text = r.writeAndRemoveText(background, foreground, textBeforeColorOverride, textBeforeColorOverride, text) text = r.writeAndRemoveText(background, foreground, textBeforeColorOverride, textBeforeColorOverride, text)
text = r.writeAndRemoveText(background, extractedColor, innerText, escapedTextSegment, text) text = r.writeAndRemoveText(extractedBackgroundColor, extractedForegroundColor, innerText, escapedTextSegment, text)
} }
// color the remaining part of text with background and foreground // color the remaining part of text with background and foreground
r.writeColoredText(background, foreground, text) r.writeColoredText(background, foreground, text)

View file

@ -41,6 +41,50 @@ func TestWriteColorOverride(t *testing.T) {
assert.NotContains(t, renderer.string(), "<#ff5733>") assert.NotContains(t, renderer.string(), "<#ff5733>")
} }
func TestWriteColorOverrideBackground(t *testing.T) {
renderer := &Renderer{
Buffer: new(bytes.Buffer),
}
text := "This is white, <,#000000>this is black</>, white again"
renderer.init("pwsh")
renderer.write("#193549", "#ff5733", text)
assert.NotContains(t, renderer.string(), "000000")
}
func TestWriteColorOverrideBackground16(t *testing.T) {
renderer := &Renderer{
Buffer: new(bytes.Buffer),
}
text := "This is default <,white> this background is changed</> default again"
renderer.init("pwsh")
renderer.write("#193549", "#ff5733", text)
assert.NotContains(t, renderer.string(), "white")
assert.NotContains(t, renderer.string(), "</>")
assert.NotContains(t, renderer.string(), "<,")
}
func TestWriteColorOverrideBoth(t *testing.T) {
renderer := &Renderer{
Buffer: new(bytes.Buffer),
}
text := "This is white, <#000000,#ffffff>this is black</>, white again"
renderer.init("pwsh")
renderer.write("#193549", "#ff5733", text)
assert.NotContains(t, renderer.string(), "ffffff")
assert.NotContains(t, renderer.string(), "000000")
}
func TestWriteColorOverrideBoth16(t *testing.T) {
renderer := &Renderer{
Buffer: new(bytes.Buffer),
}
text := "This is white, <black,white>this is black</>, white again"
renderer.init("pwsh")
renderer.write("#193549", "#ff5733", text)
assert.NotContains(t, renderer.string(), "<black,white>")
assert.NotContains(t, renderer.string(), "</>")
}
func TestWriteColorTransparent(t *testing.T) { func TestWriteColorTransparent(t *testing.T) {
renderer := &Renderer{ renderer := &Renderer{
Buffer: new(bytes.Buffer), Buffer: new(bytes.Buffer),