1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-15 10:30:25 -08:00

Merge from origin/emacs-29

ea87c54f35 ; * lisp/subr.el (setq-local): Add missing period (bug#62...
90362f87d5 ; Correct last commit, downcase node reference
38067f05b9 Enhance section about troubleshooting in Eglot manual.
6f82596b49 Fix Eglot's snippet insertion to follow the manual
c54bda15e3 Reset abbrevs-changed after saving abbrevs (bug#62208)
e8cee15f78 ; Fix markup in previous change
e4a7d0cd6e Document `keymap-unset' in lispref
bb3e0ded9e Don't add a key binding when REMOVE is non-nil
a4a9ffdd80 Fix the documentation of various aspects of adding Xref h...
a2222b9a9b ; Minor wording fix in ELisp reference manual
5cf1de683b Fix python-fill-paragraph problems on filling strings (bu...
7385c991df Also exempt eglot-inlay-hints-mode from desktop.el's fumb...
1961bdb52e ; Add WebDAV entry to index in Tramp manual
dfb36d3623 Refer to EWW instead of w3 and w3m
9d3fdf7e0d Fix Eglot's command generation for code actions

# Conflicts:
#	etc/NEWS
This commit is contained in:
Stefan Kangas 2023-03-20 06:30:32 +01:00
commit 20d8a1cf4b
16 changed files with 345 additions and 101 deletions

View file

@ -2283,16 +2283,25 @@ buffer, but doesn't select any of them.
@kindex M-, @kindex M-,
@findex xref-go-back @findex xref-go-back
To go back to places @emph{from where} you've displayed the definition, To go back to places @emph{from where} you've displayed the
use @kbd{M-,} (@code{xref-go-back}). It jumps back to 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 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 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-, @kindex C-M-,
@findex xref-go-forward @findex xref-go-forward
If you previously went back too far with @kbd{M-,}, @kbd{C-M-,} If you previously went back too far with @kbd{M-,}, or want to
(@code{xref-go-forward}) can be used to go forward again. 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 @findex xref-etags-mode
Some major modes install @code{xref} support facilities that might Some major modes install @code{xref} support facilities that might

View file

@ -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 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 bindings in a keymap makes no difference for keyboard input, but it
does matter for menu keymaps (@pxref{Menu Keymaps}). 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 @end defun
This example creates a sparse keymap and makes a number of This example creates a sparse keymap and makes a number of

View file

@ -466,19 +466,20 @@ You can specify characters by their Unicode values.
@code{?\u@var{xxxx}} and @code{?\U@var{xxxxxxxx}} represent code @code{?\u@var{xxxx}} and @code{?\U@var{xxxxxxxx}} represent code
points @var{xxxx} and @var{xxxxxxxx}, respectively, where each @var{x} points @var{xxxx} and @var{xxxxxxxx}, respectively, where each @var{x}
is a single hexadecimal digit. For example, @code{?\N@{U+E0@}}, is a single hexadecimal digit. For example, @code{?\N@{U+E0@}},
@code{?\u00e0} and @code{?\U000000E0} are all equivalent to @code{?à} @code{?\u00e0} and @code{?\U000000E0} are all equivalent to
and to @samp{?\N@{LATIN SMALL LETTER A WITH GRAVE@}}. The Unicode @code{?@`a} and to @samp{?\N@{LATIN SMALL LETTER A WITH GRAVE@}}. The
Standard defines code points only up to @samp{U+@var{10ffff}}, so if Unicode Standard defines code points only up to @samp{U+@var{10ffff}},
you specify a code point higher than that, Emacs signals an error. so if you specify a code point higher than that, Emacs signals an
error.
@item @item
You can specify characters by their hexadecimal character You can specify characters by their hexadecimal character
codes. A hexadecimal escape sequence consists of a backslash, codes. A hexadecimal escape sequence consists of a backslash,
@samp{x}, and the hexadecimal character code. Thus, @samp{?\x41} is @samp{x}, and the hexadecimal character code. Thus, @samp{?\x41} is
the character @kbd{A}, @samp{?\x1} is the character @kbd{C-a}, and the character @kbd{A}, @samp{?\x1} is the character @kbd{C-a}, and
@code{?\xe0} is the character @kbd{à} (@kbd{a} with grave accent). @code{?\xe0} is the character @kbd{@`a} (@kbd{a} with grave accent).
You can use any number of hex digits, so you can represent any You can use one or more hex digits after @samp{x}, so you can
character code in this way. represent any character code in this way.
@item @item
@cindex octal character code @cindex octal character code

View file

@ -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 between the Eglot and language server. In many cases, this will
indicate the problems or at least provide a hint. indicate the problems or at least provide a hint.
@cindex performance
A common and easy-to-fix cause of performance problems is the length A common and easy-to-fix cause of performance problems is the length
of these two buffers. If Eglot is operating correctly but slowly, of the Eglot events buffer because it represent additional work that
customize the variable @code{eglot-events-buffer-size} (@pxref{Eglot Eglot must do. After verifying Eglot is operating correctly but
Variables}) to limit logging, and thus speed things up. 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 In other situations, the cause of poor performance lies in the LSP
there are so many variables involved, it is generally both very server itself. Servers use aggressive caching and other techniques to
@emph{difficult} and @emph{absolutely essential} to reproduce bugs improve their performance. Often, this can be tweaked by changing the
exactly as they happened to you, the user. Therefore, every bug server configuration (@pxref{Advanced server configuration}).
report should include:
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 @enumerate
@item @item
The transcript of events obtained from the buffer popped up by Include the transcript of JSONRPC events obtained from the buffer
@kbd{M-x eglot-events-buffer}. If the transcript can be narrowed down popped up by @kbd{M-x eglot-events-buffer}. You may narrow down the
to show the problematic exchange, so much the better. This is transcript if you are sure of where the problematic exchange is, but
invaluable for the investigation and reproduction of the problem. it's safer to include the whole transcript, either attached or inline.
@item @item
If Emacs signaled an error (an error message was seen or heard), make 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 sure to repeat the process after turning on @code{debug-on-error} via
(via @kbd{M-x toggle-debug-on-error}). This normally produces a @kbd{M-x toggle-debug-on-error}. This normally produces a backtrace
backtrace of the error that should also be attached to the bug report. of the error that should also be attached to the bug report.
@item @item
An explanation of how to obtain, install, and configure the language Include a description of how the maintainer should obtain, install,
server you used. If possible, try to replicate the problem with the and configure the language server you used. Maintainers usually have
C/C@t{++} or Python servers, as these are very easy to install. 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 @item
A description of how to setup the @emph{minimal} project (one or two Describe how to setup a @emph{minimal} project directory where Eglot
files and their contents) where the problem happens. 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 @item
A recipe to replicate the problem with @emph{a clean Emacs run}. This Include versions of the software used. The Emacs version can be
means @kbd{emacs -Q} invocation or a very minimal (no more that 10 obtained with @kbd{M-x emacs-version}.
lines) @file{.emacs} initialization file. @code{eglot-ensure} and
@code{use-package} calls are generally @emph{not} needed. 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 @item
Make sure to double check all the above elements and re-run the Include a recipe to replicate the problem with @emph{a clean Emacs
recipe to see that the problem is reproducible. 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 @end enumerate
Please keep in mind that some problems reported against Eglot may Please keep in mind that some problems reported against Eglot may
actually be bugs in the language server or the Emacs feature/package 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 @node GNU Free Documentation License
@appendix GNU Free Documentation License @appendix GNU Free Documentation License

View file

@ -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 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} function is used to set the variable @code{browse-url-browser-function}
locally for IDLWAVE help only. Customize the latter variable to see locally for IDLWAVE help only. Customize the latter variable to see
what choices of browsers your system offers. Certain browsers like what choices of browsers your system offers. Certain browsers like EWW
@code{w3} (bundled with many versions of Emacs) and @code{w3m} (@pxref{Top, EWW,, eww, The Emacs Web Wowser Manual}) are run within Emacs,
(@uref{http://emacs-w3m.namazu.org/}) are run within Emacs, and use and use Emacs buffers to display the HTML help. This can be convenient,
Emacs buffers to display the HTML help. This can be convenient,
especially on small displays, and images can even be displayed in-line especially on small displays, and images can even be displayed in-line
on newer Emacs versions. However, better formatting results are often on newer Emacs versions. However, better formatting results are often
achieved with external browsers, like Mozilla. IDLWAVE assumes any achieved with external browsers, like Mozilla. IDLWAVE assumes any

View file

@ -1247,6 +1247,7 @@ syntax requires a leading volume (share) name, for example:
@item @option{dav} @item @option{dav}
@item @option{davs} @item @option{davs}
@cindex WebDAV
@cindex method @option{dav} @cindex method @option{dav}
@cindex method @option{davs} @cindex method @option{davs}
@cindex @option{dav} method @cindex @option{dav} method

View file

@ -2540,8 +2540,16 @@ the project by a VC project based on that VCS.
+++ +++
*** New command 'xref-go-forward'. *** New command 'xref-go-forward'.
It is bound to 'C-M-,' and jumps to the location where 'xref-go-back' It is bound to 'C-M-,' and jumps to the location where you previously
('M-,', also known as 'xref-pop-marker-stack') was invoked 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. *** 'xref-query-replace-in-results' prompting change.

View file

@ -1250,17 +1250,17 @@ which see."
;; asked to. ;; asked to.
(and save-abbrevs (and save-abbrevs
abbrevs-changed abbrevs-changed
(progn (prog1
(if (or arg (if (or arg
(eq save-abbrevs 'silently) (eq save-abbrevs 'silently)
(y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name))) (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
(progn (progn
(write-abbrev-file nil) (write-abbrev-file nil)
nil) nil)
;; Don't keep bothering user if they say no. ;; Inhibit message in `save-some-buffers'.
(setq abbrevs-changed nil) t)
;; Inhibit message in `save-some-buffers'. ;; Don't ask again whether saved or user said no.
t))))) (setq abbrevs-changed nil)))))
(add-hook 'save-some-buffers-functions #'abbrev--possibly-save) (add-hook 'save-some-buffers-functions #'abbrev--possibly-save)

View file

@ -759,7 +759,9 @@ treated as in `eglot--dbind'."
:completion (list :dynamicRegistration :json-false :completion (list :dynamicRegistration :json-false
:completionItem :completionItem
`(:snippetSupport `(:snippetSupport
,(if (eglot--snippet-expansion-fn) ,(if (and
(not (eglot--stay-out-of-p 'yasnippet))
(eglot--snippet-expansion-fn))
t t
:json-false) :json-false)
:deprecatedSupport t :deprecatedSupport t
@ -1627,9 +1629,11 @@ If optional MARKER, return a marker instead"
(defun eglot--snippet-expansion-fn () (defun eglot--snippet-expansion-fn ()
"Compute a function to expand snippets. "Compute a function to expand snippets.
Doubles as an indicator of snippet support." Doubles as an indicator of snippet support."
(and (boundp 'yas-minor-mode) (and (fboundp 'yas-minor-mode)
(symbol-value 'yas-minor-mode) (lambda (&rest args)
'yas-expand-snippet)) (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) (defun eglot--format-markup (markup)
"Format MARKUP according to LSP's spec." "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 ;; it'll be adjusted. If no usable
;; insertText at all, label is best, ;; insertText at all, label is best,
;; too. ;; too.
(cond ((or (and (eql insertTextFormat 2) (cond ((or (eql insertTextFormat 2)
(eglot--snippet-expansion-fn))
textEdit textEdit
(null insertText) (null insertText)
(string-empty-p insertText)) (string-empty-p insertText))
@ -3376,7 +3379,7 @@ at point. With prefix argument, prompt for ACTION-KIND."
`(defun ,name (beg &optional end) `(defun ,name (beg &optional end)
,(format "Execute `%s' code actions between BEG and END." kind) ,(format "Execute `%s' code actions between BEG and END." kind)
(interactive (eglot--region-bounds)) (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-organize-imports "source.organizeImports")
(eglot--code-action eglot-code-action-extract "refactor.extract") (eglot--code-action eglot-code-action-extract "refactor.extract")
@ -3659,13 +3662,11 @@ If NOERROR, return predicate, else erroring function."
;;; Hacks ;;; Hacks
;;; ;;;
;; FIXME: Although desktop.el compatibility is Emacs bug#56407, the ;; Emacs bug#56407, the optimal solution is in desktop.el, but that's
;; optimal solution agreed to there is a bit more work than what I ;; harder. For now, use `with-eval-after-load'. See also github#1183.
;; 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'
(with-eval-after-load 'desktop (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 ;;; Misc

View file

@ -146,7 +146,10 @@ Otherwise, `find-tag-default' is used."
(define-obsolete-variable-alias 'find-tag-marker-ring-length (define-obsolete-variable-alias 'find-tag-marker-ring-length
'tags-location-ring-length "25.1") '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 (defcustom tags-tag-face 'default
"Face for tags in the output of `tags-apropos'." "Face for tags in the output of `tags-apropos'."
@ -181,8 +184,9 @@ Example value:
(sexp :tag "Tags to search"))) (sexp :tag "Tags to search")))
:version "21.1") :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 (make-obsolete-variable
'find-tag-marker-ring 'find-tag-marker-ring
"use `xref-push-marker-stack' or `xref-go-back' instead." "use `xref-push-marker-stack' or `xref-go-back' instead."

View file

@ -511,19 +511,28 @@ This variant of `rx' supports common Python named REGEXPS."
(''string (''string
`(let ((ppss (or ,syntax-ppss (syntax-ppss)))) `(let ((ppss (or ,syntax-ppss (syntax-ppss))))
(and (nth 3 ppss) (nth 8 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 (''paren
`(nth 1 (or ,syntax-ppss (syntax-ppss)))) `(nth 1 (or ,syntax-ppss (syntax-ppss))))
(_ form)))) (_ form))))
(defun python-syntax-context (type &optional syntax-ppss) (defun python-syntax-context (type &optional syntax-ppss)
"Return non-nil if point is on TYPE using 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." character address of the specified TYPE."
(declare (compiler-macro python-syntax--context-compiler-macro)) (declare (compiler-macro python-syntax--context-compiler-macro))
(let ((ppss (or syntax-ppss (syntax-ppss)))) (let ((ppss (or syntax-ppss (syntax-ppss))))
(pcase type (pcase type
('comment (and (nth 4 ppss) (nth 8 ppss))) ('comment (and (nth 4 ppss) (nth 8 ppss)))
('string (and (nth 3 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)) ('paren (nth 1 ppss))
(_ nil)))) (_ nil))))
@ -4805,9 +4814,7 @@ Optional argument JUSTIFY defines if the paragraph should be justified."
((python-syntax-context 'comment) ((python-syntax-context 'comment)
(funcall python-fill-comment-function justify)) (funcall python-fill-comment-function justify))
;; Strings/Docstrings ;; Strings/Docstrings
((save-excursion (or (python-syntax-context 'string) ((python-info-triple-quoted-string-p)
(equal (string-to-syntax "|")
(syntax-after (point)))))
(funcall python-fill-string-function justify)) (funcall python-fill-string-function justify))
;; Decorators ;; Decorators
((equal (char-after (save-excursion ((equal (char-after (save-excursion
@ -4833,10 +4840,7 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
(let* ((str-start-pos (let* ((str-start-pos
(set-marker (set-marker
(make-marker) (make-marker)
(or (python-syntax-context 'string) (python-info-triple-quoted-string-p)))
(and (equal (string-to-syntax "|")
(syntax-after (point)))
(point)))))
;; JT@2021-09-21: Since bug#49518's fix this will always be 1 ;; JT@2021-09-21: Since bug#49518's fix this will always be 1
(num-quotes (python-syntax-count-quotes (num-quotes (python-syntax-count-quotes
(char-after str-start-pos) str-start-pos)) (char-after str-start-pos) str-start-pos))
@ -6043,6 +6047,21 @@ point's current `syntax-ppss'."
((python-info-looking-at-beginning-of-defun)) ((python-info-looking-at-beginning-of-defun))
(t nil)))))) (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 () (defun python-info-encoding-from-cookie ()
"Detect current buffer's encoding from its coding cookie. "Detect current buffer's encoding from its coding cookie.
Returns the encoding as a symbol." Returns the encoding as a symbol."

View file

@ -355,8 +355,10 @@ backward."
(t (goto-char start) nil)))) (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") (make-obsolete-variable 'xref-marker-ring-length nil "29.1")
(defcustom xref-prompt-for-identifier '(not xref-find-definitions (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") (make-obsolete-variable 'xref--marker-ring 'xref--history "29.1")
(defun xref-set-marker-ring-length (_var _val) (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) nil)
(defun xref--make-xref-history () (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) (defun xref-push-marker-stack (&optional m)
"Add point M (defaults to `point-marker') to the marker stack. "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))) (xref--push-backward (or m (point-marker)))
(let ((history (xref--get-history))) (let ((history (xref--get-history)))
(dolist (mk (cdr history)) (dolist (mk (cdr history))
@ -527,7 +531,7 @@ To undo, use \\[xref-go-forward]."
;;;###autoload ;;;###autoload
(defun xref-go-forward () (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) (interactive)
(let ((history (xref--get-history))) (let ((history (xref--get-history)))
(if (null (cdr history)) (if (null (cdr history))

View file

@ -163,7 +163,7 @@ of previous VARs.
(defmacro setq-local (&rest pairs) (defmacro setq-local (&rest pairs)
"Make each VARIABLE buffer-local and assign to it the corresponding VALUE. "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 make VARIABLE buffer-local and assign to it the corresponding VALUE
of the pair. The VARIABLEs are literal symbols and should not be quoted. of the pair. The VARIABLEs are literal symbols and should not be quoted.

View file

@ -887,22 +887,23 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx,
keymap_end: keymap_end:
/* We have scanned the entire keymap, and not found a binding for /* We have scanned the entire keymap, and not found a binding for
IDX. Let's add one. */ IDX. Let's add one. */
{ if (!remove)
Lisp_Object elt; {
Lisp_Object elt;
if (CONSP (idx) && CHARACTERP (XCAR (idx))) if (CONSP (idx) && CHARACTERP (XCAR (idx)))
{ {
/* IDX specifies a range of characters, and not all of them /* IDX specifies a range of characters, and not all of them
were handled yet, which means this keymap doesn't have a were handled yet, which means this keymap doesn't have a
char-table. So, we insert a char-table now. */ char-table. So, we insert a char-table now. */
elt = Fmake_char_table (Qkeymap, Qnil); elt = Fmake_char_table (Qkeymap, Qnil);
Fset_char_table_range (elt, idx, NILP (def) ? Qt : def); Fset_char_table_range (elt, idx, NILP (def) ? Qt : def);
} }
else else
elt = Fcons (idx, def); elt = Fcons (idx, def);
CHECK_IMPURE (insertion_point, XCONS (insertion_point)); CHECK_IMPURE (insertion_point, XCONS (insertion_point));
XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point))); XSETCDR (insertion_point, Fcons (elt, XCDR (insertion_point)));
} }
} }
return def; return def;

View file

@ -305,6 +305,22 @@
(should-not (abbrev-table-p translation-table-vector)) (should-not (abbrev-table-p translation-table-vector))
(should (abbrev-table-p (make-abbrev-table)))) (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) (provide 'abbrev-tests)
;;; abbrev-tests.el ends here ;;; abbrev-tests.el ends here

View file

@ -255,6 +255,27 @@ aliqua."
;;; Font-lock and syntax ;;; 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 () (ert-deftest python-syntax-after-python-backspace ()
;; `python-indent-dedent-line-backspace' garbles syntax ;; `python-indent-dedent-line-backspace' garbles syntax
(python-tests-with-temp-buffer (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) (fill-paragraph)
(should (= (current-indentation) 0)))) (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 ;;; Mark
@ -6491,6 +6560,56 @@ class Class:
(python-tests-look-at "'''Not a method docstring.'''") (python-tests-look-at "'''Not a method docstring.'''")
(should (not (python-info-docstring-p))))) (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 () (ert-deftest python-info-encoding-from-cookie-1 ()
"Should detect it on first line." "Should detect it on first line."
(python-tests-with-temp-buffer (python-tests-with-temp-buffer