chore: add dedicates diff styles

Kujtim Hoxha created

Change summary

internal/tui/components/chat/messages/renderer.go | 35 ++++--
internal/tui/components/core/helpers.go           |  3 
internal/tui/styles/crush.go                      |  7 
internal/tui/styles/theme.go                      | 83 ++++++++++------
4 files changed, 78 insertions(+), 50 deletions(-)

Detailed changes

internal/tui/components/chat/messages/renderer.go 🔗

@@ -600,45 +600,56 @@ func renderPlainContent(v *toolCallCmp, content string) string {
 		}
 		out = append(out, t.S().Muted.
 			Width(width).
-			Background(t.BgSubtle).
+			Background(t.BgBaseLighter).
 			Render(ln))
 	}
 
 	if len(lines) > responseContextHeight {
 		out = append(out, t.S().Muted.
-			Background(t.BgSubtle).
+			Background(t.BgBaseLighter).
 			Width(width).
 			Render(fmt.Sprintf("... (%d lines)", len(lines)-responseContextHeight)))
 	}
 	return strings.Join(out, "\n")
 }
 
+func pad(v any, width int) string {
+	s := fmt.Sprintf("%v", v)
+	w := ansi.StringWidth(s)
+	if w >= width {
+		return s
+	}
+	return strings.Repeat(" ", width-w) + s
+}
+
 func renderCodeContent(v *toolCallCmp, path, content string, offset int) string {
 	t := styles.CurrentTheme()
 	truncated := truncateHeight(content, responseContextHeight)
 
-	highlighted, _ := highlight.SyntaxHighlight(truncated, path, t.BgSubtle)
+	highlighted, _ := highlight.SyntaxHighlight(truncated, path, t.BgBase)
 	lines := strings.Split(highlighted, "\n")
 
 	if len(strings.Split(content, "\n")) > responseContextHeight {
 		lines = append(lines, t.S().Muted.
-			Background(t.BgSubtle).
-			Width(v.textWidth()-2).
-			Render(fmt.Sprintf("... (%d lines)", len(strings.Split(content, "\n"))-responseContextHeight)))
+			Background(t.BgBase).
+			Render(fmt.Sprintf(" ... (%d lines)", len(strings.Split(content, "\n"))-responseContextHeight)))
 	}
 
+	maxLineNumber := len(lines) + offset
+	padding := lipgloss.Width(fmt.Sprintf("%d", maxLineNumber))
 	for i, ln := range lines {
-		num := t.S().Muted.
-			Background(t.BgSubtle).
-			PaddingLeft(4).
-			PaddingRight(2).
-			Render(fmt.Sprintf("%d", i+1+offset))
+		num := t.S().Base.
+			Foreground(t.FgMuted).
+			Background(t.BgBase).
+			PaddingRight(1).
+			PaddingLeft(1).
+			Render(pad(i+1+offset, padding))
 		w := v.textWidth() - 2 - lipgloss.Width(num) // -2 for left padding
 		lines[i] = lipgloss.JoinHorizontal(lipgloss.Left,
 			num,
 			t.S().Base.
+				PaddingLeft(1).
 				Width(w).
-				Background(t.BgSubtle).
 				Render(v.fit(ln, w)))
 	}
 	return lipgloss.JoinVertical(lipgloss.Left, lines...)

internal/tui/components/core/helpers.go 🔗

@@ -148,8 +148,9 @@ func SelectableButtons(buttons []ButtonOpts, spacing string) string {
 }
 
 func DiffFormatter() *diffview.DiffView {
+	t := styles.CurrentTheme()
 	formatDiff := diffview.New()
 	style := chroma.MustNewStyle("crush", styles.GetChromaTheme())
-	diff := formatDiff.ChromaStyle(style)
+	diff := formatDiff.ChromaStyle(style).Style(t.S().Diff)
 	return diff
 }

internal/tui/styles/crush.go 🔗

