diff --git a/src/ansi/ansi_writer.go b/src/ansi/ansi_writer.go index be5dad74..1311011e 100644 --- a/src/ansi/ansi_writer.go +++ b/src/ansi/ansi_writer.go @@ -80,6 +80,7 @@ type Writer struct { ParentColors []*Colors AnsiColors ColorString Plain bool + TrueColor bool builder strings.Builder length int @@ -283,7 +284,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.ToColor("white", false) + w.foreground = w.AnsiColors.ToColor("white", false, w.TrueColor) } // validate if we start with a color override match := regex.FindNamedRegexMatch(anchorRegex, text) @@ -365,7 +366,7 @@ func (w *Writer) writeEscapedAnsiString(text string) { } func (w *Writer) getAnsiFromColorString(colorString string, isBackground bool) Color { - return w.AnsiColors.ToColor(colorString, isBackground) + return w.AnsiColors.ToColor(colorString, isBackground, w.TrueColor) } func (w *Writer) writeSegmentColors() { diff --git a/src/ansi/ansi_writer_test.go b/src/ansi/ansi_writer_test.go index 886374b0..ffa33dde 100644 --- a/src/ansi/ansi_writer_test.go +++ b/src/ansi/ansi_writer_test.go @@ -203,6 +203,7 @@ func TestWriteANSIColors(t *testing.T) { Colors: tc.Colors, TerminalBackground: tc.TerminalBackground, AnsiColors: &DefaultColors{}, + TrueColor: true, } renderer.Init(shell.GENERIC) renderer.Write(tc.Colors.Background, tc.Colors.Foreground, tc.Input) diff --git a/src/ansi/colors.go b/src/ansi/colors.go index 7dfac222..fa95b45a 100644 --- a/src/ansi/colors.go +++ b/src/ansi/colors.go @@ -16,7 +16,7 @@ import ( // 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 ColorString interface { - ToColor(colorString string, isBackground bool) Color + ToColor(colorString string, isBackground bool, trueColor bool) Color } // Color is an ANSI color code ready to be printed to the console. @@ -98,7 +98,7 @@ const ( backgroundIndex = 1 ) -func (d *DefaultColors) ToColor(colorString string, isBackground bool) Color { +func (d *DefaultColors) ToColor(colorString string, isBackground, trueColor bool) Color { if len(colorString) == 0 { return emptyColor } @@ -128,7 +128,10 @@ func (d *DefaultColors) ToColor(colorString string, isBackground bool) Color { } style := color.HEX(colorString, isBackground) if !style.IsEmpty() { - return Color(style.String()) + if trueColor { + return Color(style.String()) + } + return Color(style.C256().String()) } if colorInt, err := strconv.ParseInt(colorString, 10, 8); err == nil { c := color.C256(uint8(colorInt), isBackground) @@ -161,12 +164,12 @@ type PaletteColors struct { palette Palette } -func (p *PaletteColors) ToColor(colorString string, isBackground bool) Color { +func (p *PaletteColors) ToColor(colorString string, isBackground, trueColor bool) Color { paletteColor, err := p.palette.ResolveColor(colorString) if err != nil { return emptyColor } - ansiColor := p.ansiColors.ToColor(paletteColor, isBackground) + ansiColor := p.ansiColors.ToColor(paletteColor, isBackground, trueColor) return ansiColor } @@ -183,7 +186,7 @@ type cachedColorKey struct { isBackground bool } -func (c *CachedColors) ToColor(colorString string, isBackground bool) Color { +func (c *CachedColors) ToColor(colorString string, isBackground, trueColor bool) Color { if c.colorCache == nil { c.colorCache = make(map[cachedColorKey]Color) } @@ -191,7 +194,7 @@ func (c *CachedColors) ToColor(colorString string, isBackground bool) Color { if ansiColor, hit := c.colorCache[key]; hit { return ansiColor } - ansiColor := c.ansiColors.ToColor(colorString, isBackground) + ansiColor := c.ansiColors.ToColor(colorString, isBackground, trueColor) c.colorCache[key] = ansiColor return ansiColor } diff --git a/src/ansi/colors_test.go b/src/ansi/colors_test.go index 018d08eb..9c59a64b 100644 --- a/src/ansi/colors_test.go +++ b/src/ansi/colors_test.go @@ -1,9 +1,12 @@ package ansi import ( + "errors" "testing" "github.com/alecthomas/assert" + "github.com/jandedobbeleer/oh-my-posh/src/mock" + "github.com/jandedobbeleer/oh-my-posh/src/platform" ) func TestGetAnsiFromColorString(t *testing.T) { @@ -12,6 +15,7 @@ func TestGetAnsiFromColorString(t *testing.T) { Expected Color Color string Background bool + Color256 bool }{ {Case: "256 color", Expected: Color("38;5;99"), Color: "99", Background: false}, {Case: "256 color", Expected: Color("38;5;122"), Color: "122", Background: false}, @@ -23,27 +27,33 @@ func TestGetAnsiFromColorString(t *testing.T) { {Case: "Base 8 background", Expected: Color("41"), Color: "red", Background: true}, {Case: "Base 16 foreground", Expected: Color("91"), Color: "lightRed", Background: false}, {Case: "Base 16 backround", Expected: Color("101"), Color: "lightRed", Background: true}, + {Case: "Non true color TERM", Expected: Color("38;5;146"), Color: "#AABBCC", Color256: true}, } for _, tc := range cases { ansiColors := &DefaultColors{} - ansiColor := ansiColors.ToColor(tc.Color, tc.Background) + ansiColor := ansiColors.ToColor(tc.Color, tc.Background, !tc.Color256) assert.Equal(t, tc.Expected, ansiColor, tc.Case) } } func TestMakeColors(t *testing.T) { - colors := MakeColors(nil, false, "", nil) + env := &mock.MockedEnvironment{} + env.On("Flags").Return(&platform.Flags{ + TrueColor: true, + }) + env.On("WindowsRegistryKeyValue", `HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM\ColorizationColor`).Return(&platform.WindowsRegistryValue{}, errors.New("err")) + colors := MakeColors(nil, false, "", env) assert.IsType(t, &DefaultColors{}, colors) - colors = MakeColors(nil, true, "", nil) + colors = MakeColors(nil, true, "", env) assert.IsType(t, &CachedColors{}, colors) assert.IsType(t, &DefaultColors{}, colors.(*CachedColors).ansiColors) - colors = MakeColors(testPalette, false, "", nil) + colors = MakeColors(testPalette, false, "", env) assert.IsType(t, &PaletteColors{}, colors) assert.IsType(t, &DefaultColors{}, colors.(*PaletteColors).ansiColors) - colors = MakeColors(testPalette, true, "", nil) + colors = MakeColors(testPalette, true, "", env) assert.IsType(t, &CachedColors{}, colors) assert.IsType(t, &PaletteColors{}, colors.(*CachedColors).ansiColors) assert.IsType(t, &DefaultColors{}, colors.(*CachedColors).ansiColors.(*PaletteColors).ansiColors) diff --git a/src/ansi/colors_unix.go b/src/ansi/colors_unix.go index f6885d68..bb2be8d5 100644 --- a/src/ansi/colors_unix.go +++ b/src/ansi/colors_unix.go @@ -8,12 +8,12 @@ func GetAccentColor(_ platform.Environment) (*RGB, error) { return nil, &platform.NotImplemented{} } -func (d *DefaultColors) SetAccentColor(_ platform.Environment, defaultColor string) { +func (d *DefaultColors) SetAccentColor(env platform.Environment, defaultColor string) { if len(defaultColor) == 0 { return } d.accent = &Colors{ - Foreground: string(d.ToColor(defaultColor, false)), - Background: string(d.ToColor(defaultColor, true)), + Foreground: string(d.ToColor(defaultColor, false, env.Flags().TrueColor)), + Background: string(d.ToColor(defaultColor, true, env.Flags().TrueColor)), } } diff --git a/src/ansi/colors_windows.go b/src/ansi/colors_windows.go index 79f61da3..e77f29d9 100644 --- a/src/ansi/colors_windows.go +++ b/src/ansi/colors_windows.go @@ -28,8 +28,8 @@ func (d *DefaultColors) SetAccentColor(env platform.Environment, defaultColor st rgb, err := GetAccentColor(env) if err != nil { d.accent = &Colors{ - Foreground: string(d.ToColor(defaultColor, false)), - Background: string(d.ToColor(defaultColor, true)), + Foreground: string(d.ToColor(defaultColor, false, env.Flags().TrueColor)), + Background: string(d.ToColor(defaultColor, true, env.Flags().TrueColor)), } return } diff --git a/src/cli/config_export_image.go b/src/cli/config_export_image.go index 74d69c1d..5d495df1 100644 --- a/src/cli/config_export_image.go +++ b/src/cli/config_export_image.go @@ -66,6 +66,7 @@ Exports the config to an image file using customized output options.`, writer := &ansi.Writer{ TerminalBackground: shell.ConsoleBackgroundColor(env, cfg.TerminalBackground), AnsiColors: writerColors, + TrueColor: env.CmdFlags.TrueColor, } writer.Init(shell.GENERIC) eng := &engine.Engine{ diff --git a/src/cli/debug.go b/src/cli/debug.go index bc0f752d..babceb0a 100644 --- a/src/cli/debug.go +++ b/src/cli/debug.go @@ -38,6 +38,7 @@ var debugCmd = &cobra.Command{ TerminalBackground: shell.ConsoleBackgroundColor(env, cfg.TerminalBackground), AnsiColors: writerColors, Plain: plain, + TrueColor: env.CmdFlags.TrueColor, } writer.Init(shell.GENERIC) eng := &engine.Engine{ diff --git a/src/engine/block.go b/src/engine/block.go index f82a8f48..5f455a81 100644 --- a/src/engine/block.go +++ b/src/engine/block.go @@ -67,6 +67,7 @@ func (b *Block) InitPlain(env platform.Environment, config *Config) { b.writer = &ansi.Writer{ TerminalBackground: shell.ConsoleBackgroundColor(env, config.TerminalBackground), AnsiColors: config.MakeColors(), + TrueColor: env.Flags().TrueColor, } b.writer.Init(shell.GENERIC) b.env = env diff --git a/src/engine/engine.go b/src/engine/engine.go index 6bcb1c5d..8297cb68 100644 --- a/src/engine/engine.go +++ b/src/engine/engine.go @@ -337,7 +337,9 @@ func (e *Engine) print() string { } // in bash, the entire rprompt needs to be escaped for the prompt to be interpreted correctly // see https://github.com/jandedobbeleer/oh-my-posh/pull/2398 - writer := &ansi.Writer{} + writer := &ansi.Writer{ + TrueColor: e.Env.Flags().TrueColor, + } writer.Init(shell.GENERIC) prompt := writer.SaveCursorPosition() prompt += writer.CarriageForward() diff --git a/src/engine/engine_test.go b/src/engine/engine_test.go index 9d9d31f9..ec38192e 100644 --- a/src/engine/engine_test.go +++ b/src/engine/engine_test.go @@ -105,6 +105,7 @@ func engineRender() { writer := &ansi.Writer{ TerminalBackground: shell.ConsoleBackgroundColor(env, cfg.TerminalBackground), AnsiColors: writerColors, + TrueColor: env.CmdFlags.TrueColor, } writer.Init(shell.GENERIC) engine := &Engine{ diff --git a/src/engine/new.go b/src/engine/new.go index 1406c8ab..fea6ac6c 100644 --- a/src/engine/new.go +++ b/src/engine/new.go @@ -22,6 +22,7 @@ func New(flags *platform.Flags) *Engine { TerminalBackground: shell.ConsoleBackgroundColor(env, cfg.TerminalBackground), AnsiColors: cfg.MakeColors(), Plain: flags.Plain, + TrueColor: env.CmdFlags.TrueColor, } ansiWriter.Init(env.Shell()) diff --git a/src/platform/shell.go b/src/platform/shell.go index f3fd3cf4..153b5921 100644 --- a/src/platform/shell.go +++ b/src/platform/shell.go @@ -71,6 +71,7 @@ type Flags struct { PromptCount int Cleared bool Version string + TrueColor bool } type CommandError struct { @@ -300,6 +301,11 @@ func (env *Shell) Init() { if env.CmdFlags.Plain { log.Plain() } + trueColor := true + if env.Getenv("TERM_PROGRAM") == "Apple_Terminal" { + trueColor = false + } + env.CmdFlags.TrueColor = trueColor env.fileCache = &fileCache{} env.fileCache.Init(env.CachePath()) env.resolveConfigPath()