zoxide
zoxide copied to clipboard
favour exact match over more frequent partial match
rupa/z has logic for matching the shortest directory:
When multiple directories match all queries, and they all have a common prefix, z will cd to the shortest matching directory, without regard to priority.
zoxide however doesn't seem to rank using length, eg:
$ zi code
457 /Users/tekumara/code
498 /Users/tekumara/code3
ie: /Users/tekumara/code3 is preferred, but I'd like z code
to always go to /Users/tekumara/code
#260 is the same issue I think, if you want to look what they said there
How would you suggest weighting the choices if one is accessed more frequently or was accessed more recently, while the other is shorter? (It might help to read up on the current rules for scoring before answering that. I don't know the current rules myself.)
Hmm maybe "shorter" is imprecise, maybe ignore the length and heavily weigh towards exact matches. In this example, the reason you want it to choose "code" instead of "code3" is not really the length, rather its because it's a precise match.
If the directories were "code34" and "code5", it's not obvious that you want to access code5 when you write "code". Similarly, with your example, if the directories were "code" and "code3" and you wrote "co" it's not obvious that you want to go to "code" if you access "code3" more frequently.
I think what makes this seem compelling is the name you chose. When you look at the names "code" and "code3" you think, of course you don't want to go to code3, that sounds like gibberish. But if z takes you there it is because you usually want to go there.
For a more unbiased alternative, consider if you have two directories "airport" and "airplane". If you write "air" I think you should be taken to the one you visit the most frequently, instead of going to "airport" because it's shorter.
TLDR I think you maybe can put small emphasis on word length but the key is to give exact matches super high prio
Great point @premell I agree - favour exact match over more frequent partial match. I'll rename the issue 😅
I agree, though I'd want to use it for a while to see if it works. I occasionally include word boundaries in searches as a way to make it more exact ('anvi' instead of 'view' when searching for 'irfanview'). But fortunately, preferring exact word matches won't break that, since a non-word boundary match will still be be better than a non-match.
With this direction, we should discuss it on #260 where I proposed rules.
I realized if exact matches are favored, "/mnt/c/any/path" will highly match "c", and I bet there are plenty of people that like to use one letter shortcuts. I'm not sure it's a good idea unless we implement some other type of filtering, like only favoring exact matches if they are >3 characters, or if they appear in the last path component.
I agree, there should be some sort of filtering. I like the idea with minimum set of characters. But what do you mean with last path component though?
@premell last path component means:
- In a query like
z foo bar
,bar
is the last component of the query. - In a path like
/home/foo/some/barbecue
,barbeque
is the last component of the path.
The algorithm requires that the last component of the query should be contained in the last component of the path -- that is, barbeque
should contain the word bar
. foo
can be found anywhere before bar
in the entire path.
I do think last path component is important. /mnt/c/any/path
shouldn't be a result for z c
.
Hmm not quite sure I understand. In the case of barbecue you say that it is the last component of the path. But you only know that when you're already in the folder. Then for instance .../barbeque/sauce would be the last path component. To be sure something is the last path it has to have only files, but like 90% of all folders you want to navigate to have some sort of folder inside it. Like in your example with "c" not being a last path component, what if you want to navigate there then? Or to like ~/.config is common, in your suggestion zoxide would see it as a last path component right?
If you want to go to /home/barbeque
, then z bar
is a valid query, because bar
matches barbeque
.
If you want to go to /home/barbeque/sauce
, then z bar
wouldn't work even though the path contains bar
, because bar
does not match sauce
.
z bar
matches /foo/bar
, but not /bar/foo
.
I like the "last component must match" more as a tie breaker than a filter. Because as a filter it breaks the use case of repeating a command with another argument to make it more specific, like:
$ z zsh
# goes to ~/.zsh, not intended
$ z zsh proj
# goes to ~/projects/zsh
But this is speculative. I'm not sure if it ends up being a real problem. I'll sit on this worry for now and report it later if it's an issue for me. But keep in mind that keyword sorting can give this a very slight weight if it's needed as a tie breaker.
@lefth in a situation like this, if you re-ran z zsh
a second time while inside ~/.zsh
, you'd go the second-best match (~/projects/zsh
), because zoxide always excludes the current directory. The use-case of ~/projects/zsh
being the third best match is too rare for us to optimize for.
Expecting the last component to match the last keyword does improve the quality of search results dramatically, so I'd still say it's better off as a filter. It completely solves a widely reported problem in z (see https://github.com/rupa/z/issues/127, https://github.com/rupa/z/issues/133, https://github.com/rupa/z/issues/296).
@tekumara the author of z seems to think the shortest prefix solution was suboptimal (https://github.com/rupa/z/issues/35). Apparently you've found an example of this too: https://github.com/rupa/z/issues/289
Is there another way we could do this?
@tekumara, zoxide 0.8.0 comes with fuzzy completions on bash/fish/zsh. Now you can type z code<SPACE><TAB>
and choose the correct one.
I acknowledge that this isn't a full-fledged "solution", but it does make this particular scenario a lot more workable.