mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-21 06:55:39 +00:00
Merge from origin/emacs-30
9b299dd79c
Revert a recent change that caused redisplay slowdown4eaab54896
; * doc/lispref/display.texi (Low-Level Font): Fix wordin...0a50019308
Indent ERT failure explanations rigidly713069dd7a
[Eglot] Stricter "expand common" behavior096730510c
eglot-tests.el: New tests for existing completion behavior969498c25d
Remove dangerous HTML edit from admin.el # Conflicts: # etc/EGLOT-NEWS
This commit is contained in:
commit
d4bd5a3cba
@ -613,9 +613,7 @@ style=\"text-align:left\">")
|
|||||||
;; item is not there anymore. So for HTML manuals produced by
|
;; item is not there anymore. So for HTML manuals produced by
|
||||||
;; those newer versions of Texinfo we punt and leave the menu in
|
;; those newer versions of Texinfo we punt and leave the menu in
|
||||||
;; its original form.
|
;; its original form.
|
||||||
(when (or (search-forward "<ul class=\"menu\">" nil t)
|
(when (or (search-forward "<ul class=\"menu\">" nil t))
|
||||||
;; FIXME? The following search seems dangerously lax.
|
|
||||||
(search-forward "<ul>" nil t))
|
|
||||||
;; Convert the list that Makeinfo made into a table.
|
;; Convert the list that Makeinfo made into a table.
|
||||||
(replace-match "<table style=\"float:left\" width=\"100%\">")
|
(replace-match "<table style=\"float:left\" width=\"100%\">")
|
||||||
(forward-line 1)
|
(forward-line 1)
|
||||||
|
@ -4374,9 +4374,10 @@ should be equal to the value of @var{height} above.
|
|||||||
The width, in pixels, of the font's space character.
|
The width, in pixels, of the font's space character.
|
||||||
|
|
||||||
@item average-width
|
@item average-width
|
||||||
The average width of the font characters. If this is zero, Emacs uses
|
The average width of the font characters. Emacs uses this for
|
||||||
the value of @var{space-width} instead, when it calculates text layout
|
calculating text layout on display; if the value of @var{average-width}
|
||||||
on display.
|
is zero, Emacs uses the value of @var{space-width} instead for those
|
||||||
|
purposes.
|
||||||
|
|
||||||
@item filename
|
@item filename
|
||||||
The file name of the font as a string. This can be @code{nil} if the
|
The file name of the font as a string. This can be @code{nil} if the
|
||||||
|
@ -26,6 +26,36 @@ Eglot will now try to not register $/progress messages from the server
|
|||||||
when the defcustom is set to nil. This requires a restart of the server
|
when the defcustom is set to nil. This requires a restart of the server
|
||||||
for the change to take effect.
|
for the change to take effect.
|
||||||
|
|
||||||
|
** LSP MarkedString interface is now supported (bug#71353)
|
||||||
|
|
||||||
|
Some servers still use this deprecated interface for communicating
|
||||||
|
documentation snippets.
|
||||||
|
|
||||||
|
** Fixes to completion logic (bug#68699, github#1339, github#1349)
|
||||||
|
|
||||||
|
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
|
||||||
|
servers. See associated github issue
|
||||||
|
https://github.com/joaotavora/eglot/discussions/1337 for examples.
|
||||||
|
|
||||||
|
** New servers have been added to 'eglot-server-programs'.
|
||||||
|
|
||||||
|
- blueprint (bug#70015)
|
||||||
|
- BasedPyright (bug#69925)
|
||||||
|
- move-analyzer (bug#69796)
|
||||||
|
- millet
|
||||||
|
- nushell (bug#68823)
|
||||||
|
|
||||||
|
|
||||||
* Changes in Eglot 1.17 (25/1/2024)
|
* Changes in Eglot 1.17 (25/1/2024)
|
||||||
|
|
||||||
|
@ -1317,13 +1317,12 @@ empty string."
|
|||||||
"Pretty-print OBJECT, indenting it to the current column of point.
|
"Pretty-print OBJECT, indenting it to the current column of point.
|
||||||
Ensures a final newline is inserted."
|
Ensures a final newline is inserted."
|
||||||
(let ((begin (point))
|
(let ((begin (point))
|
||||||
|
(cols (current-column))
|
||||||
(pp-escape-newlines t)
|
(pp-escape-newlines t)
|
||||||
(print-escape-control-characters t))
|
(print-escape-control-characters t))
|
||||||
(pp object (current-buffer))
|
(pp object (current-buffer))
|
||||||
(unless (bolp) (insert "\n"))
|
(unless (bolp) (insert "\n"))
|
||||||
(save-excursion
|
(indent-rigidly begin (point) cols)))
|
||||||
(goto-char begin)
|
|
||||||
(indent-sexp))))
|
|
||||||
|
|
||||||
(defun ert--insert-infos (result)
|
(defun ert--insert-infos (result)
|
||||||
"Insert `ert-info' infos from RESULT into current buffer.
|
"Insert `ert-info' infos from RESULT into current buffer.
|
||||||
|
@ -3142,8 +3142,18 @@ for which LSP on-type-formatting should be requested."
|
|||||||
(defun eglot--dumb-tryc (pat table pred point)
|
(defun eglot--dumb-tryc (pat table pred point)
|
||||||
(let ((probe (funcall table pat pred nil)))
|
(let ((probe (funcall table pat pred nil)))
|
||||||
(cond ((eq probe t) t)
|
(cond ((eq probe t) t)
|
||||||
(probe (cons probe (length probe)))
|
(probe
|
||||||
(t (cons pat point)))))
|
(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-category-defaults '(eglot-capf (styles eglot--dumb-flex)))
|
||||||
(add-to-list 'completion-styles-alist '(eglot--dumb-flex eglot--dumb-tryc eglot--dumb-allc))
|
(add-to-list 'completion-styles-alist '(eglot--dumb-flex eglot--dumb-tryc eglot--dumb-allc))
|
||||||
|
@ -736,11 +736,6 @@ recompute_basic_faces (struct frame *f)
|
|||||||
clear_face_cache (false);
|
clear_face_cache (false);
|
||||||
if (!realize_basic_faces (f))
|
if (!realize_basic_faces (f))
|
||||||
emacs_abort ();
|
emacs_abort ();
|
||||||
/* Force complete face recalculation next time we use the display
|
|
||||||
code, because realize_basic_faces could free the fontset used
|
|
||||||
by non-ASCII faces corresponding to ASCII faces of the basic
|
|
||||||
faces, and attempt to use that fontset might segfault. */
|
|
||||||
f->face_change = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,6 +876,60 @@ This macro is used to test if macroexpansion in `should' works."
|
|||||||
(should (eq (ert--get-explainer 'string-equal) 'ert--explain-string-equal))
|
(should (eq (ert--get-explainer 'string-equal) 'ert--explain-string-equal))
|
||||||
(should (eq (ert--get-explainer 'string=) 'ert--explain-string-equal)))
|
(should (eq (ert--get-explainer 'string=) 'ert--explain-string-equal)))
|
||||||
|
|
||||||
|
(ert-deftest ert--pp-with-indentation-and-newline ()
|
||||||
|
:tags '(:causes-redisplay)
|
||||||
|
(let ((failing-test (make-ert-test
|
||||||
|
:name 'failing-test
|
||||||
|
:body (lambda ()
|
||||||
|
(should (equal '((:one "1" :three "3" :two "2"))
|
||||||
|
'((:one "1")))))))
|
||||||
|
(want-body "\
|
||||||
|
Selector: <failing-test>
|
||||||
|
Passed: 0
|
||||||
|
Failed: 1 (1 unexpected)
|
||||||
|
Skipped: 0
|
||||||
|
Total: 1/1
|
||||||
|
|
||||||
|
Started at: @@TIMESTAMP@@
|
||||||
|
Finished.
|
||||||
|
Finished at: @@TIMESTAMP@@
|
||||||
|
|
||||||
|
F
|
||||||
|
|
||||||
|
F failing-test
|
||||||
|
(ert-test-failed
|
||||||
|
((should (equal '((:one \"1\" :three \"3\" :two \"2\")) '((:one \"1\"))))
|
||||||
|
:form (equal ((:one \"1\" :three \"3\" :two \"2\")) ((:one \"1\"))) :value
|
||||||
|
nil :explanation
|
||||||
|
(list-elt 0
|
||||||
|
(proper-lists-of-different-length 6 2
|
||||||
|
(:one \"1\" :three \"3\"
|
||||||
|
:two \"2\")
|
||||||
|
(:one \"1\")
|
||||||
|
first-mismatch-at 2))))
|
||||||
|
\n\n")
|
||||||
|
(want-msg "Ran 1 tests, 0 results were as expected, 1 unexpected")
|
||||||
|
(buffer-name (generate-new-buffer-name " *ert-test-run-tests*")))
|
||||||
|
(cl-letf* ((ert-debug-on-error nil)
|
||||||
|
(ert--output-buffer-name buffer-name)
|
||||||
|
(messages nil)
|
||||||
|
((symbol-function 'message)
|
||||||
|
(lambda (format-string &rest args)
|
||||||
|
(push (apply #'format format-string args) messages)))
|
||||||
|
((symbol-function 'ert--format-time-iso8601)
|
||||||
|
(lambda (_) "@@TIMESTAMP@@")))
|
||||||
|
(save-window-excursion
|
||||||
|
(unwind-protect
|
||||||
|
(let ((fill-column 70))
|
||||||
|
(ert-run-tests-interactively failing-test)
|
||||||
|
(should (equal (list want-msg) messages))
|
||||||
|
(should (equal (string-replace "\t" " "
|
||||||
|
(with-current-buffer buffer-name
|
||||||
|
(buffer-string)))
|
||||||
|
want-body)))
|
||||||
|
(when noninteractive
|
||||||
|
(kill-buffer buffer-name)))))))
|
||||||
|
|
||||||
(provide 'ert-tests)
|
(provide 'ert-tests)
|
||||||
|
|
||||||
;;; ert-tests.el ends here
|
;;; ert-tests.el ends here
|
||||||
|
@ -587,6 +587,18 @@ directory hierarchy."
|
|||||||
(eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
|
(eglot--wait-for (s-notifs 20) (&key method &allow-other-keys)
|
||||||
(string= method "textDocument/publishDiagnostics"))))
|
(string= method "textDocument/publishDiagnostics"))))
|
||||||
|
|
||||||
|
(defun eglot--wait-for-rust-analyzer ()
|
||||||
|
(eglot--sniffing (:server-notifications s-notifs)
|
||||||
|
(should (eglot--tests-connect))
|
||||||
|
(eglot--wait-for (s-notifs 20) (&key method params &allow-other-keys)
|
||||||
|
(and
|
||||||
|
(string= method "$/progress")
|
||||||
|
"rustAnalyzer/Indexing"
|
||||||
|
(equal params
|
||||||
|
'(:token "rustAnalyzer/Indexing" :value
|
||||||
|
;; Could wait for :kind "end" instead, but it's 2 more seconds.
|
||||||
|
(:kind "begin" :title "Indexing" :cancellable :json-false :percentage 0)))))))
|
||||||
|
|
||||||
(ert-deftest eglot-test-basic-completions ()
|
(ert-deftest eglot-test-basic-completions ()
|
||||||
"Test basic autocompletion in a clangd LSP."
|
"Test basic autocompletion in a clangd LSP."
|
||||||
(skip-unless (executable-find "clangd"))
|
(skip-unless (executable-find "clangd"))
|
||||||
@ -600,6 +612,20 @@ directory hierarchy."
|
|||||||
(message (buffer-string))
|
(message (buffer-string))
|
||||||
(should (looking-back "fprintf.?")))))
|
(should (looking-back "fprintf.?")))))
|
||||||
|
|
||||||
|
(ert-deftest eglot-test-common-prefix-completion ()
|
||||||
|
"Test completion appending the common prefix."
|
||||||
|
(skip-unless (executable-find "clangd"))
|
||||||
|
(eglot--with-fixture
|
||||||
|
`(("project" . (("coiso.c" .
|
||||||
|
,(concat "int foo_bar; int foo_bar_baz;"
|
||||||
|
"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_bar")))))
|
||||||
|
|
||||||
(ert-deftest eglot-test-non-unique-completions ()
|
(ert-deftest eglot-test-non-unique-completions ()
|
||||||
"Test completion resulting in 'Complete, but not unique'."
|
"Test completion resulting in 'Complete, but not unique'."
|
||||||
(skip-unless (executable-find "clangd"))
|
(skip-unless (executable-find "clangd"))
|
||||||
@ -619,6 +645,88 @@ directory hierarchy."
|
|||||||
(forward-line -1)
|
(forward-line -1)
|
||||||
(should (looking-at "Complete, but not unique")))))))
|
(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"))
|
||||||
|
(eglot--with-fixture
|
||||||
|
`(("project" . (("coiso.c" .
|
||||||
|
,(concat
|
||||||
|
"int foobar;"
|
||||||
|
"int main() {foo123")))))
|
||||||
|
(with-current-buffer
|
||||||
|
(eglot--find-file-noselect "project/coiso.c")
|
||||||
|
(eglot--wait-for-clangd)
|
||||||
|
(goto-char (- (point-max) 3))
|
||||||
|
(when (buffer-live-p "*Completions*")
|
||||||
|
(kill-buffer "*Completions*"))
|
||||||
|
(completion-at-point)
|
||||||
|
(should (looking-back "foo"))
|
||||||
|
(should (looking-at "123"))
|
||||||
|
(should (get-buffer "*Completions*"))
|
||||||
|
)))
|
||||||
|
|
||||||
|
(ert-deftest eglot-test-rust-completion-exit-function ()
|
||||||
|
"Ensure that the rust-analyzer exit function creates the expected contents."
|
||||||
|
(skip-unless (executable-find "rust-analyzer"))
|
||||||
|
(skip-unless (executable-find "cargo"))
|
||||||
|
(eglot--with-fixture
|
||||||
|
'(("cmpl-project" .
|
||||||
|
(("main.rs" .
|
||||||
|
"fn test() -> i32 { let v: usize = 1; v.count_on1234.1234567890;"))))
|
||||||
|
(with-current-buffer
|
||||||
|
(eglot--find-file-noselect "cmpl-project/main.rs")
|
||||||
|
(should (zerop (shell-command "cargo init")))
|
||||||
|
(eglot--tests-connect)
|
||||||
|
(goto-char (point-min))
|
||||||
|
(search-forward "v.count_on")
|
||||||
|
(let ((minibuffer-message-timeout 0)
|
||||||
|
;; Fail at (ding) if completion fails.
|
||||||
|
(executing-kbd-macro t))
|
||||||
|
(when (buffer-live-p "*Completions*")
|
||||||
|
(kill-buffer "*Completions*"))
|
||||||
|
;; The design is pretty brittle, we'll need to monitor the
|
||||||
|
;; language server for changes in behavior.
|
||||||
|
(eglot--wait-for-rust-analyzer)
|
||||||
|
(completion-at-point)
|
||||||
|
(should (looking-back "\\.count_on"))
|
||||||
|
(should (get-buffer "*Completions*"))
|
||||||
|
(minibuffer-next-completion 1)
|
||||||
|
(minibuffer-choose-completion t))
|
||||||
|
(should
|
||||||
|
(equal
|
||||||
|
"fn test() -> i32 { let v: usize = 1; v.count_ones().1234567890;"
|
||||||
|
(buffer-string))))))
|
||||||
|
|
||||||
(ert-deftest eglot-test-basic-xref ()
|
(ert-deftest eglot-test-basic-xref ()
|
||||||
"Test basic xref functionality in a clangd LSP."
|
"Test basic xref functionality in a clangd LSP."
|
||||||
(skip-unless (executable-find "clangd"))
|
(skip-unless (executable-find "clangd"))
|
||||||
|
Loading…
Reference in New Issue
Block a user