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+
124154func (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