feat: enable/disable true color per terminal

This commit is contained in:
Jan De Dobbeleer 2023-03-23 09:59:54 +01:00 committed by Jan De Dobbeleer
parent 481f096878
commit 8c5c836f22
13 changed files with 48 additions and 20 deletions

View file

@ -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() {

View file

@ -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)

View file

@ -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
}

View file

@ -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)

View file

@ -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)),
}
}

View file

@ -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
}

View file

@ -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{

View file

@ -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{

View file

@ -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

View file

@ -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()

View file

@ -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{

View file

@ -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())

View file

@ -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()