mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2025-02-21 02:55:37 -08:00
parent
6ca3d22b80
commit
86459f9a2f
|
@ -34,9 +34,9 @@ type style struct {
|
|||
End string
|
||||
}
|
||||
|
||||
type cachedColor struct {
|
||||
Background string
|
||||
Foreground string
|
||||
type Colors struct {
|
||||
Background string `json:"background"`
|
||||
Foreground string `json:"foreground"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -75,9 +75,9 @@ const (
|
|||
// Writer writes colorized ANSI strings
|
||||
type Writer struct {
|
||||
TerminalBackground string
|
||||
Colors *cachedColor
|
||||
ParentColors []*cachedColor
|
||||
AnsiColors Colors
|
||||
Colors *Colors
|
||||
ParentColors []*Colors
|
||||
AnsiColors ColorString
|
||||
Plain bool
|
||||
|
||||
builder strings.Builder
|
||||
|
@ -175,7 +175,7 @@ func (w *Writer) Init(shellName string) {
|
|||
}
|
||||
|
||||
func (w *Writer) SetColors(background, foreground string) {
|
||||
w.Colors = &cachedColor{
|
||||
w.Colors = &Colors{
|
||||
Background: background,
|
||||
Foreground: foreground,
|
||||
}
|
||||
|
@ -183,9 +183,9 @@ func (w *Writer) SetColors(background, foreground string) {
|
|||
|
||||
func (w *Writer) SetParentColors(background, foreground string) {
|
||||
if w.ParentColors == nil {
|
||||
w.ParentColors = make([]*cachedColor, 0)
|
||||
w.ParentColors = make([]*Colors, 0)
|
||||
}
|
||||
w.ParentColors = append([]*cachedColor{{
|
||||
w.ParentColors = append([]*Colors{{
|
||||
Background: background,
|
||||
Foreground: foreground,
|
||||
}}, w.ParentColors...)
|
||||
|
@ -279,7 +279,7 @@ func (w *Writer) Write(background, foreground, text string) {
|
|||
w.background, w.foreground = w.asAnsiColors(background, foreground)
|
||||
// default to white foreground
|
||||
if w.foreground.IsEmpty() {
|
||||
w.foreground = w.AnsiColors.AnsiColorFromString("white", false)
|
||||
w.foreground = w.AnsiColors.ToColor("white", false)
|
||||
}
|
||||
// validate if we start with a color override
|
||||
match := regex.FindNamedRegexMatch(anchorRegex, text)
|
||||
|
@ -361,7 +361,7 @@ func (w *Writer) writeEscapedAnsiString(text string) {
|
|||
}
|
||||
|
||||
func (w *Writer) getAnsiFromColorString(colorString string, isBackground bool) Color {
|
||||
return w.AnsiColors.AnsiColorFromString(colorString, isBackground)
|
||||
return w.AnsiColors.ToColor(colorString, isBackground)
|
||||
}
|
||||
|
||||
func (w *Writer) writeSegmentColors() {
|
||||
|
|
|
@ -13,187 +13,187 @@ func TestWriteANSIColors(t *testing.T) {
|
|||
Case string
|
||||
Expected string
|
||||
Input string
|
||||
Colors *cachedColor
|
||||
Parent *cachedColor
|
||||
Colors *Colors
|
||||
Parent *Colors
|
||||
TerminalBackground string
|
||||
}{
|
||||
{
|
||||
Case: "Bold",
|
||||
Input: "<b>test</b>",
|
||||
Expected: "\x1b[1m\x1b[30mtest\x1b[22m\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
{
|
||||
Case: "Bold with color override",
|
||||
Input: "<b><#ffffff>test</></b>",
|
||||
Expected: "\x1b[1m\x1b[30m\x1b[38;2;255;255;255mtest\x1b[0m\x1b[30m\x1b[22m\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
{
|
||||
Case: "Bold with color override, flavor 2",
|
||||
Input: "<#ffffff><b>test</b></>",
|
||||
Expected: "\x1b[38;2;255;255;255m\x1b[1mtest\x1b[22m\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
|
||||
{
|
||||
Case: "Double override",
|
||||
Input: "<#ffffff>jan</>@<#ffffff>Jans-MBP</>",
|
||||
Expected: "\x1b[48;2;255;87;51m\x1b[38;2;255;255;255mjan\x1b[32m@\x1b[38;2;255;255;255mJans-MBP\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "green", Background: "#FF5733"},
|
||||
Colors: &Colors{Foreground: "green", Background: "#FF5733"},
|
||||
},
|
||||
{
|
||||
Case: "No color override",
|
||||
Input: "test",
|
||||
Expected: "\x1b[47m\x1b[30mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
Parent: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit foreground",
|
||||
Input: "test",
|
||||
Expected: "\x1b[47m\x1b[33mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: ParentForeground, Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "white"},
|
||||
Colors: &Colors{Foreground: ParentForeground, Background: "white"},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit background",
|
||||
Input: "test",
|
||||
Expected: "\x1b[41m\x1b[30mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "red"},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "red"},
|
||||
},
|
||||
{
|
||||
Case: "No parent",
|
||||
Input: "test",
|
||||
Expected: "\x1b[30mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
{
|
||||
Case: "Inherit override foreground",
|
||||
Input: "hello <parentForeground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[33mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "red"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "red"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit override background",
|
||||
Input: "hello <black,parentBackground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[41mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "red"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "red"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit override background, no foreground specified",
|
||||
Input: "hello <,parentBackground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[41mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "red"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "red"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit no parent foreground",
|
||||
Input: "hello <parentForeground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[0m\x1b[37;49m\x1b[7mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit no parent background",
|
||||
Input: "hello <,parentBackground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[0m\x1b[30mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit override both",
|
||||
Input: "hello <parentForeground,parentBackground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[41m\x1b[33mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "red"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "red"},
|
||||
},
|
||||
{
|
||||
Case: "Inherit override both inverted",
|
||||
Input: "hello <parentBackground,parentForeground>world</>",
|
||||
Expected: "\x1b[47m\x1b[30mhello \x1b[43m\x1b[31mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Parent: &cachedColor{Foreground: "yellow", Background: "red"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
Parent: &Colors{Foreground: "yellow", Background: "red"},
|
||||
},
|
||||
{
|
||||
Case: "Inline override",
|
||||
Input: "hello, <red>world</>, rabbit",
|
||||
Expected: "\x1b[47m\x1b[30mhello, \x1b[31mworld\x1b[30m, rabbit\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Transparent background",
|
||||
Input: "hello world",
|
||||
Expected: "\x1b[37mhello world\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "white", Background: Transparent},
|
||||
Colors: &Colors{Foreground: "white", Background: Transparent},
|
||||
},
|
||||
{
|
||||
Case: "Transparent foreground override",
|
||||
Input: "hello <#ffffff>world</>",
|
||||
Expected: "\x1b[32mhello \x1b[38;2;255;255;255mworld\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "green", Background: Transparent},
|
||||
Colors: &Colors{Foreground: "green", Background: Transparent},
|
||||
},
|
||||
{
|
||||
Case: "No foreground",
|
||||
Input: "test",
|
||||
Expected: "\x1b[48;2;255;87;51m\x1b[37mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "", Background: "#FF5733"},
|
||||
Colors: &Colors{Foreground: "", Background: "#FF5733"},
|
||||
},
|
||||
{
|
||||
Case: "Transparent foreground",
|
||||
Input: "test",
|
||||
Expected: "\x1b[0m\x1b[38;2;255;87;51;49m\x1b[7mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: Transparent, Background: "#FF5733"},
|
||||
Colors: &Colors{Foreground: Transparent, Background: "#FF5733"},
|
||||
},
|
||||
{
|
||||
Case: "Transparent foreground, terminal background set",
|
||||
Input: "test",
|
||||
Expected: "\x1b[38;2;33;47;60m\x1b[48;2;255;87;51mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: Transparent, Background: "#FF5733"},
|
||||
Colors: &Colors{Foreground: Transparent, Background: "#FF5733"},
|
||||
TerminalBackground: "#212F3C",
|
||||
},
|
||||
{
|
||||
Case: "Foreground for foreground override",
|
||||
Input: "<foreground>test</>",
|
||||
Expected: "\x1b[47m\x1b[30mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Background for background override",
|
||||
Input: "<,background>test</>",
|
||||
Expected: "\x1b[47m\x1b[30mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Google",
|
||||
Input: "<blue,white>G</><red,white>o</><yellow,white>o</><blue,white>g</><green,white>l</><red,white>e</>",
|
||||
Expected: "\x1b[47m\x1b[34mG\x1b[40m\x1b[30m\x1b[47m\x1b[31mo\x1b[40m\x1b[30m\x1b[47m\x1b[33mo\x1b[40m\x1b[30m\x1b[47m\x1b[34mg\x1b[40m\x1b[30m\x1b[47m\x1b[32ml\x1b[40m\x1b[30m\x1b[47m\x1b[31me\x1b[0m", //nolint: lll
|
||||
Colors: &cachedColor{Foreground: "black", Background: "black"},
|
||||
Colors: &Colors{Foreground: "black", Background: "black"},
|
||||
},
|
||||
{
|
||||
Case: "Foreground for background override",
|
||||
Input: "<background>test</>",
|
||||
Expected: "\x1b[47m\x1b[37mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Foreground for background vice versa override",
|
||||
Input: "<background,foreground>test</>",
|
||||
Expected: "\x1b[40m\x1b[37mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
{
|
||||
Case: "Background for foreground override",
|
||||
Input: "<,foreground>test</>",
|
||||
Expected: "\x1b[40m\x1b[30mtest\x1b[0m",
|
||||
Colors: &cachedColor{Foreground: "black", Background: "white"},
|
||||
Colors: &Colors{Foreground: "black", Background: "white"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
renderer := &Writer{
|
||||
ParentColors: []*cachedColor{tc.Parent},
|
||||
ParentColors: []*Colors{tc.Parent},
|
||||
Colors: tc.Colors,
|
||||
TerminalBackground: tc.TerminalBackground,
|
||||
AnsiColors: &DefaultColors{},
|
||||
|
@ -210,37 +210,37 @@ func TestWriteLength(t *testing.T) {
|
|||
Case string
|
||||
Expected int
|
||||
Input string
|
||||
Colors *cachedColor
|
||||
Colors *Colors
|
||||
}{
|
||||
{
|
||||
Case: "Bold",
|
||||
Input: "<b>test</b>",
|
||||
Expected: 4,
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
{
|
||||
Case: "Bold with color override",
|
||||
Input: "<b><#ffffff>test</></b>",
|
||||
Expected: 4,
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
{
|
||||
Case: "Bold with color override and link",
|
||||
Input: "<b><#ffffff>test</></b> [url](https://example.com)",
|
||||
Expected: 8,
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
{
|
||||
Case: "Bold with color override and link and leading/trailing spaces",
|
||||
Input: " <b><#ffffff>test</></b> [url](https://example.com) ",
|
||||
Expected: 10,
|
||||
Colors: &cachedColor{Foreground: "black", Background: ParentBackground},
|
||||
Colors: &Colors{Foreground: "black", Background: ParentBackground},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
renderer := &Writer{
|
||||
ParentColors: []*cachedColor{},
|
||||
ParentColors: []*Colors{},
|
||||
Colors: tc.Colors,
|
||||
AnsiColors: &DefaultColors{},
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ import (
|
|||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
// Colors is the interface that wraps AnsiColorFromString method.
|
||||
// ColorString is the interface that wraps ToColor method.
|
||||
//
|
||||
// AnsiColorFromString gets the ANSI color code for a given color string.
|
||||
// ToColor 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`.
|
||||
type Colors interface {
|
||||
AnsiColorFromString(colorString string, isBackground bool) Color
|
||||
type ColorString interface {
|
||||
ToColor(colorString string, isBackground bool) Color
|
||||
}
|
||||
|
||||
// Color is an ANSI color code ready to be printed to the console.
|
||||
|
@ -48,7 +48,7 @@ func (c Color) ToForeground() Color {
|
|||
return c
|
||||
}
|
||||
|
||||
func MakeColors(palette Palette, cacheEnabled bool, accentColor string, env platform.Environment) (colors Colors) {
|
||||
func MakeColors(palette Palette, cacheEnabled bool, accentColor string, env platform.Environment) (colors ColorString) {
|
||||
defaultColors := &DefaultColors{}
|
||||
defaultColors.SetAccentColor(env, accentColor)
|
||||
colors = defaultColors
|
||||
|
@ -67,7 +67,7 @@ type RGB struct {
|
|||
|
||||
// DefaultColors is the default AnsiColors implementation.
|
||||
type DefaultColors struct {
|
||||
accent *cachedColor
|
||||
accent *Colors
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -98,7 +98,7 @@ const (
|
|||
backgroundIndex = 1
|
||||
)
|
||||
|
||||
func (d *DefaultColors) AnsiColorFromString(colorString string, isBackground bool) Color {
|
||||
func (d *DefaultColors) ToColor(colorString string, isBackground bool) Color {
|
||||
if len(colorString) == 0 {
|
||||
return emptyColor
|
||||
}
|
||||
|
@ -157,24 +157,24 @@ func IsAnsiColorName(colorString string) bool {
|
|||
// PaletteColors is the AnsiColors Decorator that uses the Palette to do named color
|
||||
// lookups before ANSI color code generation.
|
||||
type PaletteColors struct {
|
||||
ansiColors Colors
|
||||
ansiColors ColorString
|
||||
palette Palette
|
||||
}
|
||||
|
||||
func (p *PaletteColors) AnsiColorFromString(colorString string, isBackground bool) Color {
|
||||
func (p *PaletteColors) ToColor(colorString string, isBackground bool) Color {
|
||||
paletteColor, err := p.palette.ResolveColor(colorString)
|
||||
if err != nil {
|
||||
return emptyColor
|
||||
}
|
||||
ansiColor := p.ansiColors.AnsiColorFromString(paletteColor, isBackground)
|
||||
ansiColor := p.ansiColors.ToColor(paletteColor, isBackground)
|
||||
return ansiColor
|
||||
}
|
||||
|
||||
// CachedColors is the AnsiColors Decorator that does simple color lookup caching.
|
||||
// AnsiColorFromString calls are cheap, but not free, and having a simple cache in
|
||||
// ToColor calls are cheap, but not free, and having a simple cache in
|
||||
// has measurable positive effect on performance.
|
||||
type CachedColors struct {
|
||||
ansiColors Colors
|
||||
ansiColors ColorString
|
||||
colorCache map[cachedColorKey]Color
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ type cachedColorKey struct {
|
|||
isBackground bool
|
||||
}
|
||||
|
||||
func (c *CachedColors) AnsiColorFromString(colorString string, isBackground bool) Color {
|
||||
func (c *CachedColors) ToColor(colorString string, isBackground bool) Color {
|
||||
if c.colorCache == nil {
|
||||
c.colorCache = make(map[cachedColorKey]Color)
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ func (c *CachedColors) AnsiColorFromString(colorString string, isBackground bool
|
|||
if ansiColor, hit := c.colorCache[key]; hit {
|
||||
return ansiColor
|
||||
}
|
||||
ansiColor := c.ansiColors.AnsiColorFromString(colorString, isBackground)
|
||||
ansiColor := c.ansiColors.ToColor(colorString, isBackground)
|
||||
c.colorCache[key] = ansiColor
|
||||
return ansiColor
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func TestGetAnsiFromColorString(t *testing.T) {
|
|||
}
|
||||
for _, tc := range cases {
|
||||
ansiColors := &DefaultColors{}
|
||||
ansiColor := ansiColors.AnsiColorFromString(tc.Color, tc.Background)
|
||||
ansiColor := ansiColors.ToColor(tc.Color, tc.Background)
|
||||
assert.Equal(t, tc.Expected, ansiColor, tc.Case)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ func (d *DefaultColors) SetAccentColor(env platform.Environment, defaultColor st
|
|||
if len(defaultColor) == 0 {
|
||||
return
|
||||
}
|
||||
d.accent = &cachedColor{
|
||||
Foreground: string(d.AnsiColorFromString(defaultColor, false)),
|
||||
Background: string(d.AnsiColorFromString(defaultColor, true)),
|
||||
d.accent = &Colors{
|
||||
Foreground: string(d.ToColor(defaultColor, false)),
|
||||
Background: string(d.ToColor(defaultColor, true)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,15 +27,15 @@ func GetAccentColor(env platform.Environment) (*RGB, error) {
|
|||
func (d *DefaultColors) SetAccentColor(env platform.Environment, defaultColor string) {
|
||||
rgb, err := GetAccentColor(env)
|
||||
if err != nil {
|
||||
d.accent = &cachedColor{
|
||||
Foreground: string(d.AnsiColorFromString(defaultColor, false)),
|
||||
Background: string(d.AnsiColorFromString(defaultColor, true)),
|
||||
d.accent = &Colors{
|
||||
Foreground: string(d.ToColor(defaultColor, false)),
|
||||
Background: string(d.ToColor(defaultColor, true)),
|
||||
}
|
||||
return
|
||||
}
|
||||
foreground := color.RGB(rgb.R, rgb.G, rgb.B, false)
|
||||
background := color.RGB(rgb.R, rgb.G, rgb.B, true)
|
||||
d.accent = &cachedColor{
|
||||
d.accent = &Colors{
|
||||
Foreground: foreground.String(),
|
||||
Background: background.String(),
|
||||
}
|
||||
|
|
10
src/ansi/cycle.go
Normal file
10
src/ansi/cycle.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package ansi
|
||||
|
||||
type Cycle []*Colors
|
||||
|
||||
func PopColors(array []*Colors) (*Colors, Cycle) {
|
||||
if len(array) == 0 {
|
||||
return nil, array
|
||||
}
|
||||
return array[0], array[1:]
|
||||
}
|
|
@ -55,11 +55,13 @@ type Block struct {
|
|||
writer *ansi.Writer
|
||||
activeSegment *Segment
|
||||
previousActiveSegment *Segment
|
||||
cycle *ansi.Cycle
|
||||
}
|
||||
|
||||
func (b *Block) Init(env platform.Environment, writer *ansi.Writer) {
|
||||
func (b *Block) Init(env platform.Environment, writer *ansi.Writer, cycle *ansi.Cycle) {
|
||||
b.env = env
|
||||
b.writer = writer
|
||||
b.cycle = cycle
|
||||
b.executeSegmentLogic()
|
||||
}
|
||||
|
||||
|
@ -130,6 +132,11 @@ func (b *Block) RenderSegments() (string, int) {
|
|||
if !segment.Enabled && segment.style() != Accordion {
|
||||
continue
|
||||
}
|
||||
if b.cycle != nil && len(*b.cycle) > 0 {
|
||||
colors, cycle := ansi.PopColors(*b.cycle)
|
||||
b.cycle = &cycle
|
||||
segment.colors = colors
|
||||
}
|
||||
b.setActiveSegment(segment)
|
||||
b.renderActiveSegment()
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ type Config struct {
|
|||
DebugPrompt *Segment `json:"debug_prompt,omitempty"`
|
||||
Palette ansi.Palette `json:"palette,omitempty"`
|
||||
Palettes *ansi.Palettes `json:"palettes,omitempty"`
|
||||
Cycle ansi.Cycle `json:"cycle,omitempty"`
|
||||
PWD string `json:"pwd,omitempty"`
|
||||
|
||||
// Deprecated
|
||||
|
@ -63,7 +64,7 @@ type Config struct {
|
|||
|
||||
// MakeColors creates instance of AnsiColors to use in AnsiWriter according to
|
||||
// environment and configuration.
|
||||
func (cfg *Config) MakeColors() ansi.Colors {
|
||||
func (cfg *Config) MakeColors() ansi.ColorString {
|
||||
cacheDisabled := cfg.env.Getenv("OMP_CACHE_DISABLED") == "1"
|
||||
return ansi.MakeColors(cfg.getPalette(), !cacheDisabled, cfg.AccentColor, cfg.env)
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ type Engine struct {
|
|||
currentLineLength int
|
||||
rprompt string
|
||||
rpromptLength int
|
||||
cycle *ansi.Cycle
|
||||
}
|
||||
|
||||
func (e *Engine) write(text string) {
|
||||
|
@ -57,6 +58,8 @@ func (e *Engine) canWriteRightBlock(rprompt bool) bool {
|
|||
}
|
||||
|
||||
func (e *Engine) PrintPrimary() string {
|
||||
// cache a pointer to the color cycle
|
||||
e.cycle = &e.Config.Cycle
|
||||
for _, block := range e.Config.Blocks {
|
||||
e.renderBlock(block)
|
||||
}
|
||||
|
@ -156,7 +159,7 @@ func (e *Engine) renderBlock(block *Block) {
|
|||
if e.Env.Shell() == shell.BASH && (block.Type == RPrompt || block.Alignment == Right) {
|
||||
block.InitPlain(e.Env, e.Config)
|
||||
} else {
|
||||
block.Init(e.Env, e.Writer)
|
||||
block.Init(e.Env, e.Writer, e.cycle)
|
||||
}
|
||||
if !block.Enabled() {
|
||||
return
|
||||
|
@ -243,9 +246,11 @@ func (e *Engine) PrintDebug(startTime time.Time, version string) string {
|
|||
duration: time.Since(titleStartTime),
|
||||
}
|
||||
segmentTimings = append(segmentTimings, segmentTiming)
|
||||
// cache a pointer to the color cycle
|
||||
e.cycle = &e.Config.Cycle
|
||||
// loop each segments of each blocks
|
||||
for _, block := range e.Config.Blocks {
|
||||
block.Init(e.Env, e.Writer)
|
||||
block.Init(e.Env, e.Writer, e.cycle)
|
||||
longestSegmentName, timings := block.Debug()
|
||||
segmentTimings = append(segmentTimings, timings...)
|
||||
if longestSegmentName > largestSegmentNameLength {
|
||||
|
@ -344,7 +349,7 @@ func (e *Engine) PrintTooltip(tip string) string {
|
|||
}
|
||||
switch e.Env.Shell() {
|
||||
case shell.ZSH, shell.CMD, shell.FISH, shell.GENERIC:
|
||||
block.Init(e.Env, e.Writer)
|
||||
block.Init(e.Env, e.Writer, nil)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
|
@ -453,7 +458,7 @@ func (e *Engine) PrintRPrompt() string {
|
|||
if block == nil {
|
||||
return ""
|
||||
}
|
||||
block.Init(e.Env, e.Writer)
|
||||
block.Init(e.Env, e.Writer, e.cycle)
|
||||
if !block.Enabled() {
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/ansi"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/platform"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/properties"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/segments"
|
||||
|
@ -39,13 +40,13 @@ type Segment struct {
|
|||
MaxWidth int `json:"max_width,omitempty"`
|
||||
MinWidth int `json:"min_width,omitempty"`
|
||||
|
||||
env platform.Environment
|
||||
writer SegmentWriter
|
||||
Enabled bool `json:"-"`
|
||||
text string
|
||||
backgroundCache string
|
||||
foregroundCache string
|
||||
styleCache SegmentStyle
|
||||
Enabled bool `json:"-"`
|
||||
|
||||
colors *ansi.Colors
|
||||
env platform.Environment
|
||||
writer SegmentWriter
|
||||
text string
|
||||
styleCache SegmentStyle
|
||||
}
|
||||
|
||||
// SegmentTiming holds the timing context for a segment
|
||||
|
@ -360,17 +361,23 @@ func (segment *Segment) shouldInvokeWithTip(tip string) bool {
|
|||
}
|
||||
|
||||
func (segment *Segment) foreground() string {
|
||||
if len(segment.foregroundCache) == 0 {
|
||||
segment.foregroundCache = segment.ForegroundTemplates.FirstMatch(segment.writer, segment.env, segment.Foreground)
|
||||
if segment.colors == nil {
|
||||
segment.colors = &ansi.Colors{}
|
||||
}
|
||||
return segment.foregroundCache
|
||||
if len(segment.colors.Foreground) == 0 {
|
||||
segment.colors.Foreground = segment.ForegroundTemplates.FirstMatch(segment.writer, segment.env, segment.Foreground)
|
||||
}
|
||||
return segment.colors.Foreground
|
||||
}
|
||||
|
||||
func (segment *Segment) background() string {
|
||||
if len(segment.backgroundCache) == 0 {
|
||||
segment.backgroundCache = segment.BackgroundTemplates.FirstMatch(segment.writer, segment.env, segment.Background)
|
||||
if segment.colors == nil {
|
||||
segment.colors = &ansi.Colors{}
|
||||
}
|
||||
return segment.backgroundCache
|
||||
if len(segment.colors.Background) == 0 {
|
||||
segment.colors.Background = segment.BackgroundTemplates.FirstMatch(segment.writer, segment.env, segment.Background)
|
||||
}
|
||||
return segment.colors.Background
|
||||
}
|
||||
|
||||
func (segment *Segment) mapSegmentWithWriter(env platform.Environment) error {
|
||||
|
|
|
@ -3063,6 +3063,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"cycle": {
|
||||
"type": "array",
|
||||
"title": "List of settings to cycle through segment by segment",
|
||||
"description": "https://ohmyposh.dev/docs/configuration/cycle",
|
||||
"default": [],
|
||||
"items": {
|
||||
"properties": {
|
||||
"foreground": {
|
||||
"$ref": "#/definitions/color"
|
||||
},
|
||||
"background": {
|
||||
"$ref": "#/definitions/color"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"accent_color": {
|
||||
"title": "Accent color",
|
||||
"$ref": "#/definitions/color"
|
||||
|
|
|
@ -236,6 +236,32 @@ you could also add `frappe` as the default `palette`, given that one is used as
|
|||
the `template` resolves to. In case no match is available and no `palette` is defined, it will also fallback to `transparent`
|
||||
for any palette color reference in templates/colors.
|
||||
|
||||
## Cycle
|
||||
|
||||
When you want to display the same **sequence of colors** (background and foreground) regardless of which segments are active, you can
|
||||
make use of the cycle property. This property is a list of colors which are used one after the other. If there's nothing in the list
|
||||
anymore and your prompt would still render additional segments, the segment's colors are being used. A defined cycle always gets
|
||||
precendence over everything else.
|
||||
|
||||
```json
|
||||
...
|
||||
"cycle": [
|
||||
{
|
||||
"background": "p:blue",
|
||||
"foreground": "p:white"
|
||||
},
|
||||
{
|
||||
"background": "p:green",
|
||||
"foreground": "p:black"
|
||||
},
|
||||
{
|
||||
"background": "p:orange",
|
||||
"foreground": "p:white"
|
||||
}
|
||||
],
|
||||
...
|
||||
```
|
||||
|
||||
[hexcolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[ansicolors]: https://htmlcolorcodes.com/color-chart/material-design-color-chart/
|
||||
[git]: /docs/segments/git
|
||||
|
|
Loading…
Reference in a new issue