From a51716d5ac3f7aabe1428a5a6d79c6b863463ff6 Mon Sep 17 00:00:00 2001 From: Jan De Dobbeleer Date: Sun, 22 May 2022 09:11:16 +0200 Subject: [PATCH] feat(windows): accent color --- src/color/colors.go | 21 +++++++++++--- src/color/colors_test.go | 8 +++--- src/color/colors_unix.go | 13 +++++++++ src/color/colors_windows.go | 38 ++++++++++++++++++++++++++ src/color/writer.go | 2 ++ src/engine/config.go | 3 +- themes/schema.json | 6 +++- website/docs/configuration/colors.md | 16 +++++------ website/docs/configuration/overview.md | 3 ++ 9 files changed, 92 insertions(+), 18 deletions(-) create mode 100644 src/color/colors_unix.go create mode 100644 src/color/colors_windows.go diff --git a/src/color/colors.go b/src/color/colors.go index c2c9b204..3571a8c2 100644 --- a/src/color/colors.go +++ b/src/color/colors.go @@ -6,8 +6,10 @@ import ( "github.com/gookit/color" ) -func MakeColors(palette Palette, cacheEnabled bool) (colors AnsiColors) { - colors = &DefaultColors{} +func MakeColors(palette Palette, cacheEnabled bool, accentColor string) (colors AnsiColors) { + defaultColors := &DefaultColors{} + defaultColors.SetAccentColor(accentColor) + colors = defaultColors if palette != nil { colors = &PaletteColors{ansiColors: colors, palette: palette} } @@ -18,7 +20,9 @@ func MakeColors(palette Palette, cacheEnabled bool) (colors AnsiColors) { } // DefaultColors is the default AnsiColors implementation. -type DefaultColors struct{} +type DefaultColors struct { + accent *Color +} var ( // Map for color names and their respective foreground [0] or background [1] color codes @@ -48,13 +52,22 @@ const ( backgroundIndex = 1 ) -func (*DefaultColors) AnsiColorFromString(colorString string, isBackground bool) AnsiColor { +func (d *DefaultColors) AnsiColorFromString(colorString string, isBackground bool) AnsiColor { if len(colorString) == 0 { return emptyAnsiColor } if colorString == Transparent { return transparentAnsiColor } + if colorString == Accent { + if d.accent == nil { + return emptyAnsiColor + } + if isBackground { + return AnsiColor(d.accent.Background) + } + return AnsiColor(d.accent.Foreground) + } colorFromName, err := getAnsiColorFromName(colorString, isBackground) if err == nil { return colorFromName diff --git a/src/color/colors_test.go b/src/color/colors_test.go index 061e3c3e..7fdfc9d9 100644 --- a/src/color/colors_test.go +++ b/src/color/colors_test.go @@ -30,18 +30,18 @@ func TestGetAnsiFromColorString(t *testing.T) { } func TestMakeColors(t *testing.T) { - colors := MakeColors(nil, false) + colors := MakeColors(nil, false, "") assert.IsType(t, &DefaultColors{}, colors) - colors = MakeColors(nil, true) + colors = MakeColors(nil, true, "") assert.IsType(t, &CachedColors{}, colors) assert.IsType(t, &DefaultColors{}, colors.(*CachedColors).ansiColors) - colors = MakeColors(testPalette, false) + colors = MakeColors(testPalette, false, "") assert.IsType(t, &PaletteColors{}, colors) assert.IsType(t, &DefaultColors{}, colors.(*PaletteColors).ansiColors) - colors = MakeColors(testPalette, true) + colors = MakeColors(testPalette, true, "") 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/color/colors_unix.go b/src/color/colors_unix.go new file mode 100644 index 00000000..55835782 --- /dev/null +++ b/src/color/colors_unix.go @@ -0,0 +1,13 @@ +//go:build !windows + +package color + +func (d *DefaultColors) SetAccentColor(defaultColor string) { + if len(defaultColor) == 0 { + return + } + d.accent = &Color{ + Foreground: string(d.AnsiColorFromString(defaultColor, false)), + Background: string(d.AnsiColorFromString(defaultColor, true)), + } +} diff --git a/src/color/colors_windows.go b/src/color/colors_windows.go new file mode 100644 index 00000000..2fd003e8 --- /dev/null +++ b/src/color/colors_windows.go @@ -0,0 +1,38 @@ +package color + +import ( + "syscall" + "unsafe" + + "github.com/gookit/color" + "golang.org/x/sys/windows" +) + +var ( + dwmapi = syscall.NewLazyDLL("dwmapi.dll") + procDwmGetColorizationColor = dwmapi.NewProc("DwmGetColorizationColor") +) + +func (d *DefaultColors) SetAccentColor(defaultColor string) { + var accentColor uint32 + var pfOpaqueBlend bool + _, _, e := procDwmGetColorizationColor.Call( + uintptr(unsafe.Pointer(&accentColor)), + uintptr(unsafe.Pointer(&pfOpaqueBlend))) + if e != windows.ERROR_SUCCESS { + d.accent = &Color{ + Foreground: string(d.AnsiColorFromString(defaultColor, false)), + Background: string(d.AnsiColorFromString(defaultColor, true)), + } + return + } + r := byte(accentColor >> 16) + g := byte(accentColor >> 8) + b := byte(accentColor) + foreground := color.RGB(r, g, b, false) + background := color.RGB(r, g, b, true) + d.accent = &Color{ + Foreground: foreground.String(), + Background: background.String(), + } +} diff --git a/src/color/writer.go b/src/color/writer.go index b19a603a..163ae719 100644 --- a/src/color/writer.go +++ b/src/color/writer.go @@ -73,6 +73,8 @@ func (c AnsiColor) ToForeground() AnsiColor { const ( // Transparent implies a transparent color Transparent = "transparent" + // Accent is the OS accent color + Accent = "accent" // ParentBackground takes the previous segment's background color ParentBackground = "parentBackground" // ParentForeground takes the previous segment's color diff --git a/src/engine/config.go b/src/engine/config.go index 446f0806..b5028103 100644 --- a/src/engine/config.go +++ b/src/engine/config.go @@ -35,6 +35,7 @@ type Config struct { OSC99 bool `json:"osc99,omitempty"` ConsoleTitleTemplate string `json:"console_title_template,omitempty"` TerminalBackground string `json:"terminal_background,omitempty"` + AccentColor string `json:"accent_color,omitempty"` Blocks []*Block `json:"blocks,omitempty"` Tooltips []*Segment `json:"tooltips,omitempty"` TransientPrompt *Segment `json:"transient_prompt,omitempty"` @@ -56,7 +57,7 @@ type Config struct { // environment and configuration. func (cfg *Config) MakeColors(env environment.Environment) color.AnsiColors { cacheDisabled := env.Getenv("OMP_CACHE_DISABLED") == "1" - return color.MakeColors(cfg.Palette, !cacheDisabled) + return color.MakeColors(cfg.Palette, !cacheDisabled, cfg.AccentColor) } func (cfg *Config) print(message string) { diff --git a/themes/schema.json b/themes/schema.json index 999b863f..e8879625 100644 --- a/themes/schema.json +++ b/themes/schema.json @@ -17,7 +17,7 @@ }, "color_string": { "type": "string", - "pattern": "^(#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})|black|red|green|yellow|blue|magenta|cyan|white|default|darkGray|lightRed|lightGreen|lightYellow|lightBlue|lightMagenta|lightCyan|lightWhite|transparent|parentBackground|parentForeground|background|foreground)$", + "pattern": "^(#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})|black|red|green|yellow|blue|magenta|cyan|white|default|darkGray|lightRed|lightGreen|lightYellow|lightBlue|lightMagenta|lightCyan|lightWhite|transparent|parentBackground|parentForeground|background|foreground|accent)$", "title": "Color string", "description": "https://ohmyposh.dev/docs/configuration/colors", "format": "color" @@ -2552,6 +2552,10 @@ "$ref": "#/definitions/color" } } + }, + "accent_color": { + "title": "Accent color", + "$ref": "#/definitions/color" } } } diff --git a/website/docs/configuration/colors.md b/website/docs/configuration/colors.md index 4f63c66b..952e9b20 100644 --- a/website/docs/configuration/colors.md +++ b/website/docs/configuration/colors.md @@ -10,20 +10,20 @@ Oh My Posh supports multiple different color references, being: - Typical [hex colors][hexcolors] (for example `#CB4B16`). - 16 [ANSI color names][ansicolors]. -- The `transparent` keyword which can be used to create either a transparent foreground override - or transparent background color using the segment's foreground property. -- The `foreground` keyword which can be used to reference the current segment's foreground color. -- The `background` keyword which can be used to reference the current segment's background color. -- The `parentForeground` keyword which can be used to inherit the previous active segment's foreground color. -- The `parentBackground` keyword which can be used to inherit the previous active segment's background color. - - These include 8 basic ANSI colors and `default`: + These include 8 basic ANSI colors and `default` `black` `red` `green` `yellow` `blue` `magenta` `cyan` `white` `default` as well as 8 extended ANSI colors: `darkGray` `lightRed` `lightGreen` `lightYellow` `lightBlue` `lightMagenta` `lightCyan` `lightWhite` +- The `transparent` keyword which can be used to create either a transparent foreground override + or transparent background color using the segment's foreground property. +- The `foreground` keyword which can be used to reference the current segment's foreground color. +- The `background` keyword which can be used to reference the current segment's background color. +- The `parentForeground` keyword which can be used to inherit the previous active segment's foreground color. +- The `parentBackground` keyword which can be used to inherit the previous active segment's background color. +- The `accent` keyword which references the OS accent color (Windows only). ## Color templates diff --git a/website/docs/configuration/overview.md b/website/docs/configuration/overview.md index 30cbaf69..8b0d2680 100644 --- a/website/docs/configuration/overview.md +++ b/website/docs/configuration/overview.md @@ -69,8 +69,11 @@ For example, the following is a valid `--config` flag: - osc99: `boolean` - when true adds support for OSC9;9; (notify terminal of current working directory) - terminal_background: `string` [color][colors] - terminal background color, set to your terminal's background color when you notice black elements in Windows Terminal or the Visual Studio Code integrated terminal +- accent_color: `string` [color][colors] - accent color, used as a fallback when the `accent` [color][accent] is not supported [releases]: https://github.com/JanDeDobbeleer/oh-my-posh/releases/latest [font]: /docs/configuration/fonts [schema]: https://github.com/JanDeDobbeleer/oh-my-posh/blob/main/themes/schema.json [themes]: https://github.com/JanDeDobbeleer/oh-my-posh/tree/main/themes +[colors]: /docs/configuration/colors +[accent]: /docs/configuration/colors#standard-colors