diff --git a/internal/tui/exp/list/filterable_group.go b/internal/tui/exp/list/filterable_group.go index 57aa3da3b19420a5635e35419d2865ea033eb27f..6e9a5dc7eaad66d32ec34baf7e41d35ab3233048 100644 --- a/internal/tui/exp/list/filterable_group.go +++ b/internal/tui/exp/list/filterable_group.go @@ -180,11 +180,6 @@ func (f *filterableGroupList[T]) inputHeight() int { return lipgloss.Height(f.inputStyle.Render(f.input.View())) } -type groupMatch[T FilterableItem] struct { - group Group[T] - score int -} - func (f *filterableGroupList[T]) clearItemState() []tea.Cmd { var cmds []tea.Cmd for _, item := range slices.Collect(f.items.Seq()) { @@ -211,25 +206,6 @@ func (f *filterableGroupList[T]) setMatchIndexes(item T, indexes []int) { } } -func (f *filterableGroupList[T]) findMatchingGroups(firstWord string) []groupMatch[T] { - var matchedGroups []groupMatch[T] - for _, g := range f.groups { - groupName := f.getGroupName(g) - matches := fuzzy.Find(firstWord, []string{groupName}) - if len(matches) > 0 && matches[0].Score > 0 { - matchedGroups = append(matchedGroups, groupMatch[T]{ - group: g, - score: matches[0].Score, - }) - } - } - // Sort by score (higher scores first - exact matches will have higher scores) - sort.SliceStable(matchedGroups, func(i, j int) bool { - return matchedGroups[i].score > matchedGroups[j].score - }) - return matchedGroups -} - func (f *filterableGroupList[T]) filterItemsInGroup(group Group[T], query string) []T { if query == "" { // No query, return all items with cleared match indexes @@ -241,24 +217,31 @@ func (f *filterableGroupList[T]) filterItemsInGroup(group Group[T], query string return items } - // Build search words - words := make([]string, len(group.Items)) + name := f.getGroupName(group) + " " + + names := make([]string, len(group.Items)) for i, item := range group.Items { - words[i] = strings.ToLower(item.FilterValue()) + names[i] = strings.ToLower(name + item.FilterValue()) } - // Perform fuzzy search - matches := fuzzy.Find(query, words) + matches := fuzzy.Find(query, names) sort.SliceStable(matches, func(i, j int) bool { return matches[i].Score > matches[j].Score }) if len(matches) > 0 { - // Found matches, return only those with highlights var matchedItems []T for _, match := range matches { item := group.Items[match.Index] - f.setMatchIndexes(item, match.MatchedIndexes) + var idxs []int + for _, idx := range match.MatchedIndexes { + // adjusts removing group name highlights + if idx < len(name) { + continue + } + idxs = append(idxs, idx-len(name)) + } + f.setMatchIndexes(item, idxs) matchedItems = append(matchedItems, item) } return matchedItems @@ -267,20 +250,6 @@ func (f *filterableGroupList[T]) filterItemsInGroup(group Group[T], query string return []T{} } -func (f *filterableGroupList[T]) searchAllGroups(query string) []Group[T] { - var newGroups []Group[T] - for _, g := range f.groups { - matchedItems := f.filterItemsInGroup(g, query) - if len(matchedItems) > 0 { - newGroups = append(newGroups, Group[T]{ - Section: g.Section, - Items: matchedItems, - }) - } - } - return newGroups -} - func (f *filterableGroupList[T]) Filter(query string) tea.Cmd { cmds := f.clearItemState() f.selectedItem = "" @@ -289,51 +258,24 @@ func (f *filterableGroupList[T]) Filter(query string) tea.Cmd { return f.groupedList.SetGroups(f.groups) } - lowerQuery := strings.ToLower(query) - queryWords := strings.Fields(lowerQuery) - firstWord := queryWords[0] + query = strings.ToLower(strings.ReplaceAll(query, " ", "")) - // Find groups that match the first word - matchedGroups := f.findMatchingGroups(firstWord) - - var newGroups []Group[T] - if len(matchedGroups) > 0 { - // Filter within matched groups using remaining words - remainingQuery := "" - if len(queryWords) > 1 { - remainingQuery = strings.Join(queryWords[1:], " ") - } - - for _, matchedGroup := range matchedGroups { - matchedItems := f.filterItemsInGroup(matchedGroup.group, remainingQuery) - if len(matchedItems) > 0 { - newGroups = append(newGroups, Group[T]{ - Section: matchedGroup.group.Section, - Items: matchedItems, - }) - } + var result []Group[T] + for _, g := range f.groups { + if matches := fuzzy.Find(query, []string{f.getGroupName(g)}); len(matches) > 0 && matches[0].Score > 0 { + result = append(result, g) + continue } - - // add any matching items from other groups - allGroups := f.searchAllGroups(lowerQuery) - for _, g := range allGroups { - exists := false - for _, existing := range newGroups { - if existing.Section.ID() == g.Section.ID() { - exists = true - break - } - } - if !exists { - newGroups = append(newGroups, g) - } + matchedItems := f.filterItemsInGroup(g, query) + if len(matchedItems) > 0 { + result = append(result, Group[T]{ + Section: g.Section, + Items: matchedItems, + }) } - } else { - // No group matches, search all groups - newGroups = f.searchAllGroups(lowerQuery) } - cmds = append(cmds, f.groupedList.SetGroups(newGroups)) + cmds = append(cmds, f.groupedList.SetGroups(result)) return tea.Batch(cmds...) }