@@ -14,9 +14,10 @@ func NewCrushTheme() *Theme {
 		Tertiary:  charmtone.Bok,
 		Accent:    charmtone.Zest,
 		// Backgrounds
-		BgBase:    charmtone.Pepper,
-		BgSubtle:  charmtone.Charcoal,
-		BgOverlay: charmtone.Iron,
+		BgBase:        charmtone.Pepper,
+		BgBaseLighter: Lighten(charmtone.Pepper, 2),
+		BgSubtle:      charmtone.Charcoal,
+		BgOverlay:     charmtone.Iron,
 
 		// Foregrounds
 		FgBase:      charmtone.Ash,

internal/tui/styles/theme.go 🔗

@@ -10,6 +10,7 @@ import (
 	"github.com/charmbracelet/bubbles/v2/textarea"
 	"github.com/charmbracelet/bubbles/v2/textinput"
 	tea "github.com/charmbracelet/bubbletea/v2"
+	"github.com/charmbracelet/crush/internal/exp/diffview"
 	"github.com/charmbracelet/glamour/v2/ansi"
 	"github.com/charmbracelet/lipgloss/v2"
 	"github.com/lucasb-eyer/go-colorful"
@@ -31,9 +32,10 @@ type Theme struct {
 	Tertiary  color.Color
 	Accent    color.Color
 
-	BgBase    color.Color
-	BgSubtle  color.Color
-	BgOverlay color.Color
+	BgBase        color.Color
+	BgBaseLighter color.Color
+	BgSubtle      color.Color
+	BgOverlay     color.Color
 
 	FgBase      color.Color
 	FgMuted     color.Color
@@ -70,21 +72,6 @@ type Theme struct {
 	styles *Styles
 }
 
-type Diff struct {
-	Added               color.Color
-	Removed             color.Color
-	Context             color.Color
-	HunkHeader          color.Color
-	HighlightAdded      color.Color
-	HighlightRemoved    color.Color
-	AddedBg             color.Color
-	RemovedBg           color.Color
-	ContextBg           color.Color
-	LineNumber          color.Color
-	AddedLineNumberBg   color.Color
-	RemovedLineNumberBg color.Color
-}
-
 type Styles struct {
 	Base         lipgloss.Style
 	SelectedBase lipgloss.Style
@@ -112,7 +99,7 @@ type Styles struct {
 	Help help.Styles
 
 	// Diff
-	Diff Diff
+	Diff diffview.Style
 
 	// FilePicker
 	FilePicker filepicker.Styles
@@ -421,22 +408,50 @@ func (t *Theme) buildStyles() *Styles {
 			FullSeparator:  base.Foreground(t.Border),
 		},
 
-		// TODO: Fix this this is bad
-		Diff: Diff{
-			Added:               t.Green,
-			Removed:             t.Red,
-			Context:             t.FgSubtle,
-			HunkHeader:          t.FgSubtle,
-			HighlightAdded:      t.GreenLight,
-			HighlightRemoved:    t.RedLight,
-			AddedBg:             t.GreenDark,
-			RemovedBg:           t.RedDark,
-			ContextBg:           t.BgSubtle,
-			LineNumber:          t.FgMuted,
-			AddedLineNumberBg:   t.GreenDark,
-			RemovedLineNumberBg: t.RedDark,
+		Diff: diffview.Style{
+			DividerLine: diffview.LineStyle{
+				LineNumber: lipgloss.NewStyle().
+					Foreground(t.FgHalfMuted).
+					Background(t.BgBaseLighter),
+				Code: lipgloss.NewStyle().
+					Foreground(t.FgHalfMuted).
+					Background(t.BgBaseLighter),
+			},
+			MissingLine: diffview.LineStyle{
+				LineNumber: lipgloss.NewStyle().
+					Background(t.BgBaseLighter),
+				Code: lipgloss.NewStyle().
+					Background(t.BgBaseLighter),
+			},
+			EqualLine: diffview.LineStyle{
+				LineNumber: lipgloss.NewStyle().
+					Foreground(t.FgMuted).
+					Background(t.BgBase),
+				Code: lipgloss.NewStyle().
+					Foreground(t.FgMuted).
+					Background(t.BgBase),
+			},
+			InsertLine: diffview.LineStyle{
+				LineNumber: lipgloss.NewStyle().
+					Foreground(lipgloss.Color("#629657")).
+					Background(lipgloss.Color("#2b322a")),
+				Symbol: lipgloss.NewStyle().
+					Foreground(lipgloss.Color("#629657")).
+					Background(lipgloss.Color("#323931")),
+				Code: lipgloss.NewStyle().
+					Background(lipgloss.Color("#323931")),
+			},
+			DeleteLine: diffview.LineStyle{
+				LineNumber: lipgloss.NewStyle().
+					Foreground(lipgloss.Color("#a45c59")).
+					Background(lipgloss.Color("#312929")),
+				Symbol: lipgloss.NewStyle().
+					Foreground(lipgloss.Color("#a45c59")).
+					Background(lipgloss.Color("#383030")),
+				Code: lipgloss.NewStyle().
+					Background(lipgloss.Color("#383030")),
+			},
 		},
-
 		FilePicker: filepicker.Styles{
 			DisabledCursor:   base.Foreground(t.FgMuted),
 			Cursor:           base.Foreground(t.FgBase),