New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
small changes to the scoring algorithm #2452
Conversation
Is it? I thought the caller passed it in by reference. I don't know what the
Yes, clearing it doesn't make a difference in the scores, just in the set of indices of the matched characters. I'm guessing the UI just uses the first I'd also recommend resetting the index set after each Otherwise, |
I see what you mean now. What’s odd is that @tiennou specifically wrote the tests as if he was expecting the abbreviation to be repeated within the same string. I’ve asked for clarification on that. In the meantime, I’ve made the change to clear the mask and am testing it locally. Hoping to get a release out before Mojave. |
* don’t expect repeats if the abbreviation occurs more than once * reset indexes before each check, since it should be empty in real-world use * test a variety of abbreviations that hit more of the string
In the absence of feedback, I’m going for it. I think this makes more sense. 1.6.0 will be a preview release at first if you want to try it out. |
@@ -124,5 +124,6 @@ CGFloat QSScoreForAbbreviationWithRanges(CFStringRef str, CFStringRef abbr, id m | |||
} | |||
} | |||
CFRelease(userLoc); | |||
[mask removeAllIndexes]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIR, the mask-managing thing is supposed to be the responsibility of higher-level code (ie. it's not supposed to pass an already-populated/non-empty index set in here), so I'm somewhat suspicious that this could cause a spurious reset of a correctly matching mask in a (previous) recursive step in case a subsequent one doesn't. I'm failing to imagine an example of it though, so maybe the algorithm already caters to that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIR, the mask-managing thing is supposed to be the responsibility of higher-level code (ie. it's not supposed to pass an already-populated/non-empty index set in here)
But it was passing a non-empty set. If you look at testLongString
(before the changes here), the index set would have up to 10 matches for an abbreviation 4 characters long. Though now I’m wondering if that’s because the test was reusing the index without clearing it each time. You might be right about the behavior of the actual application never doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two index set issues. One is that the test code wasn't passing in a fresh set to each call, like you normally would, so it was caching hits from previous calls.
The other is that the algorithm will leave behind hits from abandoned iterations if the set isn't cleared before returning 0, which is what this line changes. I mentioned the example of matching "test"
against "t e s t tess!"
in this comment on the PR that originally added this test (a year later, so I'm assuming no one saw it).
Other than this one file, I have zero familiarity with the Quicksilver code base, but I'm betting there's something that is picking just the first abbreviation.length
chars as matches to render, so that the "extra" hits left in the index set aren't shown. I think that works in most cases, but I believe there are edge cases where it would show hits that don't actually correspond to the match that was used to calculate the score.
This one's my fault — I wasn't exactly testing the masks, only the scoring system, hence blindly passing the same indexset over and over is incorrect. Arguably, what gets "masked" should be in its own test case.
This one is what I'm worried about, ie. the spurious reset I alluded to above. I would only expect indexes from a "valid match path" to be included, since we only add All this said, I suspect something is wrong, because I've noticed this, using the default ranker. I'm not quite sure if that's correct or not… Shouldn't a 3-letter match from the start of a word be higher than a 2l + l ? Or is that the fabled TextStart ranker |
If you match
Good idea. I tried doing that in my JS version of the algorithm and all the test suites passed. The hits do get set in reverse order, though I assume that doesn't matter for a
It's due to the lengths of the strings. If you make them the same length, like |
I haven’t been following this too closely, but if someone wants to add the proposed fix, I’ll look it over and try to get it into 1.6.1. I’d like to release it soon since we currently have a bug that prevents QS from launching under 10.10. |
So are you suggesting moving that |
I addressed the first two points here @fwextensions. On the third, I don’t doubt the bug, but the fix doesn’t seem right. At that point in the code,
mask
is going to be thrown away forever anyway. Clearing it wouldn’t make a difference. (I tried and the scores didn’t change.) I haven’t had a chance to dig in and figure out the actual fix.closes #2450