@@ -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...)
}