cat / 012
clone

a spreadsheet for the terminal: lotus 1-2-3 looks, google sheets keys and formulas, one go binary

Rank palette results by fuzzy score across titles and paths

Dami committed f587c4a
A title match no longer always beats a path match: "file" now finds
the File menu's commands before a title with the letters scattered
through it. Title matches get a small bonus and win ties.
commit
f587c4a68cce27baf5e791cf6fce6b9c8cb7abbb
parent
61837c70f3f155fc7f1570585641f22dedce83d7
author
Dami <dami.etoile@gmail.com>
1 file changed, +28 -12
Minternal/ui/palette.go40+++++++++++++++++++++---------
M internal/ui/palette.go +28 -12
@@ -2,6 +2,7 @@ package ui
22 33 import (44 "cmp"5+ "maps"56 "slices"67 "strconv"78 "strings"
@@ -128,22 +129,27 @@ func (p *picker) changed(m *Model) {
128129 }129130 return130131 }131- // Items whose name matches come first; items that only match with the132- // help of their detail (e.g. the File in a menu path) follow.132+ // Rank title and path matches together by fuzzy score, so a tight133+ // match like "file" on the File menu beats letters scattered across a134+ // title. Title matches get a small bonus and win ties.133135 names, hay := make([]string, len(p.items)), make([]string, len(p.items))134136 for i, it := range p.items {135137 names[i], hay[i] = it.title[:it.name], it.haystack()136138 }137- byScore := func(a, b fuzzy.Match) int { return cmp.Compare(b.Score, a.Score) }138- matches := fuzzy.FindNoSort(q, names)139- slices.SortStableFunc(matches, byScore)140- inName := map[int]bool{}141- for _, mt := range matches {142- inName[mt.Index] = true139+ const titleBonus = 10140+ type ranked struct {141+ pm pickMatch142+ score int143+ order int143144 }144- rest := slices.DeleteFunc(fuzzy.FindNoSort(q, hay), func(mt fuzzy.Match) bool { return inName[mt.Index] })145- slices.SortStableFunc(rest, byScore)146- for _, mt := range append(matches, rest...) {145+ best := map[int]*ranked{}146+ for _, mt := range fuzzy.FindNoSort(q, names) {147+ best[mt.Index] = &ranked{pickMatch{item: &p.items[mt.Index], inTitle: mt.MatchedIndexes}, mt.Score + titleBonus, mt.Index}148+ }149+ for _, mt := range fuzzy.FindNoSort(q, hay) {150+ if r, ok := best[mt.Index]; ok && r.score >= mt.Score {151+ continue152+ }147153 it := &p.items[mt.Index]148154 pm := pickMatch{item: it}149155 for _, i := range mt.MatchedIndexes {
@@ -154,7 +160,17 @@ func (p *picker) changed(m *Model) {
154160 pm.inDesc = append(pm.inDesc, i-it.name-2)155161 }156162 }157- p.shown = append(p.shown, pm)163+ best[mt.Index] = &ranked{pm, mt.Score, mt.Index}164+ }165+ all := slices.Collect(maps.Values(best))166+ slices.SortFunc(all, func(a, b *ranked) int {167+ if c := cmp.Compare(b.score, a.score); c != 0 {168+ return c169+ }170+ return cmp.Compare(a.order, b.order)171+ })172+ for _, r := range all {173+ p.shown = append(p.shown, r.pm)158174 }159175 }160176