From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Spencer Baugh Newsgroups: gmane.emacs.devel Subject: Eglot cannot work with default completion-in-region? Date: Fri, 26 Jan 2024 15:38:29 -0500 Message-ID: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="28641"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: joaotavora@gmail.com To: emacs-devel@gnu.org Cancel-Lock: sha1:7u0LnSK3vY0CPecoHqtixHPgZAY= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Jan 27 07:33:30 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rTcFt-0007E3-UB for ged-emacs-devel@m.gmane-mx.org; Sat, 27 Jan 2024 07:33:29 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rTcFI-0003Qg-K4; Sat, 27 Jan 2024 01:32:52 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rTSyK-0008Sj-Bk for emacs-devel@gnu.org; Fri, 26 Jan 2024 15:38:44 -0500 Original-Received: from ciao.gmane.io ([116.202.254.214]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rTSyI-0007nC-JJ for emacs-devel@gnu.org; Fri, 26 Jan 2024 15:38:44 -0500 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1rTSyF-00023J-4R for emacs-devel@gnu.org; Fri, 26 Jan 2024 21:38:39 +0100 X-Injected-Via-Gmane: http://gmane.org/ Received-SPF: pass client-ip=116.202.254.214; envelope-from=ged-emacs-devel@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Sat, 27 Jan 2024 01:32:51 -0500 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:315465 Archived-At: Hi, The recent commit d376462c7183752bf44b9bd20bf5020fe7eaf75a prompted by issue https://github.com/joaotavora/eglot/issues/1339 says: >I declare it impossible to make C-M-i use of 'try-completion' behave >sanely with LSP in its current state. YMMV. Use a completion tooltip, >like Company. So completion from Eglot, which is built into Emacs, is broken out of the box? It has a hard dependency on using company-mode or similar third-party packages? If this is the case, perhaps Eglot should make it more clear that it cannot be used without also installing and using company-mode or some other package. Perhaps it should abort rather than running if the user is using the default completion-in-region. Alternatively, as someone who uses default completion-in-region and would like to use Eglot, is there some way to make the common case behave correctly? I guess the issue is that in the LSP protocol, there's a difference between the "sortText" and "filterText" which are used for displaying completions and letting the user choose them, and the "insertText"/"textEdit" which are used for inserting them. So Eglot has this somewhat hacky code which runs in :exit-function to delete the completion after completion-in-region inserts it, and insert a different string instead: (cond (textEdit ;; Revert buffer back to state when the edit ;; was obtained from server. If a `proxy' ;; "bar" was obtained from a buffer with ;; "foo.b", the LSP edit applies to that ;; state, _not_ the current "foo.bar". (delete-region orig-pos (point)) (insert (substring bounds-string (- orig-pos (car bounds)))) (eglot--dbind ((TextEdit) range newText) textEdit (pcase-let ((`(,beg . ,end) (eglot-range-region range))) (delete-region beg end) (goto-char beg) (funcall (or snippet-fn #'insert) newText)))) (snippet-fn ;; A snippet should be inserted, but using plain ;; `insertText'. This requires us to delete the ;; whole completion, since `insertText' is the full ;; completion's text. (delete-region (- (point) (length proxy)) (point)) (funcall snippet-fn (or insertText label)))) This is code which is often broken, especially with default completion-in-region. However, the common case is that sortText==insertText/textEdit. In that case, this code is not necessary, and Eglot doesn't need an :exit-function at all. Can Eglot detect this and avoid this somewhat hacky code in that case? It should be a performance improvement and simplification anyway for all completion frameworks. (BTW, besides the issue with default completion-in-region, I also ran into this while trying to write an OCaml-specific wrapper for eglot-completion-at-point function which adds some additional completions to those returned from the LSP. But if those completions are chosen, then the Eglot exit-function breaks when it tries to look up the insertText/textEdit. My LSP doesn't use textEdit at all, though, so this is another unnecessary breakage)