feat(list): add SetFilterText and SetFilterState (#335)

* Add SetFilterText and SetFilterState

* make linter happy

* make SetFilterState state not hardcoded

* tests for SetFilterText and SetFilterState

* fix small typo

---------

Co-authored-by: k-x7 <97758178+k-x7@users.noreply.github.com>
This commit is contained in:
Tai Groot
2024-09-10 14:22:03 -03:00
committed by GitHub
co-authored by k-x7
parent d3bd075ed2
commit d019ed3cc9
2 changed files with 97 additions and 5 deletions
+33 -4
View File
@@ -10,15 +10,16 @@ import (
"strings"
"time"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/ansi"
"github.com/sahilm/fuzzy"
"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/paginator"
"github.com/charmbracelet/bubbles/spinner"
"github.com/charmbracelet/bubbles/textinput"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/ansi"
"github.com/sahilm/fuzzy"
)
// Item is an item that appears in the list.
@@ -269,6 +270,34 @@ func (m *Model) SetShowTitle(v bool) {
m.updatePagination()
}
// SetFilterText explicitly sets the filter text without relying on user input.
// It also sets the filterState to a sane default of FilterApplied, but this
// can be changed with SetFilterState
func (m *Model) SetFilterText(filter string) {
m.filterState = Filtering
m.FilterInput.SetValue(filter)
cmd := filterItems(*m)
msg := cmd()
fmm, _ := msg.(FilterMatchesMsg)
m.filteredItems = filteredItems(fmm)
m.filterState = FilterApplied
m.Paginator.Page = 0
m.cursor = 0
m.FilterInput.CursorEnd()
m.updatePagination()
m.updateKeybindings()
}
// Helper method for setting the filtering state manually
func (m *Model) SetFilterState(state FilterState) {
m.Paginator.Page = 0
m.cursor = 0
m.filterState = state
m.FilterInput.CursorEnd()
m.FilterInput.Focus()
m.updateKeybindings()
}
// ShowTitle returns whether or not the title bar is set to be rendered.
func (m Model) ShowTitle() bool {
return m.showTitle
+64 -1
View File
@@ -3,6 +3,7 @@ package list
import (
"fmt"
"io"
"reflect"
"strings"
"testing"
@@ -11,7 +12,7 @@ import (
type item string
func (i item) FilterValue() string { return "" }
func (i item) FilterValue() string { return string(i) }
type itemDelegate struct{}
@@ -72,3 +73,65 @@ func TestCustomStatusBarItemName(t *testing.T) {
t.Fatalf("Error: expected view to contain %s", expected)
}
}
func TestSetFilterText(t *testing.T) {
tc := []Item{item("foo"), item("bar"), item("baz")}
list := New(tc, itemDelegate{}, 10, 10)
list.SetFilterText("ba")
list.SetFilterState(Unfiltered)
expected := tc
// TODO: replace with slices.Equal() when project move to go1.18 or later
if !reflect.DeepEqual(list.VisibleItems(), expected) {
t.Fatalf("Error: expected view to contain only %s", expected)
}
list.SetFilterState(Filtering)
expected = []Item{item("bar"), item("baz")}
if !reflect.DeepEqual(list.VisibleItems(), expected) {
t.Fatalf("Error: expected view to contain only %s", expected)
}
list.SetFilterState(FilterApplied)
if !reflect.DeepEqual(list.VisibleItems(), expected) {
t.Fatalf("Error: expected view to contain only %s", expected)
}
}
func TestSetFilterState(t *testing.T) {
tc := []Item{item("foo"), item("bar"), item("baz")}
list := New(tc, itemDelegate{}, 10, 10)
list.SetFilterText("ba")
list.SetFilterState(Unfiltered)
expected, notExpected := "up", "clear filter"
lines := strings.Split(list.View(), "\n")
footer := lines[len(lines)-1]
if !strings.Contains(footer, expected) || strings.Contains(footer, notExpected) {
t.Fatalf("Error: expected view to contain '%s' not '%s'", expected, notExpected)
}
list.SetFilterState(Filtering)
expected, notExpected = "filter", "more"
lines = strings.Split(list.View(), "\n")
footer = lines[len(lines)-1]
if !strings.Contains(footer, expected) || strings.Contains(footer, notExpected) {
t.Fatalf("Error: expected view to contain '%s' not '%s'", expected, notExpected)
}
list.SetFilterState(FilterApplied)
expected = "clear"
lines = strings.Split(list.View(), "\n")
footer = lines[len(lines)-1]
if !strings.Contains(footer, expected) {
t.Fatalf("Error: expected view to contain '%s'", expected)
}
}