emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 20d8a1cf4bd 4/8: Merge from origin/emacs-29


From: Stefan Kangas
Subject: master 20d8a1cf4bd 4/8: Merge from origin/emacs-29
Date: Mon, 20 Mar 2023 01:46:24 -0400 (EDT)

branch: master
commit 20d8a1cf4bdc1de994b5c39a8ee02af657416c56
Merge: f615968fe1b ea87c54f359
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Merge from origin/emacs-29
    
    ea87c54f359 ; * lisp/subr.el (setq-local): Add missing period (bug#62...
    90362f87d58 ; Correct last commit, downcase node reference
    38067f05b92 Enhance section about troubleshooting in Eglot manual.
    6f82596b490 Fix Eglot's snippet insertion to follow the manual
    c54bda15e35 Reset abbrevs-changed after saving abbrevs (bug#62208)
    e8cee15f780 ; Fix markup in previous change
    e4a7d0cd6ea Document `keymap-unset' in lispref
    bb3e0ded9eb Don't add a key binding when REMOVE is non-nil
    a4a9ffdd80a Fix the documentation of various aspects of adding Xref h...
    a2222b9a9bf ; Minor wording fix in ELisp reference manual
    5cf1de683b2 Fix python-fill-paragraph problems on filling strings (bu...
    7385c991dff Also exempt eglot-inlay-hints-mode from desktop.el's fumb...
    1961bdb52ed ; Add WebDAV entry to index in Tramp manual
    dfb36d36230 Refer to EWW instead of w3 and w3m
    9d3fdf7e0d4 Fix Eglot's command generation for code actions
    
    # Conflicts:
    #       etc/NEWS
---
 doc/emacs/maintaining.texi          |  19 ++++--
 doc/lispref/keymaps.texi            |  12 ++++
 doc/lispref/objects.texi            |  15 ++---
 doc/misc/eglot.texi                 | 106 +++++++++++++++++++++++---------
 doc/misc/idlwave.texi               |   7 +--
 doc/misc/tramp.texi                 |   1 +
 etc/NEWS.29                         |  12 +++-
 lisp/abbrev.el                      |  22 +++----
 lisp/progmodes/eglot.el             |  27 ++++----
 lisp/progmodes/etags.el             |  10 ++-
 lisp/progmodes/python.el            |  35 ++++++++---
 lisp/progmodes/xref.el              |  14 +++--
 lisp/subr.el                        |   2 +-
 src/keymap.c                        |  31 +++++-----
 test/lisp/abbrev-tests.el           |  16 +++++
 test/lisp/progmodes/python-tests.el | 119 ++++++++++++++++++++++++++++++++++++
 16 files changed, 346 insertions(+), 102 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/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 7876780dcd4..aab2fe58255 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -1438,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
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
diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi
index 85f83ee4b26..5ebc055ecf7 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.
-
-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:
+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.
+
+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
+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
-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.
+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 description of how to setup the @emph{minimal} project (one or two
-files and their contents) where the problem happens.
+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
-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 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.
+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
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
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 3b5ba3b1390..6f14fc875f4 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -1247,6 +1247,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
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index a5f9f8c6ec1..0b651f7a519 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -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/abbrev.el b/lisp/abbrev.el
index ef8ef1ab5a6..1a665efb0a5 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/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 6c1b9eafe43..1f077052cae 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -759,7 +759,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
@@ -1627,9 +1629,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."
@@ -2892,8 +2896,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))
@@ -3376,7 +3379,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")
@@ -3659,13 +3662,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
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/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/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))
diff --git a/lisp/subr.el b/lisp/subr.el
index 9ba0acace01..99ddd813867 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.
 
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;
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
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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]