@@ -5,6 +5,7 @@ import (
5 "github.com/charmbracelet/bubbles/v2/help"
5 "github.com/charmbracelet/bubbles/v2/help"
6 "github.com/charmbracelet/bubbles/v2/textarea"
6 "github.com/charmbracelet/bubbles/v2/textarea"
7 "github.com/charmbracelet/bubbles/v2/textinput"
7 "github.com/charmbracelet/bubbles/v2/textinput"
8+ tea "github.com/charmbracelet/bubbletea/v2"
8 "github.com/charmbracelet/crush/internal/tui/exp/diffview"
9 "github.com/charmbracelet/crush/internal/tui/exp/diffview"
9 "github.com/charmbracelet/glamour/v2/ansi"
10 "github.com/charmbracelet/glamour/v2/ansi"
10 "github.com/charmbracelet/lipgloss/v2"
11 "github.com/charmbracelet/lipgloss/v2"
@@ -30,6 +31,11 @@ const (
30 BorderThick string = "▌"
31 BorderThick string = "▌"
36+ defaultListIndent = 2
33type Styles struct {
39type Styles struct {
34 WindowTooSmall lipgloss.Style
40 WindowTooSmall lipgloss.Style
@@ -96,20 +102,28 @@ type Styles struct {
96 // Borders
102 // Borders
97 BorderFocus lipgloss.Style
103 BorderFocus lipgloss.Style
98 BorderBlur lipgloss.Style
104 BorderBlur lipgloss.Style
107+ EditorPromptNormalFocused lipgloss.Style
108+ EditorPromptNormalBlurred lipgloss.Style
109+ EditorPromptYoloIconFocused lipgloss.Style
110+ EditorPromptYoloIconBlurred lipgloss.Style
111+ EditorPromptYoloDotsFocused lipgloss.Style
112+ EditorPromptYoloDotsBlurred lipgloss.Style
101func DefaultStyles() Styles {
115func DefaultStyles() Styles {
103− // primary = charmtone.Charple
117+ primary = charmtone.Charple
104 secondary = charmtone.Dolly
118 secondary = charmtone.Dolly
105− // tertiary = charmtone.Bok
119+ tertiary = charmtone.Bok
106 // accent = charmtone.Zest
120 // accent = charmtone.Zest
108 // Backgrounds
122 // Backgrounds
109 bgBase = charmtone.Pepper
123 bgBase = charmtone.Pepper
110 bgBaseLighter = charmtone.BBQ
124 bgBaseLighter = charmtone.BBQ
111 bgSubtle = charmtone.Charcoal
125 bgSubtle = charmtone.Charcoal
112− // bgOverlay = charmtone.Iron
126+ bgOverlay = charmtone.Iron
114 // Foregrounds
128 // Foregrounds
115 fgBase = charmtone.Ash
129 fgBase = charmtone.Ash
@@ -119,7 +133,7 @@ func DefaultStyles() Styles {
119 // fgSelected = charmtone.Salt
133 // fgSelected = charmtone.Salt
121 // Borders
135 // Borders
122− // border = charmtone.Charcoal
136+ border = charmtone.Charcoal
123 borderFocus = charmtone.Charple
137 borderFocus = charmtone.Charple
125 // Status
139 // Status
@@ -147,8 +161,334 @@ func DefaultStyles() Styles {
147 // cherry = charmtone.Cherry
161 // cherry = charmtone.Cherry
164+ base := lipgloss.NewStyle().Foreground(fgBase)
150 s := Styles{}
166 s := Styles{}
168+ s.TextInput = textinput.Styles{
169+ Focused: textinput.StyleState{
171+ Placeholder: base.Foreground(fgSubtle),
172+ Prompt: base.Foreground(tertiary),
173+ Suggestion: base.Foreground(fgSubtle),
175+ Blurred: textinput.StyleState{
176+ Text: base.Foreground(fgMuted),
177+ Placeholder: base.Foreground(fgSubtle),
178+ Prompt: base.Foreground(fgMuted),
179+ Suggestion: base.Foreground(fgSubtle),
181+ Cursor: textinput.CursorStyle{
183+ Shape: tea.CursorBar,
188+ s.TextArea = textarea.Styles{
189+ Focused: textarea.StyleState{
192+ LineNumber: base.Foreground(fgSubtle),
194+ CursorLineNumber: base.Foreground(fgSubtle),
195+ Placeholder: base.Foreground(fgSubtle),
196+ Prompt: base.Foreground(tertiary),
198+ Blurred: textarea.StyleState{
200+ Text: base.Foreground(fgMuted),
201+ LineNumber: base.Foreground(fgMuted),
203+ CursorLineNumber: base.Foreground(fgMuted),
204+ Placeholder: base.Foreground(fgSubtle),
205+ Prompt: base.Foreground(fgMuted),
207+ Cursor: textarea.CursorStyle{
209+ Shape: tea.CursorBar,
214+ s.Markdown = ansi.StyleConfig{
215+ Document: ansi.StyleBlock{
216+ StylePrimitive: ansi.StylePrimitive{
217+ // BlockPrefix: "\n",
218+ // BlockSuffix: "\n",
219+ Color: stringPtr(charmtone.Smoke.Hex()),
221+ // Margin: uintPtr(defaultMargin),
223+ BlockQuote: ansi.StyleBlock{
224+ StylePrimitive: ansi.StylePrimitive{},
226+ IndentToken: stringPtr("│ "),
228+ List: ansi.StyleList{
229+ LevelIndent: defaultListIndent,
231+ Heading: ansi.StyleBlock{
232+ StylePrimitive: ansi.StylePrimitive{
234+ Color: stringPtr(charmtone.Malibu.Hex()),
235+ Bold: boolPtr(true),
238+ H1: ansi.StyleBlock{
239+ StylePrimitive: ansi.StylePrimitive{
242+ Color: stringPtr(charmtone.Zest.Hex()),
243+ BackgroundColor: stringPtr(charmtone.Charple.Hex()),
244+ Bold: boolPtr(true),
247+ H2: ansi.StyleBlock{
248+ StylePrimitive: ansi.StylePrimitive{
252+ H3: ansi.StyleBlock{
253+ StylePrimitive: ansi.StylePrimitive{
257+ H4: ansi.StyleBlock{
258+ StylePrimitive: ansi.StylePrimitive{
262+ H5: ansi.StyleBlock{
263+ StylePrimitive: ansi.StylePrimitive{
267+ H6: ansi.StyleBlock{
268+ StylePrimitive: ansi.StylePrimitive{
270+ Color: stringPtr(charmtone.Guac.Hex()),
271+ Bold: boolPtr(false),
274+ Strikethrough: ansi.StylePrimitive{
275+ CrossedOut: boolPtr(true),
277+ Emph: ansi.StylePrimitive{
278+ Italic: boolPtr(true),
280+ Strong: ansi.StylePrimitive{
281+ Bold: boolPtr(true),
283+ HorizontalRule: ansi.StylePrimitive{
284+ Color: stringPtr(charmtone.Charcoal.Hex()),
285+ Format: "\n--------\n",
287+ Item: ansi.StylePrimitive{
290+ Enumeration: ansi.StylePrimitive{
293+ Task: ansi.StyleTask{
294+ StylePrimitive: ansi.StylePrimitive{},
298+ Link: ansi.StylePrimitive{
299+ Color: stringPtr(charmtone.Zinc.Hex()),
300+ Underline: boolPtr(true),
302+ LinkText: ansi.StylePrimitive{
303+ Color: stringPtr(charmtone.Guac.Hex()),
304+ Bold: boolPtr(true),
306+ Image: ansi.StylePrimitive{
307+ Color: stringPtr(charmtone.Cheeky.Hex()),
308+ Underline: boolPtr(true),
310+ ImageText: ansi.StylePrimitive{
311+ Color: stringPtr(charmtone.Squid.Hex()),
312+ Format: "Image: {{.text}} →",
314+ Code: ansi.StyleBlock{
315+ StylePrimitive: ansi.StylePrimitive{
318+ Color: stringPtr(charmtone.Coral.Hex()),
319+ BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
322+ CodeBlock: ansi.StyleCodeBlock{
323+ StyleBlock: ansi.StyleBlock{
324+ StylePrimitive: ansi.StylePrimitive{
325+ Color: stringPtr(charmtone.Charcoal.Hex()),
327+ Margin: uintPtr(defaultMargin),
329+ Chroma: &ansi.Chroma{
330+ Text: ansi.StylePrimitive{
331+ Color: stringPtr(charmtone.Smoke.Hex()),
333+ Error: ansi.StylePrimitive{
334+ Color: stringPtr(charmtone.Butter.Hex()),
335+ BackgroundColor: stringPtr(charmtone.Sriracha.Hex()),
337+ Comment: ansi.StylePrimitive{
338+ Color: stringPtr(charmtone.Oyster.Hex()),
340+ CommentPreproc: ansi.StylePrimitive{
341+ Color: stringPtr(charmtone.Bengal.Hex()),
343+ Keyword: ansi.StylePrimitive{
344+ Color: stringPtr(charmtone.Malibu.Hex()),
346+ KeywordReserved: ansi.StylePrimitive{
347+ Color: stringPtr(charmtone.Pony.Hex()),
349+ KeywordNamespace: ansi.StylePrimitive{
350+ Color: stringPtr(charmtone.Pony.Hex()),
352+ KeywordType: ansi.StylePrimitive{
353+ Color: stringPtr(charmtone.Guppy.Hex()),
355+ Operator: ansi.StylePrimitive{
356+ Color: stringPtr(charmtone.Salmon.Hex()),
358+ Punctuation: ansi.StylePrimitive{
359+ Color: stringPtr(charmtone.Zest.Hex()),
361+ Name: ansi.StylePrimitive{
362+ Color: stringPtr(charmtone.Smoke.Hex()),
364+ NameBuiltin: ansi.StylePrimitive{
365+ Color: stringPtr(charmtone.Cheeky.Hex()),
367+ NameTag: ansi.StylePrimitive{
368+ Color: stringPtr(charmtone.Mauve.Hex()),
370+ NameAttribute: ansi.StylePrimitive{
371+ Color: stringPtr(charmtone.Hazy.Hex()),
373+ NameClass: ansi.StylePrimitive{
374+ Color: stringPtr(charmtone.Salt.Hex()),
375+ Underline: boolPtr(true),
376+ Bold: boolPtr(true),
378+ NameDecorator: ansi.StylePrimitive{
379+ Color: stringPtr(charmtone.Citron.Hex()),
381+ NameFunction: ansi.StylePrimitive{
382+ Color: stringPtr(charmtone.Guac.Hex()),
384+ LiteralNumber: ansi.StylePrimitive{
385+ Color: stringPtr(charmtone.Julep.Hex()),
387+ LiteralString: ansi.StylePrimitive{
388+ Color: stringPtr(charmtone.Cumin.Hex()),
390+ LiteralStringEscape: ansi.StylePrimitive{
391+ Color: stringPtr(charmtone.Bok.Hex()),
393+ GenericDeleted: ansi.StylePrimitive{
394+ Color: stringPtr(charmtone.Coral.Hex()),
396+ GenericEmph: ansi.StylePrimitive{
397+ Italic: boolPtr(true),
399+ GenericInserted: ansi.StylePrimitive{
400+ Color: stringPtr(charmtone.Guac.Hex()),
402+ GenericStrong: ansi.StylePrimitive{
403+ Bold: boolPtr(true),
405+ GenericSubheading: ansi.StylePrimitive{
406+ Color: stringPtr(charmtone.Squid.Hex()),
408+ Background: ansi.StylePrimitive{
409+ BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
413+ Table: ansi.StyleTable{
414+ StyleBlock: ansi.StyleBlock{
415+ StylePrimitive: ansi.StylePrimitive{},
418+ DefinitionDescription: ansi.StylePrimitive{
423+ s.Help = help.Styles{
424+ ShortKey: base.Foreground(fgMuted),
425+ ShortDesc: base.Foreground(fgSubtle),
426+ ShortSeparator: base.Foreground(border),
427+ Ellipsis: base.Foreground(border),
428+ FullKey: base.Foreground(fgMuted),
429+ FullDesc: base.Foreground(fgSubtle),
430+ FullSeparator: base.Foreground(border),
433+ s.Diff = diffview.Style{
434+ DividerLine: diffview.LineStyle{
435+ LineNumber: lipgloss.NewStyle().
436+ Foreground(fgHalfMuted).
437+ Background(bgBaseLighter),
438+ Code: lipgloss.NewStyle().
439+ Foreground(fgHalfMuted).
440+ Background(bgBaseLighter),
442+ MissingLine: diffview.LineStyle{
443+ LineNumber: lipgloss.NewStyle().
444+ Background(bgBaseLighter),
445+ Code: lipgloss.NewStyle().
446+ Background(bgBaseLighter),
448+ EqualLine: diffview.LineStyle{
449+ LineNumber: lipgloss.NewStyle().
450+ Foreground(fgMuted).
452+ Code: lipgloss.NewStyle().
453+ Foreground(fgMuted).
456+ InsertLine: diffview.LineStyle{
457+ LineNumber: lipgloss.NewStyle().
458+ Foreground(lipgloss.Color("#629657")).
459+ Background(lipgloss.Color("#2b322a")),
460+ Symbol: lipgloss.NewStyle().
461+ Foreground(lipgloss.Color("#629657")).
462+ Background(lipgloss.Color("#323931")),
463+ Code: lipgloss.NewStyle().
464+ Background(lipgloss.Color("#323931")),
466+ DeleteLine: diffview.LineStyle{
467+ LineNumber: lipgloss.NewStyle().
468+ Foreground(lipgloss.Color("#a45c59")).
469+ Background(lipgloss.Color("#312929")),
470+ Symbol: lipgloss.NewStyle().
471+ Foreground(lipgloss.Color("#a45c59")).
472+ Background(lipgloss.Color("#383030")),
473+ Code: lipgloss.NewStyle().
474+ Background(lipgloss.Color("#383030")),
478+ s.FilePicker = filepicker.Styles{
479+ DisabledCursor: base.Foreground(fgMuted),
480+ Cursor: base.Foreground(fgBase),
481+ Symlink: base.Foreground(fgSubtle),
482+ Directory: base.Foreground(primary),
483+ File: base.Foreground(fgBase),
484+ DisabledFile: base.Foreground(fgMuted),
485+ DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
486+ Permission: base.Foreground(fgMuted),
487+ Selected: base.Background(primary).Foreground(fgBase),
488+ FileSize: base.Foreground(fgMuted),
489+ EmptyDirectory: base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
152 // borders
492 // borders
153 s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
493 s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
@@ -190,5 +530,18 @@ func DefaultStyles() Styles {
190 // Borders
530 // Borders
191 s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
531 s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
534+ s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
535+ s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
536+ s.EditorPromptYoloIconFocused = lipgloss.NewStyle().Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
537+ s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
538+ s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().Foreground(charmtone.Zest).SetString(":::")
539+ s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
544+// Helper functions for style pointers
545+func boolPtr(b bool) *bool { return &b }
546+func stringPtr(s string) *string { return &s }
547+func uintPtr(u uint) *uint { return &u }