Unexpected completion auto-insertion
Description of the bug
Here I'm selecting null in a JSON file and pressing " to surround it with quotes.
After quotes are inserted, completions are requested and an LSP server responds with a single completion that suggests a null completion that gets automatically applied:
https://user-images.githubusercontent.com/153197/196772615-9ad7a949-b76c-439f-bc58-f2bc34129989.mov
Steps to reproduce
I haven't bothered creating small repro since I think this seems like a consequence of recent change that automatically applies completions when there is only one result.
Expected behavior
I think this is a case where single completion should not be auto-applied. Not sure if this case could be differentiated from "normal" cases and treated differently...
Actual behavior
Single completions interferes with the intent of adding quotes.
Sublime Text build number
4138
Operating system & version
macOS
(Linux) Desktop environment and/or window manager
No response
Additional information
No response
OpenGL context information
No response
I thought that removing null and adding quotes would work but server still suggests null and it's automatically inserted:
https://user-images.githubusercontent.com/153197/196774265-ad4393d2-279f-4616-ae11-897789864847.mov
In light of such cases, it feels like it's not really correct to auto-insert single completions because there is no guarantee that user wants to actually insert that specific completion or just write something else...
I suppose related: https://github.com/sublimehq/sublime_text/issues/4421
It looks like that issue was misunderstood (not sure if by developer or the reporter but @jwortmann got it right in https://github.com/sublimehq/sublime_text/issues/4421#issuecomment-856805966) because it never seemed to behave in ST3 like it behaves now. ST3 would not insert the completion automatically. It would still show the popup when there was only one completion.
The part that was not working in ST4 was the case of manually pressing ctrl+space which did not insert the completion automatically anymore.
This is how it works in ST3:
https://user-images.githubusercontent.com/153197/196777015-ca9e991a-32f8-41c1-961f-7b82120b2ba6.mov
The part that was not working in ST4 was the case of manually pressing ctrl+space which did not insert the completion automatically anymore.
Don't think this statement is very correct.
In ST3 you can enter html and hit tab to directly insert the one and only available completion/snippet (insert_best_completion is called). The result is <html>|</html>.
This behavior was broken by ST4. The completion popup is displayed instead. To commit the one and only item requires another tab.
With ST4138 the old behavior of insert_best_completion is restored.
Without having investigated it, may the described issue be triggered by how and when LSP triggers auto_complete command or by the auto_complete_selector and/or auto_complete_triggers it adds for certain languages?
EDIT:
Just installed LSP-pylsp. Can insert quotes around null with LSP-json enabled normally in ST4138 on Windows.
In ST3 you can enter
htmland hit tab to directly insert the one and only available completion/snippet (insert_best_completionis called). The result is<html>|</html>.
Note how in ST3 it only expands on tab if the text matches html exactly and not when text is htm, even though ctrl+space still works to expand. So maybe ST3 considers it "best" only when the prefix matches exactly (in this case snippet).
EDIT: So in ST3 tab triggers insert_best_completion and requires that the prefix is matched exactly.
ctrl+space triggers auto_complete and also auto-inserts but only if there is one completion.
With ST4138 the old behavior of
insert_best_completionis restored.
I think that in 4138 it works "by accident" because the functionality is overzealous.
In any case, I guess the initial statement could be changed to say that this functionality should only be triggered when explicitly triggered by the user (using tab or ctrl+space) and not just on typing.
Yes, html is the tab trigger for the html.sublime-snippet. ST3 seems to hide the html completion as there is a snippet with exectly the same tab trigger. Not sure, whether this is intented or a bug.
Nevertheless, html is expanded on perfect match only as the snippet is the only candidate.
If you try the same with e.g. table you'll see you can enter tabl hit tab key and it gets expanded to <table></table> directly.
I agree with the final statement. But tbh, this is what I see on my end. ST doesn't commit single completions while typing - at least when trying static sublime-completions or even PackageDev's or HTML's completion plugins. Hence I wonder whether and how it might be related or caused by how LSP handles completions.
EDIT:
In your example of surrounding null with quotes the following output is generated as soon as " is typed.
command: insert_snippet {"contents": "\"${0:$SELECTION}\""}
command: auto_complete
command: insert_snippet {"contents": "null"}
By default - with LSP disabled - only the insert_snippet command is inserted and everything is fine.
LSP seems to actively invoke auto_complete command, which is also executed by hitting ctrl+space. ST sees an explicit call and commits the one and only candidate.
Hence I'd blame LSP to cause the fault behavior by calling auto_complete explicitly.
Even after removing all tab triggers/selectors by ...
view.settings().set("auto_complete_selector", "")
view.settings().set("auto_complete_triggers", [])
... typing " still triggers auto_complete command after insert_snippet, which doesn't happen without LSP.
...
Wait ... it seems to be caused by LSP-json....
The issue is caused by LSP-json
https://github.com/sublimelsp/LSP-json/blob/12f3548217f64c33f9196c38c8dc972571f6463e/plugin.py#L82-L87
which invokes auto_complete when typing "".
So I'd close this one as "invalid".
Good point. I forgot about that...
I suppose it might be invalid then.
I've checked ST3 in a similar situation and it seems to only auto-insert single completion on second try for some reason but it feels buggy so hard to use it as an argument...
Completions that have TextEdits(LSP-json uses text edits) are not implemented correctly in LSP for ST3... I would not even try to use LSP on ST3.
ST 4139 extends the auto_complete command by an "commit_single": true argument to control, whether the command should auto commit a single completion candidate. This should fix this issue and maintain backward compatibility with plugins using it to force displaying auto completion panel.
@deathaxe commit_single: true seems to only work for me if tab_completion is also true; I thought tab_completion was used only in the context of some default keybindings but that doesn't seem to be the case
The difference between tab_completion: false and true is just whether a snippet's trigger must be fully entered or not to be directly committed.
In HTML for instance:
- with
tab_completion: falsehtmlneeds to be entered fortabto expand the html snippet - with
tab_completion: truehtis enough fortabto expand the html snippet
@deathaxe the issue I have with this is tab_completion apparently has nothing to to with the tab key (except for being used in the context field of the key bindings); I have a ctrl+space key binding for auto_complete command being affected by this setting, which doesn't sound right. I thought adding commit_single would be enough to enable the "auto commit on single suggestion" behavior
This sounds like a separate issue to me. Maybe you should open a new issue with some code examples and steps to reproduce the issue.
I tried some syntaxes and a single tab is very much enough to directly commit a single completion. But maybe I am missing some relevant detail.
EDIT: The only difference being tab_completion expanding "snippets" only - not completions.
Fixed in Build 4139