refactor(terminal): make truecolor logic internal

This commit is contained in:
Jan De Dobbeleer 2024-07-01 09:54:03 +02:00 committed by Jan De Dobbeleer
parent 0c8b8021b8
commit dbc0a370b2
14 changed files with 81 additions and 37 deletions

View file

@ -70,7 +70,6 @@ Exports the config to an image file using customized output options.`,
terminal.Init(shell.GENERIC)
terminal.BackgroundColor = shell.ConsoleBackgroundColor(env, cfg.TerminalBackground)
terminal.AnsiColors = cfg.MakeColors()
terminal.TrueColor = env.CmdFlags.TrueColor
eng := &engine.Engine{
Config: cfg,

View file

@ -44,7 +44,6 @@ var debugCmd = &cobra.Command{
terminal.BackgroundColor = shell.ConsoleBackgroundColor(env, cfg.TerminalBackground)
terminal.AnsiColors = cfg.MakeColors()
terminal.Plain = plain
terminal.TrueColor = env.CmdFlags.TrueColor
eng := &engine.Engine{
Config: cfg,

View file

@ -69,7 +69,6 @@ func (b *Block) InitPlain(env platform.Environment, config *Config) {
terminal.Init(shell.GENERIC)
terminal.BackgroundColor = shell.ConsoleBackgroundColor(env, config.TerminalBackground)
terminal.AnsiColors = config.MakeColors()
terminal.TrueColor = env.Flags().TrueColor
b.env = env
b.executeSegmentLogic()

View file

@ -136,11 +136,11 @@ func (e *Engine) newline() {
}
func (e *Engine) isWarp() bool {
return e.Env.Getenv("TERM_PROGRAM") == "WarpTerminal"
return terminal.Program == terminal.Warp
}
func (e *Engine) isIterm() bool {
return e.Env.Getenv("TERM_PROGRAM") == "iTerm.app"
return terminal.Program == terminal.ITerm
}
func (e *Engine) shouldFill(filler string, remaining, blockLength int) (string, bool) {

View file

@ -118,7 +118,6 @@ func engineRender() {
terminal.Init(shell.GENERIC)
terminal.BackgroundColor = shell.ConsoleBackgroundColor(env, cfg.TerminalBackground)
terminal.AnsiColors = cfg.MakeColors()
terminal.TrueColor = env.CmdFlags.TrueColor
engine := &Engine{
Config: cfg,

View file

@ -28,7 +28,6 @@ func New(flags *platform.Flags) *Engine {
terminal.BackgroundColor = shell.ConsoleBackgroundColor(env, cfg.TerminalBackground)
terminal.AnsiColors = cfg.MakeColors()
terminal.Plain = flags.Plain
terminal.TrueColor = env.CmdFlags.TrueColor
eng := &Engine{
Config: cfg,

View file

@ -106,7 +106,6 @@ func (e *Engine) Primary() string {
// see https://github.com/jandedobbeleer/oh-my-posh/pull/2398
terminal.Init(shell.GENERIC)
terminal.TrueColor = e.Env.Flags().TrueColor
prompt := terminal.SaveCursorPosition()
prompt += strings.Repeat(" ", space)

View file

@ -58,7 +58,6 @@ type Flags struct {
HasTransient bool
PromptCount int
Cleared bool
TrueColor bool
NoExitCode bool
Column int
}
@ -216,24 +215,24 @@ func (env *Shell) Init() {
if env.CmdFlags == nil {
env.CmdFlags = &Flags{}
}
if env.CmdFlags.Debug {
log.Enable()
}
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()
env.cmdCache = &commandCache{
commands: NewConcurrentMap(),
}
env.tmplCache = &TemplateCache{}
env.SetPromptCount()
}

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, trueColor bool) Color
ToColor(colorString string, isBackground bool) Color
}
type ColorSet struct {
@ -153,45 +153,57 @@ const (
backgroundIndex = 1
)
func (d *DefaultColors) ToColor(colorString string, isBackground, trueColor bool) Color {
func (d *DefaultColors) ToColor(colorString string, isBackground bool) Color {
if len(colorString) == 0 {
return emptyColor
}
if colorString == Transparent {
return transparentColor
}
if colorString == Accent {
if d.accent == nil {
return emptyColor
}
if isBackground {
return Color(d.accent.Background)
}
return Color(d.accent.Foreground)
}
colorFromName, err := getAnsiColorFromName(colorString, isBackground)
if err == nil {
return colorFromName
}
if !strings.HasPrefix(colorString, "#") {
val, err := strconv.ParseUint(colorString, 10, 64)
if err != nil || val > 255 {
return emptyColor
}
c256 := color.C256(uint8(val), isBackground)
return Color(c256.String())
}
style := color.HEX(colorString, isBackground)
if !style.IsEmpty() {
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)
return Color(c.String())
}
return emptyColor
}
@ -202,8 +214,10 @@ func getAnsiColorFromName(colorName string, isBackground bool) (Color, error) {
if isBackground {
return colorCodes[backgroundIndex], nil
}
return colorCodes[foregroundIndex], nil
}
return "", fmt.Errorf("color name %s does not exist", colorName)
}
@ -219,12 +233,14 @@ type PaletteColors struct {
palette Palette
}
func (p *PaletteColors) ToColor(colorString string, isBackground, trueColor 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.ToColor(paletteColor, isBackground, trueColor)
ansiColor := p.ansiColors.ToColor(paletteColor, isBackground)
return ansiColor
}
@ -241,7 +257,7 @@ type cachedColorKey struct {
isBackground bool
}
func (c *CachedColors) ToColor(colorString string, isBackground, trueColor bool) Color {
func (c *CachedColors) ToColor(colorString string, isBackground bool) Color {
if c.colorCache == nil {
c.colorCache = make(map[cachedColorKey]Color)
}
@ -249,7 +265,7 @@ func (c *CachedColors) ToColor(colorString string, isBackground, trueColor bool)
if ansiColor, hit := c.colorCache[key]; hit {
return ansiColor
}
ansiColor := c.ansiColors.ToColor(colorString, isBackground, trueColor)
ansiColor := c.ansiColors.ToColor(colorString, isBackground)
c.colorCache[key] = ansiColor
return ansiColor
}

View file

@ -31,16 +31,15 @@ func TestGetAnsiFromColorString(t *testing.T) {
}
for _, tc := range cases {
ansiColors := &DefaultColors{}
ansiColor := ansiColors.ToColor(tc.Color, tc.Background, !tc.Color256)
trueColor = !tc.Color256
ansiColor := ansiColors.ToColor(tc.Color, tc.Background)
assert.Equal(t, tc.Expected, ansiColor, tc.Case)
}
}
func TestMakeColors(t *testing.T) {
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)

View file

@ -12,8 +12,9 @@ func (d *DefaultColors) SetAccentColor(_ platform.Environment, defaultColor stri
if len(defaultColor) == 0 {
return
}
d.accent = &Colors{
Foreground: string(d.ToColor(defaultColor, false, env.Flags().TrueColor)),
Background: string(d.ToColor(defaultColor, true, env.Flags().TrueColor)),
Foreground: string(d.ToColor(defaultColor, false)),
Background: string(d.ToColor(defaultColor, true)),
}
}

View file

@ -12,11 +12,13 @@ func GetAccentColor(env platform.Environment) (*RGB, error) {
if env == nil {
return nil, errors.New("unable to get color without environment")
}
// see https://stackoverflow.com/questions/3560890/vista-7-how-to-get-glass-color
value, err := env.WindowsRegistryKeyValue(`HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM\ColorizationColor`)
if err != nil || value.ValueType != platform.DWORD {
return nil, err
}
return &RGB{
R: byte(value.DWord >> 16),
G: byte(value.DWord >> 8),
@ -28,13 +30,16 @@ 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, env.Flags().TrueColor)),
Background: string(d.ToColor(defaultColor, true, env.Flags().TrueColor)),
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 = &Colors{
Foreground: foreground.String(),
Background: background.String(),

View file

@ -2,8 +2,10 @@ package terminal
import (
"fmt"
"os"
"strings"
"github.com/jandedobbeleer/oh-my-posh/src/log"
"github.com/jandedobbeleer/oh-my-posh/src/regex"
"github.com/jandedobbeleer/oh-my-posh/src/shell"
"github.com/mattn/go-runewidth"
@ -46,9 +48,10 @@ var (
AnsiColors ColorString
Plain bool
TrueColor bool
Interactive bool
trueColor bool
builder strings.Builder
length int
@ -63,7 +66,8 @@ var (
lastRune rune
shellName string
Shell string
Program string
formats *shellFormats
)
@ -129,12 +133,24 @@ const (
hyperLinkEnd = "</LINK>"
hyperLinkText = "<TEXT>"
hyperLinkTextEnd = "</TEXT>"
WindowsTerminal = "Windows Terminal"
Warp = "WarpTerminal"
ITerm = "iTerm.app"
AppleTerminal = "Apple_Terminal"
Unknown = "Unknown"
)
func Init(sh string) {
shellName = sh
Shell = sh
Program = getTerminalName()
switch shellName {
log.Debug("Terminal shell: %s", Shell)
log.Debug("Terminal program: %s", Program)
trueColor = Program != AppleTerminal
switch Shell {
case shell.BASH:
formats = &shellFormats{
escape: "\\[%s\\]",
@ -203,7 +219,7 @@ func Init(sh string) {
}
}
if shellName == shell.ZSH {
if Shell == shell.ZSH {
formats.escapeSequences = map[rune]rune{
96: 92, // backtick
37: 37, // %
@ -211,6 +227,20 @@ func Init(sh string) {
}
}
func getTerminalName() string {
Program = os.Getenv("TERM_PROGRAM")
if len(Program) != 0 {
return Program
}
wtSession := os.Getenv("WT_SESSION")
if len(wtSession) != 0 {
return WindowsTerminal
}
return Unknown
}
func SetColors(background, foreground string) {
CurrentColors = &Colors{
Background: background,
@ -281,7 +311,7 @@ func FormatTitle(title string) string {
}
// we have to do this to prevent bash/zsh from misidentifying escape sequences
switch shellName {
switch Shell {
case shell.BASH:
title = strings.NewReplacer("`", "\\`", `\`, `\\`).Replace(title)
case shell.ZSH:
@ -339,7 +369,7 @@ func Write(background, foreground, text string) {
// default to white foreground
if foregroundColor.IsEmpty() {
foregroundColor = AnsiColors.ToColor("white", false, TrueColor)
foregroundColor = AnsiColors.ToColor("white", false)
}
// validate if we start with a color override
@ -451,7 +481,7 @@ func writeEscapedAnsiString(text string) {
}
func getAnsiFromColorString(colorString string, isBackground bool) Color {
return AnsiColors.ToColor(colorString, isBackground, TrueColor)
return AnsiColors.ToColor(colorString, isBackground)
}
func write(s rune) {

View file

@ -226,7 +226,7 @@ func TestWriteANSIColors(t *testing.T) {
CurrentColors = tc.Colors
BackgroundColor = tc.TerminalBackground
AnsiColors = &DefaultColors{}
TrueColor = true
trueColor = true
Write(tc.Colors.Background, tc.Colors.Foreground, tc.Input)