Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Fix scoring to favor exact substring matches #15

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions spec/filter-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ rootPath = (segments...) ->

describe "filtering", ->
it "returns an array of the most accurate results", ->
candidates = ['Gruntfile','filter', 'bile', null, '', undefined]
expect(filter(candidates, 'file')).toEqual ['filter', 'Gruntfile']
candidates = ['Gruntfile', 'filter', 'bile', null, '', undefined]
expect(filter(candidates, 'file')).toEqual ['Gruntfile', 'filter']

describe "when the maxResults option is set", ->
it "limits the results to the result size", ->
candidates = ['Gruntfile', 'filter', 'bile']
expect(bestMatch(candidates, 'file')).toBe 'filter'
expect(bestMatch(candidates, 'file')).toBe 'Gruntfile'

describe "when the entries contains slashes", ->
it "weighs basename matches higher", ->
Expand Down Expand Up @@ -112,6 +112,9 @@ describe "filtering", ->
expect(bestMatch(['z_a_b', 'a_b'], 'ab')).toBe 'a_b'
expect(bestMatch(['a_b_c', 'c_a_b'], 'ab')).toBe 'a_b_c'

it "weighs matches that are substring matches higher", ->
expect(bestMatch(['/a/b/c/install.txt', 'inst-all.txt'])).toBe '/a/b/c/install.txt'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the other examples pass in an array of candidates and then a search string. All you're passing in here are candidates?


describe "when the entries are of differing directory depths", ->
it "places exact matches first, even if they're deeper", ->
candidates = [
Expand Down
1 change: 1 addition & 0 deletions src/filter.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module.exports = (candidates, query, queryHasSlashes, {key, maxResults}={}) ->
score = scorer.score(string, query, queryHasSlashes)
unless queryHasSlashes
score = scorer.basenameScore(string, query, score)
score = scorer.substringScore(string, query, score)
scoredCandidates.push({candidate, score}) if score > 0

# Sort scores in descending order
Expand Down
1 change: 1 addition & 0 deletions src/fuzzaldrin.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module.exports =
query = query.replace(SpaceRegex, '')
score = scorer.score(string, query)
score = scorer.basenameScore(string, query, score) unless queryHasSlashes
score = scorer.substringScore(string, query, score)
score

match: (string, query) ->
Expand Down
16 changes: 16 additions & 0 deletions src/scorer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,22 @@ exports.basenameScore = (string, query, score) ->
score *= depth * 0.01
score

exports.substringScore = (string, query, score) ->
# Return a near perfect score if the query is a substring match
substrIndex = string.indexOf(query)
substrIndexi = string.toLowerCase().indexOf(query.toLowerCase())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like these two are calculated up front but there are cases where this method will return by only checking substrIndex.

Could you then move the calculation of substrIndexi down past all the return checks for substrIndex? So lower-casing the string and searching it again is only done if the first substring match attempt fails.


if substrIndex >= 0
return score + 1.155 if substrIndex == 0
return score + 1.145 if string[substrIndex - 1] == PathSeparator
return score + 1.135
else if substrIndexi >= 0
return score + 1.15 if substrIndexi == 0
return score + 1.14 if string[substrIndexi - 1] == PathSeparator
return score + 1.13

return score

exports.score = (string, query) ->
return 1 if string is query

Expand Down