mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-01-26 02:21:25 -08:00
parent
aa36303962
commit
00e62e4810
|
@ -103,8 +103,8 @@ understand how to configure a segment.
|
|||
- invert_powerline: `boolean`
|
||||
- leading_diamond: `string`
|
||||
- trailing_diamond: `string`
|
||||
- foreground: `string` [hex color code][colors]
|
||||
- background: `string` [hex color code][colors]
|
||||
- foreground: `string` [color][colors]
|
||||
- background: `string` [color][colors]
|
||||
- properties: `array` of `Property`: `string`
|
||||
|
||||
### Type
|
||||
|
@ -205,8 +205,21 @@ do so like this:
|
|||
"prefix": "<#CB4B16>┏[</>",
|
||||
```
|
||||
|
||||
Oh my Posh offers support for hex [colors][colors] as well as the `transparent` keyword to create either a transparent foreground
|
||||
override or transparent background color using the segement's [foreground][fg] property.
|
||||
Oh my Posh mainly supports three different color types being
|
||||
* Typical [hex colors][hexcolors] (for example `#CB4B16`).
|
||||
|
||||
* The `transparent` keyword which can be used to create either a transparent foreground override
|
||||
or transparent background color using the segement's foreground property.
|
||||
|
||||
* 16 [ANSI color names][ansicolors].
|
||||
|
||||
These include 8 basic ANSI colors and `default`:
|
||||
|
||||
`black` `red` `green` `yellow` `blue` `magenta` `cyan` `white` `default`
|
||||
|
||||
as well as 8 extended ANSI colors:
|
||||
|
||||
`darkGray` `lightRed` `lightGreen` `lightYellow` `lightBlue` `lightMagenta` `lightCyan` `lightWhite`
|
||||
|
||||
## Full Sample
|
||||
|
||||
|
@ -294,5 +307,7 @@ override or transparent background color using the segement's [foreground][fg] p
|
|||
[releases]: https://github.com/JanDeDobbeleer/oh-my-posh3/releases/latest
|
||||
[nf]: https://www.nerdfonts.com/
|
||||
[segments]: /docs/battery
|
||||
[colors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[colors]: #colors
|
||||
[hexcolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[ansicolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[fg]: /docs/configure#foreground
|
||||
|
|
|
@ -39,8 +39,8 @@ Battery displays the remaining power percentage for your battery.
|
|||
- discharging_icon: `string` - icon to display on the left when discharging - defaults to empty
|
||||
- charged_icon: `string` - icon to display on the left when fully charged - defaults to empty
|
||||
- color_background: `boolean` - color the background or foreground for properties below - defaults to `false`
|
||||
- charged_color: `string` [hex color code][colors] - color to use when fully charged - defaults to segment color
|
||||
- charging_color: `string` [hex color code][colors] - color to use when charging - defaults to segment color
|
||||
- discharging_color: `string` [hex color code][colors] - color to use when discharging - defaults to segment color
|
||||
- charged_color: `string` [color][colors] - color to use when fully charged - defaults to segment color
|
||||
- charging_color: `string` [color][colors] - color to use when charging - defaults to segment color
|
||||
- discharging_color: `string` [color][colors] - color to use when discharging - defaults to segment color
|
||||
|
||||
[colors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[colors]: /docs/configure#colors
|
||||
|
|
|
@ -33,6 +33,6 @@ Displays the last exit code or that the last command failed based on the configu
|
|||
- display_exit_code: `boolean` - show or hide the exit code - defaults to `true`
|
||||
- always_enabled: `boolean` - always show the status - defaults to `false`
|
||||
- color_background: `boolean` - color the background or foreground when an error occurs - defaults to `false`
|
||||
- error_color: `string` [hex color code][colors] - color to use when an error occured
|
||||
- error_color: `string` [color][colors] - color to use when an error occured
|
||||
|
||||
[colors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[colors]: /docs/configure#colors
|
||||
|
|
|
@ -67,17 +67,17 @@ Local changes can also shown by default using the following syntax for both the
|
|||
|
||||
### Colors
|
||||
|
||||
- working_color: `string` [hex color code][colors] - foreground color for the working area status - defaults to segment foreground
|
||||
- staging_color: `string` [hex color code][colors] - foreground color for the staging area status - defaults to segment foreground
|
||||
- working_color: `string` [color][colors] - foreground color for the working area status - defaults to segment foreground
|
||||
- staging_color: `string` [color][colors] - foreground color for the staging area status - defaults to segment foreground
|
||||
- status_colors_enabled: `boolean` - color the segment based on the repository status - defaults to `false`
|
||||
- color_background: `boolean` - color background or foreground - defaults to `true`
|
||||
- local_changes_color: `string` [hex color code][colors] - segment color when there are local changes - defaults to segment
|
||||
- local_changes_color: `string` [color][colors] - segment color when there are local changes - defaults to segment
|
||||
foreground/background (see `color_background`)
|
||||
- ahead_and_behind_color: `string` [hex color code][colors] - segment color when the branch is ahead and behind -
|
||||
- ahead_and_behind_color: `string` [color][colors] - segment color when the branch is ahead and behind -
|
||||
defaults to segment foreground/background (see `color_background`)
|
||||
- behind_color: `string` [hex color code][colors] - segment color when the branch is behind - defaults to segment
|
||||
- behind_color: `string` [color][colors] - segment color when the branch is behind - defaults to segment
|
||||
foreground/background (see `color_background`)
|
||||
- ahead_color: `string` [hex color code][colors] - segment color when the branch is ahead - defaults to segment
|
||||
- ahead_color: `string` [color][colors] - segment color when the branch is ahead - defaults to segment
|
||||
foreground/background (see `color_background`)
|
||||
|
||||
[colors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[colors]: /docs/configure#colors
|
||||
|
|
|
@ -26,9 +26,9 @@ Show the current user and host name.
|
|||
- user_info_separator: `string` - text/icon to put in between the user and host name - defaults to `@`
|
||||
- ssh_icon: `string` - text/icon to display first when in an active SSH session - defaults
|
||||
to `\uF817 `
|
||||
- user_color: `string` [hex color code][colors] - override the foreground color of the user name
|
||||
- host_color: `string` [hex color code][colors] - override the foreground color of the host name
|
||||
- user_color: `string` [color][colors] - override the foreground color of the user name
|
||||
- host_color: `string` [color][colors] - override the foreground color of the host name
|
||||
- display_user: `boolean` - display the user name or not - defaults to `true`
|
||||
- display_host: `boolean` - display the host name or not - defaults to `true`
|
||||
|
||||
[colors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[colors]: /docs/configure#colors
|
||||
|
|
|
@ -12,7 +12,7 @@ const features = [
|
|||
description: (
|
||||
<>
|
||||
Oh my Posh enables you to use the full color set of your terminal
|
||||
by using hex colors to define and render the prompt.
|
||||
by using colors to define and render the prompt.
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
|
69
renderer.go
69
renderer.go
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
@ -23,6 +24,41 @@ type formats struct {
|
|||
clearOEL string
|
||||
}
|
||||
|
||||
var (
|
||||
// Map for color names and their respective foreground [0] or background [1] color codes
|
||||
ColorMap map[string][2]string = map[string][2]string {
|
||||
"black": [2]string { "30", "40" },
|
||||
"red": [2]string { "31", "41" },
|
||||
"green": [2]string { "32", "42" },
|
||||
"yellow": [2]string { "33", "43" },
|
||||
"blue": [2]string { "34", "44" },
|
||||
"magenta": [2]string { "35", "45" },
|
||||
"cyan": [2]string { "36", "46" },
|
||||
"white": [2]string { "37", "47" },
|
||||
"default": [2]string { "39", "49" },
|
||||
"darkGray": [2]string { "90", "100" },
|
||||
"lightRed": [2]string { "91", "101" },
|
||||
"lightGreen": [2]string { "92", "102" },
|
||||
"lightYellow": [2]string { "93", "103" },
|
||||
"lightBlue": [2]string { "94", "104" },
|
||||
"lightMagenta": [2]string { "95", "105" },
|
||||
"lightCyan": [2]string { "96", "106" },
|
||||
"lightWhite": [2]string { "97", "107" },
|
||||
}
|
||||
)
|
||||
|
||||
// Returns the color code for a given color name
|
||||
func getColorFromName(colorName string, isBackground bool) (string, error) {
|
||||
colorMapOffset := 0
|
||||
if isBackground {
|
||||
colorMapOffset = 1
|
||||
}
|
||||
if colorCodes, found := ColorMap[colorName]; found {
|
||||
return colorCodes[colorMapOffset], nil
|
||||
}
|
||||
return "", errors.New("This color name does not exist.")
|
||||
}
|
||||
|
||||
//Renderer writes colorized strings
|
||||
type Renderer struct {
|
||||
Buffer *bytes.Buffer
|
||||
|
@ -74,22 +110,29 @@ func (r *Renderer) init(shell string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Renderer) getAnsiFromHex(hexColor string, isBackground bool) string {
|
||||
style := color.HEX(hexColor, isBackground)
|
||||
// Gets the ANSI color code for a given color string.
|
||||
// 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`.
|
||||
func (r *Renderer) getAnsiFromColorString(colorString string, isBackground bool) string {
|
||||
colorFromName, err := getColorFromName(colorString, isBackground)
|
||||
if err == nil {
|
||||
return colorFromName
|
||||
}
|
||||
style := color.HEX(colorString, isBackground)
|
||||
return style.Code()
|
||||
}
|
||||
|
||||
func (r *Renderer) writeColoredText(background string, foreground string, text string) {
|
||||
var coloredText string
|
||||
if foreground == Transparent && background != "" {
|
||||
ansiColor := r.getAnsiFromHex(background, false)
|
||||
ansiColor := r.getAnsiFromColorString(background, false)
|
||||
coloredText = fmt.Sprintf(r.formats.transparent, ansiColor, text)
|
||||
} else if background == "" || background == Transparent {
|
||||
ansiColor := r.getAnsiFromHex(foreground, false)
|
||||
ansiColor := r.getAnsiFromColorString(foreground, false)
|
||||
coloredText = fmt.Sprintf(r.formats.single, ansiColor, text)
|
||||
} else if foreground != "" && background != "" {
|
||||
bgAnsiColor := r.getAnsiFromHex(background, true)
|
||||
fgAnsiColor := r.getAnsiFromHex(foreground, false)
|
||||
bgAnsiColor := r.getAnsiFromColorString(background, true)
|
||||
fgAnsiColor := r.getAnsiFromColorString(foreground, false)
|
||||
coloredText = fmt.Sprintf(r.formats.full, bgAnsiColor, fgAnsiColor, text)
|
||||
}
|
||||
r.Buffer.WriteString(coloredText)
|
||||
|
@ -101,13 +144,19 @@ func (r *Renderer) writeAndRemoveText(background string, foreground string, text
|
|||
}
|
||||
|
||||
func (r *Renderer) write(background string, foreground string, text string) {
|
||||
rex := regexp.MustCompile(`<((#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})|transparent))>(.*?)</>`)
|
||||
// first we match for any potentially valid color enclosed in <>
|
||||
rex := regexp.MustCompile(`<([#A-Za-z0-9]+)>(.*?)<\/>`)
|
||||
match := rex.FindAllStringSubmatch(text, -1)
|
||||
for i := range match {
|
||||
// get the text before the color override and write that first
|
||||
textBeforeColorOverride := strings.Split(text, match[i][0])[0]
|
||||
extractedColor := match[i][1]
|
||||
if col := r.getAnsiFromColorString(extractedColor, false); col == "" && extractedColor != Transparent {
|
||||
continue // we skip invalid colors
|
||||
}
|
||||
escapedTextSegment := match[i][0]
|
||||
innerText := match[i][2]
|
||||
textBeforeColorOverride := strings.Split(text, escapedTextSegment)[0]
|
||||
text = r.writeAndRemoveText(background, foreground, textBeforeColorOverride, textBeforeColorOverride, text)
|
||||
text = r.writeAndRemoveText(background, match[i][1], match[i][4], match[i][0], text)
|
||||
text = r.writeAndRemoveText(background, extractedColor, innerText, escapedTextSegment, text)
|
||||
}
|
||||
// color the remaining part of text with background and foreground
|
||||
r.writeColoredText(background, foreground, text)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
func TestWriteAndRemoveText(t *testing.T) {
|
||||
|
@ -49,6 +50,36 @@ func TestWriteColorTransparent(t *testing.T) {
|
|||
t.Log(renderer.string())
|
||||
}
|
||||
|
||||
func TestWriteColorName(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
renderer.init("pwsh")
|
||||
text := "This is white, <red>this is red</>, white again"
|
||||
|
||||
// when
|
||||
renderer.write("#193549", "red", text)
|
||||
|
||||
// then
|
||||
assert.NotContains(t, renderer.string(), "<red>")
|
||||
}
|
||||
|
||||
func TestWriteColorInvalid(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
renderer.init("pwsh")
|
||||
text := "This is white, <invalid>this is orange</>, white again"
|
||||
|
||||
// when
|
||||
renderer.write("#193549", "invalid", text)
|
||||
|
||||
// then
|
||||
assert.Contains(t, renderer.string(), "<invalid>")
|
||||
}
|
||||
|
||||
func TestLenWithoutANSI(t *testing.T) {
|
||||
text := "\x1b[44mhello\x1b[0m"
|
||||
renderer := &Renderer{
|
||||
|
@ -68,3 +99,68 @@ func TestLenWithoutANSIZsh(t *testing.T) {
|
|||
strippedLength := renderer.lenWithoutANSI(text)
|
||||
assert.Equal(t, 5, strippedLength)
|
||||
}
|
||||
|
||||
func TestGetAnsiFromColorStringBg(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
// when
|
||||
colorCode := renderer.getAnsiFromColorString("blue", true)
|
||||
|
||||
// then
|
||||
assert.Equal(t, color.BgBlue.Code(), colorCode)
|
||||
}
|
||||
|
||||
func TestGetAnsiFromColorStringFg(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
// when
|
||||
colorCode := renderer.getAnsiFromColorString("red", false)
|
||||
|
||||
// then
|
||||
assert.Equal(t, color.FgRed.Code(), colorCode)
|
||||
}
|
||||
|
||||
func TestGetAnsiFromColorStringHex(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
// when
|
||||
colorCode := renderer.getAnsiFromColorString("#AABBCC", false)
|
||||
|
||||
// then
|
||||
assert.Equal(t, color.HEX("#AABBCC").Code(), colorCode)
|
||||
}
|
||||
|
||||
func TestGetAnsiFromColorStringInvalidFg(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
// when
|
||||
colorCode := renderer.getAnsiFromColorString("invalid", false)
|
||||
|
||||
// then
|
||||
assert.Equal(t, "", colorCode)
|
||||
}
|
||||
|
||||
func TestGetAnsiFromColorStringInvalidBg(t *testing.T) {
|
||||
// given
|
||||
renderer := &Renderer{
|
||||
Buffer: new(bytes.Buffer),
|
||||
}
|
||||
|
||||
// when
|
||||
colorCode := renderer.getAnsiFromColorString("invalid", true)
|
||||
|
||||
// then
|
||||
assert.Equal(t, "", colorCode)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue