@@ -194,7 +194,9 @@ func NewTree(dbName string, dbdriver drivers.Driver) *Tree {
194194 if filterText == "" {
195195 tree .ClearSearch ()
196196 } else {
197- tree .FoundNodeCountInput .SetText (fmt .Sprintf ("[%d/%d]" , len (tree .state .searchFoundNodes ), len (tree .state .searchFoundNodes )))
197+ if len (tree .state .searchFoundNodes ) > 0 {
198+ tree .FoundNodeCountInput .SetText (fmt .Sprintf ("[1/%d]" , len (tree .state .searchFoundNodes )))
199+ }
198200 tree .SetBorderPadding (1 , 0 , 0 , 0 )
199201 }
200202
@@ -291,6 +293,38 @@ func (tree *Tree) databasesToNodes(children map[string][]string, node *tview.Tre
291293 }
292294}
293295
296+ func prioritizeResult (pattern , target string , fuzzyRank int ) int {
297+ // play match golf - lowest score wins
298+
299+ // Exact match
300+ if pattern == target {
301+ return 0
302+ }
303+
304+ // Prefix is scored on length difference, 1-99
305+ if strings .HasPrefix (target , pattern ) {
306+ lengthDiff := len (target ) - len (pattern )
307+ if lengthDiff > 98 {
308+ lengthDiff = 98
309+ }
310+ return 1 + lengthDiff
311+ }
312+
313+ // Substr penalized by distance from start and length diff
314+ if strings .Contains (target , pattern ) {
315+ index := strings .Index (target , pattern )
316+ lengthPenalty := len (target ) - len (pattern )
317+ score := 100 + index + lengthPenalty
318+ if score > 9999 {
319+ score = 9999
320+ }
321+ return score
322+ }
323+
324+ // If no other matches, fall back to fuzzy match with a low score
325+ return 10000 + fuzzyRank
326+ }
327+
294328func (tree * Tree ) search (searchText string ) {
295329 rootNode := tree .GetRoot ()
296330 lowerSearchText := strings .ToLower (searchText )
@@ -317,32 +351,57 @@ func (tree *Tree) search(searchText string) {
317351 tableNameFilter = parts [1 ]
318352 }
319353
354+ // Collect nodes with their match ranks
355+ type rankedNode struct {
356+ node * tview.TreeNode
357+ rank int
358+ }
359+ var rankedNodes []rankedNode
360+
320361 rootNode .Walk (func (node , parent * tview.TreeNode ) bool {
321362 nodeText := strings .ToLower (node .GetText ())
322363
323364 if databaseNameFilter == "" {
324- if fuzzy .Match (tableNameFilter , nodeText ) {
365+ rank := fuzzy .RankMatch (tableNameFilter , nodeText )
366+ if rank >= 0 {
325367 if parent != nil {
326368 parent .SetExpanded (true )
327369 }
328- tree .state .searchFoundNodes = append (tree .state .searchFoundNodes , node )
329- tree .SetCurrentNode (node )
330- tree .state .currentFocusFoundNode = node
370+ adjustedRank := prioritizeResult (tableNameFilter , nodeText , rank )
371+ rankedNodes = append (rankedNodes , rankedNode {node : node , rank : adjustedRank })
331372 }
332373 } else {
333- if fuzzy .Match (tableNameFilter , nodeText ) && parent != nil {
374+ rank := fuzzy .RankMatch (tableNameFilter , nodeText )
375+ if rank >= 0 && parent != nil {
334376 parentText := strings .ToLower (parent .GetText ())
335- if fuzzy .Match (databaseNameFilter , parentText ) {
377+ parentRank := fuzzy .RankMatch (databaseNameFilter , parentText )
378+ if parentRank >= 0 {
336379 parent .SetExpanded (true )
337- tree .state .searchFoundNodes = append (tree .state .searchFoundNodes , node )
338- tree .SetCurrentNode (node )
339- tree .state .currentFocusFoundNode = node
380+ adjustedTableRank := prioritizeResult (tableNameFilter , nodeText , rank )
381+ adjustedParentRank := prioritizeResult (databaseNameFilter , parentText , parentRank )
382+ // Combine ranks: prioritize table match but factor in database match
383+ combinedRank := adjustedTableRank + (adjustedParentRank / 2 )
384+ rankedNodes = append (rankedNodes , rankedNode {node : node , rank : combinedRank })
340385 }
341386 }
342387 }
343388
344389 return true
345390 })
391+
392+ sort .Slice (rankedNodes , func (i , j int ) bool {
393+ return rankedNodes [i ].rank < rankedNodes [j ].rank
394+ })
395+
396+ for _ , rn := range rankedNodes {
397+ tree .state .searchFoundNodes = append (tree .state .searchFoundNodes , rn .node )
398+ }
399+
400+ // Set current node to best match
401+ if len (tree .state .searchFoundNodes ) > 0 {
402+ tree .SetCurrentNode (tree .state .searchFoundNodes [0 ])
403+ tree .state .currentFocusFoundNode = tree .state .searchFoundNodes [0 ]
404+ }
346405}
347406
348407// Subscribe to changes in the tree state
@@ -482,12 +541,6 @@ func (tree *Tree) Highlight() {
482541}
483542
484543func (tree * Tree ) goToNextFoundNode () {
485- foundNodesText := make ([]string , len (tree .state .searchFoundNodes ))
486-
487- for i , node := range tree .state .searchFoundNodes {
488- foundNodesText [i ] = node .GetText ()
489- }
490-
491544 for i , node := range tree .state .searchFoundNodes {
492545 if node == tree .state .currentFocusFoundNode {
493546 var newFocusNodeIndex int
0 commit comments