From dff1bac59a978ecce390ebf62a6d6df42d6da541 Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Sun, 1 Jun 2025 17:16:09 +0200 Subject: [PATCH] wip small fixes --- .../tui/components/chat/sidebar/sidebar.go | 8 +- internal/tui/components/core/helpers.go | 2 +- internal/tui/layout/split.go | 9 +- internal/tui/page/chat/chat.go | 2 +- internal/tui/styles/markdown.go | 2 - internal/tui/styles/theme.go | 221 +++++++++++++++++- 6 files changed, 230 insertions(+), 14 deletions(-) diff --git a/internal/tui/components/chat/sidebar/sidebar.go b/internal/tui/components/chat/sidebar/sidebar.go index c362a3723617398f3d54c9e33142de800c812afb..e8197835a2ef393409940a416380257831f32267 100644 --- a/internal/tui/components/chat/sidebar/sidebar.go +++ b/internal/tui/components/chat/sidebar/sidebar.go @@ -115,7 +115,7 @@ func (m *sidebarCmp) lspBlock() string { t := styles.CurrentTheme() section := t.S().Muted.Render( - core.Section("Configured LSPs", maxWidth), + core.Section("LSPs", maxWidth), ) lspList := []string{section, ""} @@ -126,7 +126,7 @@ func (m *sidebarCmp) lspBlock() string { lipgloss.Left, section, "", - t.S().Muted.Render("No LSPs configured."), + t.S().Base.Foreground(t.Border).Render("None"), ) } @@ -158,7 +158,7 @@ func (m *sidebarCmp) mcpBlock() string { t := styles.CurrentTheme() section := t.S().Muted.Render( - core.Section("Configured MCPs", maxWidth), + core.Section("MCPs", maxWidth), ) mcpList := []string{section, ""} @@ -169,7 +169,7 @@ func (m *sidebarCmp) mcpBlock() string { lipgloss.Left, section, "", - t.S().Muted.Render("No MCPs configured."), + t.S().Base.Foreground(t.Border).Render("None"), ) } diff --git a/internal/tui/components/core/helpers.go b/internal/tui/components/core/helpers.go index b5fbb7ed9f113c5d9c6274a030e00532dd2aea4b..efc3ac745691f11c0a5769ec7761c5f150f18217 100644 --- a/internal/tui/components/core/helpers.go +++ b/internal/tui/components/core/helpers.go @@ -15,7 +15,7 @@ func Section(title string, width int) string { length := len(title) + 1 remainingWidth := width - length if remainingWidth > 0 { - title = title + " " + t.S().Subtle.Render(strings.Repeat(char, remainingWidth)) + title = title + " " + t.S().Base.Foreground(t.Border).Render(strings.Repeat(char, remainingWidth)) } return title } diff --git a/internal/tui/layout/split.go b/internal/tui/layout/split.go index 2eded093a4ef43708fb08183ceac0dd28105c18c..6023648a8de14fe9f3a7a13d429d17dfd1f751e9 100644 --- a/internal/tui/layout/split.go +++ b/internal/tui/layout/split.go @@ -4,7 +4,7 @@ import ( "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/styles" "github.com/opencode-ai/opencode/internal/tui/util" ) @@ -126,12 +126,11 @@ func (s *splitPaneLayout) View() tea.View { cursor = s.leftPanel.View().Cursor() } - t := theme.CurrentTheme() + t := styles.CurrentTheme() - style := lipgloss.NewStyle(). + style := t.S().Base. Width(s.width). - Height(s.height). - Background(t.Background()) + Height(s.height) view := tea.NewView(style.Render(finalView)) view.SetCursor(cursor) diff --git a/internal/tui/page/chat/chat.go b/internal/tui/page/chat/chat.go index 7a0cffd814ebf968e82667b3295634f581e36845..d8c1f0eb81d2b86f2898a0ff43a50e5799ad66a9 100644 --- a/internal/tui/page/chat/chat.go +++ b/internal/tui/page/chat/chat.go @@ -166,7 +166,7 @@ func NewChatPage(app *app.App) util.Model { layout: layout.NewSplitPane( layout.WithRightPanel(sidebarContainer), layout.WithBottomPanel(editorContainer), - layout.WithFixedBottomHeight(3), + layout.WithFixedBottomHeight(5), layout.WithFixedRightWidth(31), ), } diff --git a/internal/tui/styles/markdown.go b/internal/tui/styles/markdown.go index 39ab57d14785222dbcf88116bd62060513c01ec4..df6b91bd8e876b4ae44700e7daeb28484d120bd6 100644 --- a/internal/tui/styles/markdown.go +++ b/internal/tui/styles/markdown.go @@ -9,8 +9,6 @@ import ( "github.com/opencode-ai/opencode/internal/tui/theme" ) -const defaultMargin = 1 - // Helper functions for style pointers func boolPtr(b bool) *bool { return &b } func stringPtr(s string) *string { return &s } diff --git a/internal/tui/styles/theme.go b/internal/tui/styles/theme.go index 03bf9004a410d04cec240148c7e7f2950afc8888..c14bab9c6bda3772749dcd2f13931d630fac2b46 100644 --- a/internal/tui/styles/theme.go +++ b/internal/tui/styles/theme.go @@ -6,9 +6,16 @@ import ( "github.com/charmbracelet/bubbles/v2/textarea" tea "github.com/charmbracelet/bubbletea/v2" + "github.com/charmbracelet/glamour/v2/ansi" "github.com/charmbracelet/lipgloss/v2" ) +const ( + defaultListIndent = 2 + defaultListLevelIndent = 4 + defaultMargin = 2 +) + type Theme struct { Name string IsDark bool @@ -56,6 +63,9 @@ type Styles struct { Error lipgloss.Style Warning lipgloss.Style Info lipgloss.Style + // Markdown & Chroma + + Markdown ansi.StyleConfig // Inputs TextArea textarea.Styles @@ -70,7 +80,6 @@ func (t *Theme) S() *Styles { func (t *Theme) buildStyles() *Styles { base := lipgloss.NewStyle(). - Background(t.BgBase). Foreground(t.FgBase) return &Styles{ Base: base, @@ -122,6 +131,216 @@ func (t *Theme) buildStyles() *Styles { Blink: true, }, }, + + // TODO: update using the colors and add colors if missing + Markdown: ansi.StyleConfig{ + Document: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + BlockPrefix: "\n", + BlockSuffix: "\n", + Color: stringPtr("252"), + }, + Margin: uintPtr(defaultMargin), + }, + BlockQuote: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{}, + Indent: uintPtr(1), + IndentToken: stringPtr("│ "), + }, + List: ansi.StyleList{ + LevelIndent: defaultListIndent, + }, + Heading: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + BlockSuffix: "\n", + Color: stringPtr("39"), + Bold: boolPtr(true), + }, + }, + H1: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: " ", + Suffix: " ", + Color: stringPtr("228"), + BackgroundColor: stringPtr("63"), + Bold: boolPtr(true), + }, + }, + H2: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: "## ", + }, + }, + H3: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: "### ", + }, + }, + H4: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: "#### ", + }, + }, + H5: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: "##### ", + }, + }, + H6: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: "###### ", + Color: stringPtr("35"), + Bold: boolPtr(false), + }, + }, + Strikethrough: ansi.StylePrimitive{ + CrossedOut: boolPtr(true), + }, + Emph: ansi.StylePrimitive{ + Italic: boolPtr(true), + }, + Strong: ansi.StylePrimitive{ + Bold: boolPtr(true), + }, + HorizontalRule: ansi.StylePrimitive{ + Color: stringPtr("240"), + Format: "\n--------\n", + }, + Item: ansi.StylePrimitive{ + BlockPrefix: "• ", + }, + Enumeration: ansi.StylePrimitive{ + BlockPrefix: ". ", + }, + Task: ansi.StyleTask{ + StylePrimitive: ansi.StylePrimitive{}, + Ticked: "[✓] ", + Unticked: "[ ] ", + }, + Link: ansi.StylePrimitive{ + Color: stringPtr("30"), + Underline: boolPtr(true), + }, + LinkText: ansi.StylePrimitive{ + Color: stringPtr("35"), + Bold: boolPtr(true), + }, + Image: ansi.StylePrimitive{ + Color: stringPtr("212"), + Underline: boolPtr(true), + }, + ImageText: ansi.StylePrimitive{ + Color: stringPtr("243"), + Format: "Image: {{.text}} →", + }, + Code: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Prefix: " ", + Suffix: " ", + Color: stringPtr("203"), + BackgroundColor: stringPtr("236"), + }, + }, + CodeBlock: ansi.StyleCodeBlock{ + StyleBlock: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{ + Color: stringPtr("244"), + }, + Margin: uintPtr(defaultMargin), + }, + Chroma: &ansi.Chroma{ + Text: ansi.StylePrimitive{ + Color: stringPtr("#C4C4C4"), + }, + Error: ansi.StylePrimitive{ + Color: stringPtr("#F1F1F1"), + BackgroundColor: stringPtr("#F05B5B"), + }, + Comment: ansi.StylePrimitive{ + Color: stringPtr("#676767"), + }, + CommentPreproc: ansi.StylePrimitive{ + Color: stringPtr("#FF875F"), + }, + Keyword: ansi.StylePrimitive{ + Color: stringPtr("#00AAFF"), + }, + KeywordReserved: ansi.StylePrimitive{ + Color: stringPtr("#FF5FD2"), + }, + KeywordNamespace: ansi.StylePrimitive{ + Color: stringPtr("#FF5F87"), + }, + KeywordType: ansi.StylePrimitive{ + Color: stringPtr("#6E6ED8"), + }, + Operator: ansi.StylePrimitive{ + Color: stringPtr("#EF8080"), + }, + Punctuation: ansi.StylePrimitive{ + Color: stringPtr("#E8E8A8"), + }, + Name: ansi.StylePrimitive{ + Color: stringPtr("#C4C4C4"), + }, + NameBuiltin: ansi.StylePrimitive{ + Color: stringPtr("#FF8EC7"), + }, + NameTag: ansi.StylePrimitive{ + Color: stringPtr("#B083EA"), + }, + NameAttribute: ansi.StylePrimitive{ + Color: stringPtr("#7A7AE6"), + }, + NameClass: ansi.StylePrimitive{ + Color: stringPtr("#F1F1F1"), + Underline: boolPtr(true), + Bold: boolPtr(true), + }, + NameDecorator: ansi.StylePrimitive{ + Color: stringPtr("#FFFF87"), + }, + NameFunction: ansi.StylePrimitive{ + Color: stringPtr("#00D787"), + }, + LiteralNumber: ansi.StylePrimitive{ + Color: stringPtr("#6EEFC0"), + }, + LiteralString: ansi.StylePrimitive{ + Color: stringPtr("#C69669"), + }, + LiteralStringEscape: ansi.StylePrimitive{ + Color: stringPtr("#AFFFD7"), + }, + GenericDeleted: ansi.StylePrimitive{ + Color: stringPtr("#FD5B5B"), + }, + GenericEmph: ansi.StylePrimitive{ + Italic: boolPtr(true), + }, + GenericInserted: ansi.StylePrimitive{ + Color: stringPtr("#00D787"), + }, + GenericStrong: ansi.StylePrimitive{ + Bold: boolPtr(true), + }, + GenericSubheading: ansi.StylePrimitive{ + Color: stringPtr("#777777"), + }, + Background: ansi.StylePrimitive{ + BackgroundColor: stringPtr("#373737"), + }, + }, + }, + Table: ansi.StyleTable{ + StyleBlock: ansi.StyleBlock{ + StylePrimitive: ansi.StylePrimitive{}, + }, + }, + DefinitionDescription: ansi.StylePrimitive{ + BlockPrefix: "\n ", + }, + }, } }