mirror of
https://github.com/Maks1mS/bubbles.git
synced 2024-12-23 22:32:59 +03:00
feat(list): ability to SetStatusBarItemName
(#169)
This commit is contained in:
parent
e57fd292cc
commit
57d79daf4d
35
list/list.go
35
list/list.go
@ -87,7 +87,7 @@ type Rank struct {
|
||||
// DefaultFilter uses the sahilm/fuzzy to filter through the list.
|
||||
// This is set by default.
|
||||
func DefaultFilter(term string, targets []string) []Rank {
|
||||
var ranks fuzzy.Matches = fuzzy.Find(term, targets)
|
||||
var ranks = fuzzy.Find(term, targets)
|
||||
sort.Stable(ranks)
|
||||
result := make([]Rank, len(ranks))
|
||||
for i, r := range ranks {
|
||||
@ -129,6 +129,9 @@ type Model struct {
|
||||
showHelp bool
|
||||
filteringEnabled bool
|
||||
|
||||
itemNameSingular string
|
||||
itemNamePlural string
|
||||
|
||||
Title string
|
||||
Styles Styles
|
||||
|
||||
@ -202,6 +205,8 @@ func New(items []Item, delegate ItemDelegate, width, height int) Model {
|
||||
showStatusBar: true,
|
||||
showPagination: true,
|
||||
showHelp: true,
|
||||
itemNameSingular: "item",
|
||||
itemNamePlural: "items",
|
||||
filteringEnabled: true,
|
||||
KeyMap: DefaultKeyMap(),
|
||||
Filter: DefaultFilter,
|
||||
@ -286,6 +291,18 @@ func (m Model) ShowStatusBar() bool {
|
||||
return m.showStatusBar
|
||||
}
|
||||
|
||||
// SetStatusBarItemName defines a replacement for the items identifier. Defaults
|
||||
// to item/items
|
||||
func (m *Model) SetStatusBarItemName(singular, plural string) {
|
||||
m.itemNameSingular = singular
|
||||
m.itemNamePlural = plural
|
||||
}
|
||||
|
||||
// StatusBarItemName returns singular and plural status bar item names
|
||||
func (m Model) StatusBarItemName() (string, string) {
|
||||
return m.itemNameSingular, m.itemNamePlural
|
||||
}
|
||||
|
||||
// ShowingPagination hides or shoes the paginator. Note that pagination will
|
||||
// still be active, it simply won't be displayed.
|
||||
func (m *Model) SetShowPagination(v bool) {
|
||||
@ -1048,21 +1065,25 @@ func (m Model) statusView() string {
|
||||
totalItems := len(m.items)
|
||||
visibleItems := len(m.VisibleItems())
|
||||
|
||||
plural := ""
|
||||
var itemName string
|
||||
if visibleItems != 1 {
|
||||
plural = "s"
|
||||
itemName = m.itemNamePlural
|
||||
} else {
|
||||
itemName = m.itemNameSingular
|
||||
}
|
||||
|
||||
itemsDisplay := fmt.Sprintf("%d %s", visibleItems, itemName)
|
||||
|
||||
if m.filterState == Filtering {
|
||||
// Filter results
|
||||
if visibleItems == 0 {
|
||||
status = m.Styles.StatusEmpty.Render("Nothing matched")
|
||||
} else {
|
||||
status = fmt.Sprintf("%d item%s", visibleItems, plural)
|
||||
status = itemsDisplay
|
||||
}
|
||||
} else if len(m.items) == 0 {
|
||||
// Not filtering: no items.
|
||||
status = m.Styles.StatusEmpty.Render("No items")
|
||||
status = m.Styles.StatusEmpty.Render("No " + m.itemNamePlural)
|
||||
} else {
|
||||
// Normal
|
||||
filtered := m.FilterState() == FilterApplied
|
||||
@ -1073,7 +1094,7 @@ func (m Model) statusView() string {
|
||||
status += fmt.Sprintf("“%s” ", f)
|
||||
}
|
||||
|
||||
status += fmt.Sprintf("%d item%s", visibleItems, plural)
|
||||
status += itemsDisplay
|
||||
}
|
||||
|
||||
numFiltered := totalItems - visibleItems
|
||||
@ -1117,7 +1138,7 @@ func (m Model) populatedView() string {
|
||||
if m.filterState == Filtering {
|
||||
return ""
|
||||
}
|
||||
return m.Styles.NoItems.Render("No items found.")
|
||||
return m.Styles.NoItems.Render("No " + m.itemNamePlural + " found.")
|
||||
}
|
||||
|
||||
if len(items) > 0 {
|
||||
|
74
list/list_test.go
Normal file
74
list/list_test.go
Normal file
@ -0,0 +1,74 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type item string
|
||||
|
||||
func (i item) FilterValue() string { return "" }
|
||||
|
||||
type itemDelegate struct{}
|
||||
|
||||
func (d itemDelegate) Height() int { return 1 }
|
||||
func (d itemDelegate) Spacing() int { return 0 }
|
||||
func (d itemDelegate) Update(msg tea.Msg, m *Model) tea.Cmd { return nil }
|
||||
func (d itemDelegate) Render(w io.Writer, m Model, index int, listItem Item) {
|
||||
i, ok := listItem.(item)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("%d. %s", index+1, i)
|
||||
fmt.Fprint(w, m.Styles.TitleBar.Render(str))
|
||||
}
|
||||
|
||||
func TestStatusBarItemName(t *testing.T) {
|
||||
list := New([]Item{item("foo"), item("bar")}, itemDelegate{}, 10, 10)
|
||||
expected := "2 items"
|
||||
if !strings.Contains(list.statusView(), expected) {
|
||||
t.Fatalf("Error: expected view to contain %s", expected)
|
||||
}
|
||||
|
||||
list.SetItems([]Item{item("foo")})
|
||||
expected = "1 item"
|
||||
if !strings.Contains(list.statusView(), expected) {
|
||||
t.Fatalf("Error: expected view to contain %s", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStatusBarWithoutItems(t *testing.T) {
|
||||
list := New([]Item{}, itemDelegate{}, 10, 10)
|
||||
|
||||
expected := "No items"
|
||||
if !strings.Contains(list.statusView(), expected) {
|
||||
t.Fatalf("Error: expected view to contain %s", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomStatusBarItemName(t *testing.T) {
|
||||
list := New([]Item{item("foo"), item("bar")}, itemDelegate{}, 10, 10)
|
||||
list.SetStatusBarItemName("connection", "connections")
|
||||
|
||||
expected := "2 connections"
|
||||
if !strings.Contains(list.statusView(), expected) {
|
||||
t.Fatalf("Error: expected view to contain %s", expected)
|
||||
}
|
||||
|
||||
list.SetItems([]Item{item("foo")})
|
||||
expected = "1 connection"
|
||||
if !strings.Contains(list.statusView(), expected) {
|
||||
t.Fatalf("Error: expected view to contain %s", expected)
|
||||
}
|
||||
|
||||
list.SetItems([]Item{})
|
||||
expected = "No connections"
|
||||
if !strings.Contains(list.statusView(), expected) {
|
||||
t.Fatalf("Error: expected view to contain %s", expected)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user