summaryrefslogtreecommitdiffhomepage
path: root/internal/tui/theme/manager.go
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-04-28 08:46:09 -0500
committeradamdottv <[email protected]>2025-04-30 07:46:34 -0500
commit61b605e724eb4cc50ab831534fcdd18e031d68eb (patch)
treeb15b074a8fed1931e179a8d3df08d05b753c7aa3 /internal/tui/theme/manager.go
parent61d9dc95111d2645a49816f6d9d6cc1014be1a22 (diff)
downloadopencode-61b605e724eb4cc50ab831534fcdd18e031d68eb.tar.gz
opencode-61b605e724eb4cc50ab831534fcdd18e031d68eb.zip
feat: themes
Diffstat (limited to 'internal/tui/theme/manager.go')
-rw-r--r--internal/tui/theme/manager.go113
1 files changed, 113 insertions, 0 deletions
diff --git a/internal/tui/theme/manager.go b/internal/tui/theme/manager.go
new file mode 100644
index 000000000..161563c26
--- /dev/null
+++ b/internal/tui/theme/manager.go
@@ -0,0 +1,113 @@
+package theme
+
+import (
+ "fmt"
+ "slices"
+ "strings"
+ "sync"
+
+ "github.com/alecthomas/chroma/v2/styles"
+ "github.com/opencode-ai/opencode/internal/config"
+ "github.com/opencode-ai/opencode/internal/logging"
+)
+
+// Manager handles theme registration, selection, and retrieval.
+// It maintains a registry of available themes and tracks the currently active theme.
+type Manager struct {
+ themes map[string]Theme
+ currentName string
+ mu sync.RWMutex
+}
+
+// Global instance of the theme manager
+var globalManager = &Manager{
+ themes: make(map[string]Theme),
+ currentName: "",
+}
+
+// RegisterTheme adds a new theme to the registry.
+// If this is the first theme registered, it becomes the default.
+func RegisterTheme(name string, theme Theme) {
+ globalManager.mu.Lock()
+ defer globalManager.mu.Unlock()
+
+ globalManager.themes[name] = theme
+
+ // If this is the first theme, make it the default
+ if globalManager.currentName == "" {
+ globalManager.currentName = name
+ }
+}
+
+// SetTheme changes the active theme to the one with the specified name.
+// Returns an error if the theme doesn't exist.
+func SetTheme(name string) error {
+ globalManager.mu.Lock()
+ defer globalManager.mu.Unlock()
+
+ delete(styles.Registry, "charm")
+ if _, exists := globalManager.themes[name]; !exists {
+ return fmt.Errorf("theme '%s' not found", name)
+ }
+
+ globalManager.currentName = name
+
+ // Update the config file using viper
+ if err := updateConfigTheme(name); err != nil {
+ // Log the error but don't fail the theme change
+ logging.Warn("Warning: Failed to update config file with new theme", "err", err)
+ }
+
+ return nil
+}
+
+// CurrentTheme returns the currently active theme.
+// If no theme is set, it returns nil.
+func CurrentTheme() Theme {
+ globalManager.mu.RLock()
+ defer globalManager.mu.RUnlock()
+
+ if globalManager.currentName == "" {
+ return nil
+ }
+
+ return globalManager.themes[globalManager.currentName]
+}
+
+// CurrentThemeName returns the name of the currently active theme.
+func CurrentThemeName() string {
+ globalManager.mu.RLock()
+ defer globalManager.mu.RUnlock()
+
+ return globalManager.currentName
+}
+
+// AvailableThemes returns a list of all registered theme names.
+func AvailableThemes() []string {
+ globalManager.mu.RLock()
+ defer globalManager.mu.RUnlock()
+
+ names := make([]string, 0, len(globalManager.themes))
+ for name := range globalManager.themes {
+ names = append(names, name)
+ }
+ slices.SortFunc(names, func(a, b string) int {
+ return strings.Compare(a, b)
+ })
+ return names
+}
+
+// GetTheme returns a specific theme by name.
+// Returns nil if the theme doesn't exist.
+func GetTheme(name string) Theme {
+ globalManager.mu.RLock()
+ defer globalManager.mu.RUnlock()
+
+ return globalManager.themes[name]
+}
+
+// updateConfigTheme updates the theme setting in the configuration file
+func updateConfigTheme(themeName string) error {
+ // Use the config package to update the theme
+ return config.UpdateTheme(themeName)
+}