diff --git a/src/cli/config_export_image.go b/src/cli/config_export_image.go index 11c4aee4..e779ce38 100644 --- a/src/cli/config_export_image.go +++ b/src/cli/config_export_image.go @@ -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, diff --git a/src/cli/debug.go b/src/cli/debug.go index 38e31c0a..a9818159 100644 --- a/src/cli/debug.go +++ b/src/cli/debug.go @@ -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, diff --git a/src/engine/block.go b/src/engine/block.go index 98c17c61..10f67961 100644 --- a/src/engine/block.go +++ b/src/engine/block.go @@ -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() diff --git a/src/engine/engine.go b/src/engine/engine.go index 9a540d85..3c135428 100644 --- a/src/engine/engine.go +++ b/src/engine/engine.go @@ -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) { diff --git a/src/engine/engine_test.go b/src/engine/engine_test.go index ea96d531..0e0d5f90 100644 --- a/src/engine/engine_test.go +++ b/src/engine/engine_test.go @@ -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, diff --git a/src/engine/new.go b/src/engine/new.go index bb0eb920..465748cf 100644 --- a/src/engine/new.go +++ b/src/engine/new.go @@ -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, diff --git a/src/engine/prompt.go b/src/engine/prompt.go index 9fb27857..100442ea 100644 --- a/src/engine/prompt.go +++ b/src/engine/prompt.go @@ -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) diff --git a/src/platform/shell.go b/src/platform/shell.go index cda0635e..83f9b939 100644 --- a/src/platform/shell.go +++ b/src/platform/shell.go @@ -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() } diff --git a/src/terminal/colors.go b/src/terminal/colors.go index db80b9df..4c8a0a8e 100644 --- a/src/terminal/colors.go +++ b/src/terminal/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, 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 } diff --git a/src/terminal/colors_test.go b/src/terminal/colors_test.go index d40d793b..827d1027 100644 --- a/src/terminal/colors_test.go +++ b/src/terminal/colors_test.go @@ -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) diff --git a/src/terminal/colors_unix.go b/src/terminal/colors_unix.go index d0c68a49..a7d4e864 100644 --- a/src/terminal/colors_unix.go +++ b/src/terminal/colors_unix.go @@ -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)), } } diff --git a/src/terminal/colors_windows.go b/src/terminal/colors_windows.go index f38e14b1..21d68133 100644 --- a/src/terminal/colors_windows.go +++ b/src/terminal/colors_windows.go @@ -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(), diff --git a/src/terminal/writer.go b/src/terminal/writer.go index 6330113e..0a3498e7 100644 --- a/src/terminal/writer.go +++ b/src/terminal/writer.go @@ -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 = "" hyperLinkText = "" hyperLinkTextEnd = "" + + 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) { diff --git a/src/terminal/writer_test.go b/src/terminal/writer_test.go index e7c1d314..fe537cc2 100644 --- a/src/terminal/writer_test.go +++ b/src/terminal/writer_test.go @@ -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)