Detailed changes
@@ -112,15 +112,6 @@ func (s *Slice[T]) Len() int {
return len(s.inner)
}
-// Slice returns a copy of the underlying slice.
-func (s *Slice[T]) Slice() []T {
- s.mu.RLock()
- defer s.mu.RUnlock()
- result := make([]T, len(s.inner))
- copy(result, s.inner)
- return result
-}
-
// SetSlice replaces the entire slice with a new one.
func (s *Slice[T]) SetSlice(items []T) {
s.mu.Lock()
@@ -138,10 +129,8 @@ func (s *Slice[T]) Clear() {
// Seq returns an iterator that yields elements from the slice.
func (s *Slice[T]) Seq() iter.Seq[T] {
- // Take a snapshot to avoid holding the lock during iteration
- items := s.Slice()
return func(yield func(T) bool) {
- for _, v := range items {
+ for _, v := range s.Seq2() {
if !yield(v) {
return
}
@@ -151,8 +140,10 @@ func (s *Slice[T]) Seq() iter.Seq[T] {
// Seq2 returns an iterator that yields index-value pairs from the slice.
func (s *Slice[T]) Seq2() iter.Seq2[int, T] {
- // Take a snapshot to avoid holding the lock during iteration
- items := s.Slice()
+ s.mu.RLock()
+ items := make([]T, len(s.inner))
+ copy(items, s.inner)
+ s.mu.RUnlock()
return func(yield func(int, T) bool) {
for i, v := range items {
if !yield(i, v) {
@@ -1,6 +1,7 @@
package csync
import (
+ "slices"
"sync"
"sync/atomic"
"testing"
@@ -145,7 +146,7 @@ func TestSlice(t *testing.T) {
assert.Equal(t, 4, s.Len())
expected := []int{1, 2, 4, 5}
- actual := s.Slice()
+ actual := slices.Collect(s.Seq())
assert.Equal(t, expected, actual)
// Delete out of bounds
@@ -203,7 +204,7 @@ func TestSlice(t *testing.T) {
s.SetSlice(newItems)
assert.Equal(t, 3, s.Len())
- assert.Equal(t, newItems, s.Slice())
+ assert.Equal(t, newItems, slices.Collect(s.Seq()))
// Verify it's a copy
newItems[0] = 999
@@ -224,7 +225,7 @@ func TestSlice(t *testing.T) {
original := []int{1, 2, 3}
s := NewSliceFrom(original)
- copy := s.Slice()
+ copy := slices.Collect(s.Seq())
assert.Equal(t, original, copy)
// Verify it's a copy
@@ -97,7 +97,7 @@ func NewFilterableList[T FilterableItem](items []T, opts ...filterableListOption
f.list = New[T](items, f.listOptions...).(*list[T])
f.updateKeyMaps()
- f.items = f.list.items.Slice()
+ f.items = slices.Collect(f.list.items.Seq())
if f.inputHidden {
return f
@@ -2,6 +2,7 @@ package list
import (
"regexp"
+ "slices"
"sort"
"strings"
@@ -179,7 +180,7 @@ func (f *filterableGroupList[T]) inputHeight() int {
func (f *filterableGroupList[T]) Filter(query string) tea.Cmd {
var cmds []tea.Cmd
- for _, item := range f.items.Slice() {
+ for _, item := range slices.Collect(f.items.Seq()) {
if i, ok := any(item).(layout.Focusable); ok {
cmds = append(cmds, i.Blur())
}
@@ -1,6 +1,8 @@
package list
import (
+ "slices"
+
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/charmbracelet/crush/internal/csync"
"github.com/charmbracelet/crush/internal/tui/components/core/layout"
@@ -89,7 +91,7 @@ func (g *groupedList[T]) convertItems() {
func (g *groupedList[T]) SetGroups(groups []Group[T]) tea.Cmd {
g.groups = groups
g.convertItems()
- return g.SetItems(g.items.Slice())
+ return g.SetItems(slices.Collect(g.items.Seq()))
}
func (g *groupedList[T]) Groups() []Group[T] {
@@ -1,6 +1,7 @@
package list
import (
+ "slices"
"strings"
"github.com/charmbracelet/bubbles/v2/key"
@@ -201,7 +202,7 @@ func (l *list[T]) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return l, nil
case anim.StepMsg:
var cmds []tea.Cmd
- for _, item := range l.items.Slice() {
+ for _, item := range slices.Collect(l.items.Seq()) {
if i, ok := any(item).(HasAnim); ok && i.Spinning() {
updated, cmd := i.Update(msg)
cmds = append(cmds, cmd)
@@ -288,7 +289,7 @@ func (l *list[T]) viewPosition() (int, int) {
func (l *list[T]) recalculateItemPositions() {
currentContentHeight := 0
- for _, item := range l.items.Slice() {
+ for _, item := range slices.Collect(l.items.Seq()) {
rItem, ok := l.renderedItems.Get(item.ID())
if !ok {
continue
@@ -561,7 +562,7 @@ func (l *list[T]) focusSelectedItem() tea.Cmd {
return nil
}
var cmds []tea.Cmd
- for _, item := range l.items.Slice() {
+ for _, item := range slices.Collect(l.items.Seq()) {
if f, ok := any(item).(layout.Focusable); ok {
if item.ID() == l.selectedItem && !f.IsFocused() {
cmds = append(cmds, f.Focus())
@@ -580,7 +581,7 @@ func (l *list[T]) blurSelectedItem() tea.Cmd {
return nil
}
var cmds []tea.Cmd
- for _, item := range l.items.Slice() {
+ for _, item := range slices.Collect(l.items.Seq()) {
if f, ok := any(item).(layout.Focusable); ok {
if item.ID() == l.selectedItem && f.IsFocused() {
cmds = append(cmds, f.Blur())
@@ -655,7 +656,7 @@ func (l *list[T]) AppendItem(item T) tea.Cmd {
l.items.Append(item)
l.indexMap = csync.NewMap[string, int]()
- for inx, item := range l.items.Slice() {
+ for inx, item := range slices.Collect(l.items.Seq()) {
l.indexMap.Set(item.ID(), inx)
}
if l.width > 0 && l.height > 0 {
@@ -702,7 +703,7 @@ func (l *list[T]) DeleteItem(id string) tea.Cmd {
}
l.items.Delete(inx)
l.renderedItems.Del(id)
- for inx, item := range l.items.Slice() {
+ for inx, item := range slices.Collect(l.items.Seq()) {
l.indexMap.Set(item.ID(), inx)
}
@@ -767,7 +768,7 @@ func (l *list[T]) IsFocused() bool {
// Items implements List.
func (l *list[T]) Items() []T {
- return l.items.Slice()
+ return slices.Collect(l.items.Seq())
}
func (l *list[T]) incrementOffset(n int) {
@@ -822,7 +823,7 @@ func (l *list[T]) PrependItem(item T) tea.Cmd {
}
l.items.Prepend(item)
l.indexMap = csync.NewMap[string, int]()
- for inx, item := range l.items.Slice() {
+ for inx, item := range slices.Collect(l.items.Seq()) {
l.indexMap.Set(item.ID(), inx)
}
if l.width > 0 && l.height > 0 {
@@ -926,7 +927,7 @@ func (l *list[T]) SelectedItem() *T {
func (l *list[T]) SetItems(items []T) tea.Cmd {
l.items.SetSlice(items)
var cmds []tea.Cmd
- for inx, item := range l.items.Slice() {
+ for inx, item := range slices.Collect(l.items.Seq()) {
if i, ok := any(item).(Indexable); ok {
i.SetIndex(inx)
}
@@ -949,7 +950,7 @@ func (l *list[T]) reset(selectedItem string) tea.Cmd {
l.selectedItem = selectedItem
l.indexMap = csync.NewMap[string, int]()
l.renderedItems = csync.NewMap[string, renderedItem]()
- for inx, item := range l.items.Slice() {
+ for inx, item := range slices.Collect(l.items.Seq()) {
l.indexMap.Set(item.ID(), inx)
if l.width > 0 && l.height > 0 {
cmds = append(cmds, item.SetSize(l.width, l.height))