diff --git a/cmd/root.go b/cmd/root.go index 3a58cec4ed0914116f5c2a415540f0df8a0f143d..160be9dbec092493a6607326f9b9ea5304004d50 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -7,8 +7,7 @@ import ( "sync" "time" - tea "github.com/charmbracelet/bubbletea" - zone "github.com/lrstanley/bubblezone" + tea "github.com/charmbracelet/bubbletea/v2" "github.com/opencode-ai/opencode/internal/app" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/db" @@ -114,9 +113,7 @@ to assist developers in writing, debugging, and understanding code directly from return app.RunNonInteractive(ctx, prompt, outputFormat, quiet) } - // Interactive mode // Set up the TUI - zone.NewGlobal() program := tea.NewProgram( tui.New(app), tea.WithAltScreen(), diff --git a/go.mod b/go.mod index 82994450a85848a8b1be260b8d1611dec023ac1d..2891cac0969dd2c7f9ae6b512cb0d42130ffe2c0 100644 --- a/go.mod +++ b/go.mod @@ -11,15 +11,14 @@ require ( github.com/aymanbagabas/go-udiff v0.2.0 github.com/bmatcuk/doublestar/v4 v4.8.1 github.com/catppuccin/go v0.3.0 - github.com/charmbracelet/bubbles v0.21.0 - github.com/charmbracelet/bubbletea v1.3.5 - github.com/charmbracelet/glamour v0.9.1 - github.com/charmbracelet/lipgloss v1.1.0 - github.com/charmbracelet/x/ansi v0.8.0 + github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1 + github.com/charmbracelet/bubbletea/v2 v2.0.0-beta1 + github.com/charmbracelet/glamour/v2 v2.0.0-20250513163904-eeeced3bb3c6 + github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1.0.20250513162854-28902d027c40 + github.com/charmbracelet/x/ansi v0.9.2 github.com/fsnotify/fsnotify v1.8.0 github.com/go-logfmt/logfmt v0.6.0 github.com/google/uuid v1.6.0 - github.com/lrstanley/bubblezone v0.0.0-20250315020633-c249a3fe1231 github.com/mark3labs/mcp-go v0.17.0 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 github.com/muesli/reflow v0.3.0 @@ -58,13 +57,15 @@ require ( github.com/aws/smithy-go v1.20.3 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect - github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect + github.com/charmbracelet/colorprofile v0.3.0 // indirect + github.com/charmbracelet/x/cellbuf v0.0.14-0.20250326144200-0875329e71da // indirect + github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect + github.com/charmbracelet/x/input v0.3.4 // indirect github.com/charmbracelet/x/term v0.2.1 // indirect + github.com/charmbracelet/x/windows v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/disintegration/imaging v1.6.2 github.com/dlclark/regexp2 v1.11.4 // indirect - github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -81,7 +82,6 @@ require ( github.com/lithammer/fuzzysearch v1.1.8 github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mfridman/interpolate v0.0.2 // indirect github.com/microcosm-cc/bluemonday v1.0.27 // indirect @@ -119,7 +119,6 @@ require ( golang.org/x/net v0.39.0 // indirect golang.org/x/sync v0.13.0 // indirect golang.org/x/sys v0.32.0 // indirect - golang.org/x/term v0.31.0 // indirect golang.org/x/text v0.24.0 // indirect google.golang.org/genai v1.3.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect diff --git a/go.sum b/go.sum index 8b7e307442ad96a69ff3471fe8164a1ba2a46e8a..dfa16aaaba641df5043e9d2af89b626cc34bfc17 100644 --- a/go.sum +++ b/go.sum @@ -68,24 +68,30 @@ github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= -github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= -github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= -github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc= -github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= -github.com/charmbracelet/glamour v0.9.1 h1:11dEfiGP8q1BEqvGoIjivuc2rBk+5qEXdPtaQ2WoiCM= -github.com/charmbracelet/glamour v0.9.1/go.mod h1:+SHvIS8qnwhgTpVMiXwn7OfGomSqff1cHBCI8jLOetk= -github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= -github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= -github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= -github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= -github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1 h1:swACzss0FjnyPz1enfX56GKkLiuKg5FlyVmOLIlU2kE= +github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1/go.mod h1:6HamsBKWqEC/FVHuQMHgQL+knPyvHH55HwJDHl/adMw= +github.com/charmbracelet/bubbletea/v2 v2.0.0-beta1 h1:yaxFt97mvofGY7bYZn8U/aSVoamXGE3O4AEvWhshUDI= +github.com/charmbracelet/bubbletea/v2 v2.0.0-beta1/go.mod h1:qbcZLI5z8R49v9xBdU5V5Dh5D2uccx8wSwBqxQyErqc= +github.com/charmbracelet/colorprofile v0.3.0 h1:KtLh9uuu1RCt+Hml4s6Hz+kB1PfV3wi++1h5ia65yKQ= +github.com/charmbracelet/colorprofile v0.3.0/go.mod h1:oHJ340RS2nmG1zRGPmhJKJ/jf4FPNNk0P39/wBPA1G0= +github.com/charmbracelet/glamour/v2 v2.0.0-20250513163904-eeeced3bb3c6 h1:AKhOV8dSRU3KpqMgpGME9JU7ouumB2S6hMmD6PRJeTc= +github.com/charmbracelet/glamour/v2 v2.0.0-20250513163904-eeeced3bb3c6/go.mod h1:7xBAUTCSADx9mHG0uBf4NDoVpYxMzIQ2j/NMLGdFsFM= +github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1.0.20250513162854-28902d027c40 h1:SxOUomYAVo5zh+6WCH1bGshlAnSKP0ZeovI0FHAl9kg= +github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1.0.20250513162854-28902d027c40/go.mod h1:tRlx/Hu0lo/j9viunCN2H+Ze6JrmdjQlXUQvvArgaOc= +github.com/charmbracelet/x/ansi v0.9.2 h1:92AGsQmNTRMzuzHEYfCdjQeUzTrgE1vfO5/7fEVoXdY= +github.com/charmbracelet/x/ansi v0.9.2/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/cellbuf v0.0.14-0.20250326144200-0875329e71da h1:8MGKD5WBtuzfXglq0CnyzVSwGojv57X+H46OL9OUyRA= +github.com/charmbracelet/x/cellbuf v0.0.14-0.20250326144200-0875329e71da/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a h1:FsHEJ52OC4VuTzU8t+n5frMjLvpYWEznSr/u8tnkCYw= +github.com/charmbracelet/x/exp/golden v0.0.0-20250207160936-21c02780d27a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI= +github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU= +github.com/charmbracelet/x/input v0.3.4 h1:Mujmnv/4DaitU0p+kIsrlfZl/UlmeLKw1wAP3e1fMN0= +github.com/charmbracelet/x/input v0.3.4/go.mod h1:JI8RcvdZWQIhn09VzeK3hdp4lTz7+yhiEdpEQtZN+2c= github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/charmbracelet/x/windows v0.2.0 h1:ilXA1GJjTNkgOm94CLPeSz7rar54jtFatdmoiONPuEw= +github.com/charmbracelet/x/windows v0.2.0/go.mod h1:ZibNFR49ZFqCXgP76sYanisxRyC+EYrBE7TTknD8s1s= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -96,8 +102,6 @@ github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yA github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -146,16 +150,12 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= -github.com/lrstanley/bubblezone v0.0.0-20250315020633-c249a3fe1231 h1:9rjt7AfnrXKNSZhp36A3/4QAZAwGGCGD/p8Bse26zms= -github.com/lrstanley/bubblezone v0.0.0-20250315020633-c249a3fe1231/go.mod h1:S5etECMx+sZnW0Gm100Ma9J1PgVCTgNyFaqGu2b08b4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mark3labs/mcp-go v0.17.0 h1:5Ps6T7qXr7De/2QTqs9h6BKeZ/qdeUeGrgM5lPzi930= github.com/mark3labs/mcp-go v0.17.0/go.mod h1:KmJndYv7GIgcPVwEKJjNcbhVQ+hJGJhrCCB/9xITzpE= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -297,7 +297,6 @@ golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -318,8 +317,6 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= -golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= diff --git a/internal/diff/diff.go b/internal/diff/diff.go index 8f5e669d3c2c6741ea6facaab3f447283ed5a5ab..6dcafa984cd052102807e8454e7bfe047cf08d5d 100644 --- a/internal/diff/diff.go +++ b/internal/diff/diff.go @@ -3,6 +3,7 @@ package diff import ( "bytes" "fmt" + "image/color" "io" "regexp" "strconv" @@ -13,7 +14,7 @@ import ( "github.com/alecthomas/chroma/v2/lexers" "github.com/alecthomas/chroma/v2/styles" "github.com/aymanbagabas/go-udiff" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" "github.com/charmbracelet/x/ansi" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/tui/theme" @@ -323,7 +324,7 @@ func pairLines(lines []DiffLine) []linePair { // ------------------------------------------------------------------------- // SyntaxHighlight applies syntax highlighting to text based on file extension -func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg lipgloss.TerminalColor) error { +func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg color.Color) error { t := theme.CurrentTheme() // Determine the language lexer to use @@ -531,16 +532,13 @@ func SyntaxHighlight(w io.Writer, source, fileName, formatter string, bg lipglos return f.Format(w, s, it) } -// getColor returns the appropriate hex color string based on terminal background -func getColor(adaptiveColor lipgloss.AdaptiveColor) string { - if lipgloss.HasDarkBackground() { - return adaptiveColor.Dark - } - return adaptiveColor.Light +func getColor(c color.Color) string { + rgba := color.RGBAModel.Convert(c).(color.RGBA) + return fmt.Sprintf("#%02x%02x%02x", rgba.R, rgba.G, rgba.B) } // highlightLine applies syntax highlighting to a single line -func highlightLine(fileName string, line string, bg lipgloss.TerminalColor) string { +func highlightLine(fileName string, line string, bg color.Color) string { var buf bytes.Buffer err := SyntaxHighlight(&buf, line, fileName, "terminal16m", bg) if err != nil { @@ -563,7 +561,7 @@ func createStyles(t theme.Theme) (removedLineStyle, addedLineStyle, contextLineS // Rendering Functions // ------------------------------------------------------------------------- -func lipglossToHex(color lipgloss.Color) string { +func lipglossToHex(color color.Color) string { r, g, b, a := color.RGBA() // Scale uint32 values (0-65535) to uint8 (0-255). @@ -576,7 +574,7 @@ func lipglossToHex(color lipgloss.Color) string { } // applyHighlighting applies intra-line highlighting to a piece of text -func applyHighlighting(content string, segments []Segment, segmentType LineType, highlightBg lipgloss.AdaptiveColor) string { +func applyHighlighting(content string, segments []Segment, segmentType LineType, highlightBg color.Color) string { // Find all ANSI sequences in the content ansiRegex := regexp.MustCompile(`\x1b(?:[@-Z\\-_]|\[[0-9?]*(?:;[0-9?]*)*[@-~])`) ansiMatches := ansiRegex.FindAllStringIndex(content, -1) diff --git a/internal/format/spinner.go b/internal/format/spinner.go index 083ee557f82ea903fb9d1d7be5da1da120744f6c..89eb9d25cacd28584575711508ec5f89b7ef163c 100644 --- a/internal/format/spinner.go +++ b/internal/format/spinner.go @@ -5,8 +5,8 @@ import ( "fmt" "os" - "github.com/charmbracelet/bubbles/spinner" - tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/bubbles/v2/spinner" + tea "github.com/charmbracelet/bubbletea/v2" ) // Spinner wraps the bubbles spinner for non-interactive mode diff --git a/internal/tui/components/chat/chat.go b/internal/tui/components/chat/chat.go index 1ad3f683d7a7e7f851c6e6696d4d7d4692f313bd..2aa7ee5d07f324ca45e80dc4fbab9964f05721bb 100644 --- a/internal/tui/components/chat/chat.go +++ b/internal/tui/components/chat/chat.go @@ -4,7 +4,7 @@ import ( "fmt" "sort" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" "github.com/charmbracelet/x/ansi" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/message" diff --git a/internal/tui/components/chat/editor.go b/internal/tui/components/chat/editor.go index a6c5a44e8d96bdd6cc69a52f3f0ac95fad883fb3..4f3f69665a9af6d622214431ca563dff20764412 100644 --- a/internal/tui/components/chat/editor.go +++ b/internal/tui/components/chat/editor.go @@ -8,10 +8,10 @@ import ( "strings" "unicode" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/textarea" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/textarea" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/app" "github.com/opencode-ai/opencode/internal/logging" "github.com/opencode-ai/opencode/internal/message" @@ -162,7 +162,7 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, cmd } m.attachments = append(m.attachments, msg.Attachment) - case tea.KeyMsg: + case tea.KeyPressMsg: if key.Matches(msg, DeleteKeyMaps.AttachmentDeleteMode) { m.deleteMode = true return m, nil @@ -172,8 +172,9 @@ func (m *editorCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.attachments = nil return m, nil } - if m.deleteMode && len(msg.Runes) > 0 && unicode.IsDigit(msg.Runes[0]) { - num := int(msg.Runes[0] - '0') + rune := msg.Code + if m.deleteMode && unicode.IsDigit(rune) { + num := int(rune - '0') m.deleteMode = false if num < 10 && len(m.attachments) > num { if num == 0 { @@ -286,14 +287,22 @@ func CreateTextArea(existing *textarea.Model) textarea.Model { textMutedColor := t.TextMuted() ta := textarea.New() - ta.BlurredStyle.Base = styles.BaseStyle().Background(bgColor).Foreground(textColor) - ta.BlurredStyle.CursorLine = styles.BaseStyle().Background(bgColor) - ta.BlurredStyle.Placeholder = styles.BaseStyle().Background(bgColor).Foreground(textMutedColor) - ta.BlurredStyle.Text = styles.BaseStyle().Background(bgColor).Foreground(textColor) - ta.FocusedStyle.Base = styles.BaseStyle().Background(bgColor).Foreground(textColor) - ta.FocusedStyle.CursorLine = styles.BaseStyle().Background(bgColor) - ta.FocusedStyle.Placeholder = styles.BaseStyle().Background(bgColor).Foreground(textMutedColor) - ta.FocusedStyle.Text = styles.BaseStyle().Background(bgColor).Foreground(textColor) + s := textarea.DefaultDarkStyles() + b := s.Blurred + b.Base = styles.BaseStyle().Background(bgColor).Foreground(textColor) + b.CursorLine = styles.BaseStyle().Background(bgColor) + b.Placeholder = styles.BaseStyle().Background(bgColor).Foreground(textMutedColor) + b.Text = styles.BaseStyle().Background(bgColor).Foreground(textColor) + + f := s.Focused + f.Base = styles.BaseStyle().Background(bgColor).Foreground(textColor) + f.CursorLine = styles.BaseStyle().Background(bgColor) + f.Placeholder = styles.BaseStyle().Background(bgColor).Foreground(textMutedColor) + f.Text = styles.BaseStyle().Background(bgColor).Foreground(textColor) + + s.Focused = f + s.Blurred = b + ta.Styles = s ta.Prompt = " " ta.ShowLineNumbers = false @@ -309,7 +318,7 @@ func CreateTextArea(existing *textarea.Model) textarea.Model { return ta } -func NewEditorCmp(app *app.App) tea.Model { +func NewEditorCmp(app *app.App) util.Model { ta := CreateTextArea(nil) return &editorCmp{ app: app, diff --git a/internal/tui/components/chat/list.go b/internal/tui/components/chat/list.go index 40d5b962876f09f60f44092f0c21b1f1ec9e4bb1..9cfb5c51cc91723fcedd3a03d1e11c173c33509d 100644 --- a/internal/tui/components/chat/list.go +++ b/internal/tui/components/chat/list.go @@ -5,11 +5,11 @@ import ( "fmt" "math" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/spinner" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/spinner" + "github.com/charmbracelet/bubbles/v2/viewport" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/app" "github.com/opencode-ai/opencode/internal/message" "github.com/opencode-ai/opencode/internal/pubsub" @@ -426,10 +426,10 @@ func (m *messagesCmp) SetSize(width, height int) tea.Cmd { } m.width = width m.height = height - m.viewport.Width = width - m.viewport.Height = height - 2 - m.attachments.Width = width + 40 - m.attachments.Height = 3 + m.viewport.SetWidth(width) + m.viewport.SetHeight(height - 2) + m.attachments.SetWidth(width + 40) + m.attachments.SetHeight(3) m.rerender() return nil } @@ -468,11 +468,11 @@ func (m *messagesCmp) BindingKeys() []key.Binding { } } -func NewMessagesCmp(app *app.App) tea.Model { +func NewMessagesCmp(app *app.App) util.Model { s := spinner.New() s.Spinner = spinner.Pulse - vp := viewport.New(0, 0) - attachmets := viewport.New(0, 0) + vp := viewport.New() + attachmets := viewport.New() vp.KeyMap.PageUp = messageKeys.PageUp vp.KeyMap.PageDown = messageKeys.PageDown vp.KeyMap.HalfPageUp = messageKeys.HalfPageUp diff --git a/internal/tui/components/chat/message.go b/internal/tui/components/chat/message.go index 0732366d94c01dc8d183f97dcebbe8a220554f74..f1fdda7265cb1697f10d68cde45c9d0563ecbed3 100644 --- a/internal/tui/components/chat/message.go +++ b/internal/tui/components/chat/message.go @@ -8,7 +8,7 @@ import ( "strings" "time" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" "github.com/charmbracelet/x/ansi" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/diff" @@ -60,7 +60,7 @@ func renderMessage(msg string, isUser bool, isFocused bool, width int, info ...s // Apply markdown formatting and handle background color parts := []string{ - styles.ForceReplaceBackgroundWithLipgloss(toMarkdown(msg, isFocused, width), t.Background()), + toMarkdown(msg, isFocused, width), } // Remove newline at the end @@ -454,16 +454,10 @@ func renderToolResponse(toolCall message.ToolCall, response message.ToolResult, resultContent := truncateHeight(response.Content, maxResultHeight) switch toolCall.Name { case agent.AgentToolName: - return styles.ForceReplaceBackgroundWithLipgloss( - toMarkdown(resultContent, false, width), - t.Background(), - ) + return toMarkdown(resultContent, false, width) case tools.BashToolName: resultContent = fmt.Sprintf("```bash\n%s\n```", resultContent) - return styles.ForceReplaceBackgroundWithLipgloss( - toMarkdown(resultContent, true, width), - t.Background(), - ) + return toMarkdown(resultContent, true, width) case tools.EditToolName: metadata := tools.EditResponseMetadata{} json.Unmarshal([]byte(response.Metadata), &metadata) @@ -481,10 +475,7 @@ func renderToolResponse(toolCall message.ToolCall, response message.ToolResult, mdFormat = "html" } resultContent = fmt.Sprintf("```%s\n%s\n```", mdFormat, resultContent) - return styles.ForceReplaceBackgroundWithLipgloss( - toMarkdown(resultContent, true, width), - t.Background(), - ) + return toMarkdown(resultContent, true, width) case tools.GlobToolName: return baseStyle.Width(width).Foreground(t.TextMuted()).Render(resultContent) case tools.GrepToolName: @@ -503,10 +494,7 @@ func renderToolResponse(toolCall message.ToolCall, response message.ToolResult, ext = strings.ToLower(ext[1:]) } resultContent = fmt.Sprintf("```%s\n%s\n```", ext, truncateHeight(metadata.Content, maxResultHeight)) - return styles.ForceReplaceBackgroundWithLipgloss( - toMarkdown(resultContent, true, width), - t.Background(), - ) + return toMarkdown(resultContent, true, width) case tools.WriteToolName: params := tools.WriteParams{} json.Unmarshal([]byte(toolCall.Input), ¶ms) @@ -519,16 +507,10 @@ func renderToolResponse(toolCall message.ToolCall, response message.ToolResult, ext = strings.ToLower(ext[1:]) } resultContent = fmt.Sprintf("```%s\n%s\n```", ext, truncateHeight(params.Content, maxResultHeight)) - return styles.ForceReplaceBackgroundWithLipgloss( - toMarkdown(resultContent, true, width), - t.Background(), - ) + return toMarkdown(resultContent, true, width) default: resultContent = fmt.Sprintf("```text\n%s\n```", resultContent) - return styles.ForceReplaceBackgroundWithLipgloss( - toMarkdown(resultContent, true, width), - t.Background(), - ) + return toMarkdown(resultContent, true, width) } } diff --git a/internal/tui/components/chat/sidebar.go b/internal/tui/components/chat/sidebar.go index a66249b368cd28274333395cb79a5b127b3fb8f9..b54769038c508894f0fa289aadcba9e82b3f189f 100644 --- a/internal/tui/components/chat/sidebar.go +++ b/internal/tui/components/chat/sidebar.go @@ -6,8 +6,8 @@ import ( "sort" "strings" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/diff" "github.com/opencode-ai/opencode/internal/history" @@ -15,6 +15,7 @@ import ( "github.com/opencode-ai/opencode/internal/session" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" + "github.com/opencode-ai/opencode/internal/tui/util" ) type sidebarCmp struct { @@ -235,7 +236,7 @@ func (m *sidebarCmp) GetSize() (int, int) { return m.width, m.height } -func NewSidebarCmp(session session.Session, history history.Service) tea.Model { +func NewSidebarCmp(session session.Session, history history.Service) util.Model { return &sidebarCmp{ session: session, history: history, diff --git a/internal/tui/components/core/status.go b/internal/tui/components/core/status.go index 0dc227a80ebbbcdd8a4e3578a11b1fe6f64aca4a..037bd7417897a75f62feb16eca90b81a82360648 100644 --- a/internal/tui/components/core/status.go +++ b/internal/tui/components/core/status.go @@ -5,8 +5,8 @@ import ( "strings" "time" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/llm/models" "github.com/opencode-ai/opencode/internal/lsp" @@ -20,7 +20,7 @@ import ( ) type StatusCmp interface { - tea.Model + util.Model } type statusCmp struct { diff --git a/internal/tui/components/dialog/arguments.go b/internal/tui/components/dialog/arguments.go index 684d8662fcc357adb33f873da9eadab1d3ca6a67..a988407453322267c7cf96fa626b09f6b2ac36fd 100644 --- a/internal/tui/components/dialog/arguments.go +++ b/internal/tui/components/dialog/arguments.go @@ -2,10 +2,11 @@ package dialog import ( "fmt" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/textinput" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" @@ -70,17 +71,18 @@ func NewMultiArgumentsDialogCmp(commandID, content string, argNames []string) Mu for i, name := range argNames { ti := textinput.New() ti.Placeholder = fmt.Sprintf("Enter value for %s...", name) - ti.Width = 40 + ti.SetWidth(40) ti.Prompt = "" - ti.PlaceholderStyle = ti.PlaceholderStyle.Background(t.Background()) - ti.PromptStyle = ti.PromptStyle.Background(t.Background()) - ti.TextStyle = ti.TextStyle.Background(t.Background()) - + ti.Styles.Focused.Placeholder = ti.Styles.Focused.Placeholder.Background(t.Background()) + ti.Styles.Blurred.Placeholder = ti.Styles.Blurred.Placeholder.Background(t.Background()) + ti.Styles.Focused.Suggestion = ti.Styles.Focused.Suggestion.Background(t.Background()).Foreground(t.Primary()) + ti.Styles.Blurred.Suggestion = ti.Styles.Blurred.Suggestion.Background(t.Background()) + ti.Styles.Focused.Text = ti.Styles.Focused.Text.Background(t.Background()).Foreground(t.Primary()) + ti.Styles.Blurred.Text = ti.Styles.Blurred.Text.Background(t.Background()) + // Only focus the first input initially if i == 0 { ti.Focus() - ti.PromptStyle = ti.PromptStyle.Foreground(t.Primary()) - ti.TextStyle = ti.TextStyle.Foreground(t.Primary()) } else { ti.Blur() } @@ -89,11 +91,11 @@ func NewMultiArgumentsDialogCmp(commandID, content string, argNames []string) Mu } return MultiArgumentsDialogCmp{ - inputs: inputs, - keys: argumentsDialogKeyMap{}, - commandID: commandID, - content: content, - argNames: argNames, + inputs: inputs, + keys: argumentsDialogKeyMap{}, + commandID: commandID, + content: content, + argNames: argNames, focusIndex: 0, } } @@ -108,15 +110,13 @@ func (m MultiArgumentsDialogCmp) Init() tea.Cmd { m.inputs[i].Blur() } } - + return textinput.Blink } // Update implements tea.Model. func (m MultiArgumentsDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmds []tea.Cmd - t := theme.CurrentTheme() - switch msg := msg.(type) { case tea.KeyMsg: switch { @@ -145,22 +145,16 @@ func (m MultiArgumentsDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.inputs[m.focusIndex].Blur() m.focusIndex++ m.inputs[m.focusIndex].Focus() - m.inputs[m.focusIndex].PromptStyle = m.inputs[m.focusIndex].PromptStyle.Foreground(t.Primary()) - m.inputs[m.focusIndex].TextStyle = m.inputs[m.focusIndex].TextStyle.Foreground(t.Primary()) case key.Matches(msg, key.NewBinding(key.WithKeys("tab"))): // Move to the next input m.inputs[m.focusIndex].Blur() m.focusIndex = (m.focusIndex + 1) % len(m.inputs) m.inputs[m.focusIndex].Focus() - m.inputs[m.focusIndex].PromptStyle = m.inputs[m.focusIndex].PromptStyle.Foreground(t.Primary()) - m.inputs[m.focusIndex].TextStyle = m.inputs[m.focusIndex].TextStyle.Foreground(t.Primary()) case key.Matches(msg, key.NewBinding(key.WithKeys("shift+tab"))): // Move to the previous input m.inputs[m.focusIndex].Blur() m.focusIndex = (m.focusIndex - 1 + len(m.inputs)) % len(m.inputs) m.inputs[m.focusIndex].Focus() - m.inputs[m.focusIndex].PromptStyle = m.inputs[m.focusIndex].PromptStyle.Foreground(t.Primary()) - m.inputs[m.focusIndex].TextStyle = m.inputs[m.focusIndex].TextStyle.Foreground(t.Primary()) } case tea.WindowSizeMsg: m.width = msg.Width @@ -206,13 +200,13 @@ func (m MultiArgumentsDialogCmp) View() string { Width(maxWidth). Padding(1, 1, 0, 1). Background(t.Background()) - + if i == m.focusIndex { labelStyle = labelStyle.Foreground(t.Primary()).Bold(true) } else { labelStyle = labelStyle.Foreground(t.TextMuted()) } - + label := labelStyle.Render(m.argNames[i] + ":") field := lipgloss.NewStyle(). @@ -254,4 +248,4 @@ func (m *MultiArgumentsDialogCmp) SetSize(width, height int) { // Bindings implements layout.Bindings. func (m MultiArgumentsDialogCmp) Bindings() []key.Binding { return m.keys.ShortHelp() -} \ No newline at end of file +} diff --git a/internal/tui/components/dialog/commands.go b/internal/tui/components/dialog/commands.go index 25069b8a6dd39633e46b8627ff4a066bc52b1239..695f94da6191dcc5015b954e9890be37bb0d03fa 100644 --- a/internal/tui/components/dialog/commands.go +++ b/internal/tui/components/dialog/commands.go @@ -1,9 +1,9 @@ package dialog import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" utilComponents "github.com/opencode-ai/opencode/internal/tui/components/util" "github.com/opencode-ai/opencode/internal/tui/layout" "github.com/opencode-ai/opencode/internal/tui/styles" @@ -56,7 +56,7 @@ type CloseCommandDialogMsg struct{} // CommandDialog interface for the command selection dialog type CommandDialog interface { - tea.Model + util.Model layout.Bindings SetCommands(commands []Command) } diff --git a/internal/tui/components/dialog/complete.go b/internal/tui/components/dialog/complete.go index 1ce66e12ae79eee479c45a7e6138123f1c77879c..cda4636be44ac637ffb8172015c7863c422fcde7 100644 --- a/internal/tui/components/dialog/complete.go +++ b/internal/tui/components/dialog/complete.go @@ -1,10 +1,10 @@ package dialog import ( - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/textarea" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/textarea" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/logging" utilComponents "github.com/opencode-ai/opencode/internal/tui/components/util" "github.com/opencode-ai/opencode/internal/tui/layout" @@ -77,7 +77,7 @@ type CompletionDialogCompleteItemMsg struct { type CompletionDialogCloseMsg struct{} type CompletionDialog interface { - tea.Model + util.Model layout.Bindings SetWidth(width int) } diff --git a/internal/tui/components/dialog/custom_commands.go b/internal/tui/components/dialog/custom_commands.go index 049c4735b5bc4302da87d349d885756882e3c14f..cd1ed3988ea10ff35400f90e427b9b054e6348cd 100644 --- a/internal/tui/components/dialog/custom_commands.go +++ b/internal/tui/components/dialog/custom_commands.go @@ -7,7 +7,7 @@ import ( "regexp" "strings" - tea "github.com/charmbracelet/bubbletea" + tea "github.com/charmbracelet/bubbletea/v2" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/tui/util" ) diff --git a/internal/tui/components/dialog/filepicker.go b/internal/tui/components/dialog/filepicker.go index 3b9a0dc6c39a090e084b010a4ac5640f338a4836..2955c27514eb3eeb8cf7ec1c48a9b5e31d2a6c84 100644 --- a/internal/tui/components/dialog/filepicker.go +++ b/internal/tui/components/dialog/filepicker.go @@ -9,11 +9,11 @@ import ( "strings" "time" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/textinput" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/textinput" + "github.com/charmbracelet/bubbles/v2/viewport" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/app" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/logging" @@ -122,8 +122,8 @@ func (f *filepickerCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: f.width = 60 f.height = 20 - f.viewport.Width = 80 - f.viewport.Height = 22 + f.viewport.SetWidth(80) + f.viewport.SetHeight(22) f.cursor = 0 f.getCurrentFileBelowCursor() case tea.KeyMsg: @@ -319,7 +319,7 @@ func (f *filepickerCmp) View() string { Render(f.cwd.View()) viewportstyle := lipgloss.NewStyle(). - Width(f.viewport.Width). + Width(f.viewport.Width()). Background(t.Background()). Border(lipgloss.RoundedBorder()). BorderForeground(t.TextMuted()). @@ -353,7 +353,7 @@ func (f *filepickerCmp) View() string { } type FilepickerCmp interface { - tea.Model + util.Model ToggleFilepicker(showFilepicker bool) IsCWDFocused() bool } @@ -374,11 +374,11 @@ func NewFilepickerCmp(app *app.App) FilepickerCmp { } baseDir := DirNode{parent: nil, directory: homepath} dirs := readDir(homepath, false) - viewport := viewport.New(0, 0) + viewport := viewport.New() currentDirectory := textinput.New() currentDirectory.CharLimit = 200 - currentDirectory.Width = 44 - currentDirectory.Cursor.Blink = true + currentDirectory.SetWidth(44) + currentDirectory.Cursor().Blink = true currentDirectory.SetValue(baseDir.directory) return &filepickerCmp{cwdDetails: &baseDir, dirs: dirs, cursorChain: make(stack, 0), viewport: viewport, cwd: currentDirectory, app: app} } @@ -396,7 +396,7 @@ func (f *filepickerCmp) getCurrentFileBelowCursor() { fullPath := f.cwdDetails.directory + "/" + dir.Name() go func() { - imageString, err := image.ImagePreview(f.viewport.Width-4, fullPath) + imageString, err := image.ImagePreview(f.viewport.Width()-4, fullPath) if err != nil { logging.Error(err.Error()) f.viewport.SetContent("Preview unavailable") diff --git a/internal/tui/components/dialog/help.go b/internal/tui/components/dialog/help.go index 90959ad2ed540ac23e3285da0380c7b88635f708..63416f4250548c51cce14308b6efac617221a2c2 100644 --- a/internal/tui/components/dialog/help.go +++ b/internal/tui/components/dialog/help.go @@ -3,11 +3,12 @@ package dialog import ( "strings" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" + "github.com/opencode-ai/opencode/internal/tui/util" ) type helpCmp struct { @@ -134,7 +135,7 @@ func (h *helpCmp) render() string { pairs = append(pairs, pair) } - // https://github.com/charmbracelet/lipgloss/issues/209 + // https://github.com/charmbracelet/lipgloss/v2/issues/209 if len(pairs) > 1 { prefix := pairs[:len(pairs)-1] lastPair := pairs[len(pairs)-1] @@ -144,7 +145,7 @@ func (h *helpCmp) render() string { lipgloss.Left, // x lipgloss.Top, // y lastPair, // content - lipgloss.WithWhitespaceBackground(t.Background()), + lipgloss.WithWhitespaceStyle(lipgloss.NewStyle().Background(t.Background())), )) content := baseStyle.Width(h.width).Render( lipgloss.JoinHorizontal( @@ -191,7 +192,7 @@ func (h *helpCmp) View() string { } type HelpCmp interface { - tea.Model + util.Model SetBindings([]key.Binding) } diff --git a/internal/tui/components/dialog/init.go b/internal/tui/components/dialog/init.go index 77c76584d9bf1abaceb2206c3f577c8834c3cc04..1224cbe10ad7dd54811ea1db4b16cddb718544a2 100644 --- a/internal/tui/components/dialog/init.go +++ b/internal/tui/components/dialog/init.go @@ -1,9 +1,9 @@ package dialog import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" diff --git a/internal/tui/components/dialog/models.go b/internal/tui/components/dialog/models.go index 77c2a02ac1979d7ad5fe0c8f4845f73f6ea36e81..c17f87cde3c5a3f066c7a5371fbff66f2a8c7d09 100644 --- a/internal/tui/components/dialog/models.go +++ b/internal/tui/components/dialog/models.go @@ -5,9 +5,9 @@ import ( "slices" "strings" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/llm/models" "github.com/opencode-ai/opencode/internal/tui/layout" @@ -31,7 +31,7 @@ type CloseModelDialogMsg struct{} // ModelDialog interface for the model selection dialog type ModelDialog interface { - tea.Model + util.Model layout.Bindings } @@ -281,7 +281,6 @@ func (m *modelDialogCmp) setupModels() { } func GetSelectedModel(cfg *config.Config) models.Model { - agentCfg := cfg.Agents[config.AgentCoder] selectedModelId := agentCfg.Model return models.SupportedModels[selectedModelId] diff --git a/internal/tui/components/dialog/permission.go b/internal/tui/components/dialog/permission.go index 6c135098a7ade938e7bec1a69b4a3a6f5db79d6f..16c53266383d3cdfc1d5f8bda096b099b7bb170a 100644 --- a/internal/tui/components/dialog/permission.go +++ b/internal/tui/components/dialog/permission.go @@ -4,10 +4,10 @@ import ( "fmt" "strings" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/viewport" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/diff" "github.com/opencode-ai/opencode/internal/llm/tools" "github.com/opencode-ai/opencode/internal/permission" @@ -34,7 +34,7 @@ type PermissionResponseMsg struct { // PermissionDialogCmp interface for permission dialog component type PermissionDialogCmp interface { - tea.Model + util.Model layout.Bindings SetPermissions(permission permission.PermissionRequest) tea.Cmd } @@ -268,7 +268,6 @@ func (p *permissionDialogCmp) renderHeader() string { } func (p *permissionDialogCmp) renderBashContent() string { - t := theme.CurrentTheme() baseStyle := styles.BaseStyle() if pr, ok := p.permission.Params.(tools.BashPermissionsParams); ok { @@ -278,11 +277,11 @@ func (p *permissionDialogCmp) renderBashContent() string { renderedContent := p.GetOrSetMarkdown(p.permission.ID, func() (string, error) { r := styles.GetMarkdownRenderer(p.width - 10) s, err := r.Render(content) - return styles.ForceReplaceBackgroundWithLipgloss(s, t.Background()), err + return s, err }) finalContent := baseStyle. - Width(p.contentViewPort.Width). + Width(p.contentViewPort.Width()). Render(renderedContent) p.contentViewPort.SetContent(finalContent) return p.styleViewport() @@ -293,7 +292,7 @@ func (p *permissionDialogCmp) renderBashContent() string { func (p *permissionDialogCmp) renderEditContent() string { if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok { diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) { - return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width)) + return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width())) }) p.contentViewPort.SetContent(diff) @@ -305,7 +304,7 @@ func (p *permissionDialogCmp) renderEditContent() string { func (p *permissionDialogCmp) renderPatchContent() string { if pr, ok := p.permission.Params.(tools.EditPermissionsParams); ok { diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) { - return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width)) + return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width())) }) p.contentViewPort.SetContent(diff) @@ -318,7 +317,7 @@ func (p *permissionDialogCmp) renderWriteContent() string { if pr, ok := p.permission.Params.(tools.WritePermissionsParams); ok { // Use the cache for diff rendering diff := p.GetOrSetDiff(p.permission.ID, func() (string, error) { - return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width)) + return diff.FormatDiff(pr.Diff, diff.WithTotalWidth(p.contentViewPort.Width())) }) p.contentViewPort.SetContent(diff) @@ -328,7 +327,6 @@ func (p *permissionDialogCmp) renderWriteContent() string { } func (p *permissionDialogCmp) renderFetchContent() string { - t := theme.CurrentTheme() baseStyle := styles.BaseStyle() if pr, ok := p.permission.Params.(tools.FetchPermissionsParams); ok { @@ -338,11 +336,11 @@ func (p *permissionDialogCmp) renderFetchContent() string { renderedContent := p.GetOrSetMarkdown(p.permission.ID, func() (string, error) { r := styles.GetMarkdownRenderer(p.width - 10) s, err := r.Render(content) - return styles.ForceReplaceBackgroundWithLipgloss(s, t.Background()), err + return s, err }) finalContent := baseStyle. - Width(p.contentViewPort.Width). + Width(p.contentViewPort.Width()). Render(renderedContent) p.contentViewPort.SetContent(finalContent) return p.styleViewport() @@ -351,7 +349,6 @@ func (p *permissionDialogCmp) renderFetchContent() string { } func (p *permissionDialogCmp) renderDefaultContent() string { - t := theme.CurrentTheme() baseStyle := styles.BaseStyle() content := p.permission.Description @@ -360,11 +357,11 @@ func (p *permissionDialogCmp) renderDefaultContent() string { renderedContent := p.GetOrSetMarkdown(p.permission.ID, func() (string, error) { r := styles.GetMarkdownRenderer(p.width - 10) s, err := r.Render(content) - return styles.ForceReplaceBackgroundWithLipgloss(s, t.Background()), err + return s, err }) finalContent := baseStyle. - Width(p.contentViewPort.Width). + Width(p.contentViewPort.Width()). Render(renderedContent) p.contentViewPort.SetContent(finalContent) @@ -398,8 +395,8 @@ func (p *permissionDialogCmp) render() string { buttons := p.renderButtons() // Calculate content height dynamically based on window size - p.contentViewPort.Height = p.height - lipgloss.Height(headerContent) - lipgloss.Height(buttons) - 2 - lipgloss.Height(title) - p.contentViewPort.Width = p.width - 4 + p.contentViewPort.SetHeight(p.height - lipgloss.Height(headerContent) - lipgloss.Height(buttons) - 2 - lipgloss.Height(title)) + p.contentViewPort.SetWidth(p.width - 4) // Render content based on tool type var contentFinal string @@ -511,7 +508,7 @@ func (c *permissionDialogCmp) GetOrSetMarkdown(key string, generator func() (str func NewPermissionDialogCmp() PermissionDialogCmp { // Create viewport for content - contentViewport := viewport.New(0, 0) + contentViewport := viewport.New() return &permissionDialogCmp{ contentViewPort: contentViewport, diff --git a/internal/tui/components/dialog/quit.go b/internal/tui/components/dialog/quit.go index f755fa272547657c84a40125421d9e7411a1530e..0331a9ac5fe433b0a02b39a1f498ce8a28d4bb78 100644 --- a/internal/tui/components/dialog/quit.go +++ b/internal/tui/components/dialog/quit.go @@ -3,9 +3,9 @@ package dialog import ( "strings" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/layout" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" @@ -17,7 +17,7 @@ const question = "Are you sure you want to quit?" type CloseQuitMsg struct{} type QuitDialog interface { - tea.Model + util.Model layout.Bindings } @@ -84,7 +84,7 @@ func (q *quitDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (q *quitDialogCmp) View() string { t := theme.CurrentTheme() baseStyle := styles.BaseStyle() - + yesStyle := baseStyle noStyle := baseStyle spacerStyle := baseStyle.Background(t.Background()) diff --git a/internal/tui/components/dialog/session.go b/internal/tui/components/dialog/session.go index a29fa7131ed1b1abbe7ae170eb2af107ad5c5647..60b5b8f360bc0383bde7e38ac4fa14ecf99d4fd1 100644 --- a/internal/tui/components/dialog/session.go +++ b/internal/tui/components/dialog/session.go @@ -1,9 +1,9 @@ package dialog import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/session" "github.com/opencode-ai/opencode/internal/tui/layout" "github.com/opencode-ai/opencode/internal/tui/styles" @@ -21,7 +21,7 @@ type CloseSessionDialogMsg struct{} // SessionDialog interface for the session switching dialog type SessionDialog interface { - tea.Model + util.Model layout.Bindings SetSessions(sessions []session.Session) SetSelectedSession(sessionID string) @@ -108,7 +108,7 @@ func (s *sessionDialogCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (s *sessionDialogCmp) View() string { t := theme.CurrentTheme() baseStyle := styles.BaseStyle() - + if len(s.sessions) == 0 { return baseStyle.Padding(1, 2). Border(lipgloss.RoundedBorder()). @@ -181,7 +181,6 @@ func (s *sessionDialogCmp) View() string { Border(lipgloss.RoundedBorder()). BorderBackground(t.Background()). BorderForeground(t.TextMuted()). - Width(lipgloss.Width(content) + 4). Render(content) } diff --git a/internal/tui/components/dialog/theme.go b/internal/tui/components/dialog/theme.go index d35d3e2b6df04ca6049728224533293ba0ef2285..29e854d3d6b2db07a4aaaa3ebc218e4e6d1dfaf5 100644 --- a/internal/tui/components/dialog/theme.go +++ b/internal/tui/components/dialog/theme.go @@ -1,9 +1,9 @@ package dialog import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/layout" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" @@ -20,7 +20,7 @@ type CloseThemeDialogMsg struct{} // ThemeDialog interface for the theme switching dialog type ThemeDialog interface { - tea.Model + util.Model layout.Bindings } @@ -195,4 +195,3 @@ func NewThemeDialogCmp() ThemeDialog { currentTheme: "", } } - diff --git a/internal/tui/components/logs/details.go b/internal/tui/components/logs/details.go index 9d7713bbf048beea68dc0d007af948df2b2a6127..875395cfe5c535eba8be73a3eccc92f4f666dc53 100644 --- a/internal/tui/components/logs/details.go +++ b/internal/tui/components/logs/details.go @@ -5,18 +5,18 @@ import ( "strings" "time" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/viewport" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/logging" "github.com/opencode-ai/opencode/internal/tui/layout" - "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" + "github.com/opencode-ai/opencode/internal/tui/util" ) type DetailComponent interface { - tea.Model + util.Model layout.Sizeable layout.Bindings } @@ -99,7 +99,7 @@ func (i *detailCmp) updateContent() { func getLevelStyle(level string) lipgloss.Style { style := lipgloss.NewStyle().Bold(true) t := theme.CurrentTheme() - + switch strings.ToLower(level) { case "info": return style.Foreground(t.Info()) @@ -115,8 +115,7 @@ func getLevelStyle(level string) lipgloss.Style { } func (i *detailCmp) View() string { - t := theme.CurrentTheme() - return styles.ForceReplaceBackgroundWithLipgloss(i.viewport.View(), t.Background()) + return i.viewport.View() } func (i *detailCmp) GetSize() (int, int) { @@ -126,8 +125,8 @@ func (i *detailCmp) GetSize() (int, int) { func (i *detailCmp) SetSize(width int, height int) tea.Cmd { i.width = width i.height = height - i.viewport.Width = i.width - i.viewport.Height = i.height + i.viewport.SetWidth(i.width) + i.viewport.SetHeight(i.height) i.updateContent() return nil } @@ -138,6 +137,6 @@ func (i *detailCmp) BindingKeys() []key.Binding { func NewLogsDetails() DetailComponent { return &detailCmp{ - viewport: viewport.New(0, 0), + viewport: viewport.New(), } } diff --git a/internal/tui/components/logs/table.go b/internal/tui/components/logs/table.go index 8d59f967f0a53a80133a3c5d3b7d0e6785bda96e..689ea087406cb64be62d06c4beff71fce6483304 100644 --- a/internal/tui/components/logs/table.go +++ b/internal/tui/components/logs/table.go @@ -4,19 +4,18 @@ import ( "encoding/json" "slices" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/table" - tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/bubbles/v2/key" + "github.com/charmbracelet/bubbles/v2/table" + tea "github.com/charmbracelet/bubbletea/v2" "github.com/opencode-ai/opencode/internal/logging" "github.com/opencode-ai/opencode/internal/pubsub" "github.com/opencode-ai/opencode/internal/tui/layout" - "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" "github.com/opencode-ai/opencode/internal/tui/util" ) type TableComponent interface { - tea.Model + util.Model layout.Sizeable layout.Bindings } @@ -66,7 +65,7 @@ func (i *tableCmp) View() string { defaultStyles := table.DefaultStyles() defaultStyles.Selected = defaultStyles.Selected.Foreground(t.Primary()) i.table.SetStyles(defaultStyles) - return styles.ForceReplaceBackgroundWithLipgloss(i.table.View(), t.Background()) + return i.table.View() } func (i *tableCmp) GetSize() (int, int) { diff --git a/internal/tui/components/util/simple-list.go b/internal/tui/components/util/simple-list.go index 7aad2494c6f93f084d52c3e11fa80d5b795ca217..541bfe5b297049b1479f6834fa9d3cdcb292a488 100644 --- a/internal/tui/components/util/simple-list.go +++ b/internal/tui/components/util/simple-list.go @@ -1,12 +1,13 @@ package utilComponents import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/layout" "github.com/opencode-ai/opencode/internal/tui/styles" "github.com/opencode-ai/opencode/internal/tui/theme" + "github.com/opencode-ai/opencode/internal/tui/util" ) type SimpleListItem interface { @@ -14,7 +15,7 @@ type SimpleListItem interface { } type SimpleList[T SimpleListItem] interface { - tea.Model + util.Model layout.Bindings SetMaxWidth(maxWidth int) GetSelectedItem() (item T, idx int) diff --git a/internal/tui/image/images.go b/internal/tui/image/images.go index d10a169fd5d46d37b75a66fe6ad17f1bb0c284f2..72ce2b38f069deff64a367dc89003489d92a498c 100644 --- a/internal/tui/image/images.go +++ b/internal/tui/image/images.go @@ -3,10 +3,11 @@ package image import ( "fmt" "image" + "image/color" "os" "strings" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" "github.com/disintegration/imaging" "github.com/lucasb-eyer/go-colorful" ) @@ -36,7 +37,7 @@ func ToString(width int, img image.Image) string { c1, _ := colorful.MakeColor(img.At(x, heightCounter)) color1 := lipgloss.Color(c1.Hex()) - var color2 lipgloss.Color + var color2 color.Color if heightCounter+1 < h { c2, _ := colorful.MakeColor(img.At(x, heightCounter+1)) color2 = lipgloss.Color(c2.Hex()) diff --git a/internal/tui/layout/container.go b/internal/tui/layout/container.go index 83aef587938cc1f7ed56690bab98e10c9351b350..81e331c3c27fc2a3fbd3e9010516facce681d683 100644 --- a/internal/tui/layout/container.go +++ b/internal/tui/layout/container.go @@ -1,14 +1,15 @@ package layout import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/theme" + "github.com/opencode-ai/opencode/internal/tui/util" ) type Container interface { - tea.Model + util.Model Sizeable Bindings } @@ -16,7 +17,7 @@ type container struct { width int height int - content tea.Model + content util.Model // Style options paddingTop int @@ -37,7 +38,7 @@ func (c *container) Init() tea.Cmd { func (c *container) Update(msg tea.Msg) (tea.Model, tea.Cmd) { u, cmd := c.content.Update(msg) - c.content = u + c.content = u.(util.Model) return c, cmd } @@ -123,8 +124,7 @@ func (c *container) BindingKeys() []key.Binding { type ContainerOption func(*container) -func NewContainer(content tea.Model, options ...ContainerOption) Container { - +func NewContainer(content util.Model, options ...ContainerOption) Container { c := &container{ content: content, borderStyle: lipgloss.NormalBorder(), diff --git a/internal/tui/layout/layout.go b/internal/tui/layout/layout.go index 495a3fbc5140917b35c342e96672aa4dd8ee4b18..08aa3173ef89230a31962965d7607e4c043829c5 100644 --- a/internal/tui/layout/layout.go +++ b/internal/tui/layout/layout.go @@ -3,8 +3,8 @@ package layout import ( "reflect" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" ) type Focusable interface { diff --git a/internal/tui/layout/overlay.go b/internal/tui/layout/overlay.go index 3a14dbc5eeb9d9245dfd1b1c6a4ddda7f791b5f1..4c9dd5a9435e7d3d9a58a0b0829526532d76f2e0 100644 --- a/internal/tui/layout/overlay.go +++ b/internal/tui/layout/overlay.go @@ -3,7 +3,7 @@ package layout import ( "strings" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" chAnsi "github.com/charmbracelet/x/ansi" "github.com/muesli/ansi" "github.com/muesli/reflow/truncate" @@ -14,7 +14,7 @@ import ( ) // Most of this code is borrowed from -// https://github.com/charmbracelet/lipgloss/pull/102 +// https://github.com/charmbracelet/lipgloss/v2/pull/102 // as well as the lipgloss library, with some modification for what I needed. // Split a string into lines, additionally returning the size of the widest diff --git a/internal/tui/layout/split.go b/internal/tui/layout/split.go index 2684a8447cbe4fec4e3d389cf148cec622bfd72b..c40a6a0e79771ec8ea669382a99aa387384abc58 100644 --- a/internal/tui/layout/split.go +++ b/internal/tui/layout/split.go @@ -1,14 +1,15 @@ package layout import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/theme" + "github.com/opencode-ai/opencode/internal/tui/util" ) type SplitPaneLayout interface { - tea.Model + util.Model Sizeable Bindings SetLeftPanel(panel Container) tea.Cmd @@ -241,7 +242,6 @@ func (s *splitPaneLayout) BindingKeys() []key.Binding { } func NewSplitPane(options ...SplitPaneOption) SplitPaneLayout { - layout := &splitPaneLayout{ ratio: 0.7, verticalRatio: 0.9, // Default 90% for top section, 10% for bottom diff --git a/internal/tui/page/chat.go b/internal/tui/page/chat.go index d297a34c2c1c828315b688c5fd4b60410cd97704..7096d7d159e2f86c37d26fc74d36b2249cd72f6f 100644 --- a/internal/tui/page/chat.go +++ b/internal/tui/page/chat.go @@ -4,9 +4,9 @@ import ( "context" "strings" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/app" "github.com/opencode-ai/opencode/internal/completions" "github.com/opencode-ai/opencode/internal/message" @@ -76,7 +76,7 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if p.app.CoderAgent.IsBusy() { return p, util.ReportWarn("Agent is busy, please wait before executing a command...") } - + // Process the command content with arguments if any content := msg.Content if msg.Args != nil { @@ -86,7 +86,7 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) { content = strings.ReplaceAll(content, placeholder, value) } } - + // Handle custom command execution cmd := p.sendMessage(content, nil) if cmd != nil { @@ -212,7 +212,7 @@ func (p *chatPage) BindingKeys() []key.Binding { return bindings } -func NewChatPage(app *app.App) tea.Model { +func NewChatPage(app *app.App) util.Model { cg := completions.NewFileAndFolderContextGroup() completionDialog := dialog.NewCompletionDialogCmp(cg) diff --git a/internal/tui/page/logs.go b/internal/tui/page/logs.go index 9bd545287f4c35c1ea99d33efd5f274275d63a4f..89c69b8654672987b4c49c1dec000fd83fb62031 100644 --- a/internal/tui/page/logs.go +++ b/internal/tui/page/logs.go @@ -1,18 +1,19 @@ package page import ( - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/components/logs" "github.com/opencode-ai/opencode/internal/tui/layout" "github.com/opencode-ai/opencode/internal/tui/styles" + "github.com/opencode-ai/opencode/internal/tui/util" ) var LogsPage PageID = "logs" type LogPage interface { - tea.Model + util.Model layout.Sizeable layout.Bindings } diff --git a/internal/tui/styles/background.go b/internal/tui/styles/background.go deleted file mode 100644 index 2fbb34efbbe52ecd5e233c33ee32fbb2981fb8f1..0000000000000000000000000000000000000000 --- a/internal/tui/styles/background.go +++ /dev/null @@ -1,123 +0,0 @@ -package styles - -import ( - "fmt" - "regexp" - "strings" - - "github.com/charmbracelet/lipgloss" -) - -var ansiEscape = regexp.MustCompile("\x1b\\[[0-9;]*m") - -func getColorRGB(c lipgloss.TerminalColor) (uint8, uint8, uint8) { - r, g, b, a := c.RGBA() - - // Un-premultiply alpha if needed - if a > 0 && a < 0xffff { - r = (r * 0xffff) / a - g = (g * 0xffff) / a - b = (b * 0xffff) / a - } - - // Convert from 16-bit to 8-bit color - return uint8(r >> 8), uint8(g >> 8), uint8(b >> 8) -} - -// ForceReplaceBackgroundWithLipgloss replaces any ANSI background color codes -// in `input` with a single 24‑bit background (48;2;R;G;B). -func ForceReplaceBackgroundWithLipgloss(input string, newBgColor lipgloss.TerminalColor) string { - // Precompute our new-bg sequence once - r, g, b := getColorRGB(newBgColor) - newBg := fmt.Sprintf("48;2;%d;%d;%d", r, g, b) - - return ansiEscape.ReplaceAllStringFunc(input, func(seq string) string { - const ( - escPrefixLen = 2 // "\x1b[" - escSuffixLen = 1 // "m" - ) - - raw := seq - start := escPrefixLen - end := len(raw) - escSuffixLen - - var sb strings.Builder - // reserve enough space: original content minus bg codes + our newBg - sb.Grow((end - start) + len(newBg) + 2) - - // scan from start..end, token by token - for i := start; i < end; { - // find the next ';' or end - j := i - for j < end && raw[j] != ';' { - j++ - } - token := raw[i:j] - - // fast‑path: skip "48;5;N" or "48;2;R;G;B" - if len(token) == 2 && token[0] == '4' && token[1] == '8' { - k := j + 1 - if k < end { - // find next token - l := k - for l < end && raw[l] != ';' { - l++ - } - next := raw[k:l] - if next == "5" { - // skip "48;5;N" - m := l + 1 - for m < end && raw[m] != ';' { - m++ - } - i = m + 1 - continue - } else if next == "2" { - // skip "48;2;R;G;B" - m := l + 1 - for count := 0; count < 3 && m < end; count++ { - for m < end && raw[m] != ';' { - m++ - } - m++ - } - i = m - continue - } - } - } - - // decide whether to keep this token - // manually parse ASCII digits to int - isNum := true - val := 0 - for p := i; p < j; p++ { - c := raw[p] - if c < '0' || c > '9' { - isNum = false - break - } - val = val*10 + int(c-'0') - } - keep := !isNum || - ((val < 40 || val > 47) && (val < 100 || val > 107) && val != 49) - - if keep { - if sb.Len() > 0 { - sb.WriteByte(';') - } - sb.WriteString(token) - } - // advance past this token (and the semicolon) - i = j + 1 - } - - // append our new background - if sb.Len() > 0 { - sb.WriteByte(';') - } - sb.WriteString(newBg) - - return "\x1b[" + sb.String() + "m" - }) -} diff --git a/internal/tui/styles/markdown.go b/internal/tui/styles/markdown.go index 6b43d97cfeeea6829d298816b6f90f9d61e91629..bf9114d35ad9b2d36f742deb622a64210772bf20 100644 --- a/internal/tui/styles/markdown.go +++ b/internal/tui/styles/markdown.go @@ -1,9 +1,11 @@ package styles import ( - "github.com/charmbracelet/glamour" - "github.com/charmbracelet/glamour/ansi" - "github.com/charmbracelet/lipgloss" + "fmt" + "image/color" + + "github.com/charmbracelet/glamour/v2" + "github.com/charmbracelet/glamour/v2/ansi" "github.com/opencode-ai/opencode/internal/tui/theme" ) @@ -33,13 +35,13 @@ func generateMarkdownStyleConfig() ansi.StyleConfig { StylePrimitive: ansi.StylePrimitive{ BlockPrefix: "", BlockSuffix: "", - Color: stringPtr(adaptiveColorToString(t.MarkdownText())), + Color: stringPtr(colorToString(t.MarkdownText())), }, Margin: uintPtr(defaultMargin), }, BlockQuote: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownBlockQuote())), + Color: stringPtr(colorToString(t.MarkdownBlockQuote())), Italic: boolPtr(true), Prefix: "┃ ", }, @@ -51,82 +53,82 @@ func generateMarkdownStyleConfig() ansi.StyleConfig { StyleBlock: ansi.StyleBlock{ IndentToken: stringPtr(BaseStyle().Render(" ")), StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownText())), + Color: stringPtr(colorToString(t.MarkdownText())), }, }, }, Heading: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ BlockSuffix: "\n", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, H1: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: "# ", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, H2: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: "## ", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, H3: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: "### ", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, H4: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: "#### ", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, H5: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: "##### ", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, H6: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: "###### ", - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), Bold: boolPtr(true), }, }, Strikethrough: ansi.StylePrimitive{ CrossedOut: boolPtr(true), - Color: stringPtr(adaptiveColorToString(t.TextMuted())), + Color: stringPtr(colorToString(t.TextMuted())), }, Emph: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownEmph())), + Color: stringPtr(colorToString(t.MarkdownEmph())), Italic: boolPtr(true), }, Strong: ansi.StylePrimitive{ Bold: boolPtr(true), - Color: stringPtr(adaptiveColorToString(t.MarkdownStrong())), + Color: stringPtr(colorToString(t.MarkdownStrong())), }, HorizontalRule: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownHorizontalRule())), + Color: stringPtr(colorToString(t.MarkdownHorizontalRule())), Format: "\n─────────────────────────────────────────\n", }, Item: ansi.StylePrimitive{ BlockPrefix: "• ", - Color: stringPtr(adaptiveColorToString(t.MarkdownListItem())), + Color: stringPtr(colorToString(t.MarkdownListItem())), }, Enumeration: ansi.StylePrimitive{ BlockPrefix: ". ", - Color: stringPtr(adaptiveColorToString(t.MarkdownListEnumeration())), + Color: stringPtr(colorToString(t.MarkdownListEnumeration())), }, Task: ansi.StyleTask{ StylePrimitive: ansi.StylePrimitive{}, @@ -134,25 +136,25 @@ func generateMarkdownStyleConfig() ansi.StyleConfig { Unticked: "[ ] ", }, Link: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownLink())), + Color: stringPtr(colorToString(t.MarkdownLink())), Underline: boolPtr(true), }, LinkText: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownLinkText())), + Color: stringPtr(colorToString(t.MarkdownLinkText())), Bold: boolPtr(true), }, Image: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownImage())), + Color: stringPtr(colorToString(t.MarkdownImage())), Underline: boolPtr(true), Format: "🖼 {{.text}}", }, ImageText: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownImageText())), + Color: stringPtr(colorToString(t.MarkdownImageText())), Format: "{{.text}}", }, Code: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownCode())), + Color: stringPtr(colorToString(t.MarkdownCode())), Prefix: "", Suffix: "", }, @@ -161,90 +163,90 @@ func generateMarkdownStyleConfig() ansi.StyleConfig { StyleBlock: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ Prefix: " ", - Color: stringPtr(adaptiveColorToString(t.MarkdownCodeBlock())), + Color: stringPtr(colorToString(t.MarkdownCodeBlock())), }, Margin: uintPtr(defaultMargin), }, Chroma: &ansi.Chroma{ Text: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownText())), + Color: stringPtr(colorToString(t.MarkdownText())), }, Error: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.Error())), + Color: stringPtr(colorToString(t.Error())), }, Comment: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxComment())), + Color: stringPtr(colorToString(t.SyntaxComment())), }, CommentPreproc: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxKeyword())), + Color: stringPtr(colorToString(t.SyntaxKeyword())), }, Keyword: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxKeyword())), + Color: stringPtr(colorToString(t.SyntaxKeyword())), }, KeywordReserved: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxKeyword())), + Color: stringPtr(colorToString(t.SyntaxKeyword())), }, KeywordNamespace: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxKeyword())), + Color: stringPtr(colorToString(t.SyntaxKeyword())), }, KeywordType: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxType())), + Color: stringPtr(colorToString(t.SyntaxType())), }, Operator: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxOperator())), + Color: stringPtr(colorToString(t.SyntaxOperator())), }, Punctuation: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxPunctuation())), + Color: stringPtr(colorToString(t.SyntaxPunctuation())), }, Name: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxVariable())), + Color: stringPtr(colorToString(t.SyntaxVariable())), }, NameBuiltin: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxVariable())), + Color: stringPtr(colorToString(t.SyntaxVariable())), }, NameTag: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxKeyword())), + Color: stringPtr(colorToString(t.SyntaxKeyword())), }, NameAttribute: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxFunction())), + Color: stringPtr(colorToString(t.SyntaxFunction())), }, NameClass: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxType())), + Color: stringPtr(colorToString(t.SyntaxType())), }, NameConstant: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxVariable())), + Color: stringPtr(colorToString(t.SyntaxVariable())), }, NameDecorator: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxFunction())), + Color: stringPtr(colorToString(t.SyntaxFunction())), }, NameFunction: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxFunction())), + Color: stringPtr(colorToString(t.SyntaxFunction())), }, LiteralNumber: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxNumber())), + Color: stringPtr(colorToString(t.SyntaxNumber())), }, LiteralString: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxString())), + Color: stringPtr(colorToString(t.SyntaxString())), }, LiteralStringEscape: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.SyntaxKeyword())), + Color: stringPtr(colorToString(t.SyntaxKeyword())), }, GenericDeleted: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.DiffRemoved())), + Color: stringPtr(colorToString(t.DiffRemoved())), }, GenericEmph: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownEmph())), + Color: stringPtr(colorToString(t.MarkdownEmph())), Italic: boolPtr(true), }, GenericInserted: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.DiffAdded())), + Color: stringPtr(colorToString(t.DiffAdded())), }, GenericStrong: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownStrong())), + Color: stringPtr(colorToString(t.MarkdownStrong())), Bold: boolPtr(true), }, GenericSubheading: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownHeading())), + Color: stringPtr(colorToString(t.MarkdownHeading())), }, }, }, @@ -261,24 +263,20 @@ func generateMarkdownStyleConfig() ansi.StyleConfig { }, DefinitionDescription: ansi.StylePrimitive{ BlockPrefix: "\n ❯ ", - Color: stringPtr(adaptiveColorToString(t.MarkdownLinkText())), + Color: stringPtr(colorToString(t.MarkdownLinkText())), }, Text: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownText())), + Color: stringPtr(colorToString(t.MarkdownText())), }, Paragraph: ansi.StyleBlock{ StylePrimitive: ansi.StylePrimitive{ - Color: stringPtr(adaptiveColorToString(t.MarkdownText())), + Color: stringPtr(colorToString(t.MarkdownText())), }, }, } } -// adaptiveColorToString converts a lipgloss.AdaptiveColor to the appropriate -// hex color string based on the current terminal background -func adaptiveColorToString(color lipgloss.AdaptiveColor) string { - if lipgloss.HasDarkBackground() { - return color.Dark - } - return color.Light +func colorToString(c color.Color) string { + rgba := color.RGBAModel.Convert(c).(color.RGBA) + return fmt.Sprintf("#%02x%02x%02x", rgba.R, rgba.G, rgba.B) } diff --git a/internal/tui/styles/styles.go b/internal/tui/styles/styles.go index 7094b537318843db3b453b194c3617fc219e1c89..a502e411c74c52b6f4521164f18710213ed62b03 100644 --- a/internal/tui/styles/styles.go +++ b/internal/tui/styles/styles.go @@ -1,13 +1,13 @@ package styles import ( - "github.com/charmbracelet/lipgloss" + "image/color" + + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/tui/theme" ) -var ( - ImageBakcground = "#212121" -) +var ImageBakcground = "#212121" // Style generation functions that use the current theme @@ -75,81 +75,81 @@ func DimBorder() lipgloss.Style { } // PrimaryColor returns the primary color from the current theme -func PrimaryColor() lipgloss.AdaptiveColor { +func PrimaryColor() color.Color { return theme.CurrentTheme().Primary() } // SecondaryColor returns the secondary color from the current theme -func SecondaryColor() lipgloss.AdaptiveColor { +func SecondaryColor() color.Color { return theme.CurrentTheme().Secondary() } // AccentColor returns the accent color from the current theme -func AccentColor() lipgloss.AdaptiveColor { +func AccentColor() color.Color { return theme.CurrentTheme().Accent() } // ErrorColor returns the error color from the current theme -func ErrorColor() lipgloss.AdaptiveColor { +func ErrorColor() color.Color { return theme.CurrentTheme().Error() } // WarningColor returns the warning color from the current theme -func WarningColor() lipgloss.AdaptiveColor { +func WarningColor() color.Color { return theme.CurrentTheme().Warning() } // SuccessColor returns the success color from the current theme -func SuccessColor() lipgloss.AdaptiveColor { +func SuccessColor() color.Color { return theme.CurrentTheme().Success() } // InfoColor returns the info color from the current theme -func InfoColor() lipgloss.AdaptiveColor { +func InfoColor() color.Color { return theme.CurrentTheme().Info() } // TextColor returns the text color from the current theme -func TextColor() lipgloss.AdaptiveColor { +func TextColor() color.Color { return theme.CurrentTheme().Text() } // TextMutedColor returns the muted text color from the current theme -func TextMutedColor() lipgloss.AdaptiveColor { +func TextMutedColor() color.Color { return theme.CurrentTheme().TextMuted() } // TextEmphasizedColor returns the emphasized text color from the current theme -func TextEmphasizedColor() lipgloss.AdaptiveColor { +func TextEmphasizedColor() color.Color { return theme.CurrentTheme().TextEmphasized() } // BackgroundColor returns the background color from the current theme -func BackgroundColor() lipgloss.AdaptiveColor { +func BackgroundColor() color.Color { return theme.CurrentTheme().Background() } // BackgroundSecondaryColor returns the secondary background color from the current theme -func BackgroundSecondaryColor() lipgloss.AdaptiveColor { +func BackgroundSecondaryColor() color.Color { return theme.CurrentTheme().BackgroundSecondary() } // BackgroundDarkerColor returns the darker background color from the current theme -func BackgroundDarkerColor() lipgloss.AdaptiveColor { +func BackgroundDarkerColor() color.Color { return theme.CurrentTheme().BackgroundDarker() } // BorderNormalColor returns the normal border color from the current theme -func BorderNormalColor() lipgloss.AdaptiveColor { +func BorderNormalColor() color.Color { return theme.CurrentTheme().BorderNormal() } // BorderFocusedColor returns the focused border color from the current theme -func BorderFocusedColor() lipgloss.AdaptiveColor { +func BorderFocusedColor() color.Color { return theme.CurrentTheme().BorderFocused() } // BorderDimColor returns the dim border color from the current theme -func BorderDimColor() lipgloss.AdaptiveColor { +func BorderDimColor() color.Color { return theme.CurrentTheme().BorderDim() } diff --git a/internal/tui/theme/catppuccin.go b/internal/tui/theme/catppuccin.go index a843100ab21c0b3b5b035b67a6322ef2ea5239ef..fd4df0657f82538b57a8eabcb73553df9f9ce9e1 100644 --- a/internal/tui/theme/catppuccin.go +++ b/internal/tui/theme/catppuccin.go @@ -2,7 +2,7 @@ package theme import ( catppuccin "github.com/catppuccin/go" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // CatppuccinTheme implements the Theme interface with Catppuccin colors. @@ -11,238 +11,162 @@ type CatppuccinTheme struct { BaseTheme } -// NewCatppuccinTheme creates a new instance of the Catppuccin theme. -func NewCatppuccinTheme() *CatppuccinTheme { - // Get the Catppuccin palettes +// NewCatppuccinMochaTheme creates a new instance of the Catppuccin Mocha theme. +func NewCatppuccinMochaTheme() *CatppuccinTheme { + // Get the Catppuccin palette mocha := catppuccin.Mocha + + theme := &CatppuccinTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(mocha.Blue().Hex) + theme.SecondaryColor = lipgloss.Color(mocha.Mauve().Hex) + theme.AccentColor = lipgloss.Color(mocha.Peach().Hex) + + // Status colors + theme.ErrorColor = lipgloss.Color(mocha.Red().Hex) + theme.WarningColor = lipgloss.Color(mocha.Peach().Hex) + theme.SuccessColor = lipgloss.Color(mocha.Green().Hex) + theme.InfoColor = lipgloss.Color(mocha.Blue().Hex) + + // Text colors + theme.TextColor = lipgloss.Color(mocha.Text().Hex) + theme.TextMutedColor = lipgloss.Color(mocha.Subtext0().Hex) + theme.TextEmphasizedColor = lipgloss.Color(mocha.Lavender().Hex) + + // Background colors + theme.BackgroundColor = lipgloss.Color("#212121") // From existing styles + theme.BackgroundSecondaryColor = lipgloss.Color("#2c2c2c") // From existing styles + theme.BackgroundDarkerColor = lipgloss.Color("#181818") // From existing styles + + // Border colors + theme.BorderNormalColor = lipgloss.Color("#4b4c5c") // From existing styles + theme.BorderFocusedColor = lipgloss.Color(mocha.Blue().Hex) + theme.BorderDimColor = lipgloss.Color(mocha.Surface0().Hex) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color("#478247") // From existing diff.go + theme.DiffRemovedColor = lipgloss.Color("#7C4444") // From existing diff.go + theme.DiffContextColor = lipgloss.Color("#a0a0a0") // From existing diff.go + theme.DiffHunkHeaderColor = lipgloss.Color("#a0a0a0") // From existing diff.go + theme.DiffHighlightAddedColor = lipgloss.Color("#DAFADA") // From existing diff.go + theme.DiffHighlightRemovedColor = lipgloss.Color("#FADADD") // From existing diff.go + theme.DiffAddedBgColor = lipgloss.Color("#303A30") // From existing diff.go + theme.DiffRemovedBgColor = lipgloss.Color("#3A3030") // From existing diff.go + theme.DiffContextBgColor = lipgloss.Color("#212121") // From existing diff.go + theme.DiffLineNumberColor = lipgloss.Color("#888888") // From existing diff.go + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#293229") // From existing diff.go + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#332929") // From existing diff.go + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(mocha.Text().Hex) + theme.MarkdownHeadingColor = lipgloss.Color(mocha.Mauve().Hex) + theme.MarkdownLinkColor = lipgloss.Color(mocha.Sky().Hex) + theme.MarkdownLinkTextColor = lipgloss.Color(mocha.Pink().Hex) + theme.MarkdownCodeColor = lipgloss.Color(mocha.Green().Hex) + theme.MarkdownBlockQuoteColor = lipgloss.Color(mocha.Yellow().Hex) + theme.MarkdownEmphColor = lipgloss.Color(mocha.Yellow().Hex) + theme.MarkdownStrongColor = lipgloss.Color(mocha.Peach().Hex) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(mocha.Overlay0().Hex) + theme.MarkdownListItemColor = lipgloss.Color(mocha.Blue().Hex) + theme.MarkdownListEnumerationColor = lipgloss.Color(mocha.Sky().Hex) + theme.MarkdownImageColor = lipgloss.Color(mocha.Sapphire().Hex) + theme.MarkdownImageTextColor = lipgloss.Color(mocha.Pink().Hex) + theme.MarkdownCodeBlockColor = lipgloss.Color(mocha.Text().Hex) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(mocha.Overlay1().Hex) + theme.SyntaxKeywordColor = lipgloss.Color(mocha.Pink().Hex) + theme.SyntaxFunctionColor = lipgloss.Color(mocha.Green().Hex) + theme.SyntaxVariableColor = lipgloss.Color(mocha.Sky().Hex) + theme.SyntaxStringColor = lipgloss.Color(mocha.Yellow().Hex) + theme.SyntaxNumberColor = lipgloss.Color(mocha.Teal().Hex) + theme.SyntaxTypeColor = lipgloss.Color(mocha.Sky().Hex) + theme.SyntaxOperatorColor = lipgloss.Color(mocha.Pink().Hex) + theme.SyntaxPunctuationColor = lipgloss.Color(mocha.Text().Hex) + + return theme +} + +// NewCatppuccinLatteTheme creates a new instance of the Catppuccin Latte theme. +func NewCatppuccinLatteTheme() *CatppuccinTheme { + // Get the Catppuccin palette latte := catppuccin.Latte theme := &CatppuccinTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: mocha.Blue().Hex, - Light: latte.Blue().Hex, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: mocha.Mauve().Hex, - Light: latte.Mauve().Hex, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: mocha.Peach().Hex, - Light: latte.Peach().Hex, - } + theme.PrimaryColor = lipgloss.Color(latte.Blue().Hex) + theme.SecondaryColor = lipgloss.Color(latte.Mauve().Hex) + theme.AccentColor = lipgloss.Color(latte.Peach().Hex) // Status colors - theme.ErrorColor = lipgloss.AdaptiveColor{ - Dark: mocha.Red().Hex, - Light: latte.Red().Hex, - } - theme.WarningColor = lipgloss.AdaptiveColor{ - Dark: mocha.Peach().Hex, - Light: latte.Peach().Hex, - } - theme.SuccessColor = lipgloss.AdaptiveColor{ - Dark: mocha.Green().Hex, - Light: latte.Green().Hex, - } - theme.InfoColor = lipgloss.AdaptiveColor{ - Dark: mocha.Blue().Hex, - Light: latte.Blue().Hex, - } + theme.ErrorColor = lipgloss.Color(latte.Red().Hex) + theme.WarningColor = lipgloss.Color(latte.Peach().Hex) + theme.SuccessColor = lipgloss.Color(latte.Green().Hex) + theme.InfoColor = lipgloss.Color(latte.Blue().Hex) // Text colors - theme.TextColor = lipgloss.AdaptiveColor{ - Dark: mocha.Text().Hex, - Light: latte.Text().Hex, - } - theme.TextMutedColor = lipgloss.AdaptiveColor{ - Dark: mocha.Subtext0().Hex, - Light: latte.Subtext0().Hex, - } - theme.TextEmphasizedColor = lipgloss.AdaptiveColor{ - Dark: mocha.Lavender().Hex, - Light: latte.Lavender().Hex, - } + theme.TextColor = lipgloss.Color(latte.Text().Hex) + theme.TextMutedColor = lipgloss.Color(latte.Subtext0().Hex) + theme.TextEmphasizedColor = lipgloss.Color(latte.Lavender().Hex) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: "#212121", // From existing styles - Light: "#EEEEEE", // Light equivalent - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: "#2c2c2c", // From existing styles - Light: "#E0E0E0", // Light equivalent - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: "#181818", // From existing styles - Light: "#F5F5F5", // Light equivalent - } + theme.BackgroundColor = lipgloss.Color("#EEEEEE") // Light equivalent + theme.BackgroundSecondaryColor = lipgloss.Color("#E0E0E0") // Light equivalent + theme.BackgroundDarkerColor = lipgloss.Color("#F5F5F5") // Light equivalent // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: "#4b4c5c", // From existing styles - Light: "#BDBDBD", // Light equivalent - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: mocha.Blue().Hex, - Light: latte.Blue().Hex, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: mocha.Surface0().Hex, - Light: latte.Surface0().Hex, - } + theme.BorderNormalColor = lipgloss.Color("#BDBDBD") // Light equivalent + theme.BorderFocusedColor = lipgloss.Color(latte.Blue().Hex) + theme.BorderDimColor = lipgloss.Color(latte.Surface0().Hex) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: "#478247", // From existing diff.go - Light: "#2E7D32", // Light equivalent - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#7C4444", // From existing diff.go - Light: "#C62828", // Light equivalent - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: "#a0a0a0", // From existing diff.go - Light: "#757575", // Light equivalent - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: "#a0a0a0", // From existing diff.go - Light: "#757575", // Light equivalent - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: "#DAFADA", // From existing diff.go - Light: "#A5D6A7", // Light equivalent - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#FADADD", // From existing diff.go - Light: "#EF9A9A", // Light equivalent - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#303A30", // From existing diff.go - Light: "#E8F5E9", // Light equivalent - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#3A3030", // From existing diff.go - Light: "#FFEBEE", // Light equivalent - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: "#212121", // From existing diff.go - Light: "#F5F5F5", // Light equivalent - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: "#888888", // From existing diff.go - Light: "#9E9E9E", // Light equivalent - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#293229", // From existing diff.go - Light: "#C8E6C9", // Light equivalent - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#332929", // From existing diff.go - Light: "#FFCDD2", // Light equivalent - } + theme.DiffAddedColor = lipgloss.Color("#2E7D32") // Light equivalent + theme.DiffRemovedColor = lipgloss.Color("#C62828") // Light equivalent + theme.DiffContextColor = lipgloss.Color("#757575") // Light equivalent + theme.DiffHunkHeaderColor = lipgloss.Color("#757575") // Light equivalent + theme.DiffHighlightAddedColor = lipgloss.Color("#A5D6A7") // Light equivalent + theme.DiffHighlightRemovedColor = lipgloss.Color("#EF9A9A") // Light equivalent + theme.DiffAddedBgColor = lipgloss.Color("#E8F5E9") // Light equivalent + theme.DiffRemovedBgColor = lipgloss.Color("#FFEBEE") // Light equivalent + theme.DiffContextBgColor = lipgloss.Color("#F5F5F5") // Light equivalent + theme.DiffLineNumberColor = lipgloss.Color("#9E9E9E") // Light equivalent + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#C8E6C9") // Light equivalent + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#FFCDD2") // Light equivalent // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: mocha.Text().Hex, - Light: latte.Text().Hex, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: mocha.Mauve().Hex, - Light: latte.Mauve().Hex, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: mocha.Sky().Hex, - Light: latte.Sky().Hex, - } - theme.MarkdownLinkTextColor = lipgloss.AdaptiveColor{ - Dark: mocha.Pink().Hex, - Light: latte.Pink().Hex, - } - theme.MarkdownCodeColor = lipgloss.AdaptiveColor{ - Dark: mocha.Green().Hex, - Light: latte.Green().Hex, - } - theme.MarkdownBlockQuoteColor = lipgloss.AdaptiveColor{ - Dark: mocha.Yellow().Hex, - Light: latte.Yellow().Hex, - } - theme.MarkdownEmphColor = lipgloss.AdaptiveColor{ - Dark: mocha.Yellow().Hex, - Light: latte.Yellow().Hex, - } - theme.MarkdownStrongColor = lipgloss.AdaptiveColor{ - Dark: mocha.Peach().Hex, - Light: latte.Peach().Hex, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: mocha.Overlay0().Hex, - Light: latte.Overlay0().Hex, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: mocha.Blue().Hex, - Light: latte.Blue().Hex, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: mocha.Sky().Hex, - Light: latte.Sky().Hex, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: mocha.Sapphire().Hex, - Light: latte.Sapphire().Hex, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: mocha.Pink().Hex, - Light: latte.Pink().Hex, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: mocha.Text().Hex, - Light: latte.Text().Hex, - } + theme.MarkdownTextColor = lipgloss.Color(latte.Text().Hex) + theme.MarkdownHeadingColor = lipgloss.Color(latte.Mauve().Hex) + theme.MarkdownLinkColor = lipgloss.Color(latte.Sky().Hex) + theme.MarkdownLinkTextColor = lipgloss.Color(latte.Pink().Hex) + theme.MarkdownCodeColor = lipgloss.Color(latte.Green().Hex) + theme.MarkdownBlockQuoteColor = lipgloss.Color(latte.Yellow().Hex) + theme.MarkdownEmphColor = lipgloss.Color(latte.Yellow().Hex) + theme.MarkdownStrongColor = lipgloss.Color(latte.Peach().Hex) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(latte.Overlay0().Hex) + theme.MarkdownListItemColor = lipgloss.Color(latte.Blue().Hex) + theme.MarkdownListEnumerationColor = lipgloss.Color(latte.Sky().Hex) + theme.MarkdownImageColor = lipgloss.Color(latte.Sapphire().Hex) + theme.MarkdownImageTextColor = lipgloss.Color(latte.Pink().Hex) + theme.MarkdownCodeBlockColor = lipgloss.Color(latte.Text().Hex) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: mocha.Overlay1().Hex, - Light: latte.Overlay1().Hex, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: mocha.Pink().Hex, - Light: latte.Pink().Hex, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: mocha.Green().Hex, - Light: latte.Green().Hex, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: mocha.Sky().Hex, - Light: latte.Sky().Hex, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: mocha.Yellow().Hex, - Light: latte.Yellow().Hex, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: mocha.Teal().Hex, - Light: latte.Teal().Hex, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: mocha.Sky().Hex, - Light: latte.Sky().Hex, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: mocha.Pink().Hex, - Light: latte.Pink().Hex, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: mocha.Text().Hex, - Light: latte.Text().Hex, - } + theme.SyntaxCommentColor = lipgloss.Color(latte.Overlay1().Hex) + theme.SyntaxKeywordColor = lipgloss.Color(latte.Pink().Hex) + theme.SyntaxFunctionColor = lipgloss.Color(latte.Green().Hex) + theme.SyntaxVariableColor = lipgloss.Color(latte.Sky().Hex) + theme.SyntaxStringColor = lipgloss.Color(latte.Yellow().Hex) + theme.SyntaxNumberColor = lipgloss.Color(latte.Teal().Hex) + theme.SyntaxTypeColor = lipgloss.Color(latte.Sky().Hex) + theme.SyntaxOperatorColor = lipgloss.Color(latte.Pink().Hex) + theme.SyntaxPunctuationColor = lipgloss.Color(latte.Text().Hex) return theme } func init() { - // Register the Catppuccin theme with the theme manager - RegisterTheme("catppuccin", NewCatppuccinTheme()) -} \ No newline at end of file + // Register the Catppuccin themes with the theme manager + RegisterTheme("catppuccin-mocha", NewCatppuccinMochaTheme()) + RegisterTheme("catppuccin-latte", NewCatppuccinLatteTheme()) +} diff --git a/internal/tui/theme/dracula.go b/internal/tui/theme/dracula.go index e625206ae5e0470081244fa306443bbdd81a0b93..eaf981c786e20f605bdeb7ac90c1e3f955421f59 100644 --- a/internal/tui/theme/dracula.go +++ b/internal/tui/theme/dracula.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // DraculaTheme implements the Theme interface with Dracula colors. @@ -28,242 +28,74 @@ func NewDraculaTheme() *DraculaTheme { darkYellow := "#f1fa8c" darkBorder := "#44475a" - // Light mode approximation (Dracula is primarily a dark theme) - lightBackground := "#f8f8f2" - lightCurrentLine := "#e6e6e6" - lightSelection := "#d8d8d8" - lightForeground := "#282a36" - lightComment := "#6272a4" - lightCyan := "#0097a7" - lightGreen := "#388e3c" - lightOrange := "#f57c00" - lightPink := "#d81b60" - lightPurple := "#7e57c2" - lightRed := "#e53935" - lightYellow := "#fbc02d" - lightBorder := "#d8d8d8" - theme := &DraculaTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkPink, - Light: lightPink, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } + theme.PrimaryColor = lipgloss.Color(darkPurple) + theme.SecondaryColor = lipgloss.Color(darkPink) + theme.AccentColor = lipgloss.Color(darkCyan) // 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, - } + theme.ErrorColor = lipgloss.Color(darkRed) + theme.WarningColor = lipgloss.Color(darkOrange) + theme.SuccessColor = lipgloss.Color(darkGreen) + theme.InfoColor = lipgloss.Color(darkCyan) // 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, - } + theme.TextColor = lipgloss.Color(darkForeground) + theme.TextMutedColor = lipgloss.Color(darkComment) + theme.TextEmphasizedColor = lipgloss.Color(darkYellow) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkCurrentLine, - Light: lightCurrentLine, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: "#21222c", // Slightly darker than background - Light: "#ffffff", // Slightly lighter than background - } + theme.BackgroundColor = lipgloss.Color(darkBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(darkCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#21222c") // Slightly darker than background // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: darkBorder, - Light: lightBorder, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: darkSelection, - Light: lightSelection, - } + theme.BorderNormalColor = lipgloss.Color(darkBorder) + theme.BorderFocusedColor = lipgloss.Color(darkPurple) + theme.BorderDimColor = lipgloss.Color(darkSelection) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: darkRed, - Light: lightRed, - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: "#50fa7b", - Light: "#a5d6a7", - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#ff5555", - Light: "#ef9a9a", - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#2c3b2c", - Light: "#e8f5e9", - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#3b2c2c", - Light: "#ffebee", - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#253025", - Light: "#c8e6c9", - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#302525", - Light: "#ffcdd2", - } + theme.DiffAddedColor = lipgloss.Color(darkGreen) + theme.DiffRemovedColor = lipgloss.Color(darkRed) + theme.DiffContextColor = lipgloss.Color(darkComment) + theme.DiffHunkHeaderColor = lipgloss.Color(darkPurple) + theme.DiffHighlightAddedColor = lipgloss.Color("#50fa7b") + theme.DiffHighlightRemovedColor = lipgloss.Color("#ff5555") + theme.DiffAddedBgColor = lipgloss.Color("#2c3b2c") + theme.DiffRemovedBgColor = lipgloss.Color("#3b2c2c") + theme.DiffContextBgColor = lipgloss.Color(darkBackground) + theme.DiffLineNumberColor = lipgloss.Color(darkComment) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#253025") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#302525") // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: darkPink, - Light: lightPink, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - 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: darkOrange, - Light: lightOrange, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.MarkdownTextColor = lipgloss.Color(darkForeground) + theme.MarkdownHeadingColor = lipgloss.Color(darkPink) + theme.MarkdownLinkColor = lipgloss.Color(darkPurple) + theme.MarkdownLinkTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeColor = lipgloss.Color(darkGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(darkYellow) + theme.MarkdownEmphColor = lipgloss.Color(darkYellow) + theme.MarkdownStrongColor = lipgloss.Color(darkOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(darkComment) + theme.MarkdownListItemColor = lipgloss.Color(darkPurple) + theme.MarkdownListEnumerationColor = lipgloss.Color(darkCyan) + theme.MarkdownImageColor = lipgloss.Color(darkPurple) + theme.MarkdownImageTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(darkForeground) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: darkPink, - Light: lightPink, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: darkYellow, - Light: lightYellow, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: darkPink, - Light: lightPink, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.SyntaxCommentColor = lipgloss.Color(darkComment) + theme.SyntaxKeywordColor = lipgloss.Color(darkPink) + theme.SyntaxFunctionColor = lipgloss.Color(darkGreen) + theme.SyntaxVariableColor = lipgloss.Color(darkOrange) + theme.SyntaxStringColor = lipgloss.Color(darkYellow) + theme.SyntaxNumberColor = lipgloss.Color(darkPurple) + theme.SyntaxTypeColor = lipgloss.Color(darkCyan) + theme.SyntaxOperatorColor = lipgloss.Color(darkPink) + theme.SyntaxPunctuationColor = lipgloss.Color(darkForeground) return theme } diff --git a/internal/tui/theme/flexoki.go b/internal/tui/theme/flexoki.go index 49d94beb15656775d7f79679391aa6589fb18473..fc7f59b81ee056ef0ef771b2132f181388036a4a 100644 --- a/internal/tui/theme/flexoki.go +++ b/internal/tui/theme/flexoki.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // Flexoki color palette constants @@ -49,234 +49,156 @@ type FlexokiTheme struct { BaseTheme } -// NewFlexokiTheme creates a new instance of the Flexoki theme. -func NewFlexokiTheme() *FlexokiTheme { +// NewFlexokiDarkTheme creates a new instance of the Flexoki Dark theme. +func NewFlexokiDarkTheme() *FlexokiTheme { theme := &FlexokiTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlue400, - Light: flexokiBlue600, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: flexokiPurple400, - Light: flexokiPurple600, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: flexokiOrange400, - Light: flexokiOrange600, - } + theme.PrimaryColor = lipgloss.Color(flexokiBlue400) + theme.SecondaryColor = lipgloss.Color(flexokiPurple400) + theme.AccentColor = lipgloss.Color(flexokiOrange400) // Status colors - theme.ErrorColor = lipgloss.AdaptiveColor{ - Dark: flexokiRed400, - Light: flexokiRed600, - } - theme.WarningColor = lipgloss.AdaptiveColor{ - Dark: flexokiYellow400, - Light: flexokiYellow600, - } - theme.SuccessColor = lipgloss.AdaptiveColor{ - Dark: flexokiGreen400, - Light: flexokiGreen600, - } - theme.InfoColor = lipgloss.AdaptiveColor{ - Dark: flexokiCyan400, - Light: flexokiCyan600, - } + theme.ErrorColor = lipgloss.Color(flexokiRed400) + theme.WarningColor = lipgloss.Color(flexokiYellow400) + theme.SuccessColor = lipgloss.Color(flexokiGreen400) + theme.InfoColor = lipgloss.Color(flexokiCyan400) // Text colors - theme.TextColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase300, - Light: flexokiBase600, - } - theme.TextMutedColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase700, - Light: flexokiBase500, - } - theme.TextEmphasizedColor = lipgloss.AdaptiveColor{ - Dark: flexokiYellow400, - Light: flexokiYellow600, - } + theme.TextColor = lipgloss.Color(flexokiBase300) + theme.TextMutedColor = lipgloss.Color(flexokiBase700) + theme.TextEmphasizedColor = lipgloss.Color(flexokiYellow400) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlack, - Light: flexokiPaper, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase950, - Light: flexokiBase50, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase900, - Light: flexokiBase100, - } + theme.BackgroundColor = lipgloss.Color(flexokiBlack) + theme.BackgroundSecondaryColor = lipgloss.Color(flexokiBase950) + theme.BackgroundDarkerColor = lipgloss.Color(flexokiBase900) // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase900, - Light: flexokiBase100, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlue400, - Light: flexokiBlue600, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase850, - Light: flexokiBase150, - } + theme.BorderNormalColor = lipgloss.Color(flexokiBase900) + theme.BorderFocusedColor = lipgloss.Color(flexokiBlue400) + theme.BorderDimColor = lipgloss.Color(flexokiBase850) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: flexokiGreen400, - Light: flexokiGreen600, - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: flexokiRed400, - Light: flexokiRed600, - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase700, - Light: flexokiBase500, - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase700, - Light: flexokiBase500, - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: flexokiGreen400, - Light: flexokiGreen600, - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: flexokiRed400, - Light: flexokiRed600, - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#1D2419", // Darker green background - Light: "#EFF2E2", // Light green background - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#241919", // Darker red background - Light: "#F2E2E2", // Light red background - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlack, - Light: flexokiPaper, - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase700, - Light: flexokiBase500, - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#1A2017", // Slightly darker green - Light: "#E5EBD9", // Light green - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#201717", // Slightly darker red - Light: "#EBD9D9", // Light red - } + theme.DiffAddedColor = lipgloss.Color(flexokiGreen400) + theme.DiffRemovedColor = lipgloss.Color(flexokiRed400) + theme.DiffContextColor = lipgloss.Color(flexokiBase700) + theme.DiffHunkHeaderColor = lipgloss.Color(flexokiBase700) + theme.DiffHighlightAddedColor = lipgloss.Color(flexokiGreen400) + theme.DiffHighlightRemovedColor = lipgloss.Color(flexokiRed400) + theme.DiffAddedBgColor = lipgloss.Color("#1D2419") // Darker green background + theme.DiffRemovedBgColor = lipgloss.Color("#241919") // Darker red background + theme.DiffContextBgColor = lipgloss.Color(flexokiBlack) + theme.DiffLineNumberColor = lipgloss.Color(flexokiBase700) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#1A2017") // Slightly darker green + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#201717") // Slightly darker red // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase300, - Light: flexokiBase600, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: flexokiYellow400, - Light: flexokiYellow600, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: flexokiCyan400, - Light: flexokiCyan600, - } - theme.MarkdownLinkTextColor = lipgloss.AdaptiveColor{ - Dark: flexokiMagenta400, - Light: flexokiMagenta600, - } - theme.MarkdownCodeColor = lipgloss.AdaptiveColor{ - Dark: flexokiGreen400, - Light: flexokiGreen600, - } - theme.MarkdownBlockQuoteColor = lipgloss.AdaptiveColor{ - Dark: flexokiCyan400, - Light: flexokiCyan600, - } - theme.MarkdownEmphColor = lipgloss.AdaptiveColor{ - Dark: flexokiYellow400, - Light: flexokiYellow600, - } - theme.MarkdownStrongColor = lipgloss.AdaptiveColor{ - Dark: flexokiOrange400, - Light: flexokiOrange600, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase800, - Light: flexokiBase200, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlue400, - Light: flexokiBlue600, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlue400, - Light: flexokiBlue600, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: flexokiPurple400, - Light: flexokiPurple600, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: flexokiMagenta400, - Light: flexokiMagenta600, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase300, - Light: flexokiBase600, - } + theme.MarkdownTextColor = lipgloss.Color(flexokiBase300) + theme.MarkdownHeadingColor = lipgloss.Color(flexokiYellow400) + theme.MarkdownLinkColor = lipgloss.Color(flexokiCyan400) + theme.MarkdownLinkTextColor = lipgloss.Color(flexokiMagenta400) + theme.MarkdownCodeColor = lipgloss.Color(flexokiGreen400) + theme.MarkdownBlockQuoteColor = lipgloss.Color(flexokiCyan400) + theme.MarkdownEmphColor = lipgloss.Color(flexokiYellow400) + theme.MarkdownStrongColor = lipgloss.Color(flexokiOrange400) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(flexokiBase800) + theme.MarkdownListItemColor = lipgloss.Color(flexokiBlue400) + theme.MarkdownListEnumerationColor = lipgloss.Color(flexokiBlue400) + theme.MarkdownImageColor = lipgloss.Color(flexokiPurple400) + theme.MarkdownImageTextColor = lipgloss.Color(flexokiMagenta400) + theme.MarkdownCodeBlockColor = lipgloss.Color(flexokiBase300) // Syntax highlighting colors (based on Flexoki's mappings) - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase700, // tx-3 - Light: flexokiBase300, // tx-3 - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: flexokiGreen400, // gr - Light: flexokiGreen600, // gr - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: flexokiOrange400, // or - Light: flexokiOrange600, // or - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: flexokiBlue400, // bl - Light: flexokiBlue600, // bl - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: flexokiCyan400, // cy - Light: flexokiCyan600, // cy - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: flexokiPurple400, // pu - Light: flexokiPurple600, // pu - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: flexokiYellow400, // ye - Light: flexokiYellow600, // ye - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase500, // tx-2 - Light: flexokiBase500, // tx-2 - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: flexokiBase500, // tx-2 - Light: flexokiBase500, // tx-2 - } + theme.SyntaxCommentColor = lipgloss.Color(flexokiBase700) // tx-3 + theme.SyntaxKeywordColor = lipgloss.Color(flexokiGreen400) // gr + theme.SyntaxFunctionColor = lipgloss.Color(flexokiOrange400) // or + theme.SyntaxVariableColor = lipgloss.Color(flexokiBlue400) // bl + theme.SyntaxStringColor = lipgloss.Color(flexokiCyan400) // cy + theme.SyntaxNumberColor = lipgloss.Color(flexokiPurple400) // pu + theme.SyntaxTypeColor = lipgloss.Color(flexokiYellow400) // ye + theme.SyntaxOperatorColor = lipgloss.Color(flexokiBase500) // tx-2 + theme.SyntaxPunctuationColor = lipgloss.Color(flexokiBase500) // tx-2 + + return theme +} + +// NewFlexokiLightTheme creates a new instance of the Flexoki Light theme. +func NewFlexokiLightTheme() *FlexokiTheme { + theme := &FlexokiTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(flexokiBlue600) + theme.SecondaryColor = lipgloss.Color(flexokiPurple600) + theme.AccentColor = lipgloss.Color(flexokiOrange600) + + // Status colors + theme.ErrorColor = lipgloss.Color(flexokiRed600) + theme.WarningColor = lipgloss.Color(flexokiYellow600) + theme.SuccessColor = lipgloss.Color(flexokiGreen600) + theme.InfoColor = lipgloss.Color(flexokiCyan600) + + // Text colors + theme.TextColor = lipgloss.Color(flexokiBase600) + theme.TextMutedColor = lipgloss.Color(flexokiBase500) + theme.TextEmphasizedColor = lipgloss.Color(flexokiYellow600) + + // Background colors + theme.BackgroundColor = lipgloss.Color(flexokiPaper) + theme.BackgroundSecondaryColor = lipgloss.Color(flexokiBase50) + theme.BackgroundDarkerColor = lipgloss.Color(flexokiBase100) + + // Border colors + theme.BorderNormalColor = lipgloss.Color(flexokiBase100) + theme.BorderFocusedColor = lipgloss.Color(flexokiBlue600) + theme.BorderDimColor = lipgloss.Color(flexokiBase150) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color(flexokiGreen600) + theme.DiffRemovedColor = lipgloss.Color(flexokiRed600) + theme.DiffContextColor = lipgloss.Color(flexokiBase500) + theme.DiffHunkHeaderColor = lipgloss.Color(flexokiBase500) + theme.DiffHighlightAddedColor = lipgloss.Color(flexokiGreen600) + theme.DiffHighlightRemovedColor = lipgloss.Color(flexokiRed600) + theme.DiffAddedBgColor = lipgloss.Color("#EFF2E2") // Light green background + theme.DiffRemovedBgColor = lipgloss.Color("#F2E2E2") // Light red background + theme.DiffContextBgColor = lipgloss.Color(flexokiPaper) + theme.DiffLineNumberColor = lipgloss.Color(flexokiBase500) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#E5EBD9") // Light green + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#EBD9D9") // Light red + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(flexokiBase600) + theme.MarkdownHeadingColor = lipgloss.Color(flexokiYellow600) + theme.MarkdownLinkColor = lipgloss.Color(flexokiCyan600) + theme.MarkdownLinkTextColor = lipgloss.Color(flexokiMagenta600) + theme.MarkdownCodeColor = lipgloss.Color(flexokiGreen600) + theme.MarkdownBlockQuoteColor = lipgloss.Color(flexokiCyan600) + theme.MarkdownEmphColor = lipgloss.Color(flexokiYellow600) + theme.MarkdownStrongColor = lipgloss.Color(flexokiOrange600) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(flexokiBase200) + theme.MarkdownListItemColor = lipgloss.Color(flexokiBlue600) + theme.MarkdownListEnumerationColor = lipgloss.Color(flexokiBlue600) + theme.MarkdownImageColor = lipgloss.Color(flexokiPurple600) + theme.MarkdownImageTextColor = lipgloss.Color(flexokiMagenta600) + theme.MarkdownCodeBlockColor = lipgloss.Color(flexokiBase600) + + // Syntax highlighting colors (based on Flexoki's mappings) + theme.SyntaxCommentColor = lipgloss.Color(flexokiBase300) // tx-3 + theme.SyntaxKeywordColor = lipgloss.Color(flexokiGreen600) // gr + theme.SyntaxFunctionColor = lipgloss.Color(flexokiOrange600) // or + theme.SyntaxVariableColor = lipgloss.Color(flexokiBlue600) // bl + theme.SyntaxStringColor = lipgloss.Color(flexokiCyan600) // cy + theme.SyntaxNumberColor = lipgloss.Color(flexokiPurple600) // pu + theme.SyntaxTypeColor = lipgloss.Color(flexokiYellow600) // ye + theme.SyntaxOperatorColor = lipgloss.Color(flexokiBase500) // tx-2 + theme.SyntaxPunctuationColor = lipgloss.Color(flexokiBase500) // tx-2 return theme } func init() { - // Register the Flexoki theme with the theme manager - RegisterTheme("flexoki", NewFlexokiTheme()) + // Register the Flexoki themes with the theme manager + RegisterTheme("flexoki-dark", NewFlexokiDarkTheme()) + RegisterTheme("flexoki-light", NewFlexokiLightTheme()) } \ No newline at end of file diff --git a/internal/tui/theme/gruvbox.go b/internal/tui/theme/gruvbox.go index ed544b84de80446bf0f90be40adbc35cd0ba0689..6df6ebb4d5723052d419476f5c9b9397e1bafb3d 100644 --- a/internal/tui/theme/gruvbox.go +++ b/internal/tui/theme/gruvbox.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // Gruvbox color palette constants @@ -74,229 +74,151 @@ func NewGruvboxTheme() *GruvboxTheme { theme := &GruvboxTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkPurpleBright, - Light: gruvboxLightPurpleBright, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkOrangeBright, - Light: gruvboxLightOrangeBright, - } + theme.PrimaryColor = lipgloss.Color(gruvboxDarkBlueBright) + theme.SecondaryColor = lipgloss.Color(gruvboxDarkPurpleBright) + theme.AccentColor = lipgloss.Color(gruvboxDarkOrangeBright) // Status colors - theme.ErrorColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkRedBright, - Light: gruvboxLightRedBright, - } - theme.WarningColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkYellowBright, - Light: gruvboxLightYellowBright, - } - theme.SuccessColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkGreenBright, - Light: gruvboxLightGreenBright, - } - theme.InfoColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } + theme.ErrorColor = lipgloss.Color(gruvboxDarkRedBright) + theme.WarningColor = lipgloss.Color(gruvboxDarkYellowBright) + theme.SuccessColor = lipgloss.Color(gruvboxDarkGreenBright) + theme.InfoColor = lipgloss.Color(gruvboxDarkBlueBright) // Text colors - theme.TextColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg1, - Light: gruvboxLightFg1, - } - theme.TextMutedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg4, - Light: gruvboxLightFg4, - } - theme.TextEmphasizedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkYellowBright, - Light: gruvboxLightYellowBright, - } + theme.TextColor = lipgloss.Color(gruvboxDarkFg1) + theme.TextMutedColor = lipgloss.Color(gruvboxDarkFg4) + theme.TextEmphasizedColor = lipgloss.Color(gruvboxDarkYellowBright) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg0, - Light: gruvboxLightBg0, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg1, - Light: gruvboxLightBg1, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg0Soft, - Light: gruvboxLightBg0Soft, - } + theme.BackgroundColor = lipgloss.Color(gruvboxDarkBg0) + theme.BackgroundSecondaryColor = lipgloss.Color(gruvboxDarkBg1) + theme.BackgroundDarkerColor = lipgloss.Color(gruvboxDarkBg0Soft) // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg2, - Light: gruvboxLightBg2, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg1, - Light: gruvboxLightBg1, - } + theme.BorderNormalColor = lipgloss.Color(gruvboxDarkBg2) + theme.BorderFocusedColor = lipgloss.Color(gruvboxDarkBlueBright) + theme.BorderDimColor = lipgloss.Color(gruvboxDarkBg1) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkGreenBright, - Light: gruvboxLightGreenBright, - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkRedBright, - Light: gruvboxLightRedBright, - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg4, - Light: gruvboxLightFg4, - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg3, - Light: gruvboxLightFg3, - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkGreenBright, - Light: gruvboxLightGreenBright, - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkRedBright, - Light: gruvboxLightRedBright, - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#3C4C3C", // Darker green background - Light: "#E8F5E9", // Light green background - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#4C3C3C", // Darker red background - Light: "#FFEBEE", // Light red background - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg0, - Light: gruvboxLightBg0, - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg4, - Light: gruvboxLightFg4, - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#32432F", // Slightly darker green - Light: "#C8E6C9", // Light green - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#43322F", // Slightly darker red - Light: "#FFCDD2", // Light red - } + theme.DiffAddedColor = lipgloss.Color(gruvboxDarkGreenBright) + theme.DiffRemovedColor = lipgloss.Color(gruvboxDarkRedBright) + theme.DiffContextColor = lipgloss.Color(gruvboxDarkFg4) + theme.DiffHunkHeaderColor = lipgloss.Color(gruvboxDarkFg3) + theme.DiffHighlightAddedColor = lipgloss.Color(gruvboxDarkGreenBright) + theme.DiffHighlightRemovedColor = lipgloss.Color(gruvboxDarkRedBright) + theme.DiffAddedBgColor = lipgloss.Color("#3C4C3C") // Darker green background + theme.DiffRemovedBgColor = lipgloss.Color("#4C3C3C") // Darker red background + theme.DiffContextBgColor = lipgloss.Color(gruvboxDarkBg0) + theme.DiffLineNumberColor = lipgloss.Color(gruvboxDarkFg4) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#32432F") // Slightly darker green + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#43322F") // Slightly darker red // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg1, - Light: gruvboxLightFg1, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkYellowBright, - Light: gruvboxLightYellowBright, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } - theme.MarkdownLinkTextColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkAquaBright, - Light: gruvboxLightAquaBright, - } - theme.MarkdownCodeColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkGreenBright, - Light: gruvboxLightGreenBright, - } - theme.MarkdownBlockQuoteColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkAquaBright, - Light: gruvboxLightAquaBright, - } - theme.MarkdownEmphColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkYellowBright, - Light: gruvboxLightYellowBright, - } - theme.MarkdownStrongColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkOrangeBright, - Light: gruvboxLightOrangeBright, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBg3, - Light: gruvboxLightBg3, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkPurpleBright, - Light: gruvboxLightPurpleBright, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkAquaBright, - Light: gruvboxLightAquaBright, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg1, - Light: gruvboxLightFg1, - } + theme.MarkdownTextColor = lipgloss.Color(gruvboxDarkFg1) + theme.MarkdownHeadingColor = lipgloss.Color(gruvboxDarkYellowBright) + theme.MarkdownLinkColor = lipgloss.Color(gruvboxDarkBlueBright) + theme.MarkdownLinkTextColor = lipgloss.Color(gruvboxDarkAquaBright) + theme.MarkdownCodeColor = lipgloss.Color(gruvboxDarkGreenBright) + theme.MarkdownBlockQuoteColor = lipgloss.Color(gruvboxDarkAquaBright) + theme.MarkdownEmphColor = lipgloss.Color(gruvboxDarkYellowBright) + theme.MarkdownStrongColor = lipgloss.Color(gruvboxDarkOrangeBright) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(gruvboxDarkBg3) + theme.MarkdownListItemColor = lipgloss.Color(gruvboxDarkBlueBright) + theme.MarkdownListEnumerationColor = lipgloss.Color(gruvboxDarkBlueBright) + theme.MarkdownImageColor = lipgloss.Color(gruvboxDarkPurpleBright) + theme.MarkdownImageTextColor = lipgloss.Color(gruvboxDarkAquaBright) + theme.MarkdownCodeBlockColor = lipgloss.Color(gruvboxDarkFg1) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkGray, - Light: gruvboxLightGray, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkRedBright, - Light: gruvboxLightRedBright, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkGreenBright, - Light: gruvboxLightGreenBright, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkBlueBright, - Light: gruvboxLightBlueBright, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkYellowBright, - Light: gruvboxLightYellowBright, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkPurpleBright, - Light: gruvboxLightPurpleBright, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkYellow, - Light: gruvboxLightYellow, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkAquaBright, - Light: gruvboxLightAquaBright, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: gruvboxDarkFg1, - Light: gruvboxLightFg1, - } + theme.SyntaxCommentColor = lipgloss.Color(gruvboxDarkGray) + theme.SyntaxKeywordColor = lipgloss.Color(gruvboxDarkRedBright) + theme.SyntaxFunctionColor = lipgloss.Color(gruvboxDarkGreenBright) + theme.SyntaxVariableColor = lipgloss.Color(gruvboxDarkBlueBright) + theme.SyntaxStringColor = lipgloss.Color(gruvboxDarkYellowBright) + theme.SyntaxNumberColor = lipgloss.Color(gruvboxDarkPurpleBright) + theme.SyntaxTypeColor = lipgloss.Color(gruvboxDarkYellow) + theme.SyntaxOperatorColor = lipgloss.Color(gruvboxDarkAquaBright) + theme.SyntaxPunctuationColor = lipgloss.Color(gruvboxDarkFg1) + + return theme +} + +// NewGruvboxLightTheme creates a new instance of the Gruvbox Light theme. +func NewGruvboxLightTheme() *GruvboxTheme { + theme := &GruvboxTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(gruvboxLightBlueBright) + theme.SecondaryColor = lipgloss.Color(gruvboxLightPurpleBright) + theme.AccentColor = lipgloss.Color(gruvboxLightOrangeBright) + + // Status colors + theme.ErrorColor = lipgloss.Color(gruvboxLightRedBright) + theme.WarningColor = lipgloss.Color(gruvboxLightYellowBright) + theme.SuccessColor = lipgloss.Color(gruvboxLightGreenBright) + theme.InfoColor = lipgloss.Color(gruvboxLightBlueBright) + + // Text colors + theme.TextColor = lipgloss.Color(gruvboxLightFg1) + theme.TextMutedColor = lipgloss.Color(gruvboxLightFg4) + theme.TextEmphasizedColor = lipgloss.Color(gruvboxLightYellowBright) + + // Background colors + theme.BackgroundColor = lipgloss.Color(gruvboxLightBg0) + theme.BackgroundSecondaryColor = lipgloss.Color(gruvboxLightBg1) + theme.BackgroundDarkerColor = lipgloss.Color(gruvboxLightBg0Soft) + + // Border colors + theme.BorderNormalColor = lipgloss.Color(gruvboxLightBg2) + theme.BorderFocusedColor = lipgloss.Color(gruvboxLightBlueBright) + theme.BorderDimColor = lipgloss.Color(gruvboxLightBg1) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color(gruvboxLightGreenBright) + theme.DiffRemovedColor = lipgloss.Color(gruvboxLightRedBright) + theme.DiffContextColor = lipgloss.Color(gruvboxLightFg4) + theme.DiffHunkHeaderColor = lipgloss.Color(gruvboxLightFg3) + theme.DiffHighlightAddedColor = lipgloss.Color(gruvboxLightGreenBright) + theme.DiffHighlightRemovedColor = lipgloss.Color(gruvboxLightRedBright) + theme.DiffAddedBgColor = lipgloss.Color("#E8F5E9") // Light green background + theme.DiffRemovedBgColor = lipgloss.Color("#FFEBEE") // Light red background + theme.DiffContextBgColor = lipgloss.Color(gruvboxLightBg0) + theme.DiffLineNumberColor = lipgloss.Color(gruvboxLightFg4) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#C8E6C9") // Light green + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#FFCDD2") // Light red + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(gruvboxLightFg1) + theme.MarkdownHeadingColor = lipgloss.Color(gruvboxLightYellowBright) + theme.MarkdownLinkColor = lipgloss.Color(gruvboxLightBlueBright) + theme.MarkdownLinkTextColor = lipgloss.Color(gruvboxLightAquaBright) + theme.MarkdownCodeColor = lipgloss.Color(gruvboxLightGreenBright) + theme.MarkdownBlockQuoteColor = lipgloss.Color(gruvboxLightAquaBright) + theme.MarkdownEmphColor = lipgloss.Color(gruvboxLightYellowBright) + theme.MarkdownStrongColor = lipgloss.Color(gruvboxLightOrangeBright) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(gruvboxLightBg3) + theme.MarkdownListItemColor = lipgloss.Color(gruvboxLightBlueBright) + theme.MarkdownListEnumerationColor = lipgloss.Color(gruvboxLightBlueBright) + theme.MarkdownImageColor = lipgloss.Color(gruvboxLightPurpleBright) + theme.MarkdownImageTextColor = lipgloss.Color(gruvboxLightAquaBright) + theme.MarkdownCodeBlockColor = lipgloss.Color(gruvboxLightFg1) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(gruvboxLightGray) + theme.SyntaxKeywordColor = lipgloss.Color(gruvboxLightRedBright) + theme.SyntaxFunctionColor = lipgloss.Color(gruvboxLightGreenBright) + theme.SyntaxVariableColor = lipgloss.Color(gruvboxLightBlueBright) + theme.SyntaxStringColor = lipgloss.Color(gruvboxLightYellowBright) + theme.SyntaxNumberColor = lipgloss.Color(gruvboxLightPurpleBright) + theme.SyntaxTypeColor = lipgloss.Color(gruvboxLightYellow) + theme.SyntaxOperatorColor = lipgloss.Color(gruvboxLightAquaBright) + theme.SyntaxPunctuationColor = lipgloss.Color(gruvboxLightFg1) return theme } func init() { - // Register the Gruvbox theme with the theme manager + // Register the Gruvbox themes with the theme manager RegisterTheme("gruvbox", NewGruvboxTheme()) + RegisterTheme("gruvbox-light", NewGruvboxLightTheme()) } \ No newline at end of file diff --git a/internal/tui/theme/monokai.go b/internal/tui/theme/monokai.go index 4695fefa998f0e038442b1bea3074f5a8a808a0e..8b860316dc649310f6b976369c16ded9a932f3d9 100644 --- a/internal/tui/theme/monokai.go +++ b/internal/tui/theme/monokai.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // MonokaiProTheme implements the Theme interface with Monokai Pro colors. @@ -27,6 +27,80 @@ func NewMonokaiProTheme() *MonokaiProTheme { darkPurple := "#ab9df2" darkBorder := "#403e41" + theme := &MonokaiProTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(darkCyan) + theme.SecondaryColor = lipgloss.Color(darkPurple) + theme.AccentColor = lipgloss.Color(darkOrange) + + // Status colors + theme.ErrorColor = lipgloss.Color(darkRed) + theme.WarningColor = lipgloss.Color(darkOrange) + theme.SuccessColor = lipgloss.Color(darkGreen) + theme.InfoColor = lipgloss.Color(darkBlue) + + // Text colors + theme.TextColor = lipgloss.Color(darkForeground) + theme.TextMutedColor = lipgloss.Color(darkComment) + theme.TextEmphasizedColor = lipgloss.Color(darkYellow) + + // Background colors + theme.BackgroundColor = lipgloss.Color(darkBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(darkCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#221f22") // Slightly darker than background + + // Border colors + theme.BorderNormalColor = lipgloss.Color(darkBorder) + theme.BorderFocusedColor = lipgloss.Color(darkCyan) + theme.BorderDimColor = lipgloss.Color(darkSelection) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color("#a9dc76") + theme.DiffRemovedColor = lipgloss.Color("#ff6188") + theme.DiffContextColor = lipgloss.Color("#a0a0a0") + theme.DiffHunkHeaderColor = lipgloss.Color("#a0a0a0") + theme.DiffHighlightAddedColor = lipgloss.Color("#c2e7a9") + theme.DiffHighlightRemovedColor = lipgloss.Color("#ff8ca6") + theme.DiffAddedBgColor = lipgloss.Color("#3a4a35") + theme.DiffRemovedBgColor = lipgloss.Color("#4a3439") + theme.DiffContextBgColor = lipgloss.Color(darkBackground) + theme.DiffLineNumberColor = lipgloss.Color("#888888") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#2d3a28") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#3d2a2e") + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(darkForeground) + theme.MarkdownHeadingColor = lipgloss.Color(darkPurple) + theme.MarkdownLinkColor = lipgloss.Color(darkCyan) + theme.MarkdownLinkTextColor = lipgloss.Color(darkBlue) + theme.MarkdownCodeColor = lipgloss.Color(darkGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(darkYellow) + theme.MarkdownEmphColor = lipgloss.Color(darkYellow) + theme.MarkdownStrongColor = lipgloss.Color(darkOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(darkComment) + theme.MarkdownListItemColor = lipgloss.Color(darkCyan) + theme.MarkdownListEnumerationColor = lipgloss.Color(darkBlue) + theme.MarkdownImageColor = lipgloss.Color(darkCyan) + theme.MarkdownImageTextColor = lipgloss.Color(darkBlue) + theme.MarkdownCodeBlockColor = lipgloss.Color(darkForeground) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(darkComment) + theme.SyntaxKeywordColor = lipgloss.Color(darkRed) + theme.SyntaxFunctionColor = lipgloss.Color(darkGreen) + theme.SyntaxVariableColor = lipgloss.Color(darkForeground) + theme.SyntaxStringColor = lipgloss.Color(darkYellow) + theme.SyntaxNumberColor = lipgloss.Color(darkPurple) + theme.SyntaxTypeColor = lipgloss.Color(darkBlue) + theme.SyntaxOperatorColor = lipgloss.Color(darkCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(darkForeground) + + return theme +} + +// NewMonokaiProLightTheme creates a new instance of the Monokai Pro Light theme. +func NewMonokaiProLightTheme() *MonokaiProTheme { // Light mode colors (adapted from dark) lightBackground := "#fafafa" lightCurrentLine := "#f0f0f0" @@ -45,229 +119,77 @@ func NewMonokaiProTheme() *MonokaiProTheme { theme := &MonokaiProTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } + theme.PrimaryColor = lipgloss.Color(lightCyan) + theme.SecondaryColor = lipgloss.Color(lightPurple) + theme.AccentColor = lipgloss.Color(lightOrange) // 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: darkBlue, - Light: lightBlue, - } + theme.ErrorColor = lipgloss.Color(lightRed) + theme.WarningColor = lipgloss.Color(lightOrange) + theme.SuccessColor = lipgloss.Color(lightGreen) + theme.InfoColor = lipgloss.Color(lightBlue) // 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, - } + theme.TextColor = lipgloss.Color(lightForeground) + theme.TextMutedColor = lipgloss.Color(lightComment) + theme.TextEmphasizedColor = lipgloss.Color(lightYellow) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkCurrentLine, - Light: lightCurrentLine, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: "#221f22", // Slightly darker than background - Light: "#ffffff", // Slightly lighter than background - } + theme.BackgroundColor = lipgloss.Color(lightBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(lightCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#ffffff") // Slightly lighter than background // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: darkBorder, - Light: lightBorder, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: darkSelection, - Light: lightSelection, - } + theme.BorderNormalColor = lipgloss.Color(lightBorder) + theme.BorderFocusedColor = lipgloss.Color(lightCyan) + theme.BorderDimColor = lipgloss.Color(lightSelection) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: "#a9dc76", - Light: "#9bca65", - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#ff6188", - Light: "#f92672", - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: "#a0a0a0", - Light: "#757575", - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: "#a0a0a0", - Light: "#757575", - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: "#c2e7a9", - Light: "#c5e0b4", - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#ff8ca6", - Light: "#ffb3c8", - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#3a4a35", - Light: "#e8f5e9", - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#4a3439", - Light: "#ffebee", - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: "#888888", - Light: "#9e9e9e", - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#2d3a28", - Light: "#c8e6c9", - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#3d2a2e", - Light: "#ffcdd2", - } + theme.DiffAddedColor = lipgloss.Color("#9bca65") + theme.DiffRemovedColor = lipgloss.Color("#f92672") + theme.DiffContextColor = lipgloss.Color("#757575") + theme.DiffHunkHeaderColor = lipgloss.Color("#757575") + theme.DiffHighlightAddedColor = lipgloss.Color("#c5e0b4") + theme.DiffHighlightRemovedColor = lipgloss.Color("#ffb3c8") + theme.DiffAddedBgColor = lipgloss.Color("#e8f5e9") + theme.DiffRemovedBgColor = lipgloss.Color("#ffebee") + theme.DiffContextBgColor = lipgloss.Color(lightBackground) + theme.DiffLineNumberColor = lipgloss.Color("#9e9e9e") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#c8e6c9") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#ffcdd2") // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownLinkTextColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - 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: darkOrange, - Light: lightOrange, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.MarkdownTextColor = lipgloss.Color(lightForeground) + theme.MarkdownHeadingColor = lipgloss.Color(lightPurple) + theme.MarkdownLinkColor = lipgloss.Color(lightCyan) + theme.MarkdownLinkTextColor = lipgloss.Color(lightBlue) + theme.MarkdownCodeColor = lipgloss.Color(lightGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(lightYellow) + theme.MarkdownEmphColor = lipgloss.Color(lightYellow) + theme.MarkdownStrongColor = lipgloss.Color(lightOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(lightComment) + theme.MarkdownListItemColor = lipgloss.Color(lightCyan) + theme.MarkdownListEnumerationColor = lipgloss.Color(lightBlue) + theme.MarkdownImageColor = lipgloss.Color(lightCyan) + theme.MarkdownImageTextColor = lipgloss.Color(lightBlue) + theme.MarkdownCodeBlockColor = lipgloss.Color(lightForeground) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: darkRed, - Light: lightRed, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: darkYellow, - Light: lightYellow, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.SyntaxCommentColor = lipgloss.Color(lightComment) + theme.SyntaxKeywordColor = lipgloss.Color(lightRed) + theme.SyntaxFunctionColor = lipgloss.Color(lightGreen) + theme.SyntaxVariableColor = lipgloss.Color(lightForeground) + theme.SyntaxStringColor = lipgloss.Color(lightYellow) + theme.SyntaxNumberColor = lipgloss.Color(lightPurple) + theme.SyntaxTypeColor = lipgloss.Color(lightBlue) + theme.SyntaxOperatorColor = lipgloss.Color(lightCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(lightForeground) return theme } func init() { - // Register the Monokai Pro theme with the theme manager + // Register the Monokai Pro themes with the theme manager RegisterTheme("monokai", NewMonokaiProTheme()) + RegisterTheme("monokai-light", NewMonokaiProLightTheme()) } \ No newline at end of file diff --git a/internal/tui/theme/onedark.go b/internal/tui/theme/onedark.go index 2b4dee50dccdd9639e0245c3d4eaaabb798b0cfe..936998d98142e73de4396e3ccbf320061fc2289e 100644 --- a/internal/tui/theme/onedark.go +++ b/internal/tui/theme/onedark.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // OneDarkTheme implements the Theme interface with Atom's One Dark colors. @@ -28,6 +28,80 @@ func NewOneDarkTheme() *OneDarkTheme { darkPurple := "#c678dd" darkBorder := "#3b4048" + theme := &OneDarkTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(darkBlue) + theme.SecondaryColor = lipgloss.Color(darkPurple) + theme.AccentColor = lipgloss.Color(darkOrange) + + // Status colors + theme.ErrorColor = lipgloss.Color(darkRed) + theme.WarningColor = lipgloss.Color(darkOrange) + theme.SuccessColor = lipgloss.Color(darkGreen) + theme.InfoColor = lipgloss.Color(darkBlue) + + // Text colors + theme.TextColor = lipgloss.Color(darkForeground) + theme.TextMutedColor = lipgloss.Color(darkComment) + theme.TextEmphasizedColor = lipgloss.Color(darkYellow) + + // Background colors + theme.BackgroundColor = lipgloss.Color(darkBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(darkCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#21252b") // Slightly darker than background + + // Border colors + theme.BorderNormalColor = lipgloss.Color(darkBorder) + theme.BorderFocusedColor = lipgloss.Color(darkBlue) + theme.BorderDimColor = lipgloss.Color(darkSelection) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color("#478247") + theme.DiffRemovedColor = lipgloss.Color("#7C4444") + theme.DiffContextColor = lipgloss.Color("#a0a0a0") + theme.DiffHunkHeaderColor = lipgloss.Color("#a0a0a0") + theme.DiffHighlightAddedColor = lipgloss.Color("#DAFADA") + theme.DiffHighlightRemovedColor = lipgloss.Color("#FADADD") + theme.DiffAddedBgColor = lipgloss.Color("#303A30") + theme.DiffRemovedBgColor = lipgloss.Color("#3A3030") + theme.DiffContextBgColor = lipgloss.Color(darkBackground) + theme.DiffLineNumberColor = lipgloss.Color("#888888") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#293229") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#332929") + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(darkForeground) + theme.MarkdownHeadingColor = lipgloss.Color(darkPurple) + theme.MarkdownLinkColor = lipgloss.Color(darkBlue) + theme.MarkdownLinkTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeColor = lipgloss.Color(darkGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(darkYellow) + theme.MarkdownEmphColor = lipgloss.Color(darkYellow) + theme.MarkdownStrongColor = lipgloss.Color(darkOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(darkComment) + theme.MarkdownListItemColor = lipgloss.Color(darkBlue) + theme.MarkdownListEnumerationColor = lipgloss.Color(darkCyan) + theme.MarkdownImageColor = lipgloss.Color(darkBlue) + theme.MarkdownImageTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(darkForeground) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(darkComment) + theme.SyntaxKeywordColor = lipgloss.Color(darkPurple) + theme.SyntaxFunctionColor = lipgloss.Color(darkBlue) + theme.SyntaxVariableColor = lipgloss.Color(darkRed) + theme.SyntaxStringColor = lipgloss.Color(darkGreen) + theme.SyntaxNumberColor = lipgloss.Color(darkOrange) + theme.SyntaxTypeColor = lipgloss.Color(darkYellow) + theme.SyntaxOperatorColor = lipgloss.Color(darkCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(darkForeground) + + return theme +} + +// NewOneLightTheme creates a new instance of the One Light theme. +func NewOneLightTheme() *OneDarkTheme { // Light mode colors from Atom One Light lightBackground := "#fafafa" lightCurrentLine := "#f0f0f0" @@ -46,229 +120,77 @@ func NewOneDarkTheme() *OneDarkTheme { theme := &OneDarkTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } + theme.PrimaryColor = lipgloss.Color(lightBlue) + theme.SecondaryColor = lipgloss.Color(lightPurple) + theme.AccentColor = lipgloss.Color(lightOrange) // 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: darkBlue, - Light: lightBlue, - } + theme.ErrorColor = lipgloss.Color(lightRed) + theme.WarningColor = lipgloss.Color(lightOrange) + theme.SuccessColor = lipgloss.Color(lightGreen) + theme.InfoColor = lipgloss.Color(lightBlue) // 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, - } + theme.TextColor = lipgloss.Color(lightForeground) + theme.TextMutedColor = lipgloss.Color(lightComment) + theme.TextEmphasizedColor = lipgloss.Color(lightYellow) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkCurrentLine, - Light: lightCurrentLine, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: "#21252b", // Slightly darker than background - Light: "#ffffff", // Slightly lighter than background - } + theme.BackgroundColor = lipgloss.Color(lightBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(lightCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#ffffff") // Slightly lighter than background // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: darkBorder, - Light: lightBorder, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: darkSelection, - Light: lightSelection, - } + theme.BorderNormalColor = lipgloss.Color(lightBorder) + theme.BorderFocusedColor = lipgloss.Color(lightBlue) + theme.BorderDimColor = lipgloss.Color(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", - } + theme.DiffAddedColor = lipgloss.Color("#2E7D32") + theme.DiffRemovedColor = lipgloss.Color("#C62828") + theme.DiffContextColor = lipgloss.Color("#757575") + theme.DiffHunkHeaderColor = lipgloss.Color("#757575") + theme.DiffHighlightAddedColor = lipgloss.Color("#A5D6A7") + theme.DiffHighlightRemovedColor = lipgloss.Color("#EF9A9A") + theme.DiffAddedBgColor = lipgloss.Color("#E8F5E9") + theme.DiffRemovedBgColor = lipgloss.Color("#FFEBEE") + theme.DiffContextBgColor = lipgloss.Color(lightBackground) + theme.DiffLineNumberColor = lipgloss.Color("#9E9E9E") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#C8E6C9") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#FFCDD2") // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - 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: darkOrange, - Light: lightOrange, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.MarkdownTextColor = lipgloss.Color(lightForeground) + theme.MarkdownHeadingColor = lipgloss.Color(lightPurple) + theme.MarkdownLinkColor = lipgloss.Color(lightBlue) + theme.MarkdownLinkTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeColor = lipgloss.Color(lightGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(lightYellow) + theme.MarkdownEmphColor = lipgloss.Color(lightYellow) + theme.MarkdownStrongColor = lipgloss.Color(lightOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(lightComment) + theme.MarkdownListItemColor = lipgloss.Color(lightBlue) + theme.MarkdownListEnumerationColor = lipgloss.Color(lightCyan) + theme.MarkdownImageColor = lipgloss.Color(lightBlue) + theme.MarkdownImageTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(lightForeground) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: darkRed, - Light: lightRed, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: darkYellow, - Light: lightYellow, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.SyntaxCommentColor = lipgloss.Color(lightComment) + theme.SyntaxKeywordColor = lipgloss.Color(lightPurple) + theme.SyntaxFunctionColor = lipgloss.Color(lightBlue) + theme.SyntaxVariableColor = lipgloss.Color(lightRed) + theme.SyntaxStringColor = lipgloss.Color(lightGreen) + theme.SyntaxNumberColor = lipgloss.Color(lightOrange) + theme.SyntaxTypeColor = lipgloss.Color(lightYellow) + theme.SyntaxOperatorColor = lipgloss.Color(lightCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(lightForeground) return theme } func init() { - // Register the One Dark theme with the theme manager + // Register the One Dark and One Light themes with the theme manager RegisterTheme("onedark", NewOneDarkTheme()) + RegisterTheme("onelight", NewOneLightTheme()) } \ No newline at end of file diff --git a/internal/tui/theme/opencode.go b/internal/tui/theme/opencode.go index efec8615437eef1516582b2492833cfa16ffe4d8..e4a3af7b3208e3a1c475b2333043e65c4264b3e6 100644 --- a/internal/tui/theme/opencode.go +++ b/internal/tui/theme/opencode.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // OpenCodeTheme implements the Theme interface with OpenCode brand colors. @@ -10,8 +10,8 @@ type OpenCodeTheme struct { BaseTheme } -// NewOpenCodeTheme creates a new instance of the OpenCode theme. -func NewOpenCodeTheme() *OpenCodeTheme { +// NewOpenCodeDarkTheme creates a new instance of the OpenCode Dark theme. +func NewOpenCodeDarkTheme() *OpenCodeTheme { // OpenCode color palette // Dark mode colors darkBackground := "#212121" @@ -29,6 +29,80 @@ func NewOpenCodeTheme() *OpenCodeTheme { darkYellow := "#e5c07b" // Emphasized text darkBorder := "#4b4c5c" // Border color + theme := &OpenCodeTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(darkPrimary) + theme.SecondaryColor = lipgloss.Color(darkSecondary) + theme.AccentColor = lipgloss.Color(darkAccent) + + // Status colors + theme.ErrorColor = lipgloss.Color(darkRed) + theme.WarningColor = lipgloss.Color(darkOrange) + theme.SuccessColor = lipgloss.Color(darkGreen) + theme.InfoColor = lipgloss.Color(darkCyan) + + // Text colors + theme.TextColor = lipgloss.Color(darkForeground) + theme.TextMutedColor = lipgloss.Color(darkComment) + theme.TextEmphasizedColor = lipgloss.Color(darkYellow) + + // Background colors + theme.BackgroundColor = lipgloss.Color(darkBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(darkCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#121212") // Slightly darker than background + + // Border colors + theme.BorderNormalColor = lipgloss.Color(darkBorder) + theme.BorderFocusedColor = lipgloss.Color(darkPrimary) + theme.BorderDimColor = lipgloss.Color(darkSelection) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color("#478247") + theme.DiffRemovedColor = lipgloss.Color("#7C4444") + theme.DiffContextColor = lipgloss.Color("#a0a0a0") + theme.DiffHunkHeaderColor = lipgloss.Color("#a0a0a0") + theme.DiffHighlightAddedColor = lipgloss.Color("#DAFADA") + theme.DiffHighlightRemovedColor = lipgloss.Color("#FADADD") + theme.DiffAddedBgColor = lipgloss.Color("#303A30") + theme.DiffRemovedBgColor = lipgloss.Color("#3A3030") + theme.DiffContextBgColor = lipgloss.Color(darkBackground) + theme.DiffLineNumberColor = lipgloss.Color("#888888") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#293229") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#332929") + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(darkForeground) + theme.MarkdownHeadingColor = lipgloss.Color(darkSecondary) + theme.MarkdownLinkColor = lipgloss.Color(darkPrimary) + theme.MarkdownLinkTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeColor = lipgloss.Color(darkGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(darkYellow) + theme.MarkdownEmphColor = lipgloss.Color(darkYellow) + theme.MarkdownStrongColor = lipgloss.Color(darkAccent) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(darkComment) + theme.MarkdownListItemColor = lipgloss.Color(darkPrimary) + theme.MarkdownListEnumerationColor = lipgloss.Color(darkCyan) + theme.MarkdownImageColor = lipgloss.Color(darkPrimary) + theme.MarkdownImageTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(darkForeground) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(darkComment) + theme.SyntaxKeywordColor = lipgloss.Color(darkSecondary) + theme.SyntaxFunctionColor = lipgloss.Color(darkPrimary) + theme.SyntaxVariableColor = lipgloss.Color(darkRed) + theme.SyntaxStringColor = lipgloss.Color(darkGreen) + theme.SyntaxNumberColor = lipgloss.Color(darkAccent) + theme.SyntaxTypeColor = lipgloss.Color(darkYellow) + theme.SyntaxOperatorColor = lipgloss.Color(darkCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(darkForeground) + + return theme +} + +// NewOpenCodeLightTheme creates a new instance of the OpenCode Light theme. +func NewOpenCodeLightTheme() *OpenCodeTheme { // Light mode colors lightBackground := "#f8f8f8" lightCurrentLine := "#f0f0f0" @@ -48,230 +122,77 @@ func NewOpenCodeTheme() *OpenCodeTheme { 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, - } + theme.PrimaryColor = lipgloss.Color(lightPrimary) + theme.SecondaryColor = lipgloss.Color(lightSecondary) + theme.AccentColor = lipgloss.Color(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, - } + theme.ErrorColor = lipgloss.Color(lightRed) + theme.WarningColor = lipgloss.Color(lightOrange) + theme.SuccessColor = lipgloss.Color(lightGreen) + theme.InfoColor = lipgloss.Color(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, - } + theme.TextColor = lipgloss.Color(lightForeground) + theme.TextMutedColor = lipgloss.Color(lightComment) + theme.TextEmphasizedColor = lipgloss.Color(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 - } + theme.BackgroundColor = lipgloss.Color(lightBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(lightCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#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, - } + theme.BorderNormalColor = lipgloss.Color(lightBorder) + theme.BorderFocusedColor = lipgloss.Color(lightPrimary) + theme.BorderDimColor = lipgloss.Color(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", - } + theme.DiffAddedColor = lipgloss.Color("#2E7D32") + theme.DiffRemovedColor = lipgloss.Color("#C62828") + theme.DiffContextColor = lipgloss.Color("#757575") + theme.DiffHunkHeaderColor = lipgloss.Color("#757575") + theme.DiffHighlightAddedColor = lipgloss.Color("#A5D6A7") + theme.DiffHighlightRemovedColor = lipgloss.Color("#EF9A9A") + theme.DiffAddedBgColor = lipgloss.Color("#E8F5E9") + theme.DiffRemovedBgColor = lipgloss.Color("#FFEBEE") + theme.DiffContextBgColor = lipgloss.Color(lightBackground) + theme.DiffLineNumberColor = lipgloss.Color("#9E9E9E") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#C8E6C9") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#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, - } + theme.MarkdownTextColor = lipgloss.Color(lightForeground) + theme.MarkdownHeadingColor = lipgloss.Color(lightSecondary) + theme.MarkdownLinkColor = lipgloss.Color(lightPrimary) + theme.MarkdownLinkTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeColor = lipgloss.Color(lightGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(lightYellow) + theme.MarkdownEmphColor = lipgloss.Color(lightYellow) + theme.MarkdownStrongColor = lipgloss.Color(lightAccent) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(lightComment) + theme.MarkdownListItemColor = lipgloss.Color(lightPrimary) + theme.MarkdownListEnumerationColor = lipgloss.Color(lightCyan) + theme.MarkdownImageColor = lipgloss.Color(lightPrimary) + theme.MarkdownImageTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(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, - } + theme.SyntaxCommentColor = lipgloss.Color(lightComment) + theme.SyntaxKeywordColor = lipgloss.Color(lightSecondary) + theme.SyntaxFunctionColor = lipgloss.Color(lightPrimary) + theme.SyntaxVariableColor = lipgloss.Color(lightRed) + theme.SyntaxStringColor = lipgloss.Color(lightGreen) + theme.SyntaxNumberColor = lipgloss.Color(lightAccent) + theme.SyntaxTypeColor = lipgloss.Color(lightYellow) + theme.SyntaxOperatorColor = lipgloss.Color(lightCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(lightForeground) return theme } func init() { - // Register the OpenCode theme with the theme manager - RegisterTheme("opencode", NewOpenCodeTheme()) -} - + // Register the OpenCode themes with the theme manager + RegisterTheme("opencode-dark", NewOpenCodeDarkTheme()) + RegisterTheme("opencode-light", NewOpenCodeLightTheme()) +} \ No newline at end of file diff --git a/internal/tui/theme/theme.go b/internal/tui/theme/theme.go index 4ee14a07f8f2247fd7129bae8fd373d4531adf98..c2221b5483f3de37c02df01ee71ed8b0e4ac01f8 100644 --- a/internal/tui/theme/theme.go +++ b/internal/tui/theme/theme.go @@ -1,208 +1,205 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "image/color" ) -// Theme defines the interface for all UI themes in the application. -// All colors must be defined as lipgloss.AdaptiveColor to support -// both light and dark terminal backgrounds. type Theme interface { // Base colors - Primary() lipgloss.AdaptiveColor - Secondary() lipgloss.AdaptiveColor - Accent() lipgloss.AdaptiveColor + Primary() color.Color + Secondary() color.Color + Accent() color.Color // Status colors - Error() lipgloss.AdaptiveColor - Warning() lipgloss.AdaptiveColor - Success() lipgloss.AdaptiveColor - Info() lipgloss.AdaptiveColor + Error() color.Color + Warning() color.Color + Success() color.Color + Info() color.Color // Text colors - Text() lipgloss.AdaptiveColor - TextMuted() lipgloss.AdaptiveColor - TextEmphasized() lipgloss.AdaptiveColor + Text() color.Color + TextMuted() color.Color + TextEmphasized() color.Color // Background colors - Background() lipgloss.AdaptiveColor - BackgroundSecondary() lipgloss.AdaptiveColor - BackgroundDarker() lipgloss.AdaptiveColor + Background() color.Color + BackgroundSecondary() color.Color + BackgroundDarker() color.Color // Border colors - BorderNormal() lipgloss.AdaptiveColor - BorderFocused() lipgloss.AdaptiveColor - BorderDim() lipgloss.AdaptiveColor + BorderNormal() color.Color + BorderFocused() color.Color + BorderDim() color.Color // Diff view colors - DiffAdded() lipgloss.AdaptiveColor - DiffRemoved() lipgloss.AdaptiveColor - DiffContext() lipgloss.AdaptiveColor - DiffHunkHeader() lipgloss.AdaptiveColor - DiffHighlightAdded() lipgloss.AdaptiveColor - DiffHighlightRemoved() lipgloss.AdaptiveColor - DiffAddedBg() lipgloss.AdaptiveColor - DiffRemovedBg() lipgloss.AdaptiveColor - DiffContextBg() lipgloss.AdaptiveColor - DiffLineNumber() lipgloss.AdaptiveColor - DiffAddedLineNumberBg() lipgloss.AdaptiveColor - DiffRemovedLineNumberBg() lipgloss.AdaptiveColor + DiffAdded() color.Color + DiffRemoved() color.Color + DiffContext() color.Color + DiffHunkHeader() color.Color + DiffHighlightAdded() color.Color + DiffHighlightRemoved() color.Color + DiffAddedBg() color.Color + DiffRemovedBg() color.Color + DiffContextBg() color.Color + DiffLineNumber() color.Color + DiffAddedLineNumberBg() color.Color + DiffRemovedLineNumberBg() color.Color // Markdown colors - MarkdownText() lipgloss.AdaptiveColor - MarkdownHeading() lipgloss.AdaptiveColor - MarkdownLink() lipgloss.AdaptiveColor - MarkdownLinkText() lipgloss.AdaptiveColor - MarkdownCode() lipgloss.AdaptiveColor - MarkdownBlockQuote() lipgloss.AdaptiveColor - MarkdownEmph() lipgloss.AdaptiveColor - MarkdownStrong() lipgloss.AdaptiveColor - MarkdownHorizontalRule() lipgloss.AdaptiveColor - MarkdownListItem() lipgloss.AdaptiveColor - MarkdownListEnumeration() lipgloss.AdaptiveColor - MarkdownImage() lipgloss.AdaptiveColor - MarkdownImageText() lipgloss.AdaptiveColor - MarkdownCodeBlock() lipgloss.AdaptiveColor + MarkdownText() color.Color + MarkdownHeading() color.Color + MarkdownLink() color.Color + MarkdownLinkText() color.Color + MarkdownCode() color.Color + MarkdownBlockQuote() color.Color + MarkdownEmph() color.Color + MarkdownStrong() color.Color + MarkdownHorizontalRule() color.Color + MarkdownListItem() color.Color + MarkdownListEnumeration() color.Color + MarkdownImage() color.Color + MarkdownImageText() color.Color + MarkdownCodeBlock() color.Color // Syntax highlighting colors - SyntaxComment() lipgloss.AdaptiveColor - SyntaxKeyword() lipgloss.AdaptiveColor - SyntaxFunction() lipgloss.AdaptiveColor - SyntaxVariable() lipgloss.AdaptiveColor - SyntaxString() lipgloss.AdaptiveColor - SyntaxNumber() lipgloss.AdaptiveColor - SyntaxType() lipgloss.AdaptiveColor - SyntaxOperator() lipgloss.AdaptiveColor - SyntaxPunctuation() lipgloss.AdaptiveColor + SyntaxComment() color.Color + SyntaxKeyword() color.Color + SyntaxFunction() color.Color + SyntaxVariable() color.Color + SyntaxString() color.Color + SyntaxNumber() color.Color + SyntaxType() color.Color + SyntaxOperator() color.Color + SyntaxPunctuation() color.Color } // BaseTheme provides a default implementation of the Theme interface // that can be embedded in concrete theme implementations. type BaseTheme struct { // Base colors - PrimaryColor lipgloss.AdaptiveColor - SecondaryColor lipgloss.AdaptiveColor - AccentColor lipgloss.AdaptiveColor + PrimaryColor color.Color + SecondaryColor color.Color + AccentColor color.Color // Status colors - ErrorColor lipgloss.AdaptiveColor - WarningColor lipgloss.AdaptiveColor - SuccessColor lipgloss.AdaptiveColor - InfoColor lipgloss.AdaptiveColor + ErrorColor color.Color + WarningColor color.Color + SuccessColor color.Color + InfoColor color.Color // Text colors - TextColor lipgloss.AdaptiveColor - TextMutedColor lipgloss.AdaptiveColor - TextEmphasizedColor lipgloss.AdaptiveColor + TextColor color.Color + TextMutedColor color.Color + TextEmphasizedColor color.Color // Background colors - BackgroundColor lipgloss.AdaptiveColor - BackgroundSecondaryColor lipgloss.AdaptiveColor - BackgroundDarkerColor lipgloss.AdaptiveColor + BackgroundColor color.Color + BackgroundSecondaryColor color.Color + BackgroundDarkerColor color.Color // Border colors - BorderNormalColor lipgloss.AdaptiveColor - BorderFocusedColor lipgloss.AdaptiveColor - BorderDimColor lipgloss.AdaptiveColor + BorderNormalColor color.Color + BorderFocusedColor color.Color + BorderDimColor color.Color // Diff view colors - DiffAddedColor lipgloss.AdaptiveColor - DiffRemovedColor lipgloss.AdaptiveColor - DiffContextColor lipgloss.AdaptiveColor - DiffHunkHeaderColor lipgloss.AdaptiveColor - DiffHighlightAddedColor lipgloss.AdaptiveColor - DiffHighlightRemovedColor lipgloss.AdaptiveColor - DiffAddedBgColor lipgloss.AdaptiveColor - DiffRemovedBgColor lipgloss.AdaptiveColor - DiffContextBgColor lipgloss.AdaptiveColor - DiffLineNumberColor lipgloss.AdaptiveColor - DiffAddedLineNumberBgColor lipgloss.AdaptiveColor - DiffRemovedLineNumberBgColor lipgloss.AdaptiveColor + DiffAddedColor color.Color + DiffRemovedColor color.Color + DiffContextColor color.Color + DiffHunkHeaderColor color.Color + DiffHighlightAddedColor color.Color + DiffHighlightRemovedColor color.Color + DiffAddedBgColor color.Color + DiffRemovedBgColor color.Color + DiffContextBgColor color.Color + DiffLineNumberColor color.Color + DiffAddedLineNumberBgColor color.Color + DiffRemovedLineNumberBgColor color.Color // Markdown colors - MarkdownTextColor lipgloss.AdaptiveColor - MarkdownHeadingColor lipgloss.AdaptiveColor - MarkdownLinkColor lipgloss.AdaptiveColor - MarkdownLinkTextColor lipgloss.AdaptiveColor - MarkdownCodeColor lipgloss.AdaptiveColor - MarkdownBlockQuoteColor lipgloss.AdaptiveColor - MarkdownEmphColor lipgloss.AdaptiveColor - MarkdownStrongColor lipgloss.AdaptiveColor - MarkdownHorizontalRuleColor lipgloss.AdaptiveColor - MarkdownListItemColor lipgloss.AdaptiveColor - MarkdownListEnumerationColor lipgloss.AdaptiveColor - MarkdownImageColor lipgloss.AdaptiveColor - MarkdownImageTextColor lipgloss.AdaptiveColor - MarkdownCodeBlockColor lipgloss.AdaptiveColor + MarkdownTextColor color.Color + MarkdownHeadingColor color.Color + MarkdownLinkColor color.Color + MarkdownLinkTextColor color.Color + MarkdownCodeColor color.Color + MarkdownBlockQuoteColor color.Color + MarkdownEmphColor color.Color + MarkdownStrongColor color.Color + MarkdownHorizontalRuleColor color.Color + MarkdownListItemColor color.Color + MarkdownListEnumerationColor color.Color + MarkdownImageColor color.Color + MarkdownImageTextColor color.Color + MarkdownCodeBlockColor color.Color // Syntax highlighting colors - SyntaxCommentColor lipgloss.AdaptiveColor - SyntaxKeywordColor lipgloss.AdaptiveColor - SyntaxFunctionColor lipgloss.AdaptiveColor - SyntaxVariableColor lipgloss.AdaptiveColor - SyntaxStringColor lipgloss.AdaptiveColor - SyntaxNumberColor lipgloss.AdaptiveColor - SyntaxTypeColor lipgloss.AdaptiveColor - SyntaxOperatorColor lipgloss.AdaptiveColor - SyntaxPunctuationColor lipgloss.AdaptiveColor + SyntaxCommentColor color.Color + SyntaxKeywordColor color.Color + SyntaxFunctionColor color.Color + SyntaxVariableColor color.Color + SyntaxStringColor color.Color + SyntaxNumberColor color.Color + SyntaxTypeColor color.Color + SyntaxOperatorColor color.Color + SyntaxPunctuationColor color.Color } // Implement the Theme interface for BaseTheme -func (t *BaseTheme) Primary() lipgloss.AdaptiveColor { return t.PrimaryColor } -func (t *BaseTheme) Secondary() lipgloss.AdaptiveColor { return t.SecondaryColor } -func (t *BaseTheme) Accent() lipgloss.AdaptiveColor { return t.AccentColor } - -func (t *BaseTheme) Error() lipgloss.AdaptiveColor { return t.ErrorColor } -func (t *BaseTheme) Warning() lipgloss.AdaptiveColor { return t.WarningColor } -func (t *BaseTheme) Success() lipgloss.AdaptiveColor { return t.SuccessColor } -func (t *BaseTheme) Info() lipgloss.AdaptiveColor { return t.InfoColor } - -func (t *BaseTheme) Text() lipgloss.AdaptiveColor { return t.TextColor } -func (t *BaseTheme) TextMuted() lipgloss.AdaptiveColor { return t.TextMutedColor } -func (t *BaseTheme) TextEmphasized() lipgloss.AdaptiveColor { return t.TextEmphasizedColor } - -func (t *BaseTheme) Background() lipgloss.AdaptiveColor { return t.BackgroundColor } -func (t *BaseTheme) BackgroundSecondary() lipgloss.AdaptiveColor { return t.BackgroundSecondaryColor } -func (t *BaseTheme) BackgroundDarker() lipgloss.AdaptiveColor { return t.BackgroundDarkerColor } - -func (t *BaseTheme) BorderNormal() lipgloss.AdaptiveColor { return t.BorderNormalColor } -func (t *BaseTheme) BorderFocused() lipgloss.AdaptiveColor { return t.BorderFocusedColor } -func (t *BaseTheme) BorderDim() lipgloss.AdaptiveColor { return t.BorderDimColor } - -func (t *BaseTheme) DiffAdded() lipgloss.AdaptiveColor { return t.DiffAddedColor } -func (t *BaseTheme) DiffRemoved() lipgloss.AdaptiveColor { return t.DiffRemovedColor } -func (t *BaseTheme) DiffContext() lipgloss.AdaptiveColor { return t.DiffContextColor } -func (t *BaseTheme) DiffHunkHeader() lipgloss.AdaptiveColor { return t.DiffHunkHeaderColor } -func (t *BaseTheme) DiffHighlightAdded() lipgloss.AdaptiveColor { return t.DiffHighlightAddedColor } -func (t *BaseTheme) DiffHighlightRemoved() lipgloss.AdaptiveColor { return t.DiffHighlightRemovedColor } -func (t *BaseTheme) DiffAddedBg() lipgloss.AdaptiveColor { return t.DiffAddedBgColor } -func (t *BaseTheme) DiffRemovedBg() lipgloss.AdaptiveColor { return t.DiffRemovedBgColor } -func (t *BaseTheme) DiffContextBg() lipgloss.AdaptiveColor { return t.DiffContextBgColor } -func (t *BaseTheme) DiffLineNumber() lipgloss.AdaptiveColor { return t.DiffLineNumberColor } -func (t *BaseTheme) DiffAddedLineNumberBg() lipgloss.AdaptiveColor { return t.DiffAddedLineNumberBgColor } -func (t *BaseTheme) DiffRemovedLineNumberBg() lipgloss.AdaptiveColor { return t.DiffRemovedLineNumberBgColor } - -func (t *BaseTheme) MarkdownText() lipgloss.AdaptiveColor { return t.MarkdownTextColor } -func (t *BaseTheme) MarkdownHeading() lipgloss.AdaptiveColor { return t.MarkdownHeadingColor } -func (t *BaseTheme) MarkdownLink() lipgloss.AdaptiveColor { return t.MarkdownLinkColor } -func (t *BaseTheme) MarkdownLinkText() lipgloss.AdaptiveColor { return t.MarkdownLinkTextColor } -func (t *BaseTheme) MarkdownCode() lipgloss.AdaptiveColor { return t.MarkdownCodeColor } -func (t *BaseTheme) MarkdownBlockQuote() lipgloss.AdaptiveColor { return t.MarkdownBlockQuoteColor } -func (t *BaseTheme) MarkdownEmph() lipgloss.AdaptiveColor { return t.MarkdownEmphColor } -func (t *BaseTheme) MarkdownStrong() lipgloss.AdaptiveColor { return t.MarkdownStrongColor } -func (t *BaseTheme) MarkdownHorizontalRule() lipgloss.AdaptiveColor { return t.MarkdownHorizontalRuleColor } -func (t *BaseTheme) MarkdownListItem() lipgloss.AdaptiveColor { return t.MarkdownListItemColor } -func (t *BaseTheme) MarkdownListEnumeration() lipgloss.AdaptiveColor { return t.MarkdownListEnumerationColor } -func (t *BaseTheme) MarkdownImage() lipgloss.AdaptiveColor { return t.MarkdownImageColor } -func (t *BaseTheme) MarkdownImageText() lipgloss.AdaptiveColor { return t.MarkdownImageTextColor } -func (t *BaseTheme) MarkdownCodeBlock() lipgloss.AdaptiveColor { return t.MarkdownCodeBlockColor } - -func (t *BaseTheme) SyntaxComment() lipgloss.AdaptiveColor { return t.SyntaxCommentColor } -func (t *BaseTheme) SyntaxKeyword() lipgloss.AdaptiveColor { return t.SyntaxKeywordColor } -func (t *BaseTheme) SyntaxFunction() lipgloss.AdaptiveColor { return t.SyntaxFunctionColor } -func (t *BaseTheme) SyntaxVariable() lipgloss.AdaptiveColor { return t.SyntaxVariableColor } -func (t *BaseTheme) SyntaxString() lipgloss.AdaptiveColor { return t.SyntaxStringColor } -func (t *BaseTheme) SyntaxNumber() lipgloss.AdaptiveColor { return t.SyntaxNumberColor } -func (t *BaseTheme) SyntaxType() lipgloss.AdaptiveColor { return t.SyntaxTypeColor } -func (t *BaseTheme) SyntaxOperator() lipgloss.AdaptiveColor { return t.SyntaxOperatorColor } -func (t *BaseTheme) SyntaxPunctuation() lipgloss.AdaptiveColor { return t.SyntaxPunctuationColor } \ No newline at end of file +func (t *BaseTheme) Primary() color.Color { return t.PrimaryColor } +func (t *BaseTheme) Secondary() color.Color { return t.SecondaryColor } +func (t *BaseTheme) Accent() color.Color { return t.AccentColor } + +func (t *BaseTheme) Error() color.Color { return t.ErrorColor } +func (t *BaseTheme) Warning() color.Color { return t.WarningColor } +func (t *BaseTheme) Success() color.Color { return t.SuccessColor } +func (t *BaseTheme) Info() color.Color { return t.InfoColor } + +func (t *BaseTheme) Text() color.Color { return t.TextColor } +func (t *BaseTheme) TextMuted() color.Color { return t.TextMutedColor } +func (t *BaseTheme) TextEmphasized() color.Color { return t.TextEmphasizedColor } + +func (t *BaseTheme) Background() color.Color { return t.BackgroundColor } +func (t *BaseTheme) BackgroundSecondary() color.Color { return t.BackgroundSecondaryColor } +func (t *BaseTheme) BackgroundDarker() color.Color { return t.BackgroundDarkerColor } + +func (t *BaseTheme) BorderNormal() color.Color { return t.BorderNormalColor } +func (t *BaseTheme) BorderFocused() color.Color { return t.BorderFocusedColor } +func (t *BaseTheme) BorderDim() color.Color { return t.BorderDimColor } + +func (t *BaseTheme) DiffAdded() color.Color { return t.DiffAddedColor } +func (t *BaseTheme) DiffRemoved() color.Color { return t.DiffRemovedColor } +func (t *BaseTheme) DiffContext() color.Color { return t.DiffContextColor } +func (t *BaseTheme) DiffHunkHeader() color.Color { return t.DiffHunkHeaderColor } +func (t *BaseTheme) DiffHighlightAdded() color.Color { return t.DiffHighlightAddedColor } +func (t *BaseTheme) DiffHighlightRemoved() color.Color { return t.DiffHighlightRemovedColor } +func (t *BaseTheme) DiffAddedBg() color.Color { return t.DiffAddedBgColor } +func (t *BaseTheme) DiffRemovedBg() color.Color { return t.DiffRemovedBgColor } +func (t *BaseTheme) DiffContextBg() color.Color { return t.DiffContextBgColor } +func (t *BaseTheme) DiffLineNumber() color.Color { return t.DiffLineNumberColor } +func (t *BaseTheme) DiffAddedLineNumberBg() color.Color { return t.DiffAddedLineNumberBgColor } +func (t *BaseTheme) DiffRemovedLineNumberBg() color.Color { return t.DiffRemovedLineNumberBgColor } + +func (t *BaseTheme) MarkdownText() color.Color { return t.MarkdownTextColor } +func (t *BaseTheme) MarkdownHeading() color.Color { return t.MarkdownHeadingColor } +func (t *BaseTheme) MarkdownLink() color.Color { return t.MarkdownLinkColor } +func (t *BaseTheme) MarkdownLinkText() color.Color { return t.MarkdownLinkTextColor } +func (t *BaseTheme) MarkdownCode() color.Color { return t.MarkdownCodeColor } +func (t *BaseTheme) MarkdownBlockQuote() color.Color { return t.MarkdownBlockQuoteColor } +func (t *BaseTheme) MarkdownEmph() color.Color { return t.MarkdownEmphColor } +func (t *BaseTheme) MarkdownStrong() color.Color { return t.MarkdownStrongColor } +func (t *BaseTheme) MarkdownHorizontalRule() color.Color { return t.MarkdownHorizontalRuleColor } +func (t *BaseTheme) MarkdownListItem() color.Color { return t.MarkdownListItemColor } +func (t *BaseTheme) MarkdownListEnumeration() color.Color { return t.MarkdownListEnumerationColor } +func (t *BaseTheme) MarkdownImage() color.Color { return t.MarkdownImageColor } +func (t *BaseTheme) MarkdownImageText() color.Color { return t.MarkdownImageTextColor } +func (t *BaseTheme) MarkdownCodeBlock() color.Color { return t.MarkdownCodeBlockColor } + +func (t *BaseTheme) SyntaxComment() color.Color { return t.SyntaxCommentColor } +func (t *BaseTheme) SyntaxKeyword() color.Color { return t.SyntaxKeywordColor } +func (t *BaseTheme) SyntaxFunction() color.Color { return t.SyntaxFunctionColor } +func (t *BaseTheme) SyntaxVariable() color.Color { return t.SyntaxVariableColor } +func (t *BaseTheme) SyntaxString() color.Color { return t.SyntaxStringColor } +func (t *BaseTheme) SyntaxNumber() color.Color { return t.SyntaxNumberColor } +func (t *BaseTheme) SyntaxType() color.Color { return t.SyntaxTypeColor } +func (t *BaseTheme) SyntaxOperator() color.Color { return t.SyntaxOperatorColor } +func (t *BaseTheme) SyntaxPunctuation() color.Color { return t.SyntaxPunctuationColor } diff --git a/internal/tui/theme/tokyonight.go b/internal/tui/theme/tokyonight.go index acd9dbf6c0311c9226d1c81e919df30364272b62..61d82140cda3e3cc9d09f4b6d05b8459dca2cbc5 100644 --- a/internal/tui/theme/tokyonight.go +++ b/internal/tui/theme/tokyonight.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // TokyoNightTheme implements the Theme interface with Tokyo Night colors. @@ -28,6 +28,80 @@ func NewTokyoNightTheme() *TokyoNightTheme { darkPurple := "#c099ff" darkBorder := "#3b4261" + theme := &TokyoNightTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(darkBlue) + theme.SecondaryColor = lipgloss.Color(darkPurple) + theme.AccentColor = lipgloss.Color(darkOrange) + + // Status colors + theme.ErrorColor = lipgloss.Color(darkRed) + theme.WarningColor = lipgloss.Color(darkOrange) + theme.SuccessColor = lipgloss.Color(darkGreen) + theme.InfoColor = lipgloss.Color(darkBlue) + + // Text colors + theme.TextColor = lipgloss.Color(darkForeground) + theme.TextMutedColor = lipgloss.Color(darkComment) + theme.TextEmphasizedColor = lipgloss.Color(darkYellow) + + // Background colors + theme.BackgroundColor = lipgloss.Color(darkBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(darkCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#191B29") // Darker background from palette + + // Border colors + theme.BorderNormalColor = lipgloss.Color(darkBorder) + theme.BorderFocusedColor = lipgloss.Color(darkBlue) + theme.BorderDimColor = lipgloss.Color(darkSelection) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color("#4fd6be") // teal from palette + theme.DiffRemovedColor = lipgloss.Color("#c53b53") // red1 from palette + theme.DiffContextColor = lipgloss.Color("#828bb8") // fg_dark from palette + theme.DiffHunkHeaderColor = lipgloss.Color("#828bb8") // fg_dark from palette + theme.DiffHighlightAddedColor = lipgloss.Color("#b8db87") // git.add from palette + theme.DiffHighlightRemovedColor = lipgloss.Color("#e26a75") // git.delete from palette + theme.DiffAddedBgColor = lipgloss.Color("#20303b") + theme.DiffRemovedBgColor = lipgloss.Color("#37222c") + theme.DiffContextBgColor = lipgloss.Color(darkBackground) + theme.DiffLineNumberColor = lipgloss.Color("#545c7e") // dark3 from palette + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#1b2b34") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#2d1f26") + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(darkForeground) + theme.MarkdownHeadingColor = lipgloss.Color(darkPurple) + theme.MarkdownLinkColor = lipgloss.Color(darkBlue) + theme.MarkdownLinkTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeColor = lipgloss.Color(darkGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(darkYellow) + theme.MarkdownEmphColor = lipgloss.Color(darkYellow) + theme.MarkdownStrongColor = lipgloss.Color(darkOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(darkComment) + theme.MarkdownListItemColor = lipgloss.Color(darkBlue) + theme.MarkdownListEnumerationColor = lipgloss.Color(darkCyan) + theme.MarkdownImageColor = lipgloss.Color(darkBlue) + theme.MarkdownImageTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(darkForeground) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(darkComment) + theme.SyntaxKeywordColor = lipgloss.Color(darkPurple) + theme.SyntaxFunctionColor = lipgloss.Color(darkBlue) + theme.SyntaxVariableColor = lipgloss.Color(darkRed) + theme.SyntaxStringColor = lipgloss.Color(darkGreen) + theme.SyntaxNumberColor = lipgloss.Color(darkOrange) + theme.SyntaxTypeColor = lipgloss.Color(darkYellow) + theme.SyntaxOperatorColor = lipgloss.Color(darkCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(darkForeground) + + return theme +} + +// NewTokyoNightDayTheme creates a new instance of the Tokyo Night Day theme. +func NewTokyoNightDayTheme() *TokyoNightTheme { // Light mode colors (Tokyo Night Day) lightBackground := "#e1e2e7" lightCurrentLine := "#d5d6db" @@ -46,229 +120,77 @@ func NewTokyoNightTheme() *TokyoNightTheme { theme := &TokyoNightTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } + theme.PrimaryColor = lipgloss.Color(lightBlue) + theme.SecondaryColor = lipgloss.Color(lightPurple) + theme.AccentColor = lipgloss.Color(lightOrange) // 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: darkBlue, - Light: lightBlue, - } + theme.ErrorColor = lipgloss.Color(lightRed) + theme.WarningColor = lipgloss.Color(lightOrange) + theme.SuccessColor = lipgloss.Color(lightGreen) + theme.InfoColor = lipgloss.Color(lightBlue) // 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, - } + theme.TextColor = lipgloss.Color(lightForeground) + theme.TextMutedColor = lipgloss.Color(lightComment) + theme.TextEmphasizedColor = lipgloss.Color(lightYellow) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkCurrentLine, - Light: lightCurrentLine, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: "#191B29", // Darker background from palette - Light: "#f0f0f5", // Slightly lighter than background - } + theme.BackgroundColor = lipgloss.Color(lightBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(lightCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#f0f0f5") // Slightly lighter than background // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: darkBorder, - Light: lightBorder, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: darkSelection, - Light: lightSelection, - } + theme.BorderNormalColor = lipgloss.Color(lightBorder) + theme.BorderFocusedColor = lipgloss.Color(lightBlue) + theme.BorderDimColor = lipgloss.Color(lightSelection) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: "#4fd6be", // teal from palette - Light: "#1e725c", - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#c53b53", // red1 from palette - Light: "#c53b53", - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: "#828bb8", // fg_dark from palette - Light: "#7086b5", - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: "#828bb8", // fg_dark from palette - Light: "#7086b5", - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: "#b8db87", // git.add from palette - Light: "#4db380", - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#e26a75", // git.delete from palette - Light: "#f52a65", - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#20303b", - Light: "#d5e5d5", - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#37222c", - Light: "#f7d8db", - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: "#545c7e", // dark3 from palette - Light: "#848cb5", - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#1b2b34", - Light: "#c5d5c5", - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#2d1f26", - Light: "#e7c8cb", - } + theme.DiffAddedColor = lipgloss.Color("#1e725c") + theme.DiffRemovedColor = lipgloss.Color("#c53b53") + theme.DiffContextColor = lipgloss.Color("#7086b5") + theme.DiffHunkHeaderColor = lipgloss.Color("#7086b5") + theme.DiffHighlightAddedColor = lipgloss.Color("#4db380") + theme.DiffHighlightRemovedColor = lipgloss.Color("#f52a65") + theme.DiffAddedBgColor = lipgloss.Color("#d5e5d5") + theme.DiffRemovedBgColor = lipgloss.Color("#f7d8db") + theme.DiffContextBgColor = lipgloss.Color(lightBackground) + theme.DiffLineNumberColor = lipgloss.Color("#848cb5") + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#c5d5c5") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#e7c8cb") // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - 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: darkOrange, - Light: lightOrange, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.MarkdownTextColor = lipgloss.Color(lightForeground) + theme.MarkdownHeadingColor = lipgloss.Color(lightPurple) + theme.MarkdownLinkColor = lipgloss.Color(lightBlue) + theme.MarkdownLinkTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeColor = lipgloss.Color(lightGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(lightYellow) + theme.MarkdownEmphColor = lipgloss.Color(lightYellow) + theme.MarkdownStrongColor = lipgloss.Color(lightOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(lightComment) + theme.MarkdownListItemColor = lipgloss.Color(lightBlue) + theme.MarkdownListEnumerationColor = lipgloss.Color(lightCyan) + theme.MarkdownImageColor = lipgloss.Color(lightBlue) + theme.MarkdownImageTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(lightForeground) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: darkRed, - Light: lightRed, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: darkYellow, - Light: lightYellow, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.SyntaxCommentColor = lipgloss.Color(lightComment) + theme.SyntaxKeywordColor = lipgloss.Color(lightPurple) + theme.SyntaxFunctionColor = lipgloss.Color(lightBlue) + theme.SyntaxVariableColor = lipgloss.Color(lightRed) + theme.SyntaxStringColor = lipgloss.Color(lightGreen) + theme.SyntaxNumberColor = lipgloss.Color(lightOrange) + theme.SyntaxTypeColor = lipgloss.Color(lightYellow) + theme.SyntaxOperatorColor = lipgloss.Color(lightCyan) + theme.SyntaxPunctuationColor = lipgloss.Color(lightForeground) return theme } func init() { - // Register the Tokyo Night theme with the theme manager + // Register the Tokyo Night themes with the theme manager RegisterTheme("tokyonight", NewTokyoNightTheme()) + RegisterTheme("tokyonight-day", NewTokyoNightDayTheme()) } \ No newline at end of file diff --git a/internal/tui/theme/tron.go b/internal/tui/theme/tron.go index 5f1bdfb0d5aa1594c82bfb0e22f506a9b53e171a..9b55dd1e2cf46404dcacd0e7e84f4d0e78dd16ce 100644 --- a/internal/tui/theme/tron.go +++ b/internal/tui/theme/tron.go @@ -1,7 +1,7 @@ package theme import ( - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/lipgloss/v2" ) // TronTheme implements the Theme interface with Tron-inspired colors. @@ -29,6 +29,80 @@ func NewTronTheme() *TronTheme { darkGreen := "#00ff8f" darkBorder := "#1a2633" + theme := &TronTheme{} + + // Base colors + theme.PrimaryColor = lipgloss.Color(darkCyan) + theme.SecondaryColor = lipgloss.Color(darkBlue) + theme.AccentColor = lipgloss.Color(darkOrange) + + // Status colors + theme.ErrorColor = lipgloss.Color(darkRed) + theme.WarningColor = lipgloss.Color(darkOrange) + theme.SuccessColor = lipgloss.Color(darkGreen) + theme.InfoColor = lipgloss.Color(darkCyan) + + // Text colors + theme.TextColor = lipgloss.Color(darkForeground) + theme.TextMutedColor = lipgloss.Color(darkComment) + theme.TextEmphasizedColor = lipgloss.Color(darkYellow) + + // Background colors + theme.BackgroundColor = lipgloss.Color(darkBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(darkCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#070d14") // Slightly darker than background + + // Border colors + theme.BorderNormalColor = lipgloss.Color(darkBorder) + theme.BorderFocusedColor = lipgloss.Color(darkCyan) + theme.BorderDimColor = lipgloss.Color(darkSelection) + + // Diff view colors + theme.DiffAddedColor = lipgloss.Color(darkGreen) + theme.DiffRemovedColor = lipgloss.Color(darkRed) + theme.DiffContextColor = lipgloss.Color(darkComment) + theme.DiffHunkHeaderColor = lipgloss.Color(darkBlue) + theme.DiffHighlightAddedColor = lipgloss.Color("#00ff8f") + theme.DiffHighlightRemovedColor = lipgloss.Color("#ff3333") + theme.DiffAddedBgColor = lipgloss.Color("#0a2a1a") + theme.DiffRemovedBgColor = lipgloss.Color("#2a0a0a") + theme.DiffContextBgColor = lipgloss.Color(darkBackground) + theme.DiffLineNumberColor = lipgloss.Color(darkComment) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#082015") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#200808") + + // Markdown colors + theme.MarkdownTextColor = lipgloss.Color(darkForeground) + theme.MarkdownHeadingColor = lipgloss.Color(darkCyan) + theme.MarkdownLinkColor = lipgloss.Color(darkBlue) + theme.MarkdownLinkTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeColor = lipgloss.Color(darkGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(darkYellow) + theme.MarkdownEmphColor = lipgloss.Color(darkYellow) + theme.MarkdownStrongColor = lipgloss.Color(darkOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(darkComment) + theme.MarkdownListItemColor = lipgloss.Color(darkBlue) + theme.MarkdownListEnumerationColor = lipgloss.Color(darkCyan) + theme.MarkdownImageColor = lipgloss.Color(darkBlue) + theme.MarkdownImageTextColor = lipgloss.Color(darkCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(darkForeground) + + // Syntax highlighting colors + theme.SyntaxCommentColor = lipgloss.Color(darkComment) + theme.SyntaxKeywordColor = lipgloss.Color(darkCyan) + theme.SyntaxFunctionColor = lipgloss.Color(darkGreen) + theme.SyntaxVariableColor = lipgloss.Color(darkOrange) + theme.SyntaxStringColor = lipgloss.Color(darkYellow) + theme.SyntaxNumberColor = lipgloss.Color(darkBlue) + theme.SyntaxTypeColor = lipgloss.Color(darkPurple) + theme.SyntaxOperatorColor = lipgloss.Color(darkPink) + theme.SyntaxPunctuationColor = lipgloss.Color(darkForeground) + + return theme +} + +// NewTronLightTheme creates a new instance of the Tron Light theme. +func NewTronLightTheme() *TronTheme { // Light mode approximation lightBackground := "#f0f8ff" lightCurrentLine := "#e0f0ff" @@ -48,229 +122,77 @@ func NewTronTheme() *TronTheme { theme := &TronTheme{} // Base colors - theme.PrimaryColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.AccentColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } + theme.PrimaryColor = lipgloss.Color(lightCyan) + theme.SecondaryColor = lipgloss.Color(lightBlue) + theme.AccentColor = lipgloss.Color(lightOrange) // 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, - } + theme.ErrorColor = lipgloss.Color(lightRed) + theme.WarningColor = lipgloss.Color(lightOrange) + theme.SuccessColor = lipgloss.Color(lightGreen) + theme.InfoColor = lipgloss.Color(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, - } + theme.TextColor = lipgloss.Color(lightForeground) + theme.TextMutedColor = lipgloss.Color(lightComment) + theme.TextEmphasizedColor = lipgloss.Color(lightYellow) // Background colors - theme.BackgroundColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.BackgroundSecondaryColor = lipgloss.AdaptiveColor{ - Dark: darkCurrentLine, - Light: lightCurrentLine, - } - theme.BackgroundDarkerColor = lipgloss.AdaptiveColor{ - Dark: "#070d14", // Slightly darker than background - Light: "#ffffff", // Slightly lighter than background - } + theme.BackgroundColor = lipgloss.Color(lightBackground) + theme.BackgroundSecondaryColor = lipgloss.Color(lightCurrentLine) + theme.BackgroundDarkerColor = lipgloss.Color("#ffffff") // Slightly lighter than background // Border colors - theme.BorderNormalColor = lipgloss.AdaptiveColor{ - Dark: darkBorder, - Light: lightBorder, - } - theme.BorderFocusedColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.BorderDimColor = lipgloss.AdaptiveColor{ - Dark: darkSelection, - Light: lightSelection, - } + theme.BorderNormalColor = lipgloss.Color(lightBorder) + theme.BorderFocusedColor = lipgloss.Color(lightCyan) + theme.BorderDimColor = lipgloss.Color(lightSelection) // Diff view colors - theme.DiffAddedColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.DiffRemovedColor = lipgloss.AdaptiveColor{ - Dark: darkRed, - Light: lightRed, - } - theme.DiffContextColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.DiffHunkHeaderColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.DiffHighlightAddedColor = lipgloss.AdaptiveColor{ - Dark: "#00ff8f", - Light: "#a5d6a7", - } - theme.DiffHighlightRemovedColor = lipgloss.AdaptiveColor{ - Dark: "#ff3333", - Light: "#ef9a9a", - } - theme.DiffAddedBgColor = lipgloss.AdaptiveColor{ - Dark: "#0a2a1a", - Light: "#e8f5e9", - } - theme.DiffRemovedBgColor = lipgloss.AdaptiveColor{ - Dark: "#2a0a0a", - Light: "#ffebee", - } - theme.DiffContextBgColor = lipgloss.AdaptiveColor{ - Dark: darkBackground, - Light: lightBackground, - } - theme.DiffLineNumberColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.DiffAddedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#082015", - Light: "#c8e6c9", - } - theme.DiffRemovedLineNumberBgColor = lipgloss.AdaptiveColor{ - Dark: "#200808", - Light: "#ffcdd2", - } + theme.DiffAddedColor = lipgloss.Color(lightGreen) + theme.DiffRemovedColor = lipgloss.Color(lightRed) + theme.DiffContextColor = lipgloss.Color(lightComment) + theme.DiffHunkHeaderColor = lipgloss.Color(lightBlue) + theme.DiffHighlightAddedColor = lipgloss.Color("#a5d6a7") + theme.DiffHighlightRemovedColor = lipgloss.Color("#ef9a9a") + theme.DiffAddedBgColor = lipgloss.Color("#e8f5e9") + theme.DiffRemovedBgColor = lipgloss.Color("#ffebee") + theme.DiffContextBgColor = lipgloss.Color(lightBackground) + theme.DiffLineNumberColor = lipgloss.Color(lightComment) + theme.DiffAddedLineNumberBgColor = lipgloss.Color("#c8e6c9") + theme.DiffRemovedLineNumberBgColor = lipgloss.Color("#ffcdd2") // Markdown colors - theme.MarkdownTextColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } - theme.MarkdownHeadingColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownLinkColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - 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: darkOrange, - Light: lightOrange, - } - theme.MarkdownHorizontalRuleColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.MarkdownListItemColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownListEnumerationColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownImageColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.MarkdownImageTextColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.MarkdownCodeBlockColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.MarkdownTextColor = lipgloss.Color(lightForeground) + theme.MarkdownHeadingColor = lipgloss.Color(lightCyan) + theme.MarkdownLinkColor = lipgloss.Color(lightBlue) + theme.MarkdownLinkTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeColor = lipgloss.Color(lightGreen) + theme.MarkdownBlockQuoteColor = lipgloss.Color(lightYellow) + theme.MarkdownEmphColor = lipgloss.Color(lightYellow) + theme.MarkdownStrongColor = lipgloss.Color(lightOrange) + theme.MarkdownHorizontalRuleColor = lipgloss.Color(lightComment) + theme.MarkdownListItemColor = lipgloss.Color(lightBlue) + theme.MarkdownListEnumerationColor = lipgloss.Color(lightCyan) + theme.MarkdownImageColor = lipgloss.Color(lightBlue) + theme.MarkdownImageTextColor = lipgloss.Color(lightCyan) + theme.MarkdownCodeBlockColor = lipgloss.Color(lightForeground) // Syntax highlighting colors - theme.SyntaxCommentColor = lipgloss.AdaptiveColor{ - Dark: darkComment, - Light: lightComment, - } - theme.SyntaxKeywordColor = lipgloss.AdaptiveColor{ - Dark: darkCyan, - Light: lightCyan, - } - theme.SyntaxFunctionColor = lipgloss.AdaptiveColor{ - Dark: darkGreen, - Light: lightGreen, - } - theme.SyntaxVariableColor = lipgloss.AdaptiveColor{ - Dark: darkOrange, - Light: lightOrange, - } - theme.SyntaxStringColor = lipgloss.AdaptiveColor{ - Dark: darkYellow, - Light: lightYellow, - } - theme.SyntaxNumberColor = lipgloss.AdaptiveColor{ - Dark: darkBlue, - Light: lightBlue, - } - theme.SyntaxTypeColor = lipgloss.AdaptiveColor{ - Dark: darkPurple, - Light: lightPurple, - } - theme.SyntaxOperatorColor = lipgloss.AdaptiveColor{ - Dark: darkPink, - Light: lightPink, - } - theme.SyntaxPunctuationColor = lipgloss.AdaptiveColor{ - Dark: darkForeground, - Light: lightForeground, - } + theme.SyntaxCommentColor = lipgloss.Color(lightComment) + theme.SyntaxKeywordColor = lipgloss.Color(lightCyan) + theme.SyntaxFunctionColor = lipgloss.Color(lightGreen) + theme.SyntaxVariableColor = lipgloss.Color(lightOrange) + theme.SyntaxStringColor = lipgloss.Color(lightYellow) + theme.SyntaxNumberColor = lipgloss.Color(lightBlue) + theme.SyntaxTypeColor = lipgloss.Color(lightPurple) + theme.SyntaxOperatorColor = lipgloss.Color(lightPink) + theme.SyntaxPunctuationColor = lipgloss.Color(lightForeground) return theme } func init() { - // Register the Tron theme with the theme manager + // Register the Tron themes with the theme manager RegisterTheme("tron", NewTronTheme()) + RegisterTheme("tron-light", NewTronLightTheme()) } \ No newline at end of file diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 060b8c79c8572a0508ebcd95a148ff0743bc7009..92c2177ade6b0e604505b222ef299f3f4b8ca94b 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -5,9 +5,9 @@ import ( "fmt" "strings" - "github.com/charmbracelet/bubbles/key" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" + "github.com/charmbracelet/bubbles/v2/key" + tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/lipgloss/v2" "github.com/opencode-ai/opencode/internal/app" "github.com/opencode-ai/opencode/internal/config" "github.com/opencode-ai/opencode/internal/llm/agent" @@ -99,7 +99,7 @@ type appModel struct { width, height int currentPage page.PageID previousPage page.PageID - pages map[page.PageID]tea.Model + pages map[page.PageID]util.Model loadedPages map[page.PageID]bool status core.StatusCmp app *app.App @@ -143,6 +143,8 @@ type appModel struct { func (a appModel) Init() tea.Cmd { var cmds []tea.Cmd cmd := a.pages[a.currentPage].Init() + t := theme.CurrentTheme() + cmds = append(cmds, tea.SetBackgroundColor(t.Background())) a.loadedPages[a.currentPage] = true cmds = append(cmds, cmd) cmd = a.status.Init() @@ -189,7 +191,8 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { s, _ := a.status.Update(msg) a.status = s.(core.StatusCmp) - a.pages[a.currentPage], cmd = a.pages[a.currentPage].Update(msg) + updated, cmd := a.pages[a.currentPage].Update(msg) + a.pages[a.currentPage] = updated.(util.Model) cmds = append(cmds, cmd) prm, permCmd := a.permissions.Update(msg) @@ -348,9 +351,11 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return a, nil case dialog.ThemeChangedMsg: - a.pages[a.currentPage], cmd = a.pages[a.currentPage].Update(msg) + updated, cmd := a.pages[a.currentPage].Update(msg) + a.pages[a.currentPage] = updated.(util.Model) a.showThemeDialog = false - return a, tea.Batch(cmd, util.ReportInfo("Theme changed to: "+msg.ThemeName)) + t := theme.CurrentTheme() + return a, tea.Batch(cmd, util.ReportInfo("Theme changed to: "+msg.ThemeName), tea.SetBackgroundColor(t.Background())) case dialog.CloseModelDialogMsg: a.showModelDialog = false @@ -427,7 +432,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // If submitted, replace all named arguments and run the command if msg.Submit { content := msg.Content - + // Replace each named argument with its value for name, value := range msg.Args { placeholder := "$" + name @@ -658,7 +663,8 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { s, _ := a.status.Update(msg) a.status = s.(core.StatusCmp) - a.pages[a.currentPage], cmd = a.pages[a.currentPage].Update(msg) + updated, cmd := a.pages[a.currentPage].Update(msg) + a.pages[a.currentPage] = updated.(util.Model) cmds = append(cmds, cmd) return a, tea.Batch(cmds...) } @@ -914,7 +920,7 @@ func New(app *app.App) tea.Model { themeDialog: dialog.NewThemeDialogCmp(), app: app, commands: []dialog.Command{}, - pages: map[page.PageID]tea.Model{ + pages: map[page.PageID]util.Model{ page.ChatPage: page.NewChatPage(app), page.LogsPage: page.NewLogsPage(), }, diff --git a/internal/tui/util/util.go b/internal/tui/util/util.go index 2707009b3747c058d3a1625803a4283ea529f4f5..ec658a0e65b649decf31fc4134183c2fa14925f7 100644 --- a/internal/tui/util/util.go +++ b/internal/tui/util/util.go @@ -3,9 +3,14 @@ package util import ( "time" - tea "github.com/charmbracelet/bubbletea" + tea "github.com/charmbracelet/bubbletea/v2" ) +type Model interface { + tea.Model + tea.ViewModel +} + func CmdHandler(msg tea.Msg) tea.Cmd { return func() tea.Msg { return msg