diff options
author | Stefan Kangas <stefankangas@gmail.com> | 2023-03-20 06:30:32 +0100 |
---|---|---|
committer | Stefan Kangas <stefankangas@gmail.com> | 2023-03-20 06:30:32 +0100 |
commit | 20d8a1cf4bdc1de994b5c39a8ee02af657416c56 (patch) | |
tree | 542aff7d6767542a42e4fb6a84c69f4dece073ef | |
parent | f615968fe1b4726e3914aa65e4b7c6c6be07ea70 (diff) | |
parent | ea87c54f359e3d98b4f21a0904206b3696b4bb74 (diff) | |
download | emacs-20d8a1cf4bdc1de994b5c39a8ee02af657416c56.tar.gz |
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
-rw-r--r-- | doc/emacs/maintaining.texi | 19 | ||||
-rw-r--r-- | doc/lispref/keymaps.texi | 12 | ||||
-rw-r--r-- | doc/lispref/objects.texi | 15 | ||||
-rw-r--r-- | doc/misc/eglot.texi | 106 | ||||
-rw-r--r-- | doc/misc/idlwave.texi | 7 | ||||
-rw-r--r-- | doc/misc/tramp.texi | 1 | ||||
-rw-r--r-- | etc/NEWS.29 | 12 | ||||
-rw-r--r-- | lisp/abbrev.el | 22 | ||||
-rw-r--r-- | lisp/progmodes/eglot.el | 27 | ||||
-rw-r--r-- | lisp/progmodes/etags.el | 10 | ||||
-rw-r--r-- | lisp/progmodes/python.el | 35 | ||||
-rw-r--r-- | lisp/progmodes/xref.el | 14 | ||||
-rw-r--r-- | lisp/subr.el | 2 | ||||
-rw-r--r-- | src/keymap.c | 31 | ||||
-rw-r--r-- | test/lisp/abbrev-tests.el | 16 | ||||
-rw-r--r-- | 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 @@ -1440,6 +1440,18 @@ 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 bindings in it: 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 |