1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-21 06:55:39 +00:00

[Eglot] Stricter "expand common" behavior

* lisp/progmodes/eglot.el (eglot--dumb-tryc): Check that the
expanded string matches every completion strictly (bug#72705).
And in the fallback case, check whether the table matches the
original prefix at all.  Return nil otherwise.

* test/lisp/progmodes/eglot-tests.el
(eglot-test-stop-completion-on-nonprefix)
(eglot-test-try-completion-nomatch): Corresponding tests.

* etc/EGLOT-NEWS: New entry.
This commit is contained in:
Dmitry Gutov 2024-08-25 18:23:51 +03:00
parent 096730510c
commit 713069dd7a
3 changed files with 48 additions and 2 deletions

View File

@ -36,6 +36,12 @@ documentation snippets.
These affect mostly the "vanilla" frontend to completions (invoked with
C-M-i).
** More strict completion expansion (bug#72705).
It ensures that "expand common" commands (such as C-M-i or TAB in
third-party frontends) don't result in fewer completions than before
they are called.
** Experimental support for Eglot-only subprojects (github#1337)
Useful for complex projects with subprojects needing different language

View File

@ -3149,8 +3149,18 @@ for which LSP on-type-formatting should be requested."
(defun eglot--dumb-tryc (pat table pred point)
(let ((probe (funcall table pat pred nil)))
(cond ((eq probe t) t)
(probe (cons probe (length probe)))
(t (cons pat point)))))
(probe
(if (and (not (equal probe pat))
(cl-every
(lambda (s) (string-prefix-p probe s completion-ignore-case))
(funcall table pat pred t)))
(cons probe (length probe))
(cons pat point)))
(t
;; Match ignoring suffix: if there are any completions for
;; the current prefix at least, keep the current input.
(and (funcall table (substring pat 0 point) pred t)
(cons pat point))))))
(add-to-list 'completion-category-defaults '(eglot-capf (styles eglot--dumb-flex)))
(add-to-list 'completion-styles-alist '(eglot--dumb-flex eglot--dumb-tryc eglot--dumb-allc))

View File

@ -645,6 +645,36 @@ directory hierarchy."
(forward-line -1)
(should (looking-at "Complete, but not unique")))))))
(ert-deftest eglot-test-stop-completion-on-nonprefix ()
"Test completion also resulting in 'Complete, but not unique'."
(skip-unless (executable-find "clangd"))
(eglot--with-fixture
`(("project" . (("coiso.c" .
,(concat "int foot; int footer; int fo_obar;"
"int main() {foo")))))
(with-current-buffer
(eglot--find-file-noselect "project/coiso.c")
(eglot--wait-for-clangd)
(goto-char (point-max))
(completion-at-point)
(should (looking-back "foo")))))
(ert-deftest eglot-test-try-completion-nomatch ()
"Test completion table with non-matching input, returning nil."
(skip-unless (executable-find "clangd"))
(eglot--with-fixture
`(("project" . (("coiso.c" .
,(concat "int main() {abc")))))
(with-current-buffer
(eglot--find-file-noselect "project/coiso.c")
(eglot--wait-for-clangd)
(goto-char (point-max))
(should
(null
(completion-try-completion
"abc"
(nth 2 (eglot-completion-at-point)) nil 3))))))
(ert-deftest eglot-test-try-completion-inside-symbol ()
"Test completion table inside symbol, with only prefix matching."
(skip-unless (executable-find "clangd"))