Orderless is not, in fact, orderless
Hi, thanks for this package! I have been using it for a while and have found the completion to be quite intuitive, except for a specific case:
The fzf-native scorer allows reordering of words, just like orderless does. So we can match the command in M-x "org-goto" by typing "goto org".
fussy disallows this by feeding the scorer the query "gotoorg" instead of "goto org". This, of course does not match, and the candidate is discarded:
https://github.com/jojojames/fussy/blob/4080b373f3361126d4de1f063bb08718b0c08eed/fussy.el#L616-L618
I have "fixed" the issue on my end with a very ugly advice hack:
(defun my/allow-reordering-advice-replace-regexp (orig-fun regexp rep string &rest args) string)
(define-advice fussy-score (:around (orig-fun &rest args) allow-reordering)
(prog2
(advice-add 'replace-regexp-in-string :around 'my/allow-reordering-advice-replace-regexp)
(apply orig-fun args)
(advice-remove 'replace-regexp-in-string 'my/allow-reordering-advice-orderless-p)))
I understand that the word concatenation was a conscious choice and it is possible that other scorers do not support whitespace. In this case, maybe giving the user a choice per scorer would make sense?
I'm guessing you're using orderless to filter and fzf to score&sort.
(replace-regexp-in-string "\\s" "" string)
You could look into creating a list of scoring functions that would be able to accept a SPC and then conditionally skipping the replace-regexp by checking the value of fussy-score-fn.
PR accepted.
Thanks for your reply!
Another option I was thinking of, that would support all scorers would be to split all words by whitespace, score each word individually and then add/multiply the results.
I will implement such a custom scorer and use it for a while to see how well such an approach works. I‘ll get back to you then.
Hi again,
it's been a couple days and I've put a lot of thought into this problem. The big issue is that the scoring algorithms were not made with orderless in mind. Please keep in mind that I am fairly new to elisp so the code listings may not show good practices. They do work, however, and the concepts count.
Solution 1
Inputting each word into the scoring algorithm individually and then adding or multiplying results.
If the scoring algorithm receives the raw query (could be set as a text property), this can be achieved from the user-side with a custom scoring algorithm, e.g.,
(defun my/scoring-fn (str query &rest _args)
(list (seq-reduce '*
(mapcar
(lambda (query-word)
(car (fussy-flx-rs-score str query-word)))
(split-string query))
1)))
(push 'my/scoring-fn fussy-score-fns-without-indices)
For each scoring algorithm the best reduction method would have to be found.
Solution 2
Concatenating the query words in the order first seen by orderless.
Currently, fussy discards org-goto with the query goto org as the scoring algorithm receives gotoorg. Instead of concatenating the query in the given order, we could concatenate in the order first seen, in this case orggoto, which will match.
This is fairly close to the current implementation, only allowing the reordering of the query words, but no interleaving.
It is implemented here: https://github.com/kim366/fussy/commit/f2903e0d113b83628a9b79859178c483793e22ce
Solution 3
Inputting not the user's query, but instead what orderless matched, into the scoring algorithm.
Example: matching the query abc xyz with orderless-flex against ax_other_bycz will highlight [a][x]_other[b][y][c][z]. We can concatenate the highlights as axbycz and feed them to the scoring algorithm.
This approach gives maximum compatibility with orderless-flex as no candidates will be filtered out due to incompatible scoring. It also allows us to fully configure orderless, using e.g., initialism for the first word and other matching styles for other words as detailed in the orderless docs. It will require some long-term real-world use to see how intuitive the sorting is.
This also means, though, that overlapping matches will be discarded: with orderless-flex, the query org go will match org-info, as the g in go overlaps with the g in org and is discarded. This seems to be intended orderless behavior. Most scoring algorithms rank consecutive matches higher. With this query, org-goto will not match as highly as it should, as orderless-flex is greedy but scoring algorithms might not be (hotfuzz, for example).
It is implemented here: https://github.com/kim366/fussy/commit/b4575139344df3dd3a282cafe0496b08e3dac5c3
Conclusion
So solution 3 tries to maintain maximum compatiblity with orderless, being very "flex". Solution 2 tries to maintain maximum compatibility with the scoring algorithms, not allowing any interleaving.
I will use these for a while and see how I feel about them. What are your thoughts?
First question is are you trying to make this work with all backends or just the fzf one? We can go from there.
Yes, all backends. I am currently using hotfuzz and it works wellAm 29/1/2024 um 09:40 schrieb James @.***>: First question is are you trying to make this work with all backends or just the fzf one? We can go from there.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you authored the thread.Message ID: @.***>
Did you have thoughts after using your implementations after a while?