Closed natecraddock closed 1 year ago
Based on all your examples, I think that is exactly what I want.
Thank you for giving this feature request so much thought and attention. I look forward to using it once it's implemented. I already have a use in mind, in another open source project. I'll show you when integration is done.
Thanks for reviewing! I have set the deadline for version 0.8.0 for April 1, but I think I can get this feature done well before then. I'll share here once I have it working. I already think I know the changes needed and it shouldn't be too complex actually.
I think I have everything working! See the rework-strict-path-match
branch for the latest changes. Please don't feel rushed or obligated, but I would appreciate some feedback :)
The behavior is now
/
that token will be used for strict path matching/
characters) all must be found in path segments of the candidate stringIn other words, exactly as described above.
For @ratfactor's idea to leave the right part of the token "fuzzy", I didn't implement this for a few reasons.
I'm still open to this "fuzzy" right path if we can find a way to do it. But I'm not sure if it's possible. And I think adding a space is a good enough solution.
I did my best to break it (I even enlisted my wife, who is really good at breaking software). Here's my attempt at an increasingly pathological test:
$ cat paths.txt
oatmeal/sugar.txt
oatmeal/sugar_txt
oatmeal/sug/ar
oat/meal
oat/meal/sug/ar
oat/meal/sug/ar/sugar
oat/meal/sug/ar/sugar.txt
oat/meal/sug/ar/sugar.js
oatmeal/sugar/sugar.txt
oatmeal/sugar/snakes.txt
oatmeal/sugar/skeletons.txt
oatmeal/brown_sugar.txt
oatmeal/brown_sugar/brown.js
oatmeal/brown_sugar/sugar.js
oatmeal/brown_sugar/brown_sugar.js
oatmeal/brown_sugar/sugar_brown.js
oatmeal/granulated_sugar.txt
oatmeal/raisins/sugar.js
oatmeal/raisins/helicopter/sugar.js
oatmeal/raised/sugar.js
raised sugar helicopter
sugar raised helicopter
helicopter sugar raised
helicopter raised sugar
raised helicopter sugar
sugar helicopter raised
oat/rise/js
oat/rise/sug.js
Helicopter Sugar.js
oats raised suggestively jam slowly
oats raised heliocentric slowly grape
oats resist helicopter signs
oatmeal BrOwn SUGar
JavaScript text .js .txt
JavaScript text .js .txt sugar
oat sugar.js
oat.txt sugar.js
oat.txt /sugar.js
oat.txt /sugar.js /sugar.js
//////oat.txt /sugar.js /sugar.js
//////oat.txt
///../..//oat.txt
///../..//oat.txt/sugar.js
///../..//oat.txt/sug ar.js
///../..//oat.txt/ sug ar.js
/ //// /oat.txt/ sug ar.js
/ //// /oat.txt/ sug ar .js
oat/
oat/ meal
oat /meal /sug/
oat /meal/ sug/ar//
1234567890/oat
:+1: I agree that zf's existing support for separate fuzzy tokens does what I need. There's no actual need for a "right/left" matching like I was picturing. This already does what I would expect.
As long as all portions of a path are true, the match is good regardless of the order I enter them. The results of this weird search are fine:
> oat/sugar sugar/sugar meal/sugar
oatmeal/sugar/sugar.txt
oatmeal/brown_sugar/sugar.js
oatmeal/brown_sugar/brown_sugar.js
And if I want to enforce the right/left order of the path portions, I just need to keep the path together.
With a space:
> oat/sugar brown
oatmeal/brown_sugar/brown.js
oatmeal/brown_sugar/brown_sugar.js
oatmeal/brown_sugar.txt
oatmeal/brown_sugar/sugar.js
oatmeal/brown_sugar/sugar_brown.js
No space:
> oat/sugar/brown
oatmeal/brown_sugar/brown.js
oatmeal/brown_sugar/brown_sugar.js
oatmeal/brown_sugar/sugar_brown.js
The matching of the last part, "brown," is still fuzzy, but the order is enforced. That's all I need!
A cool bonus feature that is also possibly unrelated from this path matching specifically, but something I noticed while testing: A search token consisting of some number of slashes is a way to request a minimum path depth.
Example: The three slashes here filtered out any paths that weren't at least three directories deep:
> oat/sugar ///
//////oat.txt /sugar.js /sugar.js
///../..//oat.txt/sugar.js
///../..//oat.txt/sug ar.js
/ //// /oat.txt/ sug ar.js
/ //// /oat.txt/ sug ar .js
///../..//oat.txt/ sug ar.js
I thought that was neat.
In all, it works great and I wasn't able to break it. As before, I'm really excited about this feature and I've already switched to the new version for personal use. :tada:
This is good! But, and I apologize :sweat_smile:, it's not quite where I'd like it to be.
Given that this path exists:
app/models/foo/bar/baz.rb
It doesn't match with this search string:
> mod/baz.rb
./app/models/foo-bar-baz.rb
./app/models/foo/bar-baz.rb
My thinking is: I know I have a model named baz, so I type mod
for the models
tree, and baz.rb
to get at the baz model written in Ruby, which is at some unknown depth within the models/
tree.
@Pistos this really should work. I haven't looked at the code yet, but I think I know where this bug is coming from. I'll try to fix it soon
How did I not run into this? I am so bad at testing software. :rofl:
@natecraddock Yes, I had a feeling this is a bug rather than intentional design. As a clue, my first guess would be that there's an edge case having to do with a full segment match (bar.rb
).
Some more data:
> mod/ba
./app/models/foo-bar-baz.rb
./app/models/foo/bar-baz.rb
./app/models/foo/bar/baz.rb
which is highlighting the ba
of /bar
. So maybe you have some code taking baz
character by character, and, when it processes ba
, it finds /bar
, and then when a z
is added, it thinks ba
+z
doesn't match ba
+r
, and so it filters out that whole subtree.
I was right, it was a simple bug to fix! I have fixed it (and pushed to the branch) and now ./app/models/foo/bar/baz.rb
matches mod/baz.rb
Something I noticed that is related, but a separate issue I'll address later
> mod/baz.rb
./app/models/foo-bar-baz.rb
./app/models/foo/bar-baz.rb
./app/models/foo/bar/baz.rb
In this case I think we should expect mod/baz.rb
to rank ./app/models/foo/bar/baz.rb
the hightest because baz.rb
has the greatest path segment coverage on that string. I'll adjust the ranking for this later, but at least now the line does match.
@ratfactor thanks for your thorough testing. I missed this bug myself, so no worries!
I'll test some more later, but it seems all good so far! Good work. :+1:
I have some more feature requests, but I'll make them in separate github issues.
In this case I think we should expect mod/baz.rb to rank ./app/models/foo/bar/baz.rb the hightest because baz.rb has the greatest path segment coverage on that string. I'll adjust the ranking for this later, but at least now the line does match.
Issue to track this: https://github.com/natecraddock/zf/issues/26
I'll test some more later, but it seems all good so far!
I'll go ahead and merge the brach, but I'll leave the issue open for the next couple days
I added a bunch of tests inspired by the test cases in this issue. It should (hopefully) prevent any regressions in the future.
Strict path matching was implemented from a request (https://github.com/natecraddock/zf/issues/11) and I misunderstood the initial request.
As implemented in version 0.7.0 I do think it is currently useful. But there is room for improvement as suggested in later replies in that issue. Current implementation: when a
/
is found the path matching is made strict to the right and requires contiguous paths in the query.There are two good points raised in the issue
I've thought about this for a while and I believe I have a good solution
Solution
/
anywhere.Here are some examples, all using our lovely test strings
Example 1
Example 2
Example 3
With those examples in mind, I think this covers all the possible use cases, and makes things quite useful!
To recap: A query token containing any
/
will be used for strict path matching. The path segments are not required to be contiguous.Currently a query of
mod/
would match bothmo/d/
and/mod/
, but with these changes only/mod/
would be selected.Open questions
I like this idea, but zf already natively supports this fuzziness by inserting a space and adding a new query token. I'm not against adding this, but I think adding a space keeps things more consistent.