-
Notifications
You must be signed in to change notification settings - Fork 202
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
Calculation of initial bounds for completion is too simplistic #402
Comments
If I understand this correctly, the problem is that the server's idea of "initial-bounds" might be all over the place (depending on the server, that is). There is no LSP interface for telling the LSP client what the server will be completing on. I think you once tried something @nemethf by running through all the completions possible beforehand and checking if all of them were |
Sure, the language server protocol was designed differently than Emacs' completion system, but there are clients that found a way to cope with the protocol. So I do not think there is a hole in the protocol. (At least not in this regard.)
Who's responsibility should it be then? What could the latex-mode do? I think it should be the server and not the client that knows how to parse the language, do completion a given point, etc., so that the client could be totally dumb. Emacs's bounds-of-thing-at-point has to be taught about the syntax table of a given mode, a general LSP client shouldn't need this information. I'm just thinking loud: would it possible to keep the current initial heuristics intact and, after the arrival of the first completion items from the server, derive bounds from the items, compare them with the initial one and somehow restart the completion process with readjusted bounds? |
I do think there is a hole in the protocol, as I try to demonstrate in microsoft/language-server-protocol#651 even for cases other than this one. What you say is generally true, but the devil is in the details. Exactly how did those clients manage to "cope with the protocol"? Your final sentence is very ambitious, I wonder if it's worth it (it might be, I'm also thinking out loud).
I agree, that's why I said it shouldn't be Eglot's responsibility. A good-enough solution here might be to make latex-mode do what most LSP latex servers (are there very many of them?) usually do. |
It's hard for me to say because I've only seen animgifs of them. They are probably better at multithreading. Additionally, I guess they don't need a completion function that's cheap to run, because they support triggerCharacters (and commitCharacters).
There are two of them: digestif and texlab. But I disagree, latex-mode (or Eglot instead) should do what other clients do and not what the servers do. So what if the current completion-at-point remains a cheap function, but Eglot is extended with another completion function that runs only when the user explicitly triggers it and when the speed is not so important? Instead of company-capf, we could use a different backend |
I don't understand. How is this an advantage in this specific regard?
Last time I looked we supported triggerCharacters too. Not sure what commitCharacters are. Anyway, I don't think price-per-call is the issue here, rather dealing with protocol inconsistencies in a way that isn't too complex, brittle and unmaintainable.
Regarding latex-mode, it can't by definition do what other LSP clients do, since it knows nothing about LSP. The only thing it knows about is the "symbol at point" or "thing to complete at point" and this knowledge should, if possible, match the server's, which is also an interested part in that language aspect. At least I don't see a good reason why it shoudn't, do you? I think we need to take a step back. And maybe write a failing unit test for this. Exactly in which position of which latex source do problems arise? Exactly under what conditions does Eglot's "calculation of initial bounds", inherited directly from To your second part, Eglot can't do what other clients do if we don't know what other clients do (and this is why I asked above, I am not against it in principle). If you want to explore that avenue, I think it's fair to first collect that information and then decide upon it. Regarding your last proposal, Eglot must work with |
The server is supposed to be smarter than the editor when it comes to its target language, so it is natural that they might disagree about what the symbol at point is. Of course this is not limited to TeX; another example I can image is completion within strings, say dictionary keys in Python. One might wish On the other hand, it seems unlikely to me that any server returns completions with different prefixes. My TeX server certainly doesn't do that. So I'd think it's reasonable to compute a tentative "thing at point, according to server" based just on the
By the way, one thing I just don't get is the |
Indeed, and that is the whole point why Eglot users use eglot to delegate some management of their buffers to an LSP-speaking server. No argument there. To state the obvious, Emacs users are also, well, using Emacs, so they also expect a set of functionality that might not be available in other languages, like the o ability to regexp match candidates or other functionality that are obscure to some. Much of this functionality is coded into the major-mode, along with indentation rules, syntax-highlighting, etc, etc (these last two are things that some LSP servers already do, but for which currently the major-mode still has the better solution). Marrying these two expectations in the sometimes ungrateful job of Eglot, which isn't a very smart piece of software at all, it's just the messenger. But this were just generalities. I'll adress the specific problem below.
Not unless the server is using some other source of information that is unavailable to Emacs's runtime. In this case I don't think it is. But you might well disprove me, i.e. I suppose there could be a legitimate reason for disagreement. For example, the server could be correlating data in the actual "latex" runtime (if such a thing existed) and provide a somehow enhanced or smarter guess about what the current "thing-at-point" is. An example out of SLIME/SLY, the Emacs Common Lisp IDEs. They do something very similar with Lisp macros: they know the objects at runtime and so they can provide the correct indentation rules. An offline Emacs will often mis-indent a common-lisp macro since it doesn't have the insight that the SLIME/SLY server counterparts do. So he questions are, in my opinion:
It's not Eglot at all, it's |
Well, Emacs's calculation of symbol-at-point, like syntax highlighting and so on, is a regexp-based heuristic, while LSP servers tend to do a deeper static analysis. Right?
In the LaTeX case, we have at least 3 practical examples: the fuzzy completion of But I guess the Python example is even more compelling, isn't it? Here I am not sure things work as I described, since I'm extrapolating from the TeX case. But I believe completion of a string would fail if the string contents happens not to be a valid identifier (hence my example
In this case all is good. But should the server now try to guess what the editior is going to regard as the "thing at point"? I guess not.
Sure.
Again, to be clear, I've described (without testing) the behaviour I expect based on what happens with TeX. Namely: the server correctly computes
I think so. Either that, or the editor shouldn't at all attempt to filter candidates. |
Right, but do they in practice, in this situation? IOW, they might do that, and so might major modes which are not necessarily limited to regexp strategies (but often to "static" strategies, like most LSP servers).
Thanks for restating the example. What I don't understand here is: why doesn't the server return the completion
It might be more compelling, depending how the server(s) work. Maybe if it(they) matches(match)
In this particular case, I think it's reasonable to do one of the following:
Of course, as I said before, a way to let one side let the other side know what they think is the "thing at point" would solve all these problems. One thing I haven't mentioned is that LSP allows, through a rather obscure use of the |
Because it's a fuzzy match against "lorem ipsum", not anything shorter. But let me change your question so I can give the answer you are looking for. When completing
Like I said before, I totally agree. For the record, in case you decide to purse this with the LSP people, I believe two more pieces of information are missing from the completion method response: Whether the completion list is already filtered, and whether it's already sorted. (As I said, I don't see why any server wouldn't do both of these things, since otherwise it's just a glorified TAGS file. But it's not my protocol.) Currently my server needs workarounds to prevent the editor from resorting (e.g., fuzzy matches carefully sorted by score) and refiltering. |
I think we can enhance Eglot with the following compromise. Introduce two project-local variables with names like The bound-function is Once the completion items arrive from the server, Eglot can cheaply check whether its guess of the bounds was right. If the error-behavior is |
But the end effect is the same right? Unless you are you trying to complete
OK but after doing that, please also answer the actual question I gave you, since it tells me more about this issue.
Except it doesn't. One of the ways doesn't work because LSP doesn't have a good mechanism to communicate the bounds of the thing it is trying to complete. It only has a very far-fetched mechanism for doing so that is ridden with conceptual problems (which @nemethf seems intent on tackling anyway). But until there is a decent solution, if you want to flex-match in Emacs with LSP you have to telepathically communicate these rules to FTR I have no idea on the kind of resistance you'll find from the
Agree on this, but seems to be orthogonal to the bounds issue. |
Doesn't sound too bad, give it a go if you want. The names need some work but the general idea is decent, on paper. "Decent" is this context would mean "fckuing great" in another context because of the yucky monster you are trying to tame. Let's see how concise and clear you can make it. |
Yes. All the following would have the same final effect if the user request a completion after
The last prefix choice totally canonical and would require no telepathy or other form of communication. The point here is that the completion box should be placed below |
In your opinion, is there any difference between the thing designated by "completion subject" and the thing designated by "thing at point"? Spoiler alert: in my mind there isn't. The latter may also have other actions applicable on it, such as finding the definition, finding references, highlighting, evaluation in context, etc etc. |
No difference. The difference for me is that the server understands more of the language and might disagree with the editor's idea of what the thing at point is. |
Major modes can do a pretty nice job too (after all they people were programming with emacs for a pretty long time before "servers" came along). And if they don't, they can be convinced to. Why not try to at least initiate a communication with |
This clearly needs to be fixed. VSCode also has glitches related to this, see microsoft/language-server-protocol#648 for an example.
Might be a good idea, but I think the real problem here is the deficiency in LSP's completion interface. It seems that the completion bounds/prefix is needed for 3 different things
Point 3 is never an issue for Eglot, at least as long as the server provides a Now, I don't know company and completion-at-point in detail, but do you agree that, if no filtering was needed on the editor side, the only problem that could arise from a wrong bound computation would be an UI glitch (point 1)? |
Maybe, have to think about it. Maybe the two issues are indeed connected, yes. |
I've agreed to the second part many times. But it the meantime I hope you'll agree that it doesn't hurt to initiate that conversation. |
This is branched off from #366, where @astoff writes:
The issue affects other serves as well. See test
json-basic
in eglot-tests.el.Commit f5151be describes the decision behind the current behavior. But maybe we can find an alternative implementation that's also "cheap-to-run".
The text was updated successfully, but these errors were encountered: