feat: opencode theme (default)

This commit is contained in:
adamdottv
2025-04-29 08:20:41 -05:00
parent fdf5367f4f
commit 1e958b62ad
5 changed files with 400 additions and 114 deletions

View File

@@ -210,7 +210,7 @@ func configureViper() {
func setDefaults(debug bool) {
viper.SetDefault("data.directory", defaultDataDirectory)
viper.SetDefault("contextPaths", defaultContextPaths)
viper.SetDefault("tui.theme", "catppuccin")
viper.SetDefault("tui.theme", "opencode")
if debug {
viper.SetDefault("debug", true)
@@ -731,7 +731,7 @@ func UpdateTheme(themeName string) error {
// Update the in-memory config
cfg.TUI.Theme = themeName
// Get the config file path
configFile := viper.ConfigFileUsed()
if configFile == "" {
@@ -739,19 +739,19 @@ func UpdateTheme(themeName string) error {
viper.Set("tui.theme", themeName)
return viper.SafeWriteConfig()
}
// Read the existing config file
configData, err := os.ReadFile(configFile)
if err != nil {
return fmt.Errorf("failed to read config file: %w", err)
}
// Parse the JSON
var configMap map[string]interface{}
if err := json.Unmarshal(configData, &configMap); err != nil {
return fmt.Errorf("failed to parse config file: %w", err)
}
// Update just the theme value
tuiConfig, ok := configMap["tui"].(map[string]interface{})
if !ok {
@@ -762,16 +762,16 @@ func UpdateTheme(themeName string) error {
tuiConfig["theme"] = themeName
configMap["tui"] = tuiConfig
}
// Write the updated config back to file
updatedData, err := json.MarshalIndent(configMap, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal config: %w", err)
}
if err := os.WriteFile(configFile, updatedData, 0644); err != nil {
return fmt.Errorf("failed to write config file: %w", err)
}
return nil
}

View File

@@ -92,6 +92,11 @@ func AvailableThemes() []string {
names = append(names, name)
}
slices.SortFunc(names, func(a, b string) int {
if a == "opencode" {
return -1
} else if b == "opencode" {
return 1
}
return strings.Compare(a, b)
})
return names

View File

@@ -0,0 +1,277 @@
package theme
import (
"github.com/charmbracelet/lipgloss"
)
// OpenCodeTheme implements the Theme interface with OpenCode brand colors.
// It provides both dark and light variants.
type OpenCodeTheme struct {
BaseTheme
}
// NewOpenCodeTheme creates a new instance of the OpenCode theme.
func NewOpenCodeTheme() *OpenCodeTheme {
// OpenCode color palette
// Dark mode colors
darkBackground := "#212121"
darkCurrentLine := "#252525"
darkSelection := "#303030"
darkForeground := "#e0e0e0"
darkComment := "#6a6a6a"
darkPrimary := "#fab283" // Primary orange/gold
darkSecondary := "#5c9cf5" // Secondary blue
darkAccent := "#9d7cd8" // Accent purple
darkRed := "#e06c75" // Error red
darkOrange := "#f5a742" // Warning orange
darkGreen := "#7fd88f" // Success green
darkCyan := "#56b6c2" // Info cyan
darkYellow := "#e5c07b" // Emphasized text
darkBorder := "#4b4c5c" // Border color
// Light mode colors
lightBackground := "#f8f8f8"
lightCurrentLine := "#f0f0f0"
lightSelection := "#e5e5e6"
lightForeground := "#2a2a2a"
lightComment := "#8a8a8a"
lightPrimary := "#3b7dd8" // Primary blue
lightSecondary := "#7b5bb6" // Secondary purple
lightAccent := "#d68c27" // Accent orange/gold
lightRed := "#d1383d" // Error red
lightOrange := "#d68c27" // Warning orange
lightGreen := "#3d9a57" // Success green
lightCyan := "#318795" // Info cyan
lightYellow := "#b0851f" // Emphasized text
lightBorder := "#d3d3d3" // Border color
theme := &OpenCodeTheme{}
// Base colors
theme.PrimaryColor = lipgloss.AdaptiveColor{
Dark: darkPrimary,
Light: lightPrimary,
}
theme.SecondaryColor = lipgloss.AdaptiveColor{
Dark: darkSecondary,
Light: lightSecondary,
}
theme.AccentColor = lipgloss.AdaptiveColor{
Dark: darkAccent,
Light: lightAccent,
}
// Status colors
theme.ErrorColor = lipgloss.AdaptiveColor{
Dark: darkRed,
Light: lightRed,
}
theme.WarningColor = lipgloss.AdaptiveColor{
Dark: darkOrange,
Light: lightOrange,
}
theme.SuccessColor = lipgloss.AdaptiveColor{
Dark: darkGreen,
Light: lightGreen,
}
theme.InfoColor = lipgloss.AdaptiveColor{
Dark: darkCyan,
Light: lightCyan,
}
// Text colors
theme.TextColor = lipgloss.AdaptiveColor{
Dark: darkForeground,
Light: lightForeground,
}
theme.TextMutedColor = lipgloss.AdaptiveColor{
Dark: darkComment,
Light: lightComment,
}
theme.TextEmphasizedColor = lipgloss.AdaptiveColor{
Dark: darkYellow,
Light: lightYellow,
}
// Background colors
theme.BackgroundColor = lipgloss.AdaptiveColor{
Dark: darkBackground,
Light: lightBackground,
}
theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{
Dark: darkCurrentLine,
Light: lightCurrentLine,
}
theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{
Dark: "#121212", // Slightly darker than background
Light: "#ffffff", // Slightly lighter than background
}
// Border colors
theme.BorderNormalColor = lipgloss.AdaptiveColor{
Dark: darkBorder,
Light: lightBorder,
}
theme.BorderFocusedColor = lipgloss.AdaptiveColor{
Dark: darkPrimary,
Light: lightPrimary,
}
theme.BorderDimColor = lipgloss.AdaptiveColor{
Dark: darkSelection,
Light: lightSelection,
}
// Diff view colors
theme.DiffAddedColor = lipgloss.AdaptiveColor{
Dark: "#478247",
Light: "#2E7D32",
}
theme.DiffRemovedColor = lipgloss.AdaptiveColor{
Dark: "#7C4444",
Light: "#C62828",
}
theme.DiffContextColor = lipgloss.AdaptiveColor{
Dark: "#a0a0a0",
Light: "#757575",
}
theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{
Dark: "#a0a0a0",
Light: "#757575",
}
theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{
Dark: "#DAFADA",
Light: "#A5D6A7",
}
theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{
Dark: "#FADADD",
Light: "#EF9A9A",
}
theme.DiffAddedBgColor = lipgloss.AdaptiveColor{
Dark: "#303A30",
Light: "#E8F5E9",
}
theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{
Dark: "#3A3030",
Light: "#FFEBEE",
}
theme.DiffContextBgColor = lipgloss.AdaptiveColor{
Dark: darkBackground,
Light: lightBackground,
}
theme.DiffLineNumberColor = lipgloss.AdaptiveColor{
Dark: "#888888",
Light: "#9E9E9E",
}
theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{
Dark: "#293229",
Light: "#C8E6C9",
}
theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{
Dark: "#332929",
Light: "#FFCDD2",
}
// Markdown colors
theme.MarkdownTextColor = lipgloss.AdaptiveColor{
Dark: darkForeground,
Light: lightForeground,
}
theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{
Dark: darkSecondary,
Light: lightSecondary,
}
theme.MarkdownLinkColor = lipgloss.AdaptiveColor{
Dark: darkPrimary,
Light: lightPrimary,
}
theme.MarkdownLinkTextColor = lipgloss.AdaptiveColor{
Dark: darkCyan,
Light: lightCyan,
}
theme.MarkdownCodeColor = lipgloss.AdaptiveColor{
Dark: darkGreen,
Light: lightGreen,
}
theme.MarkdownBlockQuoteColor = lipgloss.AdaptiveColor{
Dark: darkYellow,
Light: lightYellow,
}
theme.MarkdownEmphColor = lipgloss.AdaptiveColor{
Dark: darkYellow,
Light: lightYellow,
}
theme.MarkdownStrongColor = lipgloss.AdaptiveColor{
Dark: darkAccent,
Light: lightAccent,
}
theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{
Dark: darkComment,
Light: lightComment,
}
theme.MarkdownListItemColor = lipgloss.AdaptiveColor{
Dark: darkPrimary,
Light: lightPrimary,
}
theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{
Dark: darkCyan,
Light: lightCyan,
}
theme.MarkdownImageColor = lipgloss.AdaptiveColor{
Dark: darkPrimary,
Light: lightPrimary,
}
theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{
Dark: darkCyan,
Light: lightCyan,
}
theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{
Dark: darkForeground,
Light: lightForeground,
}
// Syntax highlighting colors
theme.SyntaxCommentColor = lipgloss.AdaptiveColor{
Dark: darkComment,
Light: lightComment,
}
theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{
Dark: darkSecondary,
Light: lightSecondary,
}
theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{
Dark: darkPrimary,
Light: lightPrimary,
}
theme.SyntaxVariableColor = lipgloss.AdaptiveColor{
Dark: darkRed,
Light: lightRed,
}
theme.SyntaxStringColor = lipgloss.AdaptiveColor{
Dark: darkGreen,
Light: lightGreen,
}
theme.SyntaxNumberColor = lipgloss.AdaptiveColor{
Dark: darkAccent,
Light: lightAccent,
}
theme.SyntaxTypeColor = lipgloss.AdaptiveColor{
Dark: darkYellow,
Light: lightYellow,
}
theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{
Dark: darkCyan,
Light: lightCyan,
}
theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{
Dark: darkForeground,
Light: lightForeground,
}
return theme
}
func init() {
// Register the OpenCode theme with the theme manager
RegisterTheme("opencode", NewOpenCodeTheme())
}