diff --git a/list/list.go b/list/list.go index da73d0fd6..f2ea6e503 100644 --- a/list/list.go +++ b/list/list.go @@ -441,7 +441,19 @@ func (m *Model) InsertItem(index int, item Item) tea.Cmd { func (m *Model) RemoveItem(index int) { m.items = removeItemFromSlice(m.items, index) if m.filterState != Unfiltered { - m.filteredItems = removeFilterMatchFromSlice(m.filteredItems, index) + // Rebuild filtered list: drop the entry matching the removed global + // index and shift down all subsequent global indices by one. + filtered := m.filteredItems[:0] + for _, fi := range m.filteredItems { + if fi.index == index { + continue + } + if fi.index > index { + fi.index-- + } + filtered = append(filtered, fi) + } + m.filteredItems = filtered if len(m.filteredItems) == 0 { m.resetFiltering() } @@ -1300,15 +1312,6 @@ func removeItemFromSlice(i []Item, index int) []Item { return i[:len(i)-1] } -func removeFilterMatchFromSlice(i []filteredItem, index int) []filteredItem { - if index >= len(i) { - return i // noop - } - copy(i[index:], i[index+1:]) - i[len(i)-1] = filteredItem{} - return i[:len(i)-1] -} - func countEnabledBindings(groups [][]key.Binding) (agg int) { for _, group := range groups { for _, kb := range group { diff --git a/list/list_test.go b/list/list_test.go index 13be41af9..ec94fe3b1 100644 --- a/list/list_test.go +++ b/list/list_test.go @@ -99,6 +99,29 @@ func TestSetFilterText(t *testing.T) { } } +func TestRemoveItemWithFilter(t *testing.T) { + items := []Item{item("foo"), item("bar"), item("baz")} + l := New(items, itemDelegate{}, 10, 10) + l.SetFilterText("ba") + l.SetFilterState(FilterApplied) + + // filtered list contains ["bar", "baz"] at global indices 1 and 2. + // Remove "foo" (global index 0) — filtered list should be unchanged. + l.RemoveItem(0) + visible := l.VisibleItems() + if !reflect.DeepEqual(visible, []Item{item("bar"), item("baz")}) { + t.Fatalf("after removing unfiltered item: got %v, want [bar baz]", visible) + } + + // The global list is now ["bar", "baz"]. Remove "bar" (global index 0). + // Filtered list should shrink to ["baz"]. + l.RemoveItem(0) + visible = l.VisibleItems() + if !reflect.DeepEqual(visible, []Item{item("baz")}) { + t.Fatalf("after removing filtered item: got %v, want [baz]", visible) + } +} + func TestSetFilterState(t *testing.T) { tc := []Item{item("foo"), item("bar"), item("baz")}