1package list
2
3import (
4 "io"
5
6 "charm.land/lipgloss/v2"
7 "github.com/charmbracelet/crush/internal/ui/common"
8 "github.com/charmbracelet/glamour/v2"
9 "github.com/charmbracelet/glamour/v2/ansi"
10)
11
12// Item represents a rendered item in the [List] component.
13type Item interface {
14 // Content is the rendered content of the item.
15 Content() string
16 // Height returns the height of the item based on its content.
17 Height() int
18}
19
20// Gap is [GapItem] to be used as a vertical gap in the list.
21var Gap = GapItem{}
22
23// GapItem represents a vertical gap in the list.
24type GapItem struct{}
25
26// Content returns the content of the gap item.
27func (g GapItem) Content() string {
28 return ""
29}
30
31// Height returns the height of the gap item.
32func (g GapItem) Height() int {
33 return 1
34}
35
36// StringItem represents a simple string item in the list.
37type StringItem struct {
38 content string
39}
40
41// NewStringItem creates a new [StringItem] with the given id and content.
42func NewStringItem(content string) StringItem {
43 return StringItem{
44 content: content,
45 }
46}
47
48// Content returns the content of the string item.
49func (s StringItem) Content() string {
50 return s.content
51}
52
53// Height returns the height of the string item based on its content.
54func (s StringItem) Height() int {
55 return lipgloss.Height(s.content)
56}
57
58// MarkdownItem represents a markdown item in the list.
59type MarkdownItem struct {
60 StringItem
61}
62
63// NewMarkdownItem creates a new [MarkdownItem] with the given id and content.
64func NewMarkdownItem(id, content string) MarkdownItem {
65 return MarkdownItem{
66 StringItem: StringItem{
67 content: content,
68 },
69 }
70}
71
72// Content returns the content of the markdown item.
73func (m MarkdownItem) Content() string {
74 return m.StringItem.Content()
75}
76
77// Height returns the height of the markdown item based on its content.
78func (m MarkdownItem) Height() int {
79 return m.StringItem.Height()
80}
81
82// MarkdownItemMaxWidth is the maximum width for rendering markdown items.
83const MarkdownItemMaxWidth = 120
84
85// MarkdownItemRenderer renders [MarkdownItem]s in a [List].
86type MarkdownItemRenderer struct {
87 Styles *ansi.StyleConfig
88}
89
90// Render implements [ItemRenderer].
91func (m *MarkdownItemRenderer) Render(w io.Writer, list *List, index int, item Item) {
92 width := min(list.Width(), MarkdownItemMaxWidth)
93 var r *glamour.TermRenderer
94 if m.Styles != nil {
95 r = common.MarkdownRenderer(*m.Styles, width)
96 } else {
97 r = common.PlainMarkdownRenderer(width)
98 }
99
100 rendered, _ := r.Render(item.Content())
101 _, _ = io.WriteString(w, rendered)
102}