joaotavora / sly

Sylvester the Cat's Common Lisp IDE
1.26k stars 142 forks source link

Company completion priority #454

Open mustiboost opened 3 years ago

mustiboost commented 3 years ago

Sly's completion seems to not choose the obvious option when "guessing" what the user is typing. This happens a lot to a point where I am thinking about turning it off completely or going back to slime again. See picture. I typed in most of the word "print-object" and sly still makes "pprint-pop" the top suggestion. Any way to improve this? Screenshot from 2021-06-10 15-54-37

mustiboost commented 3 years ago

When I say "this happens a lot" what I mean is that it happens for all kinds of words, not just with "print-object".

joaotavora commented 3 years ago

SLY doesn't have a perfect flex scoring algorithm. The one I designed for Emacs in Elisp is much better, and easy to backport to SLY in Common Lisp. Here's the description of it:

;; To understand how this works, consider these bad
;; ascii(tm) diagrams showing how the pattern "foo"
;; flex-matches "fabrobazo", "fbarbazoo" and
;; "barfoobaz":

;;      f abr o baz o
;;      + --- + --- +

;;      f barbaz oo
;;      + ------ ++

;;      bar foo baz
;;          +++

;; "+" indicates parts where the pattern matched.  A
;; "hole" in the middle of the string is indicated by
;; "-".  Note that there are no "holes" near the edges
;; of the string.  The completion score is a number
;; bound by ]0..1]: the higher the better and only a
;; perfect match (pattern equals string) will have
;; score 1.  The formula takes the form of a quotient.
;; For the numerator, we use the number of +, i.e. the
;; length of the pattern.  For the denominator, it
;; first computes
;;
;;     hole_i_contrib = 1 + (Li-1)^(1/tightness)
;;
;; , for each hole "i" of length "Li", where tightness
;; is given by `flex-score-match-tightness'.  The
;; final value for the denominator is then given by:
;;
;;    (SUM_across_i(hole_i_contrib) + 1) * len
;;
;; , where "len" is the string's length.

Someone (TM) has to do the work. SLY's version lives in slynk-completion.lisp. Good luck, and hurry, before you switch to back slime! :-)

mustiboost commented 3 years ago

Someone (TM) has to do the work. SLY's version lives in slynk-completion.lisp. Good luck, and hurry, before you switch to back slime! :-)

I didn't mean that comment to be a "threat" by the way. :) I was just getting a bit frustrated as I am used to hitting "return" quickly after typing just a few letters of a known command or symbol, and it just wasn't happening. Doing that I was getting all kinds of stuff inserted, just not what I wanted. I think it's actually important to be vocal about these issues, because we have way to many people who either stop using a given software because of certain bugs or imperfections without ever saying a word about it, or they figure out workarounds or fixes but keep them to themselves as it is "working for them." It's easy to quietly switch back to slime, but I want sly to actually improve. (I also recognize there aren't enough contributors).

Alright, I'll actually take a look at slynk-completion.lisp and see if I can do anything about it. I'll see if I "grog" your algorithm first though, before I put in a pull request. I'll also research similar flex completion algorithms elsewhere to see if we can "borrow" something from them. :)

mustiboost commented 3 years ago

Also, it would be helpful to see the elisp file where you implemented this.

joaotavora commented 3 years ago

I didn't mean that comment to be a "threat" by the way. :) I was just getting a bit frustrated as I am used to hitting "return" quickly after typing just a few letters of a known command or symbol, and it just wasn't happening.

Yes, I understand the frustration

I think it's actually important to be vocal about these issues, because we have way to many people who either stop using a given software because of certain bugs or imperfections without ever saying a word about it, or they figure out workarounds or fixes but keep them to themselves as it is "working for them." It's easy to quietly switch back to slime, but I want sly to actually improve.

You are absolutely right, and I thank you for your report.

I'll see if I "grog" your algorithm

It's not very hard you'll see.

Also, it would be helpful to see the elisp file where you implemented this.

In minibuffer.el, look for a function called completion-pcm--hilit-commonality. But it'll confuse you more. Here one really wants to adapt the current code of slynk-completion.lispthat already matches the pattern to a candidate string, to consider the "holes" as described in the algorithm description. To "get" the algorithm get a pen and paper first and run a few strings and patterns (like your printo and print-object for example)

mustiboost commented 3 years ago

Yeah, you're right. The algorithm is not very hard at all. It's just that I have to familiarize myself with sly code in general and the rest of the immediate code base where that algorithm fits in. I've always been a user or slime/sly, and never tinkered with it, so we'll see how it goes.