-
-
Notifications
You must be signed in to change notification settings - Fork 226
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
Variable to enable or disable snippets across backends #891
Comments
What you are suggesting makes sense to me. One question: You want backends to disable snippet completion or all effects that will be performed in post-completion event? For example, in lsp-mode when you complete |
No, just snippets. Or parentheses insertion, etc (see the linked issues). Adding imports at the beginning of the file shouldn't be a problem (or if it will, it can be another option). If we wanted to disable post-completion altogether, that would be easier to do. Easier to name as well. |
Having a single option to disable snippet on completion makes sense. However putting the responsibility of respecting it to backends may cause confusion. Backend developers may not be aware of this option (yea I have bad habit in not reading full documentations), and the result that some backends supports it while some don't may be an issue. Maybe it's worth standardizing snippet expansion on completion? Something that documented in |
One reason might be that the backend would have to honor all values of the variable rather than promising to handle just some value (hopefully correctly and consistently). I don't remember very well but sometimes in lsp we don't have a choice, the server might give us snippets and nothing else usable for insertion. Could be wrong tho. Then there are is the yasnippet backend itself, right? On the other hand the "literal completion" var name is a suitable cop-out for that situation. That saidI don't have a lot of time to bikeshed right now, so those are my 2c and good luck! |
People have to read the documentation anyway. The non-compliant backends will have users file issues on the subject. As long as the most popular backends obey it, though, in general we should be fine. And we can mention the new variable in the description of
That's an option, but we'll either have to implement snippet string support in Anyway, this can be a second step. We'll have to name the variable anyway. One more thing to consider: can there be other features that would also be performed in |
IIUC, some backends can do that, but that's against the spec, and
It can be exempted, considering snippets are its only purpose (and the user can disable it otherwise).
I'm no native speaker. Is that good English? Does this name sound meaningful to people? |
For irony-mode, in the post-completion, I may retrigger company-mode, but this only make sens if some post-completion text was inserted: You said earlier:
Maybe company can provide a |
Neither am I. In my hurry I might have confused you: all I meant is that a name like you proposed, If OTOH you are asking if "literal" is a good word, I think it is: it means more or less the same as "verbatim": it implies that there isn't a translation from one form to another. |
Do you consider @nikital Do we want to be able to inhibit that kind of behavior as well?
It's an option, but here we would also arrive to the necessity to describe the change in behavior in appropriate words (this time, in the description of |
It's good that you explained, then.
Like removing the parentheses and everything inside them? We do want the variable's value nil to indicate that. I'm just coming from the viewpoint that the snippet (with placeholders and stuff) is not part of a completion, because completions are strings we match against the input characters. So "literal completion" would mean to only insert the said string (the selected one).
And OTOH, to me "do not expand snippets" might mean that it's okay to insert the snippet source text into the buffer, and simply avoid calling (for instance) |
I would say it's a snippet because it's not the part of the "typed text", that is used for filtering and stuff. |
That is true, it isn't.
The issue is like that: like YouCompleteMe (I'm told), it implements a workflow where when you type TAB once or twice, it looks like a completion is already inserted in the buffer. And when you type some other char, it actually gets inserted, and that other char, is inserted as well. Which doesn't work well if the "other char" is an opening paren, and the act of inserting a completion adds a snippet with function arguments which contains an opening paren already. So we want the backend to stop right after inserting the string which the user expects (from looking at the tooltip). Adding some text at the beginning of the buffer, for instance, is fine. |
Beware that snippets, in general, can be (much) more complicated than just
OK. But 1) that operation needs no special handling from the potentially-snippet-inserting backend, does it? That is good, because discovering a reasonable literal string inside a snippet template can could potentially be a complex task. 2) it's kinda akward to do this because the snippet's trigger key is already a (presumably short) abbreviation. So inserting it literally is akward. If you do this, then Eglot wouldn't (at least in the short term) honour the variable because the way Eglot works is it erases whatever the completion engine (company or other) has selected, and honours LSP directives, which might be complex editing operations including snippet insertions. Wouldn't it be better and easier to at least inform company that some completion is a snippet, or more generally a "potentially complex insertion command"? Then the variable could be Said property's value could even be an argless function that does the insertion itself, should company one day decide to honour that (but again that would need coordination with Eglot).
Again, that would require stuff like Eglot to depend on |
That's why I wasn't sure about the name
"Potentially"? Those are basically all backends, right? The variable could be ignored by backends like
So is the only way to avoid inserting an opening paren twice, is to remove all snippet-bearing completions? I thought there's a different approach. Like when the LSP client doesn't declare snippet support. Then the server has to return appropriate results that don't use snippets. That will rely on the servers being compliant, of course.
That's right.
I don't imagine removing whole sets of completions from the list (including any function/method completion, for instance) is a good solution to this issue.
Snippets aside, what would be the difference in behavior between using and not using it? Would the completion behavior without using it be actually helpful enough on its own?
I wish we could. But these properties would require names as well. And they will have to be introduced in a backward-compatible fashion. |
I assumed there are at least some backends that wouldn't ever be used for snippets, but I don't use anything else but
I don't follow.
Why, if the user specifically chose not to expand snippets with
Is "it" the argless function or the variable you're proposing? The completion behaviour without adding the former is "insert the thing verbatim".
I don't see how that maps to all backends, but the use that eglot makes of |
Then why use the variable at all? The user can set Not quite: people want to use the backends that they need to use, and get as many completions as possible from them. Backends like Except for some undesirable behavior (like adding extra parens and function arguments, or similar).
I seem to be failing to understand you. What use is there in the term "snippet-less backend" if you apply it to
What problem are you solving? I'm trying to explain myself as clearly as I can. No, snippet-only backends won't be affected by the variable upon discussion. Or they will. But that doesn't make any real difference because, like I said already, the user can disable
"It" is the argless function. Now could you answer the questions I have asked? Snippets aside, what would be the difference in behavior between calling that argless function or not? Would the completion behavior without using it be actually helpful enough on its own? Because I see Eglot applying "text edits" even when yasnippet is not installed.
That doesn't address either of my concerns. Including the fact that if some snippet-expanding logic moves into separate property, snippet expansion will break in the previous versions of Company, as well as |
you totally lost me. I'm afraid I'm exhausting my comprehension and time available for this issue. Perhaps I'm misunderstanding this completely. I don't use any backend other than But I meant, for example the former SLY backend
Technically eglot isn't a company backend, though it strives to be usable with company.
I meant it doesn't insert snippets directly, it just honours
I though I did. There's a function on every completion item: when it's nil, it defaults to "insert the text" when it's non nil it does the insertion itself (which can be expanding a snippet, inserting and editing around, or do something else for all I know, just like selecting an option from a menu). |
I think the miscommunication has been going on for a while. I'm trying to be as clear as possible, but unless you understand the problem that this discussion is trying to solve, I'm afraid it's going to be hard to contribute. Said understanding can be gathered from re-reading the beginning of this discussion and/or the referenced issues.
Can we ask a user to switch from Eglot to Sly? No, we can't. They target different use cases. So I cannot understand why you would think that a classification of backends would help somebody.
Yes, it does.
Yes. Like I said in the previous message. So simply avoiding calling
No, it's not.
Okay, it's an option. But that doesn't answer the question of whether inserting such completion without "editing around" is something that users can still find useful. Would Eglot completions still be "functional" without "text edits"? What if, with the current implementation, |
Of course, and I hoped it would go without saying that the reciprocal is true, and I that it was you who invited me to contribute. I did the best I could to understand it, answer your questions and provide whatever insight I could.
I mentioned SLY because two exchanges ago you were very surprised when I mentioned backends that "potentially support snippets". But you countered:
I didn't think so and this is why I remember the example of a former SLY company backend that I used to maintain. I don't think it would ever implement snippet support. But that backend is gone now, SLY now uses
I was just reading company-yasnippet and it does seem like it expands snippets circa line 141. It would fit my description of a backend that expands snippets when selecting a completion. But I didn't try the code or maybe you meant some other detail that invalidated my interpretation.
Wouldn't it stop complying with the
I don't remember ever suggesting removing it. I suggested a new kind of special annotation for some completions, where backends could program special insertion behaviour. I also think that annotation should have a reciprocal in Emacs's own Tell you what: the software packages I maintain use I'm sorry I couldn't be more helpful 👋 |
In
I don't know. I imagine
It would be an option.
That needs a:
Ditto. Or else it wouldn't be accepted in Emacs. Or I don't think it would, at least. The items 1 and 2 are exactly why I started this discussion. |
That's irrelevant now, isn't it? Its something to be run after the completion has finished, and like all hooks in Emacs it can, should and is used for many purposes.
So I use your "option" in
I usually don't start ironing out implementation details like a the annotation's name before I make sure the idea is across. Regarding the semantics, there are various levels of "meaningful". Reading my post three posts ago seems like a sufficient level of description: but I'll briefly repeat according to your parameters 1) Name "something-something-expander" 2) Semantics: if non-nil, a nullary function responsible for inserting the completion candidate, which might have more side effects than just textually inserting the completion candidate. 3) Trick question?
Of course not. But this was just an embrionic suggestion in an ongoing discussion. Take it as such, or don't take it at all. You're the so-called "feature-owner" here, I'm just a consultant. |
That's what I asked: could the result be acceptable? Apparently you think that it won't. OK.
I'm just saying these are the details I'm having difficulty coming up with because I don't use a lot of backends (e.g. have worked with LSP very little), so I don't really know the behaviors that are enacted in
It would have to be optional, right? So if it's not called, the just-inserted completion candidate would still be a correct completion? Here's one problem, as I understand it: in LSP, if the client declares support for snippets, the server is free to send completions that simply don't "work" without the associated snippet expansion. But if the client does not declare support for snippets, the "regular" completions are sent instead. All in all, that means that the backend needs to know in advance whether snippets would be used, and an optional function that would simply be called (or not) at the end does not fit the bill. Please feel free to correct me.
Wouldn't |
That's understandable: it moves quickly, probably has changed since the last time I looked at it. But you needn't worry about that, the
That's accurate, or accurate enough. But the problem is that (1) I don't want to make eglot read a company-specific variable to declare (non-)support for snippets (2) I might still be interested in expanding them with other capf clients.
Not necessarily: the |
I kind of do need to worry about that while naming things, at least. I think.
Then your idea with a new properly won't really work, would it? A completion function would need to know in advance whether snippets will be used. A variable would fit that fill.
That's understandable. So we can approach that from another side:
Not sure I understand why. But another client could let-bind that variable to whatever value they want, if they're not interested in respecting that user customization.
What if it didn't happen, because the user didn't want it to? The exit-function would enact said expansion. Not to mention that exit-function would try to apply non-snippet "text edits" again, which IIUC should have been applied already. That can be solved with text properties, but... I don't like the added complexity, TBH. Every completion function would have to re-implement that logic. |
@dgutov do we have an agreement on that? At lsp-mode side, we are getting a lot of bug reports caused by a user using company-tng front-end because of some of the evil related packages (evil-collections, doom) have company-tng as a default. @tigersoldier If we do not have an action plan I would propose to change company-lsp method to check what are the currently active frontends and throw an error if company-tng is there. |
You have a user option to disable snippets, right? That seems like it's going to be the way to go for the foreseeable future. Because we don't have a better proposal that would work with Eglot. Hence, Eglot will need to add a similar user option as well.
Maybe |
Yes, we do, my main concern is that it does not work out of the box and it generates false negatives.
Works for us. Just for the record, IME users prefer to switch to another frontend instead of disabling the snippets. |
Another option would be for It won't save you from questions like "where are my snippets in completions", however. |
Interesting. Though of course the users that wouldn't mind probably don't report this problem either. (/Cc @nikital just in case) |
@joaotavora Since we haven't reached any better conclusion, could you add an Eglot-specific variable to disable snippet expansion (even when |
Sure, I guess. Though I'd prefer, also as a temporary solution, some kind of I'll reread the whole thread regardless, try to reproduce the situation (any simple recipe?), and see what I can contribute to eglot, company and Yasnippet. |
IME some users do prefer to disable snippets. Hence the existence of user options like |
Using company-tng might be one. |
It'd speed up my work if you could you expand a bit? I don't know tng, what should I do? |
You call The thing to check/verify/fix is that completion still works in a useful fashion. |
@kiennq willing to take a look? I know that you use company-tng and you have already put some effort into learning company-tng internals and you are familiar with lsp-mode as well. PS one more thing - in the long term we are going to focus on capf which eventually will replace the company-lsp |
I read most of the comments in this thread, and it seems this issue has not been resolved. I use And more to the point, is there a solution to get snippets out of my company-capf completions? |
My issue was solvable by toggling a feature in |
That's the current recommended solution, yes: use the variable specific for each completion backend. I'm not very fond of the idea of creating a global variable that's supposed to affect behavior without any technical means to enforce it, and that seems unsolvable to far, at least as far as |
I'd like to invite people for some bikeshedding and related discussion. Foremost, we'd like to solve the problem with
company-tng
(#731, #881) without doing too much work. In essence, this UI doesn't really work well when a backend appends function arguments (normally using a snippet engine, but even just adding the parens can be counter-intuitive).So one solution would be to ask every backend to add a user option to disable that, but why not add a global variable and ask backend authors to honor that instead? And there are existing variables in different backends that play this role. I've been thinking about the name, though, and haven't come to a decision yet:
company-enable-snippets
,company-allow-snippets
,company-inhibit-snippets
,company-insert-arguments
,company-insert-snippets
,company-support-snippets
,company-literal-completion-only
.Some of these might imply that all backend must insert arguments (when the variable is set to
t
) whereas the backend only do that on best-effort basis. Some of them seem to limit applicability to function arguments, whereas snippets could be used for something else as well.Thoughts? Other suggestions?
@nikital @kiennq @tigersoldier @yyoncho @joaotavora @Sarcasm
The text was updated successfully, but these errors were encountered: