company-mode / company-mode

Modular in-buffer completion framework for Emacs

Home Page:http://company-mode.github.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Variable to enable or disable snippets across backends

dgutov opened this issue · comments

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

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 ArrayList company-lsp backend might add import java.util.ArrayList; in the imports section. If this is the case I guess names like company-inhibit-post-completion will make more sense.

all effects that will be performed in post-completion event

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 company-backends as new commands or arguments will be more visible than the option itself. The option will then control the behavior of company, not backends.

but why not add a global variable and ask backend authors to honor that instead

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!

@tigersoldier

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

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 post-completion in company-backends docstring.

Maybe it's worth standardizing snippet expansion on completion?

That's an option, but we'll either have to implement snippet string support in company-template, or universally depend on yasnippet. I'm not sure I want the latter, thus far. Further, there might be some value in backends' choosing when to call the snippet-expansion code on their own.

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 post-completion, and which insert text into the buffer, that aren't directly tied to snippets?

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

IIUC, some backends can do that, but that's against the spec, and pyls has recently been fixed to avoid this behavior: palantir/python-language-server#515

Then there are is the yasnippet backend itself, right?

It can be exempted, considering snippets are its only purpose (and the user can disable it otherwise).

On the other hand the "literal completion" var name is a suitable cop-out for that situation.

I'm no native speaker. Is that good English? Does this name sound meaningful to people?

One more thing to consider: can there be other features that would also be performed in post-completion, and which insert text into the buffer, that aren't directly tied to snippets?

For irony-mode, in the post-completion, I may retrigger company-mode, but this only make sens if some post-completion text was inserted:

https://github.com/Sarcasm/company-irony/blob/b44711dfce445610c1ffaec4951c6ff3882b216a/company-irony.el#L106-L119

You said earlier:

If we wanted to disable post-completion altogether, that would be easier to do. Easier to name as well.
-- #891 (comment)

Maybe company can provide a company-inhibit-post-completion variable in, but allow a the more complex backends do things in a new safe-post-completion (bad name, but hopefully you get the idea).

On the other hand the "literal completion" var name is a suitable cop-out for that situation.

I'm no native speaker. Is that good English? Does this name sound meaningful to people?

Neither am I. In my hurry I might have confused you: all I meant is that a name like you proposed, company-literal-completion-only, seems like it would exempt backends from doing sophisticated things like pruning out snippet placeholders and stuff (which, IMO, they would have to do if the variable's name was company-expand-snippets, its value was nil, and all you had was snippet templates).

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.

@Sarcasm

For irony-mode, in the post-completion, I may retrigger company-mode, but this only make sens if some post-completion text was inserted

Do you consider :: to also be a "snippet"?

@nikital Do we want to be able to inhibit that kind of behavior as well?

Maybe company can provide a company-inhibit-post-completion variable in, but allow a the more complex backends do things in a new safe-post-completion (bad name, but hopefully you get the idea).

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 safe-post-completion). So I'm not sure it's a win.

@joaotavora

It's good that you explained, then.

company-literal-completion-only, seems like it would exempt backends from doing sophisticated things like pruning out snippet placeholders

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).

(which, IMO, they would have to do if the variable's name was company-expand-snippets, its value was nil, and all you had was snippet templates)

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) yas-expand-snippet.

Do you consider :: to also be a "snippet"?

I would say it's a snippet because it's not the part of the "typed text", that is used for filtering and stuff.
But this is a snippet without placeholders.
I was under the impression that this is ticket wasn't specifically about placeholders, but TBH, I don't understand fully the issue with company-tng.

I was under the impression that this is ticket wasn't specifically about placeholders

That is true, it isn't.

I don't understand fully the issue with company-tng

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.

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.

Beware that snippets, in general, can be (much) more complicated than just long-function-name(arg1, arg2, argn...). The form is completely free.

So "literal completion" would mean to only insert the said string (the selected one).

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.
To honour the variable Eglot in spitir would need to read it directly: it's not enough for company-capf to read it, because company-capf has no idea that this or that is a snippet.

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 company-honour-completion-commands. If it were nil, those completions wouldn't be shown at all, and things would be consistent in Eglot/LSP-land.

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).

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) yas-expand-snippet.

Again, that would require stuff like Eglot to depend on company directly, to read the variable's name and decide not to call the expander function. It's easier to use the current approach where some :company-x hint is added to objects eventually readable by company (but also other completion frontends).

Beware that snippets, in general, can be (much) more complicated than just long-function-name(arg1, arg2, argn...). The form is completely free.

That's why I wasn't sure about the name company-insert-arguments.

But 1) that operation needs no special handling from the potentially-snippet-inserting backend, does it?

"Potentially"? Those are basically all backends, right? The variable could be ignored by backends like company-yasnippet, of course, because the user could just as well disable the whole backend.

honours LSP directives, which might be complex editing operations including snippet insertions

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.

To honour the variable Eglot in spitir would need to read it directly: it's not enough for company-capf to read it, because company-capf has no idea that this or that is a snippet.

That's right.

Then the variable could be company-honour-completion-commands. If it were nil, those completions wouldn't be shown at all, and things would be consistent in Eglot/LSP-land.

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.

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).

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?

t's easier to use the current approach where some :company-x hint is added to objects eventually readable by company (but also other completion frontends).

I wish we could. But these properties would require names as well. And they will have to be introduced in a backward-compatible fashion.

"Potentially"? Those are basically all backends, right?

I assumed there are at least some backends that wouldn't ever be used for snippets, but I don't use anything else but company-capf. But at least for now, company-capf can be said to be a snippet-less backend, it supports what capf does and that for now, is not snippets, and there is no indication that it will ever be.

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.

I don't follow.

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.

Why, if the user specifically chose not to expand snippets with company? Why should we show them if we have nothing useful to do with them?

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?

Is "it" the argless function or the variable you're proposing? The completion behaviour without adding the former is "insert the thing verbatim".

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 don't see how that maps to all backends, but the use that eglot makes of company-capf could be simplified with this. But I would probably push it to Emacs, too. That is, I would lobby for this to go into capf directly.

I assumed there are at least some backends that wouldn't ever be used for snippets

Then why use the variable at all? The user can set company-backends to use the said backends, problem solved. Right?

Not quite: people want to use the backends that they need to use, and get as many completions as possible from them. Backends like company-lsp or eglot, because they give access to a lot of language servers.

Except for some undesirable behavior (like adding extra parens and function arguments, or similar).

But at least for now, company-capf can be said to be a snippet-less backend

I seem to be failing to understand you.

What use is there in the term "snippet-less backend" if you apply it to company-capf while Eglot, working through it, can and does insert snippets?

Why, if the user specifically chose not to expand snippets with company? Why should we show them if we have nothing useful to do with them?

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 company-yasnippet and similar backends altogether through other means. It's an easy problem, and not the one that I'm trying to solve.

Is "it" the argless function or the variable you're proposing? The completion behaviour without adding the former is "insert the thing verbatim".

"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.

I don't see how that maps to all backends, but the use that eglot makes of company-capf could be simplified with this.

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 M-x completion-at-point in the current and previous Emacs releases.

Then why use the variable at all? The user can set company-backends to use the said backends, problem solved. Right?

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 company-capf and it doesn't expand snippets (eglot does it in the :exit-function).

But I meant, for example the former SLY backend company-sly that I maintained didn't use any snippets, it was just for completing symbols.

Backends like company-lsp or eglot, because they give access to a lot of language servers.

Technically eglot isn't a company backend, though it strives to be usable with company.

What use is there in the term "snippet-less backend" if you apply it to company-capf while Eglot, working through it, can and does insert snippets?

I meant it doesn't insert snippets directly, it just honours :exit-function as per the capf protocol. It does more than just snippets, by the way, like editing stuff around the newly inserted completion. I supposed a snippet-able backend would be something that would insert and expand snippets through company. That is, the user would select a completion that's maybe annotated like a snippet, and upon selecting it, a snippet expansion would happen. Is this not how it works today?

Now could you answer the questions I have asked?

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).

you totally lost me. I'm afraid I'm exhausting my comprehension and time available for this issue.

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.

But I meant, for example the former SLY backend company-sly that I maintained didn't use any snippets, it was just for completing symbols.

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.

I don't use any backend other than company-capf and it doesn't expand snippets (eglot does it in the :exit-function).

Yes, it does. company-capf, in post-completion, calls :exit-function.

It does more than just snippets, by the way, like editing stuff around the newly inserted completion.

Yes. Like I said in the previous message. So simply avoiding calling post-completion is not an adequate solution for disabling snippet insertion. That is why we're looking for a different way to do that, for all backends.

I supposed a snippet-able backend would be something that would insert and expand snippets through company. That is, the user would select a completion that's maybe annotated like a snippet, and upon selecting it, a snippet expansion would happen. Is this not how it works today?

No, it's not.

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).

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, company-capf just skipped calling :exit-function? Would the result be acceptable? There are uses here saying that, at least for certain backends (mainly company-lsp), post-completion is necessary for completions to be inserted properly, snippets or not.

I think the miscommunication has been going on for a while. I'm trying to be as clear as possible, but unless you understand [...] I'm afraid it's going to be hard

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.

Can we ask a user to switch from Eglot to Sly?

I mentioned SLY because two exchanges ago you were very surprised when I mentioned backends that "potentially support snippets". But you countered:

"Potentially"? Those are basically all backends, right?

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 capf exclusively (and company via company-capf).

No, it's not.

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.

What if, with the current implementation, company-capf just skipped calling :exit-function? Would the result be acceptable?

Wouldn't it stop complying with the capf protocol? Given the company-capf name, that would be a misfeature at best.

post-completion is necessary for completions to be inserted properly, snippets or not.

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 capf so that company-capf can translate from one to the other.

Tell you what: the software packages I maintain use company-capf exclusively (and, tangentially, you're already well aware of my opinion that that should be the One Backend). Since you seem, very commendably in my view, intent on keeping backward compatibility, you can do whatever you think is better.

I'm sorry I couldn't be more helpful 👋

I was just reading company-yasnippet and it does seem like it expands snippets circa line 141

In post-completion, yes. Just like company-capf does, for Eglot and other completion functions.

Wouldn't it stop complying with the capf protocol?

I don't know. I imagine :exit-function wasn't originally conceived like something essential for completions being inserted correctly.

Given the company-capf name, that would be a misfeature at best.

It would be an option.

I suggested a new kind of special annotation for some completions, where backends could program special insertion behaviour.

That needs a:

  1. Name.
  2. Meaningful description of its semantics. Completion should work acceptably whether the special behavior is invoked or not.
  3. Some kind of backward compatibility policy or suggested approach. E.g. how would Emacs 26.1 work with completion functions that use this special annotation.

I also think that annotation should have a reciprocal in Emacs's own capf

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.

I don't know. I imagine :exit-function wasn't originally conceived like something essential for completions being inserted correctly.

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.

It would be an option.

So I use your "option" in company-blablabla and it works fine. One day I switch to Eglot or SLY or company-capf and it starts producing funny results and I don't know why... Seems like a misfeature to me.

That needs a: Name. Meaningful description of its semantics. Completion should work acceptably whether the special behavior is invoked or not.

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? capf would ignore them, obviously. But it would still honour exit-function, of course.

Ditto. Or else it wouldn't be accepted in Emacs. Or I don't think it would, at least.

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.

One day I switch to Eglot or SLY or company-capf and it starts producing funny results and I don't know why... Seems like a misfeature to me.

That's what I asked: could the result be acceptable? Apparently you think that it won't. OK.

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".

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 post-completion, or what the "text edits" do.

which might have more side effects than just textually inserting the completion candidate

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.

Trick question? capf would ignore them, obviously. But it would still honour exit-function, of course.

Wouldn't company-capf still need to honor exit-function anyway? If the expansion behavior is still present in exit-function (for compatibility with capf, say), company-capf won't function correctly.

I don't really know the behaviors that are enacted in post-completion, or what the "text edits" do.

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 capf client does.

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.

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.

If the expansion behavior is still present in exit-function (for compatibility with capf, say), company-capf won't function correctly.

Not necessarily: the capf client's exit-function could detect the situation and bail out if the expansion has already happened some other way, perhaps by reading a text-property.

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 capf client does.

I kind of do need to worry about that while naming things, at least. I think.

That's accurate, or accurate enough.

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.

(1) I don't want to make eglot read a company-specific variable to declare (non-)support for snippets

That's understandable.

So we can approach that from another side:

  • (maybe) add an eglot-specific varialbe, because most other backends already have one.
  • Try to standardize that by proposing a new variable in the core.

(2) I might still be interested in expanding them with other capf clients.

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.

Not necessarily: the capf client's exit-function could detect the situation and bail out if the expansion has already happened some other way, perhaps by reading a text-property.

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.

At lsp-mode side, we are getting a lot of bug reports

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.

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

Maybe company-tng could do that check instead: make sure that some known backends, if used, have the corresponding user options set accordingly.

You have a user option to disable snippets, right?

Yes, we do, my main concern is that it does not work out of the box and it generates false negatives.

Maybe company-tng could do that check instead: make sure that some known backends, if used, have the corresponding user options set accordingly.

Works for us.

Just for the record, IME users prefer to switch to another frontend instead of disabling the snippets.

Yes, we do, my main concern is that it does not work out of the box and it generates false negatives.

Another option would be for company-tng-configure-default so set this and similar variables. Which is probably the most sensible approach.

It won't save you from questions like "where are my snippets in completions", however.

Just for the record, IME users prefer to switch to another frontend instead of disabling the snippets

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 yas-minor-mode is on)? At least for now.

could you add an Eglot-specific variable to disable snippet expansion (even when yas-minor-mode is on)? At least for now.

Sure, I guess. Though I'd prefer, also as a temporary solution, some kind of add-function solution, since I think these problems as are kind of edge cases, and as such should be addressed with something slightly more complicated than a variable.

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 company-clang-insert-arguments (e.g. see #102). So it would make sense for Eglot to have one.

any simple recipe?

Using company-tng might be one.

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 company-tng-configure-default in your Emacs then try using company for completion. This setup is going to make sure post-completion callback in company-capf is not called, and hence no snippet expansion can be performed.

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 company-capf as my backend in lsp-mode, which populates my completions with snippets. I saw, early in this thread, that there was some discussion about creating a settable variable that would disable this behavior, which seemed reasonable; is there a reason this can't/shouldn't be done?

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 lsp-mode.

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 lsp-mode goes.