-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
FR: filename prioritization, similar to zf
#3608
Comments
|
Both help a little bit, but still leave various cases where it does not work.
|
Oh, I think this was not the right advice I had in mind. Ignore that. I usually tell users to append # Append `.` to the query to give a higher score to the `f.` in the name part of the path
fzf --query f. << EOF
src/foo/bar.go
src/bar/foo.go
EOF
That's because fzf by default gives a greater bonus point to the character at the very beginning. fzf --scheme path --tiebreak end --query foo << EOF
foo/bar/baz
baz/foo/bar
bar/baz/foo
foo/bar/filename
folder/foobar
EOF |
ah yes, indeed, appending Would it maybe make sense to modify The |
The second example shows that it works pretty well when combined with
Setting The second proposal is not feasible because it requires making a non-trivial exception to the scoring mechanism of fzf. |
yeah, I am familiar with the syntax (just not using the correct terms, since I am working with too many selector-implementations which all use different terminology). While you can achieve the desired behavior by appending Having a flag that one could add to |
Unfortunately, we don't have an objective measure to evaluate the quality of the results. There are so many different cases and different expectations from different users with different needs. I'm not familiar with zf, but the example is not really convincing. Is The problem with fzf --tiebreak end --query re << EOF
docs/README.md
vendor/some/directory/too/far/from/the/root/that/you're/not/interested/regex.c
EOF This makes me think the default
I don't think it's a good idea to put anything that affects the scoring mechanism in |
Agree, which is why I suggested an option – users who prefer a certain kind of behavior can enable the options, and those who don't, leave it disabled. The fact hat
Sorry, |
My point is that they will not benefit much from the new option contrary to their belief, because the option will not universally yield better results than the default. So I think they will benefit more in the long run by getting used to the default matching/scoring mechanism of fzf and learning tricks to make better use of it. I can understand their desire to tweak the settings, but as the maintainer of the project, I have to be careful not to add options that have minor benefits and have the potential to make the program harder to understand and confuse the users. Also, it would be easier for users to understand the matching/scoring scheme of fzf, if it worked consistently across different invocations. |
Having said that, here's a PoC patch, you can experiment with it. diff --git a/src/options.go b/src/options.go
index dcb70dc..b643c26 100644
--- a/src/options.go
+++ b/src/options.go
@@ -153,6 +153,7 @@ const (
byLength
byBegin
byEnd
+ byPathname
)
type heightSpec struct {
@@ -547,8 +548,11 @@ func processScheme(opts *Options) {
if !algo.Init(opts.Scheme) {
errorExit("invalid scoring scheme (expected: default|path|history)")
}
- if opts.Scheme == "history" {
+ switch opts.Scheme {
+ case "history":
opts.Criteria = []criterion{byScore}
+ case "path":
+ opts.Criteria = []criterion{byScore, byPathname, byLength}
}
}
@@ -775,6 +779,7 @@ func parseTiebreak(str string) []criterion {
hasLength := false
hasBegin := false
hasEnd := false
+ hasPathname := false
check := func(notExpected *bool, name string) {
if *notExpected {
errorExit("duplicate sort criteria: " + name)
@@ -791,6 +796,9 @@ func parseTiebreak(str string) []criterion {
case "chunk":
check(&hasChunk, "chunk")
criteria = append(criteria, byChunk)
+ case "pathname":
+ check(&hasPathname, "pathname")
+ criteria = append(criteria, byPathname)
case "length":
check(&hasLength, "length")
criteria = append(criteria, byLength)
diff --git a/src/result.go b/src/result.go
index b042829..76774a1 100644
--- a/src/result.go
+++ b/src/result.go
@@ -3,6 +3,7 @@ package fzf
import (
"math"
"sort"
+ "strings"
"unicode"
"github.com/junegunn/fzf/src/tui"
@@ -67,6 +68,15 @@ func buildResult(item *Item, offsets []Offset, score int) Result {
}
case byLength:
val = item.TrimLength()
+ case byPathname:
+ if validOffsetFound {
+ lastDelim := strings.LastIndexByte(item.text.ToString(), '/')
+ if lastDelim < 0 {
+ val = 0
+ } else if lastDelim < minBegin {
+ val = 1
+ }
+ }
case byBegin, byEnd:
if validOffsetFound {
whitePrefixLen := 0 |
I see. Yeah, that I can understand. |
man fzf
)Info
Problem / Steps to reproduce
I recently stumbled upon zf, which prioritizes matches in the filename over matches in the filepath, which I found to be a subtle, but really useful improvement.
I think rather than using a separate fuzzy finder for filepaths (which also has far less features), it would be really useful to have this kind of sorting behavior added to
fzf
.Currently, the one method to accomplish something similar would be
--delimiter="/" --nth=-1
, which restricts matching to the filename. This has the downside of ignoring matches in the directory path, instead of just deprioritizing them.I could see something like adding an option
--scheme=filename
to opt-in this kind of behavior.The text was updated successfully, but these errors were encountered: