diff --git a/src/algo/algo.go b/src/algo/algo.go index a02a0a8..f056918 100644 --- a/src/algo/algo.go +++ b/src/algo/algo.go @@ -847,6 +847,9 @@ func exactMatchNaive(caseSensitive bool, normalize bool, forward bool, boundaryC } if boundaryCheck { ok = bonus >= bonusBoundary + if ok && pidx_ == 0 { + ok = index_ == 0 || charClassOf(text.Get(index_-1)) <= charDelimiter + } if ok && pidx_ == len(pattern)-1 { ok = index_ == lenRunes-1 || charClassOf(text.Get(index_+1)) <= charDelimiter } @@ -878,7 +881,23 @@ func exactMatchNaive(caseSensitive bool, normalize bool, forward bool, boundaryC sidx = lenRunes - (bestPos + 1) eidx = lenRunes - (bestPos - lenPattern + 1) } - score, _ := calculateScore(caseSensitive, normalize, text, pattern, sidx, eidx, false) + var score int + if boundaryCheck { + // Underscore boundaries should be ranked lower than the other types of boundaries + score = int(bonus) + deduct := int(bonus-bonusBoundary) + 1 + if sidx > 0 && text.Get(sidx-1) == '_' { + score -= deduct + 1 + deduct = 1 + } + if eidx < lenRunes && text.Get(eidx) == '_' { + score -= deduct + } + // Add base score so that this can compete with other match types e.g. 'foo' | bar + score += scoreMatch*lenPattern + int(bonusBoundaryWhite)*(lenPattern+1) + } else { + score, _ = calculateScore(caseSensitive, normalize, text, pattern, sidx, eidx, false) + } return Result{sidx, eidx, score}, nil } return Result{-1, -1, 0}, nil diff --git a/test/test_go.rb b/test/test_go.rb index 13b96d8..c328a22 100755 --- a/test/test_go.rb +++ b/test/test_go.rb @@ -3366,6 +3366,14 @@ class TestGoFZF < TestBase tmux.send_keys :Space tmux.until { |lines| assert_includes lines[-3], 'bar' } end + + def test_boundary_match + # Underscore boundaries should be ranked lower + assert_equal( + %w[[x] -x- -x_ _x- _x_], + `printf -- 'xxx\n-xx\nxx-\n_x_\n_x-\n-x_\n[x]\n-x-\n' | #{FZF} -f"'x'"`.lines(chomp: true) + ) + end end module TestShell