diff --git a/internal/tui/exp/list/filterable.go b/internal/tui/exp/list/filterable.go index 2566ccb947e3826598988f1cc7ae297452e75bb1..e639786db5777aaeda237e959dffe36d9c6a7583 100644 --- a/internal/tui/exp/list/filterable.go +++ b/internal/tui/exp/list/filterable.go @@ -15,12 +15,8 @@ import ( "github.com/sahilm/fuzzy" ) -var ( - // Pre-compiled regex for checking if a string contains alphabetic characters. - alphaRegex = regexp.MustCompile(`[a-zA-Z]`) - // Pre-compiled regex for checking if a string is alphanumeric. - alphanumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]*$`) -) +// Pre-compiled regex for checking if a string is alphanumeric. +var alphanumericRegex = regexp.MustCompile(`^[a-zA-Z0-9]*$`) type FilterableItem interface { Item diff --git a/internal/tui/exp/list/filterable_group.go b/internal/tui/exp/list/filterable_group.go index 9f0efc49162004cebfbc57c2c5ce96319895574e..0e960fc9088be19f821e345a28cd03802573611b 100644 --- a/internal/tui/exp/list/filterable_group.go +++ b/internal/tui/exp/list/filterable_group.go @@ -198,30 +198,57 @@ func (f *filterableGroupList[T]) Filter(query string) tea.Cmd { var newGroups []Group[T] for _, g := range f.groups { - words := make([]string, len(g.Items)) - for i, item := range g.Items { - words[i] = strings.ToLower(item.FilterValue()) + // Check if group name matches the query + // Extract the group name from the section - we'll use the section's view content + // as a fallback since ItemSection doesn't implement FilterableItem + var groupName string + if section, ok := g.Section.(*itemSectionModel); ok { + groupName = strings.ToLower(section.title) + } else { + // Fallback to using the section's ID or view content + groupName = strings.ToLower(g.Section.ID()) } - - matches := fuzzy.Find(query, words) - - sort.SliceStable(matches, func(i, j int) bool { - return matches[i].Score > matches[j].Score - }) - - var matchedItems []T - for _, match := range matches { - item := g.Items[match.Index] - if i, ok := any(item).(HasMatchIndexes); ok { - i.MatchIndexes(match.MatchedIndexes) + groupMatches := fuzzy.Find(query, []string{groupName}) + + if len(groupMatches) > 0 && groupMatches[0].Score > 0 { + // If group name matches, include all items from this group + // Clear any existing match indexes for items since the group matched + for _, item := range g.Items { + if i, ok := any(item).(HasMatchIndexes); ok { + i.MatchIndexes(make([]int, 0)) + } } - matchedItems = append(matchedItems, item) - } - if len(matchedItems) > 0 { newGroups = append(newGroups, Group[T]{ Section: g.Section, - Items: matchedItems, + Items: g.Items, }) + } else { + // Group name doesn't match, check individual items + words := make([]string, len(g.Items)) + for i, item := range g.Items { + words[i] = strings.ToLower(item.FilterValue()) + } + + matches := fuzzy.Find(query, words) + + sort.SliceStable(matches, func(i, j int) bool { + return matches[i].Score > matches[j].Score + }) + + var matchedItems []T + for _, match := range matches { + item := g.Items[match.Index] + if i, ok := any(item).(HasMatchIndexes); ok { + i.MatchIndexes(match.MatchedIndexes) + } + matchedItems = append(matchedItems, item) + } + if len(matchedItems) > 0 { + newGroups = append(newGroups, Group[T]{ + Section: g.Section, + Items: matchedItems, + }) + } } } cmds = append(cmds, f.groupedList.SetGroups(newGroups))