diff --git a/.github/workflows/build_code.yml b/.github/workflows/build_code.yml index 57579328..d4b2a7cf 100644 --- a/.github/workflows/build_code.yml +++ b/.github/workflows/build_code.yml @@ -11,7 +11,7 @@ on: name: Build Code jobs: build: - runs-on: ubuntu-latest + runs-on: macos-latest defaults: run: shell: pwsh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b5374b37..023ae566 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,7 @@ on: jobs: changelog: - runs-on: ubuntu-latest + runs-on: macos-latest outputs: version: ${{ steps.changelog.outputs.version }} body: ${{ steps.changelog.outputs.clean_changelog }} diff --git a/src/.goreleaser.yml b/src/.goreleaser.yml index 541d9914..e4526295 100644 --- a/src/.goreleaser.yml +++ b/src/.goreleaser.yml @@ -13,7 +13,10 @@ builds: flags: - -a ldflags: - - -s -w -X github.com/jandedobbeleer/oh-my-posh/src/build.Version={{ .Version }} -X github.com/jandedobbeleer/oh-my-posh/src/build.Date={{ .Date }} -extldflags "-static" + - -s -w + - -X github.com/jandedobbeleer/oh-my-posh/src/build.Version={{ .Version }} + - -X github.com/jandedobbeleer/oh-my-posh/src/build.Date={{ .Date }} + - -extldflags "-static" tags: - netgo - osusergo diff --git a/src/cache/cache.go b/src/cache/cache.go index 6af23580..3475b194 100644 --- a/src/cache/cache.go +++ b/src/cache/cache.go @@ -49,6 +49,7 @@ const ( ONEDAY = 1440 ONEWEEK = 10080 ONEMONTH = 43200 + INFINITE = -1 ) type Entry struct { @@ -61,5 +62,6 @@ func (c *Entry) Expired() bool { if c.TTL < 0 { return false } + return time.Now().Unix() >= (c.Timestamp + int64(c.TTL)*60) } diff --git a/src/cache/file.go b/src/cache/file.go index fe64185c..8ae0e9f9 100644 --- a/src/cache/file.go +++ b/src/cache/file.go @@ -80,6 +80,7 @@ func (fc *File) Set(key, value string, ttl int) { Timestamp: time.Now().Unix(), TTL: ttl, }) + fc.dirty = true } diff --git a/src/color/colors.go b/src/color/colors.go index 526dfe43..622303b5 100644 --- a/src/color/colors.go +++ b/src/color/colors.go @@ -4,8 +4,10 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/gookit/color" + "github.com/jandedobbeleer/oh-my-posh/src/cache" "github.com/jandedobbeleer/oh-my-posh/src/runtime" "github.com/jandedobbeleer/oh-my-posh/src/template" ) @@ -26,6 +28,20 @@ type Set struct { Foreground Ansi `json:"foreground" toml:"foreground"` } +func (c *Set) String() string { + return fmt.Sprintf("%s|%s", c.Foreground, c.Background) +} + +func (c *Set) ParseString(colors string) { + parts := strings.Split(colors, "|") + if len(parts) != 2 { + return + } + + c.Foreground = Ansi(parts[0]) + c.Background = Ansi(parts[1]) +} + type History []*Set func (c *History) Len() int { @@ -144,6 +160,42 @@ func MakeColors(palette Palette, cacheEnabled bool, accentColor Ansi, env runtim return } +func (d *Defaults) SetAccentColor(env runtime.Environment, defaultColor Ansi) { + defer env.Trace(time.Now()) + + // get accent color from session cache first + if accent, OK := env.Session().Get("accent_color"); OK { + accentColors := &Set{} + accentColors.ParseString(accent) + d.accent = accentColors + return + } + + rgb, err := GetAccentColor(env) + if err != nil { + d.accent = &Set{ + Foreground: d.ToAnsi(defaultColor, false), + Background: d.ToAnsi(defaultColor, true), + } + + return + } + + if len(defaultColor) == 0 { + return + } + + foreground := color.RGB(rgb.R, rgb.G, rgb.B, false) + background := color.RGB(rgb.R, rgb.G, rgb.B, true) + + d.accent = &Set{ + Foreground: Ansi(foreground.String()), + Background: Ansi(background.String()), + } + + env.Session().Set("accent_color", d.accent.String(), cache.INFINITE) +} + type RGB struct { R, G, B uint8 } diff --git a/src/color/colors_darwin.go b/src/color/colors_darwin.go new file mode 100644 index 00000000..cd5c56b8 --- /dev/null +++ b/src/color/colors_darwin.go @@ -0,0 +1,40 @@ +package color + +import ( + "errors" + "strconv" + + "github.com/jandedobbeleer/oh-my-posh/src/runtime" +) + +func GetAccentColor(env runtime.Environment) (*RGB, error) { + output, err := env.RunCommand("defaults", "read", "-g", "AppleAccentColor") + if err != nil { + env.Error(err) + return nil, errors.New("unable to read accent color") + } + + index, err := strconv.Atoi(output) + if err != nil { + env.Error(err) + return nil, errors.New("unable to parse accent color index") + } + + var accentColors = map[int]RGB{ + -1: {152, 152, 152}, // Graphite + 0: {224, 55, 62}, // Red + 1: {247, 130, 25}, // Orange + 2: {255, 199, 38}, // Yellow + 3: {96, 186, 70}, // Green + 4: {0, 122, 255}, // Blue + 5: {149, 61, 150}, // Purple + 6: {247, 79, 159}, // Pink + } + + color, exists := accentColors[index] + if !exists { + color = accentColors[6] // Default to graphite (white) + } + + return &color, nil +} diff --git a/src/color/colors_test.go b/src/color/colors_test.go index db7264d1..0e6f9bb1 100644 --- a/src/color/colors_test.go +++ b/src/color/colors_test.go @@ -6,6 +6,7 @@ import ( "github.com/alecthomas/assert" "github.com/jandedobbeleer/oh-my-posh/src/cache" + cache_ "github.com/jandedobbeleer/oh-my-posh/src/cache/mock" "github.com/jandedobbeleer/oh-my-posh/src/runtime" "github.com/jandedobbeleer/oh-my-posh/src/runtime/mock" @@ -43,6 +44,12 @@ func TestGetAnsiFromColorString(t *testing.T) { func TestMakeColors(t *testing.T) { env := &mock.Environment{} + env.On("Trace", testify_.Anything, testify_.Anything).Return(nil) + + c := &cache_.Cache{} + c.On("Get", "accent_color").Return("", true) + env.On("Session").Return(c) + env.On("WindowsRegistryKeyValue", `HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM\ColorizationColor`).Return(&runtime.WindowsRegistryValue{}, errors.New("err")) colors := MakeColors(nil, false, "", env) assert.IsType(t, &Defaults{}, colors) diff --git a/src/color/colors_unix.go b/src/color/colors_unix.go index f589b056..e5a147c3 100644 --- a/src/color/colors_unix.go +++ b/src/color/colors_unix.go @@ -1,4 +1,4 @@ -//go:build !windows +//go:build !windows && !darwin package color @@ -7,14 +7,3 @@ import "github.com/jandedobbeleer/oh-my-posh/src/runtime" func GetAccentColor(_ runtime.Environment) (*RGB, error) { return nil, &runtime.NotImplemented{} } - -func (d *Defaults) SetAccentColor(_ runtime.Environment, defaultColor Ansi) { - if len(defaultColor) == 0 { - return - } - - d.accent = &Set{ - Foreground: d.ToAnsi(defaultColor, false), - Background: d.ToAnsi(defaultColor, true), - } -} diff --git a/src/color/colors_windows.go b/src/color/colors_windows.go index 47bbfa55..7092978c 100644 --- a/src/color/colors_windows.go +++ b/src/color/colors_windows.go @@ -2,12 +2,14 @@ package color import ( "errors" + "time" - "github.com/gookit/color" "github.com/jandedobbeleer/oh-my-posh/src/runtime" ) func GetAccentColor(env runtime.Environment) (*RGB, error) { + defer env.Trace(time.Now()) + if env == nil { return nil, errors.New("unable to get color without environment") } @@ -24,23 +26,3 @@ func GetAccentColor(env runtime.Environment) (*RGB, error) { B: byte(value.DWord), }, nil } - -func (d *Defaults) SetAccentColor(env runtime.Environment, defaultColor Ansi) { - rgb, err := GetAccentColor(env) - if err != nil { - d.accent = &Set{ - Foreground: d.ToAnsi(defaultColor, false), - Background: d.ToAnsi(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 = &Set{ - Foreground: Ansi(foreground.String()), - Background: Ansi(background.String()), - } -} diff --git a/src/runtime/terminal.go b/src/runtime/terminal.go index f37cbabc..c9bf444f 100644 --- a/src/runtime/terminal.go +++ b/src/runtime/terminal.go @@ -357,22 +357,27 @@ func (term *Terminal) GOOS() string { func (term *Terminal) RunCommand(command string, args ...string) (string, error) { defer term.Trace(time.Now(), append([]string{command}, args...)...) + if cacheCommand, ok := term.cmdCache.Get(command); ok { command = cacheCommand } + output, err := cmd.Run(command, args...) if err != nil { term.Error(err) } + term.Debug(output) return output, err } func (term *Terminal) RunShellCommand(shell, command string) string { defer term.Trace(time.Now()) + if out, err := term.RunCommand(shell, "-c", command); err == nil { return out } + return "" } diff --git a/website/docs/configuration/colors.mdx b/website/docs/configuration/colors.mdx index a29dd7ff..e27d2835 100644 --- a/website/docs/configuration/colors.mdx +++ b/website/docs/configuration/colors.mdx @@ -28,7 +28,7 @@ Oh My Posh supports multiple different color references, being: - 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). +- The `accent` keyword which references the OS accent color (Windows and macOS only). ## Color templates