Change summary
internal/ui/list/filterable.go | 12 ++++++++----
internal/ui/list/item.go | 19 +++++++++++++++++++
internal/ui/list/list.go | 21 +++++++++++++++++----
3 files changed, 44 insertions(+), 8 deletions(-)
Detailed changes
@@ -70,13 +70,17 @@ func (f *FilterableList) SetFilter(q string) {
f.query = q
}
-type filterableItems []FilterableItem
+// FilterableItemsSource is a type that implements [fuzzy.Source] for filtering
+// [FilterableItem]s.
+type FilterableItemsSource []FilterableItem
-func (f filterableItems) Len() int {
+// Len returns the length of the source.
+func (f FilterableItemsSource) Len() int {
return len(f)
}
-func (f filterableItems) String(i int) string {
+// String returns the string representation of the item at index i.
+func (f FilterableItemsSource) String(i int) string {
return f[i].Filter()
}
@@ -94,7 +98,7 @@ func (f *FilterableList) VisibleItems() []Item {
return items
}
- items := filterableItems(f.items)
+ items := FilterableItemsSource(f.items)
matches := fuzzy.FindFrom(f.query, items)
matchedItems := []Item{}
resultSize := len(matches)
@@ -1,6 +1,8 @@
package list
import (
+ "strings"
+
"github.com/charmbracelet/x/ansi"
)
@@ -30,3 +32,20 @@ type MouseClickable interface {
// It returns true if the event was handled, false otherwise.
HandleMouseClick(btn ansi.MouseButton, x, y int) bool
}
+
+// SpacerItem is a spacer item that adds vertical space in the list.
+type SpacerItem struct {
+ Height int
+}
+
+// NewSpacerItem creates a new [SpacerItem] with the specified height.
+func NewSpacerItem(height int) *SpacerItem {
+ return &SpacerItem{
+ Height: max(0, height-1),
+ }
+}
+
+// Render implements the Item interface for [SpacerItem].
+func (s *SpacerItem) Render(width int) string {
+ return strings.Repeat("\n", s.Height)
+}
@@ -390,6 +390,7 @@ func (l *List) SelectedItemInView() bool {
}
// SetSelected sets the selected item index in the list.
+// It returns -1 if the index is out of bounds.
func (l *List) SetSelected(index int) {
if index < 0 || index >= len(l.items) {
l.selectedIdx = -1
@@ -415,31 +416,43 @@ func (l *List) IsSelectedLast() bool {
}
// SelectPrev selects the previous item in the list.
-func (l *List) SelectPrev() {
+// It returns whether the selection changed.
+func (l *List) SelectPrev() bool {
if l.selectedIdx > 0 {
l.selectedIdx--
+ return true
}
+ return false
}
// SelectNext selects the next item in the list.
-func (l *List) SelectNext() {
+// It returns whether the selection changed.
+func (l *List) SelectNext() bool {
if l.selectedIdx < len(l.items)-1 {
l.selectedIdx++
+ return true
}
+ return false
}
// SelectFirst selects the first item in the list.
-func (l *List) SelectFirst() {
+// It returns whether the selection changed.
+func (l *List) SelectFirst() bool {
if len(l.items) > 0 {
l.selectedIdx = 0
+ return true
}
+ return false
}
// SelectLast selects the last item in the list.
-func (l *List) SelectLast() {
+// It returns whether the selection changed.
+func (l *List) SelectLast() bool {
if len(l.items) > 0 {
l.selectedIdx = len(l.items) - 1
+ return true
}
+ return false
}
// SelectedItem returns the currently selected item. It may be nil if no item