From 9d3fdf7e0d4c9355b2466aca51938291ea4e26c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Thu, 16 Mar 2023 10:45:25 +0000 Subject: [PATCH 01/15] Fix Eglot's command generation for code actions The user command generated by eglot--code-action should always call eglot-code-actions with a INTERACTIVE set to t. Reported in https://github.com/joaotavora/eglot/issues/1132. * lisp/progmodes/eglot.el (eglot--code-action): Pass INTERACTIVE=t to eglot-code-action call. --- lisp/progmodes/eglot.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 4448c4a01fc..5c61a444fd3 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3371,7 +3371,7 @@ at point. With prefix argument, prompt for ACTION-KIND." `(defun ,name (beg &optional end) ,(format "Execute `%s' code actions between BEG and END." kind) (interactive (eglot--region-bounds)) - (eglot-code-actions beg end ,kind))) + (eglot-code-actions beg end ,kind t))) (eglot--code-action eglot-code-action-organize-imports "source.organizeImports") (eglot--code-action eglot-code-action-extract "refactor.extract") From dfb36d362304f7459e7171327481d55a0b3943b2 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 16 Mar 2023 14:20:15 +0100 Subject: [PATCH 02/15] Refer to EWW instead of w3 and w3m * doc/misc/idlwave.texi (Help with HTML Documentation): Refer to EWW instead of w3 and w3m. --- doc/misc/idlwave.texi | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/misc/idlwave.texi b/doc/misc/idlwave.texi index 3ec07fb4a50..10fc4c85c7b 100644 --- a/doc/misc/idlwave.texi +++ b/doc/misc/idlwave.texi @@ -1372,10 +1372,9 @@ among, with differing advantages and disadvantages. The variable to (as long as @code{idlwave-help-use-assistant} is not set). This function is used to set the variable @code{browse-url-browser-function} locally for IDLWAVE help only. Customize the latter variable to see -what choices of browsers your system offers. Certain browsers like -@code{w3} (bundled with many versions of Emacs) and @code{w3m} -(@uref{http://emacs-w3m.namazu.org/}) are run within Emacs, and use -Emacs buffers to display the HTML help. This can be convenient, +what choices of browsers your system offers. Certain browsers like EWW +(@pxref{Top, EWW,, eww, The Emacs Web Wowser Manual}) are run within Emacs, +and use Emacs buffers to display the HTML help. This can be convenient, especially on small displays, and images can even be displayed in-line on newer Emacs versions. However, better formatting results are often achieved with external browsers, like Mozilla. IDLWAVE assumes any From 1961bdb52edc3c0b96fe9e479ea2d9da1f76b14c Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 16 Mar 2023 14:32:44 +0100 Subject: [PATCH 03/15] ; Add WebDAV entry to index in Tramp manual * doc/misc/tramp.texi (GVFS-based methods): Improve indexing. --- doc/misc/tramp.texi | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 56436d32970..cbd8d202650 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -1236,6 +1236,7 @@ syntax requires a leading volume (share) name, for example: @item @option{dav} @item @option{davs} +@cindex WebDAV @cindex method @option{dav} @cindex method @option{davs} @cindex @option{dav} method From 7385c991dff3466b37cf50628e7685cd53e71921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Thu, 16 Mar 2023 14:05:42 +0000 Subject: [PATCH 04/15] Also exempt eglot-inlay-hints-mode from desktop.el's fumblings Reported in https://github.com/joaotavora/eglot/discussions/1183. * lisp/progmodes/eglot.el (desktop): Also exempt eglot-inlay-hints-mode from desktop.el fumblings. --- lisp/progmodes/eglot.el | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 5c61a444fd3..52bba717a67 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -3654,13 +3654,11 @@ If NOERROR, return predicate, else erroring function." ;;; Hacks ;;; -;; FIXME: Although desktop.el compatibility is Emacs bug#56407, the -;; optimal solution agreed to there is a bit more work than what I -;; have time to right now. See -;; e.g. https://debbugs.gnu.org/cgi/bugreport.cgi?bug=bug%2356407#68. -;; For now, just use `with-eval-after-load' +;; Emacs bug#56407, the optimal solution is in desktop.el, but that's +;; harder. For now, use `with-eval-after-load'. See also github#1183. (with-eval-after-load 'desktop - (add-to-list 'desktop-minor-mode-handlers '(eglot--managed-mode . ignore))) + (add-to-list 'desktop-minor-mode-handlers '(eglot--managed-mode . ignore)) + (add-to-list 'desktop-minor-mode-handlers '(eglot-inlay-hints-mode . ignore))) ;;; Misc From 5cf1de683b2414927e521c34daeee460fb7649f5 Mon Sep 17 00:00:00 2001 From: kobarity Date: Sun, 12 Mar 2023 17:05:54 +0900 Subject: [PATCH 05/15] Fix python-fill-paragraph problems on filling strings (bug#62142) * lisp/progmodes/python.el (python-syntax--context-compiler-macro) (python-syntax-context): Add single-quoted-string and triple-quoted-string as TYPE argument. (python-info-triple-quoted-string-p): New helper function. (python-fill-paragraph) (python-fill-string): Use it. * test/lisp/progmodes/python-tests.el (python-syntax-context-1) (python-fill-paragraph-single-quoted-string-1) (python-fill-paragraph-single-quoted-string-2) (python-fill-paragraph-triple-quoted-string-1) (python-info-triple-quoted-string-p-1) (python-info-triple-quoted-string-p-2) (python-info-triple-quoted-string-p-3): New tests. --- lisp/progmodes/python.el | 35 ++++++-- test/lisp/progmodes/python-tests.el | 119 ++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+), 8 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 8793fdc6458..2fe88323c35 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -511,19 +511,28 @@ This variant of `rx' supports common Python named REGEXPS." (''string `(let ((ppss (or ,syntax-ppss (syntax-ppss)))) (and (nth 3 ppss) (nth 8 ppss)))) + (''single-quoted-string + `(let ((ppss (or ,syntax-ppss (syntax-ppss)))) + (and (characterp (nth 3 ppss)) (nth 8 ppss)))) + (''triple-quoted-string + `(let ((ppss (or ,syntax-ppss (syntax-ppss)))) + (and (eq t (nth 3 ppss)) (nth 8 ppss)))) (''paren `(nth 1 (or ,syntax-ppss (syntax-ppss)))) (_ form)))) (defun python-syntax-context (type &optional syntax-ppss) "Return non-nil if point is on TYPE using SYNTAX-PPSS. -TYPE can be `comment', `string' or `paren'. It returns the start +TYPE can be `comment', `string', `single-quoted-string', +`triple-quoted-string' or `paren'. It returns the start character address of the specified TYPE." (declare (compiler-macro python-syntax--context-compiler-macro)) (let ((ppss (or syntax-ppss (syntax-ppss)))) (pcase type ('comment (and (nth 4 ppss) (nth 8 ppss))) ('string (and (nth 3 ppss) (nth 8 ppss))) + ('single-quoted-string (and (characterp (nth 3 ppss)) (nth 8 ppss))) + ('triple-quoted-string (and (eq t (nth 3 ppss)) (nth 8 ppss))) ('paren (nth 1 ppss)) (_ nil)))) @@ -4805,9 +4814,7 @@ Optional argument JUSTIFY defines if the paragraph should be justified." ((python-syntax-context 'comment) (funcall python-fill-comment-function justify)) ;; Strings/Docstrings - ((save-excursion (or (python-syntax-context 'string) - (equal (string-to-syntax "|") - (syntax-after (point))))) + ((python-info-triple-quoted-string-p) (funcall python-fill-string-function justify)) ;; Decorators ((equal (char-after (save-excursion @@ -4833,10 +4840,7 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'." (let* ((str-start-pos (set-marker (make-marker) - (or (python-syntax-context 'string) - (and (equal (string-to-syntax "|") - (syntax-after (point))) - (point))))) + (python-info-triple-quoted-string-p))) ;; JT@2021-09-21: Since bug#49518's fix this will always be 1 (num-quotes (python-syntax-count-quotes (char-after str-start-pos) str-start-pos)) @@ -6043,6 +6047,21 @@ point's current `syntax-ppss'." ((python-info-looking-at-beginning-of-defun)) (t nil)))))) +(defun python-info-triple-quoted-string-p () + "Check if point is in a triple quoted string including quotes. +It returns the position of the third quote character of the start +of the string." + (save-excursion + (let ((pos (point))) + (cl-loop + for offset in '(0 3 -2 2 -1 1) + if (let ((check-pos (+ pos offset))) + (and (>= check-pos (point-min)) + (<= check-pos (point-max)) + (python-syntax-context + 'triple-quoted-string (syntax-ppss check-pos)))) + return it)))) + (defun python-info-encoding-from-cookie () "Detect current buffer's encoding from its coding cookie. Returns the encoding as a symbol." diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index e5a9d128bc5..ed4a08da6ab 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -255,6 +255,27 @@ aliqua." ;;; Font-lock and syntax +(ert-deftest python-syntax-context-1 () + (python-tests-with-temp-buffer + " +# Comment +s = 'Single Quoted String' +t = '''Triple Quoted String''' +p = (1 + 2) +" + (python-tests-look-at "Comment") + (should (= (python-syntax-context 'comment) (pos-bol))) + (python-tests-look-at "Single") + (should (= (python-syntax-context 'string) (1- (point)))) + (should (= (python-syntax-context 'single-quoted-string) (1- (point)))) + (should-not (python-syntax-context 'triple-quoted-string)) + (python-tests-look-at "Triple") + (should (= (python-syntax-context 'string) (1- (point)))) + (should-not (python-syntax-context 'single-quoted-string)) + (should (= (python-syntax-context 'triple-quoted-string) (1- (point)))) + (python-tests-look-at "1 + 2") + (should (= (python-syntax-context 'paren) (1- (point)))))) + (ert-deftest python-syntax-after-python-backspace () ;; `python-indent-dedent-line-backspace' garbles syntax (python-tests-with-temp-buffer @@ -2052,6 +2073,54 @@ this is a test this is a test this is a test this is a test this is a test this (fill-paragraph) (should (= (current-indentation) 0)))) +(ert-deftest python-fill-paragraph-single-quoted-string-1 () + "Single quoted string should not be filled." + (let ((contents " +s = 'abc def ghi jkl mno pqr stu vwx yz' +") + (fill-column 20)) + (python-tests-with-temp-buffer + contents + (python-tests-look-at "abc") + (fill-paragraph) + (should (string= (buffer-substring-no-properties (point-min) (point-max)) + contents))))) + +(ert-deftest python-fill-paragraph-single-quoted-string-2 () + "Ensure no fill is performed after the end of the single quoted string." + (let ((contents " +s1 = 'abc' +s2 = 'def' +")) + (python-tests-with-temp-buffer + contents + (python-tests-look-at "abc") + (fill-paragraph) + (should (string= (buffer-substring-no-properties (point-min) (point-max)) + contents))))) + +(ert-deftest python-fill-paragraph-triple-quoted-string-1 () + "Triple quoted string should be filled." + (let ((contents " +s = '''abc def ghi jkl mno pqr stu vwx yz''' +") + (expected " +s = '''abc def ghi +jkl mno pqr stu vwx +yz''' +") + (fill-column 20)) + (dolist (look-at '("'''abc" "z'''")) + (dolist (offset '(0 1 2 3)) + (python-tests-with-temp-buffer + contents + (python-tests-look-at look-at) + (forward-char offset) + (fill-paragraph) + (should (string= + (buffer-substring-no-properties (point-min) (point-max)) + expected))))))) + ;;; Mark @@ -6491,6 +6560,56 @@ class Class: (python-tests-look-at "'''Not a method docstring.'''") (should (not (python-info-docstring-p))))) +(ert-deftest python-info-triple-quoted-string-p-1 () + "Test triple quoted string." + (python-tests-with-temp-buffer + " +t = '''Triple''' +" + (python-tests-look-at " '''Triple") + (should-not + (python-tests-should-not-move + #'python-info-triple-quoted-string-p)) + (forward-char) + (let ((start-pos (+ (point) 2)) + (eol (pos-eol))) + (while (< (point) eol) + (should (= (python-tests-should-not-move + #'python-info-triple-quoted-string-p) + start-pos)) + (forward-char))) + (dolist (pos `(,(point) ,(point-min) ,(point-max))) + (goto-char pos) + (should-not + (python-tests-should-not-move + #'python-info-triple-quoted-string-p))))) + +(ert-deftest python-info-triple-quoted-string-p-2 () + "Test empty triple quoted string." + (python-tests-with-temp-buffer + " +e = '''''' +" + (python-tests-look-at "''''''") + (let ((start-pos (+ (point) 2)) + (eol (pos-eol))) + (while (< (point) eol) + (should (= (python-tests-should-not-move + #'python-info-triple-quoted-string-p) + start-pos)) + (forward-char))))) + +(ert-deftest python-info-triple-quoted-string-p-3 () + "Test single quoted string." + (python-tests-with-temp-buffer + " +s = 'Single' +" + (while (< (point) (point-max)) + (should-not (python-tests-should-not-move + #'python-info-triple-quoted-string-p)) + (forward-char)))) + (ert-deftest python-info-encoding-from-cookie-1 () "Should detect it on first line." (python-tests-with-temp-buffer From a2222b9a9bfa039d66f836f06762ddea1544df11 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 16 Mar 2023 22:05:07 +0200 Subject: [PATCH 06/15] ; Minor wording fix in ELisp reference manual * doc/lispref/objects.texi (General Escape Syntax): More accurate wording. Avoid non-ASCII characters in Texinfo. (Bug#62224) --- doc/lispref/objects.texi | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index 2fe7e6db560..ad079e0d63a 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -466,19 +466,20 @@ You can specify characters by their Unicode values. @code{?\u@var{xxxx}} and @code{?\U@var{xxxxxxxx}} represent code points @var{xxxx} and @var{xxxxxxxx}, respectively, where each @var{x} is a single hexadecimal digit. For example, @code{?\N@{U+E0@}}, -@code{?\u00e0} and @code{?\U000000E0} are all equivalent to @code{?à} -and to @samp{?\N@{LATIN SMALL LETTER A WITH GRAVE@}}. The Unicode -Standard defines code points only up to @samp{U+@var{10ffff}}, so if -you specify a code point higher than that, Emacs signals an error. +@code{?\u00e0} and @code{?\U000000E0} are all equivalent to +@code{?@`a} and to @samp{?\N@{LATIN SMALL LETTER A WITH GRAVE@}}. The +Unicode Standard defines code points only up to @samp{U+@var{10ffff}}, +so if you specify a code point higher than that, Emacs signals an +error. @item You can specify characters by their hexadecimal character codes. A hexadecimal escape sequence consists of a backslash, @samp{x}, and the hexadecimal character code. Thus, @samp{?\x41} is the character @kbd{A}, @samp{?\x1} is the character @kbd{C-a}, and -@code{?\xe0} is the character @kbd{à} (@kbd{a} with grave accent). -You can use any number of hex digits, so you can represent any -character code in this way. +@code{?\xe0} is the character @kbd{@`a} (@kbd{a} with grave accent). +You can use one or more hex digits after @samp{x}, so you can +represent any character code in this way. @item @cindex octal character code From a4a9ffdd80a2b8ccd2e6705887d3cae0876a50ab Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 17 Mar 2023 10:14:41 +0200 Subject: [PATCH 07/15] Fix the documentation of various aspects of adding Xref history * lisp/progmodes/xref.el (xref-marker-ring-length) (xref-set-marker-ring-length): * lisp/progmodes/etags.el (tags-location-ring-length) (find-tag-marker-ring): Add doc strings saying the variables are unused. * etc/NEWS: Enhance the description of the change which made Xref marker stack unlimited in its length. * doc/emacs/maintaining.texi (Looking Up Identifiers): Add back text lost when xref forward history was added in bug#38797. Explain the difference between 'C-M-,' and 'M-.'. Improve wording (Bug#62229) --- doc/emacs/maintaining.texi | 19 ++++++++++++++----- etc/NEWS | 12 ++++++++++-- lisp/progmodes/etags.el | 10 +++++++--- lisp/progmodes/xref.el | 14 +++++++++----- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index f5bbc4d65c0..7d49e28d11f 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2283,16 +2283,25 @@ buffer, but doesn't select any of them. @kindex M-, @findex xref-go-back - To go back to places @emph{from where} you've displayed the definition, -use @kbd{M-,} (@code{xref-go-back}). It jumps back to the + To go back to places @emph{from where} you've displayed the +definition, use @kbd{M-,} (@code{xref-go-back}). It jumps back to the point of the last invocation of @kbd{M-.}. Thus you can find and examine the definition of something with @kbd{M-.} and then return to -where you were with @kbd{M-,}. +where you were with @kbd{M-,}. @kbd{M-,} allows you to retrace the +steps you made forward in the history of places, all the way to the +first place in history, where you first invoked @kbd{M-.}, or to any +place in-between. @kindex C-M-, @findex xref-go-forward - If you previously went back too far with @kbd{M-,}, @kbd{C-M-,} -(@code{xref-go-forward}) can be used to go forward again. + If you previously went back too far with @kbd{M-,}, or want to +re-examine a place from which you went back, you can use @kbd{C-M-,} +(@code{xref-go-forward}) to go forward again. This is similar to +using @kbd{M-.}, except that you don't need on each step to move point +to the identifier whose definition you want to look up. @kbd{C-M-,} +allows you to retrace all the steps you made back in the history of +places, all the way to the last place in history, where you invoked +@kbd{M-,}, or to any place in-between. @findex xref-etags-mode Some major modes install @code{xref} support facilities that might diff --git a/etc/NEWS b/etc/NEWS index a5f9f8c6ec1..0b651f7a519 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2540,8 +2540,16 @@ the project by a VC project based on that VCS. +++ *** New command 'xref-go-forward'. -It is bound to 'C-M-,' and jumps to the location where 'xref-go-back' -('M-,', also known as 'xref-pop-marker-stack') was invoked previously. +It is bound to 'C-M-,' and jumps to the location where you previously +invoked 'xref-go-back' ('M-,', also known as 'xref-pop-marker-stack'). + ++++ +*** The depth of the Xref marker stack is now infinite. +The implementation of the Xref marker stack was changed in a way that +allows as many places to be saved on the stack as needed, limited only +by the available memory. Therefore, the variables +'find-tag-marker-ring-length' and 'xref-marker-ring-length' are now +obsolete and unused; setting them has no effect. +++ *** 'xref-query-replace-in-results' prompting change. diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index 8efdae6060f..cb95f29b5fe 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -146,7 +146,10 @@ Otherwise, `find-tag-default' is used." (define-obsolete-variable-alias 'find-tag-marker-ring-length 'tags-location-ring-length "25.1") -(defvar tags-location-ring-length 16) +(defvar tags-location-ring-length 16 + "Size of the find-tag marker ring. +This variable has no effect, and is kept only for backward compatibility. +The actual size of the find-tag marker ring is unlimited.") (defcustom tags-tag-face 'default "Face for tags in the output of `tags-apropos'." @@ -181,8 +184,9 @@ Example value: (sexp :tag "Tags to search"))) :version "21.1") -;; Obsolete variable kept for compatibility. We don't use it in any way. -(defvar find-tag-marker-ring (make-ring 16)) +(defvar find-tag-marker-ring (make-ring 16) + "Find-tag marker ring. +Obsolete variable kept for compatibility. It is not used in any way.") (make-obsolete-variable 'find-tag-marker-ring "use `xref-push-marker-stack' or `xref-go-back' instead." diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index d4e34f7e55a..ee4253960c5 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -355,8 +355,10 @@ backward." (t (goto-char start) nil)))) -;; Dummy variable retained for compatibility. -(defvar xref-marker-ring-length 16) +(defvar xref-marker-ring-length 16 + "Xref marker ring length. +This is a dummy variable retained for backward compatibility, and +otherwise unused.") (make-obsolete-variable 'xref-marker-ring-length nil "29.1") (defcustom xref-prompt-for-identifier '(not xref-find-definitions @@ -453,7 +455,9 @@ are predefined: (make-obsolete-variable 'xref--marker-ring 'xref--history "29.1") (defun xref-set-marker-ring-length (_var _val) - (declare (obsolete nil "29.1")) + (declare (obsolete + "this function has no effect: Xref marker ring is now unlimited in size" + "29.1")) nil) (defun xref--make-xref-history () @@ -499,7 +503,7 @@ Override existing value with NEW-VALUE if NEW-VALUE is set." (defun xref-push-marker-stack (&optional m) "Add point M (defaults to `point-marker') to the marker stack. -The future stack is erased." +Erase the stack slots following this one." (xref--push-backward (or m (point-marker))) (let ((history (xref--get-history))) (dolist (mk (cdr history)) @@ -527,7 +531,7 @@ To undo, use \\[xref-go-forward]." ;;;###autoload (defun xref-go-forward () - "Got to the point where a previous \\[xref-go-back] was invoked." + "Go to the point where a previous \\[xref-go-back] was invoked." (interactive) (let ((history (xref--get-history))) (if (null (cdr history)) From bb3e0ded9eba71596b34806b302d63977259c3dd Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Fri, 17 Mar 2023 09:50:38 +0100 Subject: [PATCH 08/15] Don't add a key binding when REMOVE is non-nil * src/keymap.c (store_in_keymap): Don't add a nil keybinding if we've been asked to remove a non-existent binding. (Bug#62207) --- src/keymap.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/keymap.c b/src/keymap.c index 23453eaa9a6..efac410d317 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -887,22 +887,23 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx, keymap_end: /* We have scanned the entire keymap, and not found a binding for IDX. Let's add one. */ - { - Lisp_Object elt; + if (!remove) + { + Lisp_Object elt; - if (CONSP (idx) && CHARACTERP (XCAR (idx))) - { - /* IDX specifies a range of characters, and not all of them - were handled yet, which means this keymap doesn't have a - char-table. So, we insert a char-table now. */ - elt = Fmake_char_table (Qkeymap, Qnil); - Fset_char_table_range (elt, idx, NILP (def) ? Qt : def); - } - else - elt = Fcons (idx, def); - CHECK_IMPURE (insertion_point, XCONS (insertion_point)); - XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point))); - } + if (CONSP (idx) && CHARACTERP (XCAR (idx))) + { + /* IDX specifies a range of characters, and not all of them + were handled yet, which means this keymap doesn't have a + char-table. So, we insert a char-table now. */ + elt = Fmake_char_table (Qkeymap, Qnil); + Fset_char_table_range (elt, idx, NILP (def) ? Qt : def); + } + else + elt = Fcons (idx, def); + CHECK_IMPURE (insertion_point, XCONS (insertion_point)); + XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point))); + } } return def; From e4a7d0cd6eaf4feb4cb2a6bbb8058b70d6676b62 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Fri, 17 Mar 2023 14:16:00 +0100 Subject: [PATCH 09/15] Document `keymap-unset' in lispref * doc/lispref/keymaps.texi (Changing Key Bindings): Document keymap-unset. --- doc/lispref/keymaps.texi | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 7876780dcd4..02feda5cd04 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1427,6 +1427,17 @@ If @var{key} is @kbd{}, this sets the default binding in @var{keymap}. When an event has no binding of its own, the Emacs command loop uses the keymap's default binding, if there is one. +@findex keymap-unset +@defun keymap-unset keymap key &optional remove +This function is the inverse of @code{keymap-set}, it unsets the +binding for @var{key} in @var{keymap}, which is the same as setting +the binding to @code{nil}. In order to instead remove the binding +completely, specify @var{remove} as non-nil. This only makes a +difference if @var{keymap} has a parent keymap. When unsetting a key +in a child map, it will still shadow the same key in the parent +keymap. Removing the binding will allow the key in the parent keymap +to be used. + @cindex invalid prefix key error @cindex key sequence error Every prefix of @var{key} must be a prefix key (i.e., bound to a keymap) From e8cee15f780e90ac52e674f49613d8e2b011cc59 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Fri, 17 Mar 2023 14:25:39 +0100 Subject: [PATCH 10/15] ; Fix markup in previous change --- doc/lispref/keymaps.texi | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 02feda5cd04..aab2fe58255 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1427,17 +1427,6 @@ If @var{key} is @kbd{}, this sets the default binding in @var{keymap}. When an event has no binding of its own, the Emacs command loop uses the keymap's default binding, if there is one. -@findex keymap-unset -@defun keymap-unset keymap key &optional remove -This function is the inverse of @code{keymap-set}, it unsets the -binding for @var{key} in @var{keymap}, which is the same as setting -the binding to @code{nil}. In order to instead remove the binding -completely, specify @var{remove} as non-nil. This only makes a -difference if @var{keymap} has a parent keymap. When unsetting a key -in a child map, it will still shadow the same key in the parent -keymap. Removing the binding will allow the key in the parent keymap -to be used. - @cindex invalid prefix key error @cindex key sequence error Every prefix of @var{key} must be a prefix key (i.e., bound to a keymap) @@ -1449,6 +1438,18 @@ If there was previously no binding for @var{key} in @var{keymap}, the new binding is added at the beginning of @var{keymap}. The order of bindings in a keymap makes no difference for keyboard input, but it does matter for menu keymaps (@pxref{Menu Keymaps}). +@end defun + +@findex keymap-unset +@defun keymap-unset keymap key &optional remove +This function is the inverse of @code{keymap-set}, it unsets the +binding for @var{key} in @var{keymap}, which is the same as setting +the binding to @code{nil}. In order to instead remove the binding +completely, specify @var{remove} as non-nil. This only makes a +difference if @var{keymap} has a parent keymap. When unsetting a key +in a child map, it will still shadow the same key in the parent +keymap. Removing the binding will allow the key in the parent keymap +to be used. @end defun This example creates a sparse keymap and makes a number of From c54bda15e35a6e9e2232997e805ef017a15e78c8 Mon Sep 17 00:00:00 2001 From: Filipp Gunbin Date: Wed, 15 Mar 2023 21:04:26 +0300 Subject: [PATCH 11/15] Reset abbrevs-changed after saving abbrevs (bug#62208) * lisp/abbrev.el (abbrev--possibly-save): Reset abbrevs-changed after saving abbrevs. * test/lisp/abbrev-tests.el (abbrev--possibly-save-test): New test. --- lisp/abbrev.el | 22 +++++++++++----------- test/lisp/abbrev-tests.el | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lisp/abbrev.el b/lisp/abbrev.el index 550d956fb7b..e1311dbc83b 100644 --- a/lisp/abbrev.el +++ b/lisp/abbrev.el @@ -1250,17 +1250,17 @@ which see." ;; asked to. (and save-abbrevs abbrevs-changed - (progn - (if (or arg - (eq save-abbrevs 'silently) - (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name))) - (progn - (write-abbrev-file nil) - nil) - ;; Don't keep bothering user if they say no. - (setq abbrevs-changed nil) - ;; Inhibit message in `save-some-buffers'. - t))))) + (prog1 + (if (or arg + (eq save-abbrevs 'silently) + (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name))) + (progn + (write-abbrev-file nil) + nil) + ;; Inhibit message in `save-some-buffers'. + t) + ;; Don't ask again whether saved or user said no. + (setq abbrevs-changed nil))))) (add-hook 'save-some-buffers-functions #'abbrev--possibly-save) diff --git a/test/lisp/abbrev-tests.el b/test/lisp/abbrev-tests.el index ecca21df4bc..7b2780309b0 100644 --- a/test/lisp/abbrev-tests.el +++ b/test/lisp/abbrev-tests.el @@ -305,6 +305,22 @@ (should-not (abbrev-table-p translation-table-vector)) (should (abbrev-table-p (make-abbrev-table)))) +(ert-deftest abbrev--possibly-save-test () + "Test that `abbrev--possibly-save' properly resets +`abbrevs-changed'." + (ert-with-temp-file temp-test-file + (let ((abbrev-file-name temp-test-file) + (save-abbrevs t)) + ;; Save + (let ((abbrevs-changed t)) + (should-not (abbrev--possibly-save nil t)) + (should-not abbrevs-changed)) + ;; Don't save + (let ((abbrevs-changed t)) + (ert-simulate-keys '(?n) + (should (abbrev--possibly-save nil))) + (should-not abbrevs-changed))))) + (provide 'abbrev-tests) ;;; abbrev-tests.el ends here From 6f82596b49055ad17447ee6dd51c433bd2758621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Fri, 17 Mar 2023 11:47:02 +0000 Subject: [PATCH 12/15] Fix Eglot's snippet insertion to follow the manual The manual states that YASnippet must only be installed to be useful. Before this change, it would only work if the user happened to have manually activated it before with 'yas-global-mode' or somesuch. This makes Eglot's Yasnippet-activating behaviour similar to its Flymake-activating behaviour. * lisp/progmodes/eglot.el (eglot-client-capabilities): Consult eglot--stay-out-of. (eglot--snippet-expansion-fn): Turn on yas-minor-mod eon demand. (eglot-completion-at-point): Simplify. --- lisp/progmodes/eglot.el | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 52bba717a67..68d07c7178a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -758,7 +758,9 @@ treated as in `eglot--dbind'." :completion (list :dynamicRegistration :json-false :completionItem `(:snippetSupport - ,(if (eglot--snippet-expansion-fn) + ,(if (and + (not (eglot--stay-out-of-p 'yasnippet)) + (eglot--snippet-expansion-fn)) t :json-false) :deprecatedSupport t @@ -1626,9 +1628,11 @@ If optional MARKER, return a marker instead" (defun eglot--snippet-expansion-fn () "Compute a function to expand snippets. Doubles as an indicator of snippet support." - (and (boundp 'yas-minor-mode) - (symbol-value 'yas-minor-mode) - 'yas-expand-snippet)) + (and (fboundp 'yas-minor-mode) + (lambda (&rest args) + (with-no-warnings + (unless (bound-and-true-p yas-minor-mode) (yas-minor-mode 1)) + (apply #'yas-expand-snippet args))))) (defun eglot--format-markup (markup) "Format MARKUP according to LSP's spec." @@ -2887,8 +2891,7 @@ for which LSP on-type-formatting should be requested." ;; it'll be adjusted. If no usable ;; insertText at all, label is best, ;; too. - (cond ((or (and (eql insertTextFormat 2) - (eglot--snippet-expansion-fn)) + (cond ((or (eql insertTextFormat 2) textEdit (null insertText) (string-empty-p insertText)) From 38067f05b92052042f822f6567a697af31807f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Fri, 17 Mar 2023 14:07:36 +0000 Subject: [PATCH 13/15] Enhance section about troubleshooting in Eglot manual. * doc/misc/eglot.texi (Troubleshooting Eglot): Parially rewrite. --- doc/misc/eglot.texi | 104 ++++++++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 27 deletions(-) diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi index 85f83ee4b26..30414fcb349 100644 --- a/doc/misc/eglot.texi +++ b/doc/misc/eglot.texi @@ -1292,53 +1292,103 @@ pop up special buffers that can be used to inspect the communications between the Eglot and language server. In many cases, this will indicate the problems or at least provide a hint. +@cindex performance A common and easy-to-fix cause of performance problems is the length -of these two buffers. If Eglot is operating correctly but slowly, -customize the variable @code{eglot-events-buffer-size} (@pxref{Eglot -Variables}) to limit logging, and thus speed things up. +of the Eglot events buffer because it represent additional work that +Eglot must do. After verifying Eglot is operating correctly but +slowly, try to customize the variable @code{eglot-events-buffer-size} +(@pxref{Eglot Variables}) to 0. This will disable any debug logging +and may speed things up. -If you need to report an Eglot bug, please keep in mind that, because -there are so many variables involved, it is generally both very -@emph{difficult} and @emph{absolutely essential} to reproduce bugs -exactly as they happened to you, the user. Therefore, every bug -report should include: +In other situations, the cause of poor performance lies in the LSP +server itself. Servers use aggressive caching and other techniques to +improve their performance. Often, this can be tweaked by changing the +server configuration (@pxref{Advanced Server Configuration}). + +If you think you have found a bug, we want to hear about it. Before +reporting a bug, keep in mind that interaction with LSP servers +represents a large quantity of unknown variables. Therefore, it is +generally both @emph{difficult} and @emph{absolutely essential} that +the maintainers reproduce bugs exactly as they happened to you, the +user. + +To report an Eglot bug, send e-mail to @email{bug-gnu-emacs@@gnu.org}. + +Get acquainted with Emacs's bug reporting guidelines (@pxref{Bugs,,, +emacs, GNU Emacs Manual}). Then, follow this checklist specific to +Eglot bug rerpots. @enumerate @item -The transcript of events obtained from the buffer popped up by -@kbd{M-x eglot-events-buffer}. If the transcript can be narrowed down -to show the problematic exchange, so much the better. This is -invaluable for the investigation and reproduction of the problem. +Include the transcript of JSONRPC events obtained from the buffer +popped up by @kbd{M-x eglot-events-buffer}. You may narrow down the +transcript if you are sure of where the problematic exchange is, but +it's safer to include the whole transcript, either attached or inline. @item If Emacs signaled an error (an error message was seen or heard), make -sure to repeat the process after toggling @code{debug-on-error} on -(via @kbd{M-x toggle-debug-on-error}). This normally produces a -backtrace of the error that should also be attached to the bug report. +sure to repeat the process after turning on @code{debug-on-error} via +@kbd{M-x toggle-debug-on-error}. This normally produces a backtrace +of the error that should also be attached to the bug report. @item -An explanation of how to obtain, install, and configure the language -server you used. If possible, try to replicate the problem with the -C/C@t{++} or Python servers, as these are very easy to install. +Include a description of how the maintainer should obtain, install, +and configure the language server you used. Maintainers usually have +access to GNU/Linux systems, though not necessarily the distribution +that you may be using. If possible, try to replicate the problem with +the C/C@t{++} or Python servers, as these are very easy to install. @item -A description of how to setup the @emph{minimal} project (one or two -files and their contents) where the problem happens. +Describe how to setup a @emph{minimal} project directory where Eglot +should be started for the problem to happen. Describe each file's +name and its contents. Alternatively, you can supply the address of a +public Git repository. @item -A recipe to replicate the problem with @emph{a clean Emacs run}. This -means @kbd{emacs -Q} invocation or a very minimal (no more that 10 -lines) @file{.emacs} initialization file. @code{eglot-ensure} and -@code{use-package} calls are generally @emph{not} needed. +Include versions of the software used. The Emacs version can be +obtained with @kbd{M-x emacs-version}. + +It's also essential to include the version of ELPA packages that are +explicitly or implicitly loaded. The optional but popular Company or +Markdown packages are distributed as GNU ELPA packages, not to mention +Eglot itself in some situations. Some major modes (Go, Rust, etc.) +are provided by ELPA packages. It's sometimes easy to miss these, +since they are usually implicitly loaded when visiting a file in that +language. + +ELPA packages usually live in @code{~/.emacs.d/elpa} (or what is in +@code{package-user-dir}). Please show the listing of files in that +directory as well. @item -Make sure to double check all the above elements and re-run the -recipe to see that the problem is reproducible. +Include a recipe to replicate the problem with @emph{a clean Emacs +run}. This means @kbd{emacs -Q -f package-initialize} invocation +which starts Emacs with no configuration and initializes the ELPA +packages. A very minimal (no more that 10 lines) @file{.emacs} +initialization file is also acceptable and good means to describe +changes to variables. + +There is usually no need to include @kbd{require} statements in the +recipe, as Eglot's functionality uses autoloads. + +Likewise, there is rarely the need to use things like +@code{use-package} or @code{eglot-ensure}. This just makes the recipe +harder to follow. Prefer setting variables with @code{setq} and +adding to hooks with @code{add-hook}. Prefer starting Eglot with +@code{M-x eglot}. + +@item +Make sure to double check all the above elements and re-run the recipe +to see that the problem is reproducible. Following the recipe should +produce event transcript and error backtraces that are exactly the +same or very similar to the ones you included. If the problem only +happens sometimes, include this information in your bug report. @end enumerate Please keep in mind that some problems reported against Eglot may actually be bugs in the language server or the Emacs feature/package -that used Eglot to communicate with the language server. +that used Eglot to communicate with the language server. Eglot is, in +many cases, just a frontend to that functionality. @node GNU Free Documentation License @appendix GNU Free Documentation License From 90362f87d5837bae9cde3f5859904c547318f06b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Fri, 17 Mar 2023 14:21:11 +0000 Subject: [PATCH 14/15] ; Correct last commit, downcase node reference * doc/misc/eglot.texi (Troubleshooting Eglot): Downcase node reference --- doc/misc/eglot.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi index 30414fcb349..5ebc055ecf7 100644 --- a/doc/misc/eglot.texi +++ b/doc/misc/eglot.texi @@ -1303,7 +1303,7 @@ and may speed things up. In other situations, the cause of poor performance lies in the LSP server itself. Servers use aggressive caching and other techniques to improve their performance. Often, this can be tweaked by changing the -server configuration (@pxref{Advanced Server Configuration}). +server configuration (@pxref{Advanced server configuration}). If you think you have found a bug, we want to hear about it. Before reporting a bug, keep in mind that interaction with LSP servers From ea87c54f359e3d98b4f21a0904206b3696b4bb74 Mon Sep 17 00:00:00 2001 From: Arash Esbati Date: Fri, 17 Mar 2023 14:25:37 +0100 Subject: [PATCH 15/15] ; * lisp/subr.el (setq-local): Add missing period (bug#62242). --- lisp/subr.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/subr.el b/lisp/subr.el index c800f380261..c73643f6d2b 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -163,7 +163,7 @@ of previous VARs. (defmacro setq-local (&rest pairs) "Make each VARIABLE buffer-local and assign to it the corresponding VALUE. -The arguments are variable/value pairs For each VARIABLE in a pair, +The arguments are variable/value pairs. For each VARIABLE in a pair, make VARIABLE buffer-local and assign to it the corresponding VALUE of the pair. The VARIABLEs are literal symbols and should not be quoted.