Skip to content

Commit 347b091

Browse files
committed
refactor: deduplicate compact/normal rendering in delegate
1 parent 27d6a79 commit 347b091

File tree

1 file changed

+59
-60
lines changed

1 file changed

+59
-60
lines changed

pkg/ui/resourcelist/delegate.go

Lines changed: 59 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strings"
77

88
"charm.land/bubbles/v2/list"
9+
"charm.land/lipgloss/v2"
910
"github.com/charmbracelet/x/ansi"
1011

1112
tea "charm.land/bubbletea/v2"
@@ -121,6 +122,35 @@ func (d *ItemDelegate) UpdateColumnWidths(docs []*yamls.Document) {
121122
}
122123
}
123124

125+
// itemChrome computes the gutter marker and separator string for a list row.
126+
// Highlighted items get a visible bar; others get a blank space.
127+
func (d *ItemDelegate) itemChrome(highlighted bool, unselectedSep string) (string, string) {
128+
if highlighted {
129+
return d.theme.SelectedStyle.Render("│"), d.theme.SelectedStyle.Render("")
130+
}
131+
132+
return " ", unselectedSep
133+
}
134+
135+
// styleItemText applies filter-aware styling to a single text segment.
136+
// When shouldShowFilter is true, matched characters are underlined.
137+
// When hasEmptyFilter is true, all text is rendered with the dim style.
138+
func styleItemText(
139+
text, filterValue string,
140+
shouldShowFilter, hasEmptyFilter bool,
141+
baseStyle lipgloss.Style,
142+
) string {
143+
if shouldShowFilter {
144+
return styleFilteredText(text, filterValue, baseStyle, baseStyle.Underline(true))
145+
}
146+
147+
if hasEmptyFilter {
148+
return baseStyle.Render(text)
149+
}
150+
151+
return styleFilteredText(text, filterValue, baseStyle, baseStyle.Underline(true))
152+
}
153+
124154
func (d *ItemDelegate) renderCompact(
125155
w io.Writer,
126156
doc *yamls.Document,
@@ -129,8 +159,6 @@ func (d *ItemDelegate) renderCompact(
129159
width int,
130160
) {
131161
var (
132-
gutter, styledGroup, styledKind, styledName, separator string
133-
134162
group = doc.Object.GetGroup()
135163
kind = doc.Object.GetKind()
136164
name = doc.Title
@@ -141,43 +169,24 @@ func (d *ItemDelegate) renderCompact(
141169
groupWidth = int(max(0, float64(width)*float64(float64(d.maxGroupWidth)/maxWidth)))
142170
kindWidth = int(max(0, float64(width)*float64(float64(d.maxKindWidth)/maxWidth)))
143171
nameWidth = max(0, width-groupWidth-kindWidth-horizontalPadding)
144-
145-
selectedStyle = d.theme.SelectedStyle
146-
subtleStyle = d.theme.SubtleStyle
147172
)
148173

149174
group = ansi.Truncate(group, groupWidth, d.theme.Ellipsis)
150175
kind = ansi.Truncate(kind, kindWidth, d.theme.Ellipsis)
151176
name = ansi.Truncate(name, nameWidth, d.theme.Ellipsis)
152177

178+
gutter, separator := d.itemChrome(shouldHighlight, "")
179+
180+
// Compact mode uses a single style for all columns.
181+
primaryStyle := d.theme.SubtleStyle
153182
if shouldHighlight {
154-
gutter = selectedStyle.Render("│")
155-
separator = selectedStyle.Render("")
156-
157-
if shouldShowFilter {
158-
styledGroup = styleFilteredText(group, filterValue, selectedStyle, selectedStyle.Underline(true))
159-
styledKind = styleFilteredText(kind, filterValue, selectedStyle, selectedStyle.Underline(true))
160-
styledName = styleFilteredText(name, filterValue, selectedStyle, selectedStyle.Underline(true))
161-
} else {
162-
styledGroup = selectedStyle.Render(group)
163-
styledKind = selectedStyle.Render(kind)
164-
styledName = selectedStyle.Render(name)
165-
}
166-
} else {
167-
gutter = " "
168-
separator = ""
169-
170-
if hasEmptyFilter {
171-
styledGroup = subtleStyle.Render(group)
172-
styledKind = subtleStyle.Render(kind)
173-
styledName = subtleStyle.Render(name)
174-
} else {
175-
styledGroup = styleFilteredText(group, filterValue, subtleStyle, subtleStyle.Underline(true))
176-
styledKind = styleFilteredText(kind, filterValue, subtleStyle, subtleStyle.Underline(true))
177-
styledName = styleFilteredText(name, filterValue, subtleStyle, subtleStyle.Underline(true))
178-
}
183+
primaryStyle = d.theme.SelectedStyle
179184
}
180185

186+
styledGroup := styleItemText(group, filterValue, shouldShowFilter, hasEmptyFilter, primaryStyle)
187+
styledKind := styleItemText(kind, filterValue, shouldShowFilter, hasEmptyFilter, primaryStyle)
188+
styledName := styleItemText(name, filterValue, shouldShowFilter, hasEmptyFilter, primaryStyle)
189+
181190
styledGroup += strings.Repeat(" ", max(0, min(groupWidth, d.maxGroupWidth)-len(group)))
182191
styledKind += strings.Repeat(" ", max(0, min(kindWidth, d.maxKindWidth)-len(kind)))
183192
styledName += strings.Repeat(" ", max(0, min(nameWidth, d.maxNameWidth)-len(name)))
@@ -193,43 +202,33 @@ func (d *ItemDelegate) renderNormal(
193202
shouldHighlight, shouldShowFilter, hasEmptyFilter bool,
194203
width int,
195204
) {
196-
var gutter, styledTitle, styledDesc, separator string
197-
198205
truncateTo := max(0, width-listViewHorizontalPadding*2)
199206

200207
title := ansi.Truncate(doc.Title, truncateTo, d.theme.Ellipsis)
201208
desc := ansi.Truncate(doc.Desc, truncateTo, d.theme.Ellipsis)
202209

203-
if shouldHighlight {
204-
gutter = d.theme.SelectedStyle.Render("│")
205-
separator = d.theme.SelectedStyle.Render("")
206-
207-
if shouldShowFilter {
208-
selStyle := d.theme.SelectedStyle
209-
selSubStyle := d.theme.SelectedSubtleStyle
210-
211-
styledTitle = styleFilteredText(title, filterValue, selStyle, selStyle.Underline(true))
212-
styledDesc = styleFilteredText(desc, filterValue, selSubStyle, selSubStyle.Underline(true))
213-
} else {
214-
styledTitle = d.theme.SelectedStyle.Render(title)
215-
styledDesc = d.theme.SelectedSubtleStyle.Render(desc)
216-
}
217-
} else {
218-
gutter = " "
219-
separator = d.theme.GenericTextStyle.Render("")
220-
221-
if hasEmptyFilter {
222-
styledTitle = d.theme.SubtleStyle.Render(title)
223-
styledDesc = d.theme.SubtleStyle.Render(desc)
224-
} else {
225-
genStyle := d.theme.GenericTextStyle
226-
subStyle := d.theme.SubtleStyle
227-
228-
styledTitle = styleFilteredText(title, filterValue, genStyle, genStyle.Underline(true))
229-
styledDesc = styleFilteredText(desc, filterValue, subStyle, subStyle.Underline(true))
230-
}
210+
gutter, separator := d.itemChrome(shouldHighlight, d.theme.GenericTextStyle.Render(""))
211+
212+
var titleStyle, descStyle lipgloss.Style
213+
214+
switch {
215+
case shouldHighlight:
216+
titleStyle = d.theme.SelectedStyle
217+
descStyle = d.theme.SelectedSubtleStyle
218+
219+
case hasEmptyFilter:
220+
// Dim both rows when the filter prompt is open but empty.
221+
titleStyle = d.theme.SubtleStyle
222+
descStyle = d.theme.SubtleStyle
223+
224+
default:
225+
titleStyle = d.theme.GenericTextStyle
226+
descStyle = d.theme.SubtleStyle
231227
}
232228

229+
styledTitle := styleItemText(title, filterValue, shouldShowFilter, hasEmptyFilter, titleStyle)
230+
styledDesc := styleItemText(desc, filterValue, shouldShowFilter, hasEmptyFilter, descStyle)
231+
233232
//nolint:errcheck // Writer is an in-memory buffer.
234233
fmt.Fprintf(w, "%s %s%s%s\n%s %s", gutter, separator, separator, styledTitle, gutter, styledDesc)
235234
}

0 commit comments

Comments
 (0)