From 2c1edf5f62adbe1b698e21517a455a2bac09a025 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 25 Jan 2025 10:48:38 -0500 Subject: [PATCH 001/279] doc/lispref/modes.texi (Syntactic Font Lock): Update for commit 644c6b414f3 Remove outdated `nil` element, as discussed in https://lists.gnu.org/archive/html/help-gnu-emacs/2025-01/msg00244.html --- doc/lispref/modes.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index aa13f1316c6..31d420eedb6 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -4121,7 +4121,7 @@ This variable is normally set through the ``other'' elements in @lisp (setq-local font-lock-defaults `(,python-font-lock-keywords - nil nil nil nil + nil nil nil (font-lock-syntactic-face-function . python-font-lock-syntactic-face-function))) @end lisp From 3c820cd2650a3126ac13fc4825147271285da519 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 21:36:32 +0100 Subject: [PATCH 002/279] Document insert-directory-program as a user option * doc/lispref/files.texi (Contents of Directories): Document 'insert-directory-program' as a user option. --- doc/lispref/files.texi | 10 +++++----- etc/NEWS | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 1064f347a12..97ad7c6b7fa 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -3227,11 +3227,11 @@ for the sake of dired. However, the normally equivalent short as any other option. @end defun -@defvar insert-directory-program -This variable's value is the program to run to generate a directory listing -for the function @code{insert-directory}. It is ignored on systems -which generate the listing with Lisp code. -@end defvar +@defopt insert-directory-program +This user option specifies the program to run to generate a directory +listing for the function @code{insert-directory}. It is ignored on +systems that generate the listing with Lisp code. +@end defopt @node Create/Delete Dirs @section Creating, Copying and Deleting Directories diff --git a/etc/NEWS b/etc/NEWS index ce5290171a1..ef3962db2eb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -655,6 +655,7 @@ When visiting a script that invokes 'env -S INTERPRETER ARGS...' in its shebang line, Emacs will now skip over 'env -S' and deduce the major mode based on the interpreter after 'env -S'. ++++ *** 'insert-directory-program' is now a user option. On *BSD and macOS systems, this user option now defaults to the "gls" executable, if it exists. This should remove the need to change its From a87c382cabaec41f8901c858d4abd52305622b9e Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 21:36:43 +0100 Subject: [PATCH 003/279] ; * etc/NEWS: Add missing temporary documentation tags. --- etc/NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index ef3962db2eb..69ee6da62e9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -593,6 +593,7 @@ Use 'TAB' in the minibuffer to show or hide the password. Alternatively, click the new show-password icon on the mode-line with 'mouse-1' to toggle the visibility of the password. ++++ *** 'advice-remove' is now an interactive command. When called interactively, 'advice-remove' now prompts for an advised function to the advice to remove. @@ -1785,6 +1786,7 @@ feeds, as inheriting backends of 'nnfeed'. This allow users to add Atom Syndication Format feeds to Gnus as servers. +--- *** The 'nnweb-type' option 'gmane' has been removed. The gmane.org website is, sadly, down since a number of years with no prospect of it coming back. Therefore, it is no longer valid to set From 74dcfe155a9cd42fe4d352f031297169bf3abb41 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 21:37:56 +0100 Subject: [PATCH 004/279] ; * etc/NEWS: Remove temporary documentation markers. --- etc/NEWS | 437 ------------------------------------------------------- 1 file changed, 437 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 69ee6da62e9..53f75d120d2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -15,16 +15,9 @@ in older Emacs versions. You can narrow news to a specific version by calling 'view-emacs-news' with a prefix argument or by typing 'C-u C-h C-n'. -Temporary note: -+++ indicates that all relevant manuals in doc/ have been updated. ---- means no change in the manuals is needed. -When you add a new item, use the appropriate mark if you are sure it -applies, and please also update docstrings as needed. - * Installation Changes in Emacs 30.1 ---- ** Native compilation is now enabled by default. 'configure' will enable the Emacs Lisp native compiler, so long as libgccjit is present and functional on the system. To disable native @@ -32,20 +25,17 @@ compilation, configure Emacs with the option: ./configure --with-native-compilation=no -+++ ** Emacs has been ported to the Android operating system. This requires Emacs to be compiled on another computer. The Android NDK, SDK, and a suitable Java compiler must also be installed. See the file "java/INSTALL" for more details. ---- ** Native JSON support is now always available; libjansson is no longer used. No external library is required. The '--with-json' configure option has been removed. 'json-available-p' now always returns non-nil and is only kept for compatibility. ---- ** Emacs now defaults to the ossaudio library for sound on NetBSD and OpenBSD. Previously, configure used ALSA libraries if installed on the system when configured '--with-sound=yes' (which is the default), with fallback @@ -55,7 +45,6 @@ and to resolve potential incompatibilities between GNU/Linux and *BSD versions of ALSA. Use '--with-sound=alsa' to build with ALSA on these operating systems instead. ---- ** New configuration option '--disable-gc-mark-trace'. This disables the GC mark trace buffer for about 5% better garbage collection performance. Doing so may make it more difficult for Emacs @@ -65,7 +54,6 @@ why the mark trace buffer is enabled by default. * Startup Changes in Emacs 30.1 ---- ** On GNU/Linux, Emacs is now the default application for 'org-protocol'. Org mode provides a way to quickly capture bookmarks, notes, and links using 'emacsclient': @@ -79,7 +67,6 @@ arranges for Emacs to be the default application for the 'org-protocol' URI scheme. See the Org mode manual, Info node "(org) Protocols" for more details. -+++ ** New variable lets Lisp code read emacsclient arguments. When '--eval' is passed to emacsclient and Emacs is evaluating each argument, the new variable 'server-eval-args-left' is set to those @@ -92,7 +79,6 @@ escaping (to protect them from the shell). * Incompatible Changes in Emacs 30.1 ---- ** Tree-Sitter modes are now declared as submodes of the non-TS modes. In order to help the use of those Tree-Sitter modes, they are now declared to have the corresponding non-Tree-Sitter mode as an @@ -133,7 +119,6 @@ variants of major modes are available, because that variable overrides the remapping Emacs might decide to perform as result of loading Lisp files and features. ---- ** Mouse wheel events should now always be 'wheel-up/down/left/right'. At those places where the old 'mouse-4/5/6/7' events could still occur (i.e., X11 input in the absence of XInput2, and 'xterm-mouse-mode'), @@ -143,7 +128,6 @@ The old variables 'mouse-wheel-up-event', 'mouse-wheel-down-event', 'mouse-wheel-left-event', and 'mouse-wheel-right-event' are thereby obsolete. -+++ ** 'completion-auto-help' now affects 'icomplete-in-buffer'. Previously, 'completion-auto-help' mostly affected only minibuffer completion. Now, if 'completion-auto-help' has the value 'lazy', then @@ -153,7 +137,6 @@ after the 'completion-at-point' command has been invoked twice, and if completely suppressed. Thus, if you use 'icomplete-in-buffer', ensure 'completion-auto-help' is not customized to 'lazy' or nil. -+++ ** The "*Completions*" buffer now always accompanies 'icomplete-in-buffer'. Previously, it was not consistent whether the "*Completions*" buffer would appear when using 'icomplete-in-buffer'. Now the "*Completions*" buffer @@ -164,27 +147,23 @@ to your init file: (advice-add 'completion-at-point :after #'minibuffer-hide-completions) ---- ** The default process filter was rewritten in native code. The round-trip through the Lisp function 'internal-default-process-filter' is skipped when the process filter is the default one. It is reimplemented in native code, reducing GC churn. To undo this change, set 'fast-read-process-output' to nil. -+++ ** Network Security Manager now warns about 3DES by default. This cypher is no longer recommended owing to a major vulnerability disclosed in 2016, and its small 112 bit key size. Emacs now warns about its use also when 'network-security-level' is set to 'medium' (the default). See 'network-security-protocol-checks'. ---- ** Network Security Manager now warns about <2048 bits in DH key exchange. Emacs used to warn for ephemeral Diffie-Hellman (DHE) key exchanges with prime numbers smaller than 1024 bits. Since more servers now support it, this number has been bumped to 2048 bits. -+++ ** URL now never sends user email addresses in HTTP requests. Emacs never sent email addresses by default, but it used to be possible to customize 'url-privacy-level' so that the user's email @@ -196,7 +175,6 @@ removed, as it was considered more dangerous than useful. RFC 9110 To send an email address in the header of individual HTTP requests, see the variable 'url-request-extra-headers'. ---- ** 'pixel-scroll-precision-mode' sets 'make-cursor-line-fully-visible'. 'pixel-scroll-precision-mode' sets 'make-cursor-line-fully-visible' to a nil value globally, since the usual requirement of the Emacs display to @@ -206,7 +184,6 @@ expectations. * Changes in Emacs 30.1 -+++ ** New user option 'trusted-content' to allow potentially dangerous features. This option lists those files and directories whose content Emacs should consider as sufficiently trusted to run any part of the code contained @@ -215,14 +192,11 @@ For example, Flymake's backend for Emacs Lisp consults this option and disables itself with an "untrusted content" warning if the file is not listed. ---- ** Emacs now supports Unicode Standard version 15.1. -+++ ** Emacs now comes with Org v9.7. See the file "etc/ORG-NEWS" for user-visible changes in Org. -+++ ** Improved support for touchscreen devices. On systems that understand them (at present X, Android, PGTK, and MS-Windows), many touch screen gestures are now implemented and @@ -231,7 +205,6 @@ bar buttons and opening menus has been added. Countless packages, such as Dired and Custom, have been adjusted to better understand touch screen input. -+++ ** Support for styled underline face attributes. These are implemented as new values of the 'style' attribute in a face underline specification, 'double-line', 'dots', and 'dashes', and are @@ -240,36 +213,30 @@ database entry defines the 'Su' or 'Smulx' capability, Emacs will also emit the prescribed escape sequence to render faces with such styles on TTY frames. ---- ** Support for underline colors on TTY frames. Colors specified in the underline face will now also be displayed on TTY frames on terminals that support the 'Su' or 'Smulx' capabilities. -+++ ** Modeline elements can now be right-aligned. Anything following the symbol 'mode-line-format-right-align' in 'mode-line-format' will be right-aligned. Exactly where it is right-aligned to is controlled by the new user option 'mode-line-right-align-edge'. ---- ** X selection requests are now handled much faster and asynchronously. This means it should be less necessary to disable the likes of 'select-active-regions' when Emacs is running over a slow network connection. ---- ** Emacs now updates invisible frames that are made visible by a compositor. If an invisible or an iconified frame is shown to the user by the compositing manager, Emacs will now redisplay such a frame even though 'frame-visible-p' returns nil or 'icon' for it. This can happen, for example, as part of preview for iconified frames. -+++ ** Most file notification backends detect unmounting of a watched filesystem. The only exception is w32notify. -+++ ** The ':map' property of images is now recomputed when image is transformed. Images with clickable maps now work as expected after you run commands such as 'image-increase-size', 'image-decrease-size', 'image-rotate', @@ -279,13 +246,11 @@ from recomputing image maps. ** Minibuffer and Completions -+++ *** New commands 'previous-line-completion' and 'next-line-completion'. Bound to '' and '' arrow keys, respectively, they navigate the "*Completions*" buffer vertically by lines, wrapping at the top/bottom when 'completion-auto-wrap' is non-nil. -+++ *** New user option 'minibuffer-visible-completions'. When customized to non-nil, you can use arrow keys in the minibuffer to navigate the completions displayed in the "*Completions*" window. @@ -294,7 +259,6 @@ completions window. When the completions window is not visible, then all these keys have their usual meaning in the minibuffer. This option is supported for in-buffer completion as well. ---- *** Selected completion candidates are deselected on typing. When you type at the minibuffer prompt, the current completion candidate will be un-highlighted, and point in the "*Completions*" window @@ -306,13 +270,11 @@ the minibuffer contents instead. This deselection behavior can be controlled with the new user option 'completion-auto-deselect', which is t by default. -+++ *** New value 'historical' for user option 'completions-sort'. When 'completions-sort' is set to 'historical', completion candidates will be first sorted alphabetically, and then re-sorted by their order in the minibuffer history, with more recent candidates appearing first. -+++ *** 'completion-category-overrides' supports more metadata. The new supported completion properties are 'cycle-sort-function', 'display-sort-function', 'annotation-function', 'affixation-function', @@ -320,21 +282,18 @@ and 'group-function'. You can now customize them for any category in 'completion-category-overrides' that will override the properties defined in completion metadata. -+++ *** 'completion-extra-properties' supports more metadata. The new supported completion properties are 'category', 'group-function', 'display-sort-function', and 'cycle-sort-function'. ** Windows -+++ *** New command 'toggle-window-dedicated'. This makes it easy to interactively mark a specific window as dedicated, so it won't be reused by 'display-buffer'. This can be useful for complicated window setups. It is bound to 'C-x w d' globally. -+++ *** "d" in the mode line now indicates that the window is dedicated. Windows have always been able to be dedicated to a specific buffer; see 'window-dedicated-p'. Now the mode line indicates the dedicated @@ -343,7 +302,6 @@ dedicated and "D" if the window is strongly dedicated. This indicator appears before the buffer name, and after the buffer modification and remote buffer indicators (usually "---" together). -+++ *** New action alist entry 'some-window' for 'display-buffer'. It specifies which window 'display-buffer-use-some-window' should prefer. For example, when 'display-buffer-base-action' is customized to @@ -351,25 +309,21 @@ For example, when 'display-buffer-base-action' is customized to in the same most recently used window from consecutive calls of 'display-buffer' (in a configuration with more than two windows). -+++ *** New action alist entry 'category' for 'display-buffer'. If the caller of 'display-buffer' passes '(category . symbol)' in its 'action' argument, you can match the displayed buffer by adding '(category . symbol)' to the condition part of 'display-buffer-alist' entries. -+++ *** New action alist entry 'post-command-select-window' for 'display-buffer'. It specifies whether the window of the displayed buffer should be selected or deselected at the end of executing the current command. -+++ *** New variable 'window-restore-killed-buffer-windows'. It specifies how 'set-window-configuration' and 'window-state-put' should proceed with windows whose buffer was killed after the corresponding configuration or state was recorded. ---- *** New variable 'window-point-context-set-function'. It can be used to set a context for window point in all windows by 'window-point-context-set' before calling 'current-window-configuration' @@ -379,14 +333,12 @@ and 'window-state-get'. Then later another new variable 'window-state-put' to restore positions of window points according to the context stored in a window parameter. -+++ *** New functions 'set-window-cursor-type' and 'window-cursor-type'. 'set-window-cursor-type' sets a per-window cursor type, and 'window-cursor-type' queries this setting for a given window. Windows are always created with a 'window-cursor-type' of t, which means to consult the variable 'cursor-type' as before. ---- *** The user option 'display-comint-buffer-action' is now obsolete. You can use a '(category . comint)' condition in 'display-buffer-alist' to match buffers displayed by comint-related commands. Another @@ -395,60 +347,50 @@ for which you can use '(category . tex-shell)'. ** Tool bars -+++ *** Tool bars can now be placed on the bottom on more systems. The 'tool-bar-position' frame parameter can be set to 'bottom' on all window systems other than macOS and GNUstep (Nextstep). -+++ *** New global minor mode 'modifier-bar-mode'. When this minor mode is enabled, the tool bar displays buttons representing modifier keys. Clicking on these buttons applies the corresponding modifiers to the next input event. -+++ *** New user option 'tool-bar-always-show-default'. When non-nil, the tool bar at the top of a frame does not show buffer local customization of the tool bar. The default value is nil. ** Tab Bars and Tab Lines ---- *** New user option 'tab-bar-select-restore-context'. It uses 'window-point-context-set' to save contexts where window points were located before switching away from the tab, and 'window-point-context-use' to restore positions of window points after switching back to that tab. ---- *** New user option 'tab-bar-select-restore-windows'. It defines what to do with windows whose buffer was killed since the tab was last selected. By default it displays a placeholder buffer with the name " *Old buffer *" that provides information about the name of the killed buffer that was displayed in that window. ---- *** New user option 'tab-bar-tab-name-format-functions'. It can be used to add, remove and reorder functions that change the appearance of every tab on the tab bar. ---- *** New hook 'tab-bar-tab-post-select-functions'. ---- *** New keymap 'tab-bar-mode-map'. By default it contains a keybinding 'C-TAB' to switch tabs, but only when 'C-TAB' is not bound globally. You can unbind it if it conflicts with 'C-TAB' in other modes. ---- *** New keymap 'tab-line-mode-map'. By default it contains keybindings for switching tabs: 'C-x ', 'C-x ', 'C-x C-', 'C-x C-'. You can unbind them if you want to use these keys for the commands 'previous-buffer' and 'next-buffer'. ---- *** Default list of tab-line tabs is changed to support a fixed order. This means that 'tab-line-tabs-fixed-window-buffers', the new default tabs function, is like the previous 'tab-line-tabs-window-buffers' where @@ -458,29 +400,24 @@ original order of buffers on the tab line, even after switching between these buffers. You can drag the tabs and release at a new position to manually reorder the buffers on the tab line. ---- *** New user option 'tab-line-tabs-buffer-group-function'. It provides two choices to group tab buffers by major mode and by project name. ---- *** Buffers on tab-line group tabs are now sorted alphabetically. This will keep the fixed order of tabs, even after switching between them. ** Help -+++ *** New command 'help-find-source'. Switch to a buffer visiting the source of what is being described in "*Help*". It is bound to 'C-h 4 s' globally. ---- *** New user option 'describe-bindings-outline-rules'. This user option controls outline visibility in the output buffer of 'describe-bindings' when 'describe-bindings-outline' is non-nil. ---- *** 'describe-function' shows the function's inferred type when available. For native compiled Lisp functions, 'describe-function' prints (after the signature) the automatically inferred function type as well. If the @@ -489,18 +426,15 @@ function's type was explicitly declared (via the 'declare' form's controlled by the new user option 'help-display-function-type', which is by default t; customize to nil to disable function type display. ---- *** 'describe-function' now shows the type of the function object. The text used to say things like "car is a built-in function" whereas it now says "car is a primitive-function" where "primitive-function" is the name of the symbol returned by 'cl-type-of'. You can click on those words to get information about that type. ---- *** 'C-h m' ('describe-mode') uses outlining by default. Set 'describe-mode-outline' to nil to get back the old behavior. ---- *** 'C-h k' ('describe-key') shows Unicode name. For keybindings which produce single characters via translation or input methods, 'C-h k' now shows the Unicode name of the produced character in @@ -510,7 +444,6 @@ addition to the character itself, e.g. € 'EURO SIGN' (translated from C-x 8 E) ---- *** 'C-h b' ('describe-bindings') shows Unicode names. For keybindings which produce single characters via translation (such as those using the 'C-x 8' or 'A-' prefix, or 'dead-acute', 'dead-grave', @@ -522,54 +455,42 @@ itself, i.e. and so on. -+++ *** Multi-character key echo now ends with a suggestion to use Help. Customize 'echo-keystrokes-help' to nil to prevent that. ** Customize -+++ *** New command 'customize-dirlocals'. This command pops up a buffer to edit the settings in ".dir-locals.el". ---- *** New command 'customize-toggle-option'. This command can toggle boolean options for the duration of a session. -+++ *** New prefix argument for modifying directory-local variables. The commands 'add-dir-local-variable', 'delete-dir-local-variable' and 'copy-file-locals-to-dir-locals' now take an optional prefix argument, to enter the file name where you want to modify directory-local variables. -+++ *** New user option 'safe-local-variable-directories'. This user option names directories in which Emacs will treat all directory-local variables as safe. -+++ ** CL Print -+++ *** There is a new chapter in the CL manual documenting cl-print.el. See the Info node "(cl) Printing". -+++ *** You can expand the "..." truncation everywhere. The code that allowed "..." to be expanded in the "*Backtrace*" buffer should now work anywhere the data is generated by 'cl-print'. -+++ *** The 'backtrace-ellipsis' button is replaced by 'cl-print-ellipsis'. -+++ *** hash-tables' contents can be expanded via the ellipsis. -+++ *** Modes can control the expansion via 'cl-print-expand-ellipsis-function'. -+++ *** New setting 'raw' for 'cl-print-compiled'. This setting causes byte-compiled functions to be printed in full by 'prin1'. A button on this output can be activated to disassemble the @@ -577,28 +498,23 @@ function. ** Miscellaneous -+++ *** New command 'kill-matching-buffers-no-ask'. This works like 'kill-matching-buffers', but without asking for confirmation. -+++ *** 'recover-file' can show diffs between auto save file and current file. When answering the prompt with "diff" or "=", it now shows the diffs between the auto save file and the current file. -+++ *** 'read-passwd' can toggle the visibility of passwords. Use 'TAB' in the minibuffer to show or hide the password. Alternatively, click the new show-password icon on the mode-line with 'mouse-1' to toggle the visibility of the password. -+++ *** 'advice-remove' is now an interactive command. When called interactively, 'advice-remove' now prompts for an advised function to the advice to remove. ---- *** New user option 'uniquify-dirname-transform'. This can be used to customize how buffer names are uniquified, by making arbitrary transforms on the buffer's directory name (whose @@ -607,70 +523,57 @@ can use this to distinguish between buffers visiting files with the same base name that belong to different projects by using the provided transform function 'project-uniquify-dirname-transform'. -+++ *** New user option 'remote-file-name-inhibit-delete-by-moving-to-trash'. When non-nil, this option suppresses moving remote files to the local trash when deleting. Default is nil. ---- *** New user option 'remote-file-name-inhibit-auto-save'. If this user option is non-nil, 'auto-save-mode' will not auto-save remote buffers. The default is nil. -+++ *** New user option 'remote-file-name-access-timeout'. If a positive number, this option limits the call of 'access-file' for remote files to that number of seconds. Default is nil. -+++ *** New user option 'yes-or-no-prompt'. This allows the user to customize the prompt that is appended by 'yes-or-no-p' when asking questions. The default value is "(yes or no) ". ---- *** New user option 'menu-bar-close-window'. When non-nil, selecting "Close" from the "File" menu or clicking "Close" in the tool bar will result in the current window being deleted, if possible. The default is nil, and these gestures kill the buffer shown in the current window, but don't delete the window. ---- *** New face 'display-time-date-and-time'. This is used for displaying the time and date components of 'display-time-mode'. ---- *** New face 'appt-notification' for 'appt-display-mode-line'. It can be used to customize the look of the appointment notification displayed on the mode line when 'appt-display-mode-line' is non-nil. ---- *** New icon images for general use. Several symbolic icons have been added to "etc/images/symbols", including plus, minus, check-mark, star, etc. ---- *** Emacs now recognizes shebang lines that pass '-S'/'--split-string' to 'env'. When visiting a script that invokes 'env -S INTERPRETER ARGS...' in its shebang line, Emacs will now skip over 'env -S' and deduce the major mode based on the interpreter after 'env -S'. -+++ *** 'insert-directory-program' is now a user option. On *BSD and macOS systems, this user option now defaults to the "gls" executable, if it exists. This should remove the need to change its value when installing GNU coreutils using something like ports or Homebrew. -+++ *** 'write-region-inhibit-fsync' now defaults to t in interactive mode. This is the default in batch mode since Emacs 24. ---- *** The default value of 'read-process-output-max' was increased to 65536. -+++ *** 'url-gateway-broken-resolution' is now obsolete. This option was intended for use on SunOS 4.x and Ultrix systems, neither of which have been supported by Emacs since version 23.1. @@ -680,7 +583,6 @@ The user option 'url-gateway-nslookup-program' and the command * Editing Changes in Emacs 30.1 -+++ ** New minor mode 'visual-wrap-prefix-mode'. When enabled, continuation lines displayed for a wrapped long line will receive a 'wrap-prefix' automatically computed from the line's @@ -694,7 +596,6 @@ buffers. (This minor mode is the 'adaptive-wrap' ELPA package renamed and lightly edited for inclusion in Emacs.) -+++ ** New global minor mode 'kill-ring-deindent-mode'. When enabled, text being saved to the kill ring will be de-indented by the column number at its start. For example, saving the entire @@ -716,7 +617,6 @@ long_function_with_several_arguments (argument_1_compute (), This omits the two columns of extra indentation that would otherwise be copied from the second and third lines and saved to the kill ring. ---- ** New command 'replace-regexp-as-diff'. It reads a regexp to search for and a string to replace with, then displays a buffer with replacements as diffs. After reviewing the @@ -726,7 +626,6 @@ a patch to the current file buffer. There are also new commands in a list of specified files, and 'dired-do-replace-regexp-as-diff' that shows as diffs replacements in the marked files in Dired. -+++ ** New mode of prompting for register names and showing preview. The new user option 'register-use-preview' can be customized to the value t or 'insist' to request a different user interface of prompting for @@ -739,7 +638,6 @@ The default value of 'register-use-preview' ('traditional') preserves the behavior of Emacs 29 and before. See the Info node "(emacs) Registers" for more details about the new UI and its variants. -+++ ** New advanced macro counter commands. New commands have been added to implement advanced macro counter functions. @@ -755,7 +653,6 @@ The commands 'C-x C-k C-q =', 'C-x C-k C-q <', and 'C-x C-k C-q >' compare the macro counter with an optional prefix and terminate the macro if the comparison succeeds. -+++ ** New mode 'kmacro-menu-mode' and new command 'list-keyboard-macros'. The new command 'list-keyboard-macros' is the keyboard-macro version of commands like 'list-buffers' and 'list-processes', creating a listing @@ -764,19 +661,16 @@ of the currently existing keyboards macros using the new mode duplicating them, deleting them, and editing their counters, formats, and keys. ---- ** On X, Emacs now supports input methods which perform "string conversion". This means an input method can now ask Emacs to delete text surrounding point and replace it with something else, as well as query Emacs for surrounding text. If your input method allows you to "undo" mistaken compositions, this will now work as well. ---- ** New user option 'duplicate-region-final-position'. It controls the placement of point and the region after duplicating a region with 'duplicate-dwim'. -+++ ** New user option 'mouse-prefer-closest-glyph'. When enabled, clicking or dragging with the mouse will put the point or start the drag in front of the buffer position corresponding to the @@ -787,14 +681,12 @@ whereas if the mouse pointer is in the left half of a glyph, point will be put in front the buffer position corresponding to that glyph. By default this is disabled. ---- ** New pre-defined values for 'electric-quote-chars'. The available customization options for 'electric-quote-chars' have been updated with common pairs of quotation characters, including "‘", "’", "“", "”", "«", "»", "‹", "›", "‚", "„", "「", "」", "『", and "』". The default is unchanged. -+++ ** 'M-TAB' now invokes 'completion-at-point' in Text mode. By default, Text mode no longer binds 'M-TAB' to 'ispell-complete-word'. Instead, this mode arranges for 'completion-at-point', globally bound to @@ -805,7 +697,6 @@ customizing the new user option 'text-mode-ispell-word-completion'. ** Internationalization ---- *** Mode-line mnemonics for some coding-systems have changed. The mode-line mnemonic for 'utf-7' is now the lowercase 'u', to be consistent with the other encodings of this family. @@ -821,7 +712,6 @@ previous behavior of showing 'U' in the mode line for 'koi8-u': (coding-system-put 'koi8-u :mnemonic ?U) ---- *** 'vietnamese-tcvn' is now a coding system alias for 'vietnamese-vscii'. VSCII-1 and TCVN-5712 are different names for the same character encoding. Therefore, the duplicate coding system definition has been @@ -830,7 +720,6 @@ dropped in favor of an alias. The mode-line mnemonic for 'vietnamese-vscii' and its aliases is the lowercase letter "v". ---- *** Users in CJK locales can control width of some non-CJK characters. Some characters are considered by Unicode as "ambiguous" with respect to their display width: either "full-width" (i.e., taking 2 columns on @@ -847,25 +736,20 @@ or narrow (if the variable is customized to the nil value). This setting affects the results of 'string-width' and similar functions in CJK locales. ---- *** New input methods for the Urdu, Pashto, and Sindhi languages. These languages are spoken in Pakistan and Afghanistan. ---- *** New input method "english-colemak". This input method supports the Colemak keyboard layout. ---- *** Additional 'C-x 8' key translations for "æ" and "Æ". These characters can now be input with 'C-x 8 a e' and 'C-x 8 A E', respectively, in addition to the existing translations 'C-x 8 / e' and 'C-x 8 / E'. ---- *** New 'C-x 8' key translations for "low" quotes "„", and "‚". These can now be entered with 'C-x , "' and 'C-x , ''. ---- *** New German language 'C-x 8' key translations for quotation marks. The characters "„", "“", and "”" can now be entered with 'C-x 8 v', 'C-x 8 b' and 'C-x 8 n'. The single versions "‚", "‘", and "’" can now @@ -873,7 +757,6 @@ be entered with 'C-x 8 V', 'C-x 8 B' and 'C-x 8 N'. These characters are used for the official German quoting style. Using them requires activating German language support via 'iso-transl-set-language'. ---- *** "latin-prefix" and "latin-postfix" quotation marks additions. These input methods can now produce single, double and "low" left and right quotation marks: @@ -883,20 +766,17 @@ right quotation marks: by using "[", "]", and "," for "left", "right", and "low" respectively to modify "'" and """. ---- *** "latin-prefix" and "latin-postfix" guillemets support. These input methods can now produce single guillemets "‹" and "›". For "latin-prefix" use "~~<" and "~~>", for "latin-postfix" use "<~" and ">~". Double guillemets ("«" and "»") were already supported. ---- *** New French language 'C-x 8' key translations for "‹" and "›". These characters can now be entered using 'C-x 8 ~ <' and 'C-x 8 ~ >', respectively, after activating French language support via 'iso-transl-set-language'. Double guillemets were already supported via 'C-x 8 <' and 'C-x 8 >' ---- *** Additional 'C-x 8' key translation for Euro "€" currency symbol. This can now be entered using 'C-x 8 E' in addition to the existing 'C-x 8 * E' translation. @@ -906,44 +786,37 @@ This can now be entered using 'C-x 8 E' in addition to the existing ** Outline mode -+++ *** New commands to show/hide outlines by regexp. 'C-c / h' ('outline-hide-by-heading-regexp') asks for a regexp and then hides the body lines of all outlines whose heading lines match the regexp. 'C-c / s' ('outline-show-by-heading-regexp') does the inverse: it shows the bodies of outlines that matched a regexp. -+++ *** 'outline-minor-mode' is supported in tree-sitter major modes. It can be used in all tree-sitter major modes that set either the variable 'treesit-simple-imenu-settings' or 'treesit-outline-predicate'. ** Info ---- *** New user option 'Info-url-alist'. This user option associates manual names with URLs. It affects the 'Info-goto-node-web' command. By default, associations for all Emacs-included manuals are set. Further associations can be added for arbitrary Info manuals. ---- *** Emacs can now display Info manuals compressed with 'lzip'. This requires the 'lzip' program to be installed on your system. ** GUD (Grand Unified Debugger) -+++ *** New user option 'gud-highlight-current-line'. When enabled, GUD will visually emphasize the line being executed upon pauses in the debuggee's execution, such as those occasioned by breakpoints being hit. -+++ *** New command 'lldb'. Run the LLDB debugger, analogous to the 'gud-gdb' command. ---- *** Variable order and truncation can now be configured in 'gdb-many-windows'. The new user option 'gdb-locals-table-row-config' allows users to configure the order and max length of various properties in the local @@ -959,7 +832,6 @@ If you want to get back the old behavior, set the user option to the value (setopt gdb-locals-table-row-config `((type . 0) (name . 0) (value . ,gdb-locals-value-limit))) -+++ *** New user option 'gdb-display-io-buffer'. If this is nil, command 'gdb' will neither create nor display a separate buffer for the I/O of the program being debugged, but will instead @@ -968,7 +840,6 @@ default is t, to preserve previous behavior. ** Grep -+++ *** New user option 'grep-use-headings'. When non-nil, the output of Grep is split into sections, one for each file, instead of having file names prefixed to each line. It is @@ -978,13 +849,11 @@ The default is nil. ** Compilation mode ---- *** The 'omake' matching rule is now disabled by default. This is because it partly acts by modifying other rules which may occasionally be surprising. It can be re-enabled by adding 'omake' to 'compilation-error-regexp-alist'. ---- *** Lua errors and stack traces are now recognized. Compilation mode now recognizes Lua language errors and stack traces. Every Lua error is recognized as a compilation error, and every Lua @@ -992,24 +861,20 @@ stack frame is recognized as a compilation info. ** Project -+++ *** New user option 'project-mode-line'. When non-nil, display the name of the current project on the mode line. Clicking 'mouse-1' on the project name pops up the project menu. The default value is nil. ---- *** New user option 'project-file-history-behavior'. Customizing it to 'relativize' makes commands like 'project-find-file' and 'project-find-dir' display previous history entries relative to the current project. ---- *** New user option 'project-key-prompt-style'. The look of the key prompt in the project switcher has been changed slightly. To get the previous one, set this option to 'brackets'. ---- *** Function 'project-try-vc' tries harder to find the responsible VCS. When 'project-vc-extra-root-markers' is non-nil, and causes a subdirectory project to be detected which is not a VCS root, Project now @@ -1017,7 +882,6 @@ additionally traverses the parent directories until a VCS root is found (if any), so that the ignore rules for that repository are used, and the file listing's performance is still optimized. -+++ *** New commands 'project-any-command' and 'project-prefix-or-any-command'. The former is now bound to 'C-x p o' by default. The latter is designed primarily for use as a value of @@ -1028,7 +892,6 @@ you can add this to your init script: (setopt project-switch-commands #'project-prefix-or-any-command) ---- *** New variable 'project-files-relative-names'. If it is non-nil, 'project-files' can return file names relative to the project root. Project backends can use this to improve the performance @@ -1036,26 +899,21 @@ of their 'project-files' implementation. ** VC ---- *** Log-Edit buffers now display a tool bar. This tool bar contains items for committing log entries and editing or generating log entries, among other editing operations. ---- *** New user option 'vc-git-shortlog-switches'. This is a string or a list of strings that specifies the Git log switches for shortlogs, such as the one produced by 'C-x v L'. 'vc-git-log-switches' is no longer used for shortlogs. ---- *** New value 'no-backend' for user option 'vc-display-status'. With this value only the revision number is displayed on the mode-line. ---- *** Obsolete command 'vc-switch-backend' re-added as 'vc-change-backend'. The command was previously obsoleted and unbound in Emacs 28. ---- *** Support for viewing VC change history across renames. When a fileset's VC change history ends at a rename, 'C-x v l' now prints the old name(s) and shows a button which jumps to the history of @@ -1066,17 +924,14 @@ Unlike when the '--follow' switch is used, commands to see the diff of the old revision ('d'), to check out an old file version ('f') or to annotate it ('a'), also work on revisions which precede renames. ---- *** 'vc-annotate' now abbreviates the Git revision in the buffer name. When using the Git backend, 'vc-annotate' will use an abbreviated revision identifier in its buffer name. To restore the previous behavior, set user option 'vc-annotate-use-short-revision' to nil. ---- *** New user option 'vc-git-file-name-changes-switches'. It allows tweaking the thresholds for rename and copy detection. ---- *** VC Directory buffers now display the upstream branch in Git repositories. The "upstream branch" is the branch from which 'vc-pull' fetches changes by default. In Git terms, the upstream branch of branch B is determined @@ -1088,7 +943,6 @@ the "Tracking" header. ** Diff mode ---- *** New user option 'diff-refine-nonmodified'. When this is non-nil, 'diff-refine-hunk' will highlight lines that were added or removed in their entirety (as opposed to modified lines, where @@ -1096,26 +950,22 @@ some parts of the line were modified), using the same faces as for highlighting the words added and removed within modified lines. The default value is nil. -+++ *** 'diff-ignore-whitespace-hunk' can now be applied to all hunks. When called with a non-nil prefix argument, 'diff-ignore-whitespace-hunk' now iterates over all the hunks in the current diff, regenerating them without whitespace changes. -+++ *** New user option 'diff-ignore-whitespace-switches'. This allows changing which type of whitespace changes are ignored when regenerating hunks with 'diff-ignore-whitespace-hunk'. Defaults to the previously hard-coded "-b". -+++ *** New command 'diff-apply-buffer' bound to 'C-c RET a'. It applies the diff in the entire diff buffer and saves all modified file buffers. ** Dired ---- *** New user option 'dired-movement-style'. When non-nil, make 'dired-next-line', 'dired-previous-line', 'dired-next-dirline', 'dired-prev-dirline' skip empty lines. @@ -1123,7 +973,6 @@ It also controls how to move point when encountering a boundary (e.g., if every line is visible, invoking 'dired-next-line' at the last line will move to the first line). The default is nil. ---- *** New user option 'dired-filename-display-length'. It is an integer representing the maximum display length of file names. The middle part of a file name whose length exceeds the restriction is @@ -1131,7 +980,6 @@ hidden and an ellipsis is displayed instead. A value of 'window' means using the right edge of window as the display restriction. The default is nil. ---- *** New user option 'shell-command-guess-functions'. It defines how to populate a list of commands available for 'M-!', 'M-&', '!', '&' and the context menu "Open With" @@ -1140,32 +988,27 @@ based on marked files in Dired. Possible backends are and a universal command such as "open" or "start" that delegates to the OS. -+++ *** New command 'dired-do-open'. This command is bound to 'E' (mnemonics "External"). Also it can be used by clicking "Open" in the context menu; it "opens" the marked or clicked on files according to the OS conventions. For example, on systems supporting XDG, this runs 'xdg-open' on the files. -+++ *** New variable 'dired-guess-shell-alist-optional'. It contains commands for external viewers and players for various media formats, moved to this list from 'dired-guess-shell-alist-default'. ---- *** The default value of 'dired-omit-size-limit' was increased. After performance improvements to omitting in large directories, the new default value is 300k, up from 100k. This means 'dired-omit-mode' will omit files in directories whose directory listing is up to 300 kilobytes in size. -+++ *** 'dired-listing-switches' handles connection-local values if exist. This allows you to customize different switches for different remote machines. ** Ediff ---- *** New user option 'ediff-floating-control-frame'. If non-nil, try making the control frame be floating rather than tiled. @@ -1175,21 +1018,18 @@ This option is useful to set if you use such a window manager. ** Buffer Selection ---- *** New user option 'bs-default-action-list'. You can now configure how to display the "*buffer-selection*" buffer using this new option. (Or set 'display-buffer-alist' directly.) ** Eshell -+++ *** You can now run Eshell scripts in batch mode. By adding the following interpreter directive to an Eshell script, you can make it executable like other shell scripts: #!/usr/bin/env -S emacs --batch -f eshell-batch-file -+++ *** New builtin Eshell command 'compile'. This command runs another command, sending its output to a compilation buffer when the command would output interactively. This can be useful @@ -1198,14 +1038,12 @@ appropriate, but still allow piping the output elsewhere if desired. For more information, see the "(eshell) Built-ins" node in the Eshell manual. -+++ *** Eshell's 'env' command now supports running commands. Like in many other shells, Eshell's 'env' command now lets you run a command passed as arguments to 'env'. If you pass any initial arguments of the form 'VAR=VALUE', 'env' will first set 'VAR' to 'VALUE' before running the command. ---- *** Eshell's 'umask' command now supports setting the mask symbolically. Now, you can pass an argument like "u+w,o-r" to Eshell's 'umask' command, which will give write permission for owners of newly-created @@ -1213,7 +1051,6 @@ files and deny read permission for users who are not members of the file's group. See the Info node "(coreutils) File permissions" for more information on this notation. ---- *** Performance improvements for interactive output in Eshell. Interactive output in Eshell should now be significantly faster, especially for commands that can print large amounts of output @@ -1222,12 +1059,10 @@ for password prompts in the last 256 characters of each block of output. To restore the previous behavior when checking for password prompts, set 'eshell-password-prompt-max-length' to 'most-positive-fixnum'. ---- *** Eshell built-in commands can now display progress. Eshell built-in commands like "cat" and "ls" now update the display periodically while running to show their progress. -+++ *** New special reference type '#'. This special reference type returns a marker at 'POSITION' in 'BUFFER'. You can insert it by typing or using the new interactive @@ -1236,7 +1071,6 @@ references of any type using the new interactive command 'eshell-insert-special-reference'. See the "(eshell) Arguments" node in the Eshell manual for more details. -+++ *** New splice operator for Eshell dollar expansions. Dollar expansions in Eshell now let you splice the elements of the expansion in-place using '$@expr'. This makes it easier to fill lists @@ -1244,21 +1078,18 @@ of arguments into a command, such as when defining aliases. For more information, see the "(eshell) Dollars Expansion" node in the Eshell manual. -+++ *** You can now splice Eshell globs in-place into argument lists. By setting 'eshell-glob-splice-results' to a non-nil value, Eshell will expand glob results in-place as if you had typed each matching file name individually. For more information, see the "(eshell) Globbing" node in the Eshell manual. -+++ *** Eshell now supports negative numbers and ranges for indices. Now, you can retrieve the last element of a list with '$my-list[-1]' or get a sublist of elements 2 through 4 with '$my-list[2..5]'. For more information, see the "(eshell) Dollars Expansion" node in the Eshell manual. -+++ *** Eshell commands can now be explicitly-remote (or local). By prefixing a command name in Eshell with a remote identifier, like "/ssh:user@remote:whoami", you can now run commands on a particular @@ -1267,12 +1098,10 @@ command on your local system no matter your current directory via "/local:whoami". For more information, see the "(eshell) Remote Access" node in the Eshell manual. -+++ *** Eshell's '$UID' and '$GID' variables are now connection-aware. Now, when expanding '$UID' or '$GID' in a remote directory, the value is the user or group ID associated with the remote connection. ---- *** Eshell now uses 'field' properties in its output. In particular, this means that pressing the '' key moves the point to the beginning of your input, not the beginning of the whole @@ -1284,25 +1113,20 @@ this to your configuration: This also means you no longer need to adjust 'eshell-prompt-regexp' when customizing your Eshell prompt. ---- *** You can now properly unload Eshell. Calling '(unload-feature 'eshell)' no longer signals an error, and now correctly unloads Eshell and all of its modules. -+++ *** 'eshell-read-aliases-list' is now an interactive command. After manually editing 'eshell-aliases-file', you can use this command to load the edited aliases. -+++ *** 'rgrep' is now a builtin Eshell command. Running 'rgrep' in Eshell now uses the Emacs grep facility instead of calling external rgrep. -+++ *** If a command exits abnormally, the Eshell prompt now shows its exit code. -+++ *** New user option 'eshell-history-append'. If non-nil, each Eshell session will save history by appending new entries of that session to the history file rather than overwriting @@ -1310,25 +1134,21 @@ the file with the whole history of the session. The default is nil. ** Pcomplete ---- *** New user option 'pcomplete-remote-file-ignore'. When this option is non-nil, remote file names are not completed by Pcomplete. Packages, like 'shell-mode', could set this in order to suppress remote file name completion at all. ---- *** Completion for the 'doas' command has been added. Command completion for 'doas' in Eshell and Shell mode will now work. ** Shell mode -+++ *** New user option 'shell-get-old-input-include-continuation-lines'. When this user option is non-nil, 'shell-get-old-input' ('C-RET') includes multiple shell "\" continuation lines from command output. Default is nil. -+++ *** New user option 'shell-history-file-name'. When this user option is set to t, 'shell-mode' does not read the shell history file. Setting this user option to a string specifies the name @@ -1337,7 +1157,6 @@ environment variable 'HISTFILE'. In a 'shell' buffer, this user option is connection-local. ---- *** Performance improvements for interactive output. Interactive output in Shell mode now scans more selectively for password prompts by only examining the last 256 characters of each block of @@ -1347,7 +1166,6 @@ To restore the old behavior, set 'comint-password-prompt-max-length' to ** Prog mode -+++ *** New command 'prog-fill-reindent-defun'. This command either fills a single paragraph in a defun, such as a docstring, or a comment, or (re)indents the surrounding defun if point @@ -1356,26 +1174,22 @@ is not in a comment or a string. By default, it is bound to 'M-q' in ** Imenu -+++ *** New user option 'imenu-flatten'. It controls whether to flatten the list of sections in an imenu, and how to display the sections in the flattened list. -+++ *** The sort order of Imenu completions can now be customized. You can customize the user option 'completion-category-overrides' and set 'display-sort-function' for the category 'imenu'. ** Which Function mode -+++ *** Which Function mode can now display function names on the header line. The new user option 'which-func-display' allows choosing where the function name is displayed. The default is 'mode' to display in the mode line. 'header' will display in the header line; 'mode-and-header' displays in both the header line and mode line. -+++ *** New user option 'which-func-update-delay'. This replaces the user option 'idle-update-delay', which was previously used to control the delay before 'which-function-mode' updated its @@ -1384,28 +1198,23 @@ Which Function mode, is now obsolete. ** Tramp -+++ *** Tramp methods can be optional. An optional connection method is not enabled by default. The user must enable it explicitly by the 'tramp-enable-method' command. The existing methods "fcp", "krlogin", " ksu" and "nc" are optional now. -+++ *** New optional connection method "androidsu". This provides access to system files with elevated privileges granted by the idiosyncratic 'su' implementations and system utilities customary on Android. -+++ *** New optional connection method "run0". This connection method is similar to "sudo", but it uses the 'systemd' framework internally. -+++ *** New connection methods "dockercp" and "podmancp". These are the external methods counterparts of "docker" and "podman". -+++ *** New optional connection methods for containers. There are new optional connection methods "toolbox", "distrobox", "flatpak", "apptainer" and "nspawn". They allow accessing system @@ -1413,7 +1222,6 @@ containers provided by Toolbox or Distrobox, sandboxes provided by Flatpak, instances managed by Apptainer, or accessing systemd-based light-weight containers.. -+++ *** Connection method "kubernetes" supports now optional container name. The host name for Kubernetes connections can be of kind [CONTAINER.]POD, in order to specify a dedicated container. If there is just the pod @@ -1421,7 +1229,6 @@ name, the first container in the pod is taken. The new user options 'tramp-kubernetes-context' and 'tramp-kubernetes-namespace' allow accessing pods with different context or namespace but the default one. -+++ *** Rename 'tramp-use-ssh-controlmaster-options' to 'tramp-use-connection-share'. The old name still exists as obsolete variable alias. This user option controls now connection sharing for both ssh-based and @@ -1430,39 +1237,33 @@ The latter suppresses also "ControlMaster" settings in the user's "~/.ssh/config" file, or connection share configuration in PuTTY sessions, respectively. -+++ *** New command 'tramp-cleanup-some-buffers'. It kills only a subset of opened remote buffers, subject to the user option 'tramp-cleanup-some-buffers-hook'. -+++ *** New command 'inhibit-remote-files'. This command disables the handling of file names with the special remote file name syntax. It should be applied only when remote files won't be used in this Emacs instance. It provides a slightly improved performance of file name handling in Emacs. -+++ *** New macro 'without-remote-files'. This macro could wrap code which handles local files only. Due to the temporary deactivation of remote files, it results in a slightly improved performance of file name handling in Emacs. -+++ *** New user option 'tramp-completion-multi-hop-methods'. It contains a list of connection methods for which completion should be attempted at the end of a multi-hop chain. This allows completion candidates to include a list of, for example, containers running on a remote docker host. -+++ *** New command 'tramp-revert-buffer-with-sudo'. It reverts the current buffer to visit with "sudo" permissions. The buffer must either visit a file, or it must run 'dired-mode'. Another method but "sudo" can be configured with user option 'tramp-file-name-with-method'. -+++ *** Direct asynchronous processes are indicated by a connection-local variable. If direct asynchronous processes shall be used, set the connection-local variable 'tramp-direct-async-process' to a non-nil value. In previous @@ -1472,14 +1273,12 @@ properties and 'tramp-connection-properties' in general) is now deprecated. See the Tramp manual "(tramp) Improving performance of asynchronous remote processes". ---- *** Direct asynchronous processes use 'tramp-remote-path'. When a direct asynchronous process is invoked, it uses 'tramp-remote-path' for setting the remote 'PATH' environment variable. ** SHR ---- *** New user option 'shr-fill-text'. When 'shr-fill-text' is non-nil (the default), SHR will fill text according to the width of the window. If you customize it to nil, SHR @@ -1489,7 +1288,6 @@ visually wrapped at word boundaries. ** EWW ---- *** New mouse bindings in EWW buffers. Certain form elements that were displayed as buttons, yet could only be activated by keyboard input, are now operable using 'mouse-2'. With @@ -1497,45 +1295,38 @@ activated by keyboard input, are now operable using 'mouse-2'. With other classes of buttons either toggle their values or prompt for user input, as the case may be. ---- *** EWW text input fields and areas are now fields. In consequence, movement commands and OS input method features now recognize and confine their activities to the text input field around point. See also the Info node "(elisp) Fields". -+++ *** 'eww-open-file' can now display the file in a new buffer. By default, the command reuses the "*eww*" buffer, but if called with the new argument NEW-BUFFER non-nil, it will use a new buffer instead. Interactively, invoke 'eww-open-file' with a prefix argument to activate this behavior. ---- *** 'eww' URL or keyword prompt now has tab completion. The interactive minibuffer prompt when invoking 'eww' now has support for tab completion. -+++ *** 'eww' URL and keyword prompt now completes suggested URIs and bookmarks. The interactive minibuffer prompt when invoking 'eww' now provides completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes bookmark URIs. -+++ *** New command 'eww-copy-alternate-url'. It copies an alternate link on the page currently visited in EWW into the kill ring. Alternate links are optional metadata that HTML pages use for linking to their alternative representations, such as translated versions or associated RSS feeds. It is bound to 'A' by default. -+++ *** 'eww-open-in-new-buffer' supports the prefix argument. When invoked with the prefix argument ('C-u'), 'eww-open-in-new-buffer' will not make the new buffer the current one. This is useful for continuing reading the URL in the current buffer when the new URL is fetched. ---- *** History navigation in EWW now behaves as in other browsers. Previously, when navigating back and forward through page history, EWW would add a duplicate entry to the end of the history list each time. @@ -1548,27 +1339,23 @@ entries newer than the current page. To change the behavior when browsing from "historical" pages, you can customize 'eww-before-browse-history-function'. -+++ *** 'eww-readable' now toggles display of the readable parts of a web page. When called interactively, 'eww-readable' toggles whether to display only the readable parts of a page or the full page. With a positive prefix argument, it always displays the readable parts, and with a zero or negative prefix, it always displays the full page. -+++ *** New user option 'eww-readable-urls'. This is a list of regular expressions matching the URLs where EWW should display only the readable parts by default. For more details, see "(eww) Basics" in the EWW manual. ---- *** New user option 'eww-readable-adds-to-history'. When non-nil (the default), calling 'eww-readable' adds a new entry to the EWW page history. ** Go-ts mode -+++ *** New command 'go-ts-mode-docstring'. This command adds a docstring comment to the current defun. If a comment already exists, point is only moved to the comment. It is @@ -1576,12 +1363,10 @@ bound to 'C-c C-d' in 'go-ts-mode'. ** Man mode -+++ *** New user option 'Man-prefer-synchronous-call'. When this is non-nil, run the 'man' command synchronously rather than asynchronously (which is the default behavior). -+++ *** New user option 'Man-support-remote-systems'. This option controls whether the man page is formatted on the remote system when the current buffer's default-directory is remote. You can @@ -1590,12 +1375,10 @@ value of this option for the current invocation of 'man'. ** DocView ---- *** New user option 'doc-view-mpdf-use-svg'. If non-nil, DocView uses SVG images to display PDF documents. The default is non-nil if your system supports display of SVG images. ---- *** New face 'doc-view-svg-face'. This replaces 'doc-view-svg-foreground' and 'doc-view-svg-background'. By default, this face has black foreground on white background and @@ -1605,7 +1388,6 @@ current theme. However, this, or any non-standard values, can result in poor contrast for documents which aren't simply black text on white background. ---- *** DocView buffers now display a new tool bar. This tool bar contains options for searching and navigating within the document, replacing the incompatible items for incremental search and @@ -1613,12 +1395,10 @@ editing within the default tool bar displayed in the past. ** Shortdoc -+++ *** New function 'shortdoc-function-examples'. This function returns examples of use of a given Emacs Lisp function from the available shortdoc information. -+++ *** New function 'shortdoc-help-fns-examples-function'. This function inserts into the current buffer examples of use of a given Emacs Lisp function, which it gleans from the shortdoc @@ -1631,24 +1411,20 @@ following to your init file: ** Package ---- *** New user option 'package-vc-register-as-project'. When non-nil, 'package-vc-install' and 'package-vc-checkout' will automatically register every package they install as a project, that you can quickly select using 'project-switch-project' ('C-x p p'). Default is t. ---- *** New user option 'package-vc-allow-build-commands'. Controls for which packages Emacs runs extra build commands when installing directly from the package VCS repository. ---- *** New command 'package-vc-log-incoming'. This commands displays incoming changes for a VC package without modifying the current checkout. ---- *** New command to start an inferior Emacs loading only specific packages. The new command 'package-isolate' will start a new Emacs process, as a sub-process of Emacs where you invoke the command, in a way that @@ -1659,29 +1435,24 @@ in a clean environment. ** Flymake -+++ *** New user option 'flymake-indicator-type'. This controls which error indicator type Flymake should use in the current buffer. Depending on your preference, this can either use fringes or margins for indicating errors, the default is 'margins'. -+++ *** New user option 'flymake-margin-indicators-string'. It controls, for each error type, the string and its face to display as the margin indicator. -+++ *** New user option 'flymake-autoresize-margins'. If non-nil (the default), Flymake will resize the margins when 'flymake-mode' is turned on or off. Only relevant if 'flymake-indicator-type' is set to 'margins'. -+++ *** New user option 'flymake-margin-indicator-position'. It controls whether to use margins for margin indicators, and which margin (left or right) to use. Default is to use the left margin. -+++ *** New user option 'flymake-show-diagnostics-at-end-of-line'. When non-nil, Flymake shows summarized descriptions of diagnostics at the end of the line. Depending on your preference, this can either be @@ -1691,13 +1462,11 @@ mouse to consult an error message. Default is nil. ** Flyspell -+++ *** New user option 'flyspell-check-changes'. When non-nil, Flyspell mode spell-checks only words that you edited; it does not check unedited words just because you move point across them. Default is nil. ---- ** JS mode. The binding 'M-.' has been removed from the major mode keymaps in 'js-mode' and 'js-ts-mode', having it default to the global binding @@ -1705,7 +1474,6 @@ which calls 'xref-find-definitions'. If the previous one worked better for you, use 'define-key' in your init script to bind 'js-find-symbol' to that combination again. ---- ** Json mode. 'js-json-mode' does not derive from 'js-mode' any more so as not to confuse tools like Eglot or YASnippet into thinking that those @@ -1713,7 +1481,6 @@ buffers contain Javascript code. ** Python mode ---- *** New user option 'python-indent-block-paren-deeper'. If non-nil, increase the indentation of the lines inside parens in a header of a block when they are indented to the same level as the body @@ -1731,19 +1498,16 @@ instead of: Default is nil. ---- *** New user option 'python-interpreter-args'. This allows the user to specify command line arguments to the non interactive Python interpreter specified by 'python-interpreter'. ---- *** New function 'python-shell-send-block'. It sends the python block delimited by 'python-nav-beginning-of-block' and 'python-nav-end-of-block' to the inferior Python process. ** Inferior Python mode ---- *** Default value of 'python-shell-compilation-regexp-alist' is changed. Support for Python's ExceptionGroup has been added, so in the Python shell, the line indicating the source of an error in the error messages @@ -1751,13 +1515,11 @@ from ExceptionGroup will be recognized as well. ** Eldoc ---- *** 'eldoc' no longer truncates to a single line by default. Previously, the entire docstring was not available to eldoc, which made 'eldoc-echo-area-use-multiline-p' ineffective. The old behavior may be kept by customizing 'eldoc-echo-area-use-multiline-p'. ---- ** Scheme mode. Scheme mode now handles the regular expression literal '#/regexp/' that is available in some Scheme implementations. @@ -1765,47 +1527,39 @@ Also, it should now handle nested sexp-comments. ** Use package -+++ *** New ':vc' keyword. This keyword enables the user to install packages using package-vc.el. -+++ *** New user option 'use-package-vc-prefer-newest'. If non-nil, always install the newest commit of a package when using the ':vc' keyword rather than its stable release. Default is nil. ** Gnus -+++ *** New backend 'nnfeed'. This allows backend developers to easily create new backends for web feeds, as inheriting backends of 'nnfeed'. -+++ *** New backend 'nnatom'. This allow users to add Atom Syndication Format feeds to Gnus as servers. ---- *** The 'nnweb-type' option 'gmane' has been removed. The gmane.org website is, sadly, down since a number of years with no prospect of it coming back. Therefore, it is no longer valid to set the server variable 'nnweb-type' to 'gmane'. ---- *** New user option 'gnus-mode-line-logo'. This allows the user to either disable the display of any logo or specify which logo will be displayed as part of the buffer-identification in the mode-line of Gnus buffers. ---- *** 'gnus-summary-limit-to-age' now counts days since midnight. "Less than 1 day" now means "since last midnight", rather than "less than 24 hours old". ** Rmail ---- *** New commands for reading mailing lists. The new Rmail commands 'rmail-mailing-list-post', 'rmail-mailing-list-unsubscribe', 'rmail-mailing-list-help', and @@ -1816,7 +1570,6 @@ delivered. ** Dictionary ---- *** New user option 'dictionary-search-interface'. Controls how the 'dictionary-search' command prompts for and displays dictionary definitions. Customize this user option to 'help' to have @@ -1824,13 +1577,11 @@ dictionary definitions. Customize this user option to 'help' to have provide dictionary-based minibuffer completion for word selection. Default is nil, which means to use a "*Dictionary*" buffer. ---- *** New user option 'dictionary-read-word-prompt'. This allows the user to customize the prompt that is used by 'dictionary-search' when asking for a word to search in the dictionaries. ---- *** New user option 'dictionary-display-definition-function'. This allows the user to customize the way in which 'dictionary-search' displays word definitions. If non-nil, this user option should be set @@ -1840,7 +1591,6 @@ dictionary server. The new function the definition in a "*Help*" buffer, instead of the default "*Dictionary*" buffer. ---- *** New user option 'dictionary-read-word-function'. This allows the user to customize the way in which 'dictionary-search' prompts for a word to search in the dictionary. This user option @@ -1849,7 +1599,6 @@ returns it as a string. The new function 'dictionary-completing-read-word' can be used to prompt with completion based on dictionary matches. ---- *** New user option 'dictionary-read-dictionary-function'. This allows the user to customize the way in which 'dictionary-search' prompts for a dictionary to search in. This user option should be set @@ -1858,7 +1607,6 @@ name as a string. The new function 'dictionary-completing-read-dictionary' can be used to prompt with completion based on dictionaries that the server supports. ---- *** The default value of 'dictionary-tooltip-dictionary' has changed. The new default value is t, which means use the same dictionary as the value of 'dictionary-default-dictionary'. The previous default value @@ -1867,52 +1615,43 @@ the mode was turned on. ** Pp -+++ *** New 'pp-default-function' user option replaces 'pp-use-max-width'. Its default value is 'pp-fill', a new default pretty-printing function, which tries to obey 'fill-column'. ---- *** 'pp-to-string' takes an additional PP-FUNCTION argument. This argument specifies the prettifying algorithm to use. ---- *** 'pp' and 'pp-to-string' now always include a terminating newline. In the past they included a terminating newline in most cases but not all. ** Emacs Lisp mode -+++ *** 'elisp-flymake-byte-compile' is disabled for untrusted files. For security reasons, this backend can be used only in those files specified as trusted according to 'trusted-content' and emits an "untrusted content" warning otherwise. This fixes CVE-2024-53920. ---- *** ',@' now has 'prefix' syntax. Previously, the '@' character, which normally has 'symbol' syntax, would combine with a following Lisp symbol and interfere with symbol searching. -+++ *** 'emacs-lisp-docstring-fill-column' now defaults to 72. It was previously 65. The new default formats documentation strings to fit on fewer lines without negatively impacting readability. ** CPerl mode ---- *** Subroutine signatures are now supported. CPerl mode fontifies subroutine signatures like variable declarations which makes them visually distinct from subroutine prototypes. ---- *** Syntax of Perl up to version 5.40 is supported. CPerl mode supports the new keywords for exception handling and the object oriented syntax which were added in Perl 5.36, 5.38 and 5.40. ---- *** New user option 'cperl-fontify-trailer'. This user option takes the values 'perl-code' or 'comment' and treats text after an "__END__" or "__DATA__" token accordingly. The default @@ -1920,32 +1659,27 @@ value of 'perl-code' is useful for trailing POD and for AutoSplit modules, the value 'comment' makes CPerl mode treat trailers as comment, like Perl mode does. ---- *** New command 'cperl-file-style'. This command sets the indentation style for the current buffer. To change the default style, either use the user option with the same name or use the command 'cperl-set-style'. ---- *** New minor mode 'cperl-extra-paired-delimiters-mode'. Perl 5.36 and newer allows using more than 200 non-ASCII paired delimiters for quote-like constructs, e.g. "q«text»". Use this minor mode in buffers where this feature is activated. ---- *** Commands using the Perl Info manual are obsolete. The Perl documentation in Info format is no longer distributed with Perl or on CPAN since more than 10 years. Perl documentation can be read with 'cperl-perldoc' instead. ---- *** Highlighting trailing whitespace has been removed. The user option 'cperl-invalid-face' is now obsolete, and does nothing. See the user option 'show-trailing-whitespace' instead. ** Emacs Sessions (Desktop) -+++ *** Restoring buffers visiting remote files can now time out. When a buffer is restored which visits a remote file, the restoration of the session could hang if the remote host is off-line or slow to @@ -1956,7 +1690,6 @@ desktop restoration to continue. ** Recentf -+++ *** Checking recent remote files can now time out. Similarly to buffer restoration by Desktop, 'recentf-mode' checking of the accessibility of remote files can now time out if @@ -1964,19 +1697,16 @@ of the accessibility of remote files can now time out if ** Image Dired -+++ *** New user option 'image-dired-thumb-naming'. You can now configure how thumbnails are named using this option. ** ERT -+++ *** New macro 'skip-when' to skip 'ert-deftest' tests. This can help to avoid some awkward skip conditions. For example '(skip-unless (not noninteractive))' can be changed to the easier to read '(skip-when noninteractive)'. -+++ *** Syntax highlighting unit testing support. An ERT extension ('ert-font-lock') now provides support for face assignment unit testing. For more information, see the "(ert) Syntax @@ -1984,21 +1714,18 @@ Highlighting Tests" node in the ERT manual. ** Socks -+++ *** Socks supports version 4a. The 'socks-server' user option accepts '4a' as a value for its version field. ** Edmacro -+++ *** New command 'edmacro-set-macro-to-region-lines'. Bound to 'C-c C-r', this command replaces the macro text with the lines of the region. If needed, the region is extended to include whole lines. If the region ends at the beginning of a line, that last line is excluded. -+++ *** New user option 'edmacro-reverse-macro-lines'. When this is non-nil, the lines of key sequences are displayed with the most recent line first. This is can be useful when working with @@ -2006,7 +1733,6 @@ macros with many lines, such as from 'kmacro-edit-lossage'. ** Calc -+++ *** Calc parses fractions written using U+2044 FRACTION SLASH. Fractions of the form "123⁄456" are handled as if written "123:456". Note in particular the difference in behavior from U+2215 DIVISION SLASH @@ -2018,7 +1744,6 @@ was never mentioned in the NEWS, or even the Calc manual.) ** IELM ---- *** IELM now remembers input history between sessions. The new user option 'ielm-history-file-name' is the name of the file where IELM input history will be saved. Customize it to nil to revert @@ -2026,7 +1751,6 @@ to the old behavior of not remembering input history between sessions. ** EasyPG -+++ *** New user option 'epa-keys-select-method'. This allows the user to customize the key selection method, which can be either by using a pop-up buffer or from the minibuffer. The pop-up @@ -2034,61 +1758,52 @@ buffer method is the default, which preserves previous behavior. ** Widget -+++ *** New face 'widget-unselected'. Customize this face to a non-default value to visually distinguish the labels of unselected active radio-button or checkbox widgets from the labels of unselected inactive widgets (the default value inherits from the 'widget-inactive' face). -+++ *** New user option 'widget-skip-inactive'. If non-nil, moving point forward or backward between widgets by typing 'TAB' or 'S-TAB' skips over inactive widgets. The default value is nil. ** Ruby mode ---- *** New user option 'ruby-rubocop-use-bundler'. By default it retains the previous behavior: read the contents of Gemfile and act accordingly. But you can also set it to t or nil to skip checking the Gemfile. ---- *** New user option 'ruby-bracketed-args-indent'. When it is set to nil, multiple consecutive open braces/brackets/parens result in only one additional indentation level. Default is t. ** Thingatpt ---- *** New variables for providing custom thingatpt implementations. The new variables 'bounds-of-thing-at-point-provider-alist' and 'forward-thing-provider-alist' now allow defining custom implementations of 'bounds-of-thing-at-point' and 'forward-thing', respectively. ---- *** New helper functions for text property-based thingatpt providers. The new helper functions 'thing-at-point-for-char-property', 'bounds-of-thing-at-point-for-char-property', and 'forward-thing-for-char-property' can help to implement custom thingatpt providers for "things" that are defined by text properties. ---- *** 'bug-reference-mode' now supports 'thing-at-point'. Now, calling '(thing-at-point 'url)' when point is on a bug reference will return the URL for that bug. ** Buffer-menu ---- *** New user option 'Buffer-menu-group-by'. It controls how buffers are divided into groups that are displayed with headings using Outline minor mode. Using commands that mark buffers on the outline heading line will mark all buffers in the outline. By default, no grouping is performed. -+++ *** New command 'Buffer-menu-toggle-internal'. This command toggles the display of internal buffers in Buffer Menu mode; that is, buffers not visiting a file and whose names start with a space. @@ -2097,22 +1812,18 @@ in Buffer Menu mode. ** Miscellaneous -+++ *** New user option 'rcirc-log-time-format'. This allows for rcirc logs to use a custom timestamp format, which the chat buffers use by default. ---- *** 'ffap-lax-url' now defaults to nil. Previously, it was set to t, but this broke remote file name detection. ---- *** More control on automatic update of Proced buffers. The user option 'proced-auto-update-flag' can now be set to an additional value 'visible', which controls automatic updates of Proced buffers that are displayed in some window. ---- *** nXML Mode now comes with schemas for Mono/.NET development. The following new XML schemas are now supported: - MSBuild project files @@ -2123,48 +1834,39 @@ The following new XML schemas are now supported: - Nuget package specification file - Nuget packages config file ---- *** color.el now supports the Oklab color representation. -+++ *** New user option 'xwidget-webkit-disable-javascript'. This allows disabling JavaScript in xwidget Webkit sessions. ---- *** 'ls-lisp--insert-directory' supports more long options of 'ls'. 'ls-lisp--insert-directory', the ls-lisp implementation of 'insert-directory', now supports the '--time=TIME' and '--sort=time' options of GNU 'ls'. ---- *** 'M-x ping' can now give additional flags to the 'ping' program. Typing 'C-u M-x ping' prompts first for the host, and then for the flags to give to the 'ping' command. ---- *** Webjump now assumes URIs are HTTPS instead of HTTP. For links in 'webjump-sites' without an explicit URI scheme, it was previously assumed that they should be prefixed with "http://". Such URIs are now prefixed with "https://" instead. ---- *** Added prefixes in titdic-cnv library. Most of the variables and functions in the file have been renamed to make sure they all use a 'tit-' namespace prefix. ---- *** 'xref-revert-buffer' is now an alias of 'revert-buffer'. The Xref buffer now sets up 'revert-buffer-function' such that 'revert-buffer' behaves like 'xref-revert-buffer' did in previous Emacs versions, and the latter is now an alias of the former. ---- *** The Makefile browser is now obsolete. The command 'makefile-switch-to-browser' command is now obsolete, together with related commands used in the "*Macros and Targets*" buffer. We recommend using an alternative like 'imenu' instead. ---- *** 'jsonrpc-default-request-timeout' is now a defcustom. @@ -2172,28 +1874,22 @@ buffer. We recommend using an alternative like 'imenu' instead. ** New major modes based on the tree-sitter library -+++ *** New major mode 'elixir-ts-mode'. A major mode based on the tree-sitter library for editing Elixir files. -+++ *** New major mode 'heex-ts-mode'. A major mode based on the tree-sitter library for editing HEEx files. -+++ *** New major mode 'html-ts-mode'. An optional major mode based on the tree-sitter library for editing HTML files. -+++ *** New major mode 'lua-ts-mode'. A major mode based on the tree-sitter library for editing Lua files. -+++ *** New major mode 'php-ts-mode'. A major mode based on the tree-sitter library for editing PHP files. -+++ ** New package EditorConfig. This package provides support for the EditorConfig standard, an editor-neutral way to provide directory local (project-wide) settings. @@ -2202,13 +1898,11 @@ which makes Emacs obey the '.editorconfig' files. There is also a new major mode 'editorconfig-conf-mode' to edit those configuration files. -+++ ** New global minor mode 'etags-regen-mode'. This minor mode generates the tags table automatically based on the current project configuration, and later updates it as you edit the files and save the changes. -+++ ** New package 'which-key'. The 'which-key' package from GNU ELPA is now included in Emacs. It implements the global minor mode 'which-key-mode' that displays a table @@ -2217,7 +1911,6 @@ moment. For example, after enabling the minor mode, if you enter 'C-x' and wait for one second, the minibuffer will expand with all available key bindings that follow 'C-x' (or as many as space allows). -+++ ** New minor mode 'completion-preview-mode'. This minor mode shows you symbol completion suggestions as you type, using an inline preview. New user options in the 'completion-preview' @@ -2225,7 +1918,6 @@ customization group control exactly when Emacs displays this preview. 'completion-preview-mode' is buffer-local, to enable it globally use 'global-completion-preview-mode'. -+++ ** New package Window-Tool-Bar. This provides a new minor mode, 'window-tool-bar-mode'. When this minor mode is enabled, a tool bar is displayed at the top of a window. To @@ -2233,7 +1925,6 @@ conserve space, no tool bar is shown if 'tool-bar-map' is nil. The global minor mode 'global-window-tool-bar-mode' enables this minor mode in all buffers. -+++ ** New library Track-Changes. This library is a layer of abstraction above 'before-change-functions' and 'after-change-functions' which provides a superset of @@ -2245,7 +1936,6 @@ the functionality of 'after-change-functions': reported (calls to 'before/after-change-functions' that are incorrectly paired, missing, etc...) and reports them adequately. -+++ ** New global minor mode 'minibuffer-regexp-mode'. This is a minor mode for editing regular expressions in the minibuffer, for example in 'query-replace-regexp'. It correctly highlights parens @@ -2254,7 +1944,6 @@ avoids reporting alleged paren mismatches and makes sexp navigation more intuitive. It is enabled by default, 'minibuffer-regexp-prompts' can be used to tune when it takes effect. ---- ** The highly accessible Modus themes collection has eight items. The 'modus-operandi' and 'modus-vivendi' are the main themes that have been part of Emacs since version 28. The former is light, the latter @@ -2266,7 +1955,6 @@ the needs of users with red-green or blue-yellow color deficiency. The Info manual "(modus-themes) Top" describes the details and showcases all their user options. -+++ ** New library PEG. Emacs now includes a library for writing Parsing Expression Grammars (PEG), an approach to text parsing that provides more structure @@ -2274,14 +1962,12 @@ than regular expressions, but less complexity than context-free grammars. The Info manual "(elisp) Parsing Expression Grammars" has documentation and examples. ---- ** New major mode 'shell-command-mode'. This mode is used by default for the output of asynchronous 'shell-command'. To revert to the previous behavior, set the (also new) variable 'async-shell-command-mode' to 'shell-mode'. Any hooks or mode-specific variables used should be adapted appropriately. -+++ ** New package Compat. Emacs now comes with a stub implementation of the forwards-compatibility Compat package from GNU ELPA. This allows @@ -2291,7 +1977,6 @@ preventing the installation of Compat if unnecessary. * Incompatible Lisp Changes in Emacs 30.1 -+++ ** Evaluating a 'lambda' returns an object of type 'interpreted-function'. Instead of representing interpreted functions as lists that start with either 'lambda' or 'closure', Emacs now represents them as objects @@ -2308,17 +1993,14 @@ no longer work and will need to use 'aref' instead to extract its various subparts (when 'interactive-form', 'documentation', and 'help-function-arglist' aren't adequate). ---- ** The escape sequence '\x' not followed by hex digits is now an error. Previously, '\x' without at least one hex digit denoted character code zero (NUL) but as this was neither intended nor documented or even known by anyone, it is now treated as an error by the Lisp reader. ---- ** 'subr-native-elisp-p' is renamed to 'native-comp-function-p'. The previous name still exists but is marked as obsolete. -+++ ** 'define-globalized-minor-mode' requires that modes use 'run-mode-hooks'. Minor modes defined with 'define-globalized-minor-mode', such as 'global-font-lock-mode', will not be enabled any more in those buffers @@ -2326,7 +2008,6 @@ whose major modes fail to use 'run-mode-hooks'. Major modes defined with 'define-derived-mode' are not affected. 'run-mode-hooks' has been the recommended way to run major mode hooks since Emacs 22. -+++ ** 'buffer-match-p' and 'match-buffers' take '&rest ARGS'. They used to take a single '&optional ARG' and were documented to use an unreliable hack to try and support condition predicates that @@ -2334,18 +2015,14 @@ don't accept this optional ARG. The new semantics makes no such accommodation, but the code still supports it (with a warning) for backward compatibility. ---- ** 'post-gc-hook' runs after updating 'gcs-done' and 'gc-elapsed'. ---- ** Connection-local variables are applied in buffers visiting remote files. This overrides possible directory-local or file-local variables with the same name. -+++ ** 'copy-tree' now copies records when its optional 2nd argument is non-nil. -+++ ** Regexp zero-width assertions followed by operators are better defined. Previously, regexps such as "xy\\B*" would have ill-defined behavior. Now any operator following a zero-width assertion applies to that @@ -2353,7 +2030,6 @@ assertion only (which is useless). For historical compatibility, an operator character following '^' or '\`' becomes literal, but we advise against relying on this. -+++ ** Infinities and NaNs no longer act as symbols on non-IEEE platforms. On old platforms like the VAX that do not support IEEE floating-point, tokens like '0.0e+NaN' and '1.0e+INF' are no longer read as symbols. @@ -2361,7 +2037,6 @@ Instead, the Lisp reader approximates an infinity with the nearest finite value, and a NaN with some other non-numeric object that provokes an error if used numerically. -+++ ** Conversion of strings to and from byte-arrays works with multibyte strings. The functions 'dbus-string-to-byte-array' and 'dbus-byte-array-to-string' now accept and return multibyte Lisp @@ -2372,60 +2047,48 @@ UTF-8 byte sequence, and the optional parameter MULTIBYTE of 'dbus-string-to-byte-array' should be a regular Lisp string, not a unibyte string. -+++ ** 'minibuffer-allow-text-properties' now can be set buffer-local. 'read-from-minibuffer' and functions that use it can take the buffer-local value from the minibuffer. -+++ ** 'minibuffer-allow-text-properties' now also affects completions. When it has a non-nil value, then completion functions like 'completing-read' don't discard text properties from the returned completion candidate. -+++ ** X color support compatibility aliases are now obsolete. The compatibility aliases 'x-defined-colors', 'x-color-defined-p', 'x-color-values', and 'x-display-color-p' are now obsolete. -+++ ** 'easy-mmode-define-{minor,global}-mode' aliases are now obsolete. Use 'define-minor-mode' and 'define-globalized-minor-mode' instead. -+++ ** The 'millisec' argument of 'sleep-for' is now obsolete. Use a float value for the first argument instead. ---- ** User options 'eshell-NAME-unload-hook' are now obsolete. These hooks were named incorrectly, and so they never actually ran when unloading the corresponding feature. Instead, you should use hooks named after the feature name, like 'esh-mode-unload-hook'. ---- ** User options 'eshell-process-wait-{seconds,milliseconds}' are now obsolete. Instead, use 'eshell-process-wait-time', which supports floating-point values. ---- ** User option 'tramp-completion-reread-directory-timeout' has been removed. This user option was obsoleted in Emacs 27, use 'remote-file-name-inhibit-cache' instead. -+++ ** The obsolete calling convention of 'sit-for' has been removed. That convention was: '(sit-for SECONDS MILLISEC &optional NODISP)'. ---- ** 'defadvice' is marked as obsolete. See the "(elisp) Porting Old Advice" Info node for help converting them to use 'advice-add' or 'define-advice' instead. ---- ** 'cl-old-struct-compat-mode' is marked as obsolete. You may need to recompile your code if it was compiled with Emacs < 24.3. ---- ** Old derived.el functions removed. The following functions have been deleted because they were only used by code compiled with Emacs < 21: @@ -2438,40 +2101,33 @@ by code compiled with Emacs < 21: * Lisp Changes in Emacs 30.1 -+++ ** The 'wheel-up/down/left/right' events are now bound unconditionally. The 'mouse-wheel-up/down/left/right-event' variables are thus used only to specify the 'mouse-4/5/6/7' events that might still happen to be generated by some old packages (or if 'mouse-wheel-buttons' has been set to nil). ---- ** Xterm Mouse mode now emits 'wheel-up/down/right/left' events. This is instead of 'mouse-4/5/6/7' events for the mouse wheel. It uses the new variable 'mouse-wheel-buttons' to decide which button maps to which wheel event (if any). ---- ** In batch mode, tracing now sends the trace to stdout. -+++ ** New hook 'hack-dir-local-get-variables-functions'. This can be used to provide support for other directory-local settings beside ".dir-locals.el". -+++ ** 'auto-coding-functions' can know the name of the file. The functions on this hook can now find the name of the file to which the text belongs by consulting the variable 'auto-coding-file-name'. -+++ ** New user option 'compilation-safety' to control safety of native code. It is now possible to control how safe is the code generated by native compilation, by customizing this user option. It is also possible to control this at function granularity by using the new 'safety' parameter in the function's 'declare' form. -+++ ** New types 'closure' and 'interpreted-function'. 'interpreted-function' is the new type used for interpreted functions, and 'closure' is the common parent type of 'interpreted-function' @@ -2481,91 +2137,75 @@ Those new types come with the associated new predicates 'closurep' and 'interpreted-function-p' as well as a new constructor 'make-interpreted-closure'. ---- ** New function 'help-fns-function-name'. For named functions, it just returns the name and otherwise it returns a short "unique" string that identifies the function. In either case, the string is propertized so clicking on it gives further details. -+++ ** New function 'char-to-name'. This is a convenience function to return the Unicode name of a char (if it has one). -+++ ** New function 'cl-type-of'. This function is like 'type-of' except that it sometimes returns a more precise type. For example, for nil and t it returns 'null' and 'boolean' respectively, instead of just 'symbol'. -+++ ** New functions 'primitive-function-p' and 'cl-functionp'. 'primitive-function-p' is like 'subr-primitive-p' except that it returns t only if the argument is a function rather than a special-form, and 'cl-functionp' is like 'functionp' except it returns nil for lists and symbols. ---- ** Built-in types now have corresponding classes. At the Lisp level, this means that things like '(cl-find-class 'integer)' will now return a class object, and at the UI level it means that things like 'C-h o integer RET' will show some information about that type. ---- ** New variable 'major-mode-remap-defaults' and function 'major-mode-remap'. The first is like Emacs-29's 'major-mode-remap-alist' but to be set by packages (instead of users). The second looks up those two variables. -+++ ** Pcase's functions (in 'pred' and 'app') can specify the argument position. For example, instead of '(pred (< 5))' you can write '(pred (> _ 5))'. -+++ ** 'define-advice' now sets the new advice's 'name' property to NAME. Named advices defined with 'define-advice' can now be removed with '(advice-remove SYMBOL NAME)' in addition to '(advice-remove SYMBOL SYMBOL@NAME)'. -+++ ** New function 'require-with-check' to detect new versions shadowing. This is like 'require', but it checks whether the argument 'feature' is already loaded, in which case it either signals an error or forcibly reloads the file that defines the feature. -+++ ** New variable 'lisp-eval-depth-reserve'. It puts a limit to the amount by which Emacs can temporarily increase 'max-lisp-eval-depth' when handling signals. -+++ ** New special form 'handler-bind'. It provides a functionality similar to 'condition-case' except it runs the handler code without unwinding the stack, such that we can record the backtrace and other dynamic state at the point of the error. See the Info node "(elisp) Handling Errors". -+++ ** New text properties add tooltips on fringes. It is now possible to provide tooltips on fringes by adding special text properties 'left-fringe-help' and 'right-fringe-help'. See the "(elisp) Special Properties" Info node in the Emacs Lisp Reference Manual for more details. -+++ ** New 'display-buffer' action alist entry 'pop-up-frames'. This has the same effect as the variable of the same name and takes precedence over the variable when present. ---- ** New function 'merge-ordered-lists'. Mostly used internally to do a kind of topological sort of inheritance hierarchies. -+++ ** 'drop' is now an alias for the function 'nthcdr'. -+++ ** New polymorphic comparison function 'value<'. This function returns non-nil if the first argument is less than the second. It works for any two values of the same type with reasonable @@ -2575,7 +2215,6 @@ lexicographically. It is intended as a convenient ordering predicate for sorting, and is likely to be faster than hand-written Lisp functions. -+++ ** New 'sort' arguments and features. The 'sort' function can now be called using the signature @@ -2602,13 +2241,11 @@ its input in-place as before. ** New API for 'derived-mode-p' and control of the graph of major modes -+++ *** 'derived-mode-p' now takes the list of modes as a single argument. The same holds for 'provided-mode-derived-p'. The old calling convention where multiple modes are passed as separate arguments is deprecated. -+++ *** New functions to access the graph of major modes. While 'define-derived-mode' still only supports single inheritance, modes can declare additional parents (for tests like 'derived-mode-p') @@ -2617,7 +2254,6 @@ Accessing the 'derived-mode-parent' property directly is now deprecated in favor of the new functions 'derived-mode-set-parent' and 'derived-mode-all-parents'. -+++ ** Drag-and-drop functions can now be called once for compound drops. It is now possible for drag-and-drop handler functions to respond to drops incorporating more than one URL. Functions capable of this must @@ -2627,7 +2263,6 @@ See the Info node "(elisp) Drag and Drop". The function 'dnd-handle-one-url' has been made obsolete, since it cannot take these new handlers into account. -+++ ** 'notifications-notify' can use Icon Naming Specification for ':app-icon'. You can use a symbol as the value for ':app-icon' to provide icon name without specifying a file, like this: @@ -2635,54 +2270,45 @@ without specifying a file, like this: (notifications-notify :title "I am playing music" :app-icon 'multimedia-player) ---- ** New function 're-disassemble' to see the innards of a regexp. If you built Emacs with '--enable-checking', you can use this to help debug either your regexp performance problems or the regexp engine. -+++ ** XLFDs are no longer restricted to 255 characters. 'font-xlfd-name' now returns an XLFD even if it is greater than 255 characters in length, provided that the LONG_XLFDs argument is true. Other features in Emacs which employ XLFDs have been modified to produce and understand XLFDs larger than 255 characters. -+++ ** New macro 'static-if' for conditional evaluation of code. This macro hides a form from the evaluator or byte-compiler based on a compile-time condition. This is handy for avoiding byte-compilation warnings about code that will never actually run under some conditions. -+++ ** Desktop notifications are now supported on the Haiku operating system. The new function 'haiku-notifications-notify' provides a subset of the capabilities of the 'notifications-notify' function in a manner analogous to 'w32-notification-notify'. ---- ** New Haiku specific variable 'haiku-pass-control-tab-to-system'. This sets whether Emacs should pass 'C-TAB' on to the system instead of handling it, fixing a problem where window switching would not activate if an Emacs frame had focus on the Haiku operating system. Default value is t. -+++ ** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'. It results in 'insert-file-contents' erasing the buffer instead of preserving markers if the file being inserted is not a regular file, rather than signaling an error. -+++ ** New variable 'current-key-remap-sequence'. It is bound to the key sequence that caused a call to a function bound within 'function-key-map' or 'input-decode-map' around those calls. -+++ ** The function 'key-translate' can now remove translations. If the second argument TO is nil, the existing key translation is removed. -+++ ** New variables describing the names of built in programs. The new variables 'ctags-program-name', 'ebrowse-program-name', 'etags-program-name', 'hexl-program-name', 'emacsclient-program-name' @@ -2690,7 +2316,6 @@ The new variables 'ctags-program-name', 'ebrowse-program-name', instead of "ctags", "ebrowse", "etags", "hexl", "emacsclient", and "rcs2log", when starting one of these built in programs in a subprocess. -+++ ** New variable 'case-symbols-as-words' affects case operations for symbols. If non-nil, then case operations such as 'upcase-initials' or 'replace-match' (with nil FIXEDCASE) will treat the entire symbol name @@ -2698,7 +2323,6 @@ as a single word. This is useful for programming languages and styles where only the first letter of a symbol's name is ever capitalized. The default value of this variable is nil. ---- ** Bytecode is now always loaded eagerly. Bytecode compiled with older Emacs versions for lazy loading using 'byte-compile-dynamic' is now loaded all at once. @@ -2706,7 +2330,6 @@ As a consequence, 'fetch-bytecode' has no use, does nothing, and is now obsolete. The variable 'byte-compile-dynamic' has no effect any more; compilation will always yield bytecode for eager loading. -+++ ** Returned strings from functions and macros are never docstrings. Functions and macros whose bodies consist of a single string literal now only return that string, and will not use it as a docstring. Example: @@ -2724,7 +2347,6 @@ forms; other defining forms such as 'cl-defun' already worked this way. ** New or changed byte-compilation warnings ---- *** Warn about missing 'lexical-binding' directive. The compiler now warns if an Elisp file lacks the standard '-*- lexical-binding: ... -*-' cookie on the first line. @@ -2748,7 +2370,6 @@ the line first in the file to declare that it uses the old dialect. ---- *** Warn about empty bodies for more special forms and macros. The compiler now warns about an empty body argument to 'when', 'unless', 'ignore-error' and 'with-suppressed-warnings' in addition to @@ -2759,7 +2380,6 @@ the existing warnings for 'let' and 'let*'. Example: This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'empty-body'. ---- *** Warn about quoted error names in 'condition-case' and 'ignore-error'. The compiler now warns about quoted condition (error) names in 'condition-case' and 'ignore-error'. Example: @@ -2771,7 +2391,6 @@ in 'condition-case' and 'ignore-error'. Example: Quoting them adds the error name 'quote' to those handled or ignored respectively, which was probably not intended. ---- *** Warn about comparison with literal constants without defined identity. The compiler now warns about comparisons by identity with a literal string, cons, vector, record, function, large integer or float as this @@ -2792,7 +2411,6 @@ compared reliably at all. This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'suspicious'. ---- *** Warn about 'condition-case' without handlers. The compiler now warns when the 'condition-case' form is used without any actual handlers, as in @@ -2807,7 +2425,6 @@ was to catch all errors, add an explicit handler for 'error', or use This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'suspicious'. ---- *** Warn about 'unwind-protect' without unwind forms. The compiler now warns when the 'unwind-protect' form is used without any unwind forms, as in @@ -2822,7 +2439,6 @@ simplified away. This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'suspicious'. ---- *** Warn about useless trailing 'cond' clauses. The compiler now warns when a 'cond' form contains clauses following a default (unconditional) clause. Example: @@ -2837,7 +2453,6 @@ perhaps due to misplaced parens. This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'suspicious'. ---- *** Warn about mutation of constant values. The compiler now warns about code that modifies program constants in some obvious cases. Examples: @@ -2857,7 +2472,6 @@ instead. This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'mutate-constant'. ---- *** Warn about more ignored function return values. The compiler now warns when the return value from certain functions is implicitly ignored. Example: @@ -2875,7 +2489,6 @@ name 'ignored-return-value'. The warning will only be issued for calls to functions declared 'important-return-value' or 'side-effect-free' (but not 'error-free'). ---- *** Warn about docstrings that contain control characters. The compiler now warns about docstrings with control characters other than newline and tab. This is often a result of improper escaping. @@ -2890,11 +2503,9 @@ where the docstring contains the four control characters 'CR', 'DEL', The warning name is 'docstrings-control-chars'. ---- *** The warning about wide docstrings can now be disabled separately. Its warning name is 'docstrings-wide'. -+++ ** 'fset', 'defalias' and 'defvaralias' now signal an error for cyclic aliases. Previously, 'fset', 'defalias' and 'defvaralias' could be made to build circular function and variable indirection chains as in @@ -2911,25 +2522,20 @@ Their 'noerror' arguments have no effect and are therefore obsolete. ** Touch Screen support -+++ *** 'x-popup-menu' now understands touch screen events. When a 'touchscreen-begin' or 'touchscreen-end' event is passed as the POSITION argument, it will behave as if that event was a mouse event. -+++ *** New functions for handling touch screen events. The new functions 'touch-screen-track-tap' and 'touch-screen-track-drag' handle tracking common touch screen gestures from within a command. -+++ *** New parameter to 'touchscreen-end' events. CANCEL non-nil establishes that the touch sequence has been intercepted by programs such as window managers and should be ignored with Emacs. ---- ** New variable 'inhibit-auto-fill' to temporarily prevent auto-fill. -+++ ** New variable 'secondary-tool-bar-map'. If non-nil, this variable contains a keymap of menu items that are displayed along tool bar items defined by 'tool-bar-map'. These items @@ -2937,7 +2543,6 @@ are displayed below the tool bar if the value of 'tool-bar-position' is 'top', and above it if the value is 'bottom'. This is used by 'modifier-bar-mode'. ---- ** New variable 'completion-lazy-hilit'. Lisp programs that present completion candidates may bind this variable non-nil around calls to functions such as @@ -2946,12 +2551,10 @@ styles to skip eager fontification of completion candidates, which improves performance. Such a Lisp program can then use the 'completion-lazy-hilit' function to fontify candidates just in time. -+++ ** New primitive 'buffer-last-name'. It returns the name of a buffer before the last time it was renamed or killed. -+++ ** New primitive 'marker-last-position'. It returns the last position of a marker in its buffer even if that buffer has been killed. ('marker-position' would return nil in that @@ -2959,34 +2562,28 @@ case.) ** Functions and variables to transpose sexps ---- *** New helper variable 'transpose-sexps-function'. Lisp programs can now set this variable to customize the behavior of the 'transpose-sexps' command. ---- *** New function 'transpose-sexps-default-function'. The previous implementation of 'transpose-sexps' was moved into its own function, to be used in 'transpose-sexps-function'. ---- *** New function 'treesit-transpose-sexps'. Tree-sitter now unconditionally sets 'transpose-sexps-function' for all tree-sitter enabled modes to this function. ** Functions and variables to move by program statements -+++ *** New variable 'forward-sentence-function'. Major modes can now set this variable to customize the behavior of the 'forward-sentence' command. ---- *** New function 'forward-sentence-default-function'. The previous implementation of 'forward-sentence' is moved into its own function, to be bound by 'forward-sentence-function'. -+++ *** New function 'treesit-forward-sentence'. All tree-sitter enabled modes that define 'sentence' in 'treesit-thing-settings' now set 'forward-sentence-function' to call @@ -2994,13 +2591,11 @@ All tree-sitter enabled modes that define 'sentence' in ** Functions and variables to move by program sexps -+++ *** New function 'treesit-forward-sexp'. Tree-sitter conditionally sets 'forward-sexp-function' for major modes that have defined 'sexp' in 'treesit-thing-settings' to enable sexp-related motion commands. ---- ** New user option 'native-comp-async-warnings-errors-kind'. It allows control of what kinds of warnings and errors from asynchronous native compilation are reported to the parent Emacs process. The @@ -3011,7 +2606,6 @@ and see if you get only warnings that matter. ** Function 'declare' forms -+++ *** New 'ftype' function declaration. The declaration '(ftype TYPE)' specifies the type of a function. Example: @@ -3027,24 +2621,20 @@ native compiler to produce better code, but specifying an incorrect type may lead to Emacs crashing. See the Info node "(elisp) Declare Form" for further information. -+++ *** New 'important-return-value' function declaration and property. The declaration '(important-return-value t)' sets the 'important-return-value' property which indicates that the function return value should probably not be thrown away implicitly. -+++ ** New functions 'file-user-uid' and 'file-group-gid'. These functions are like 'user-uid' and 'group-gid', respectively, but are aware of file name handlers, so they will return the remote UID or GID for remote files (or -1 if the connection has no associated user). -+++ ** 'treesit-font-lock-rules' now accepts additional global keywords. When supplied with ':default-language LANGUAGE', rules after it will default to use 'LANGUAGE'. ---- ** New optional argument to 'modify-dir-local-variable'. An optional 5th argument FILE has been added to 'modify-dir-local-variable'. It can be used to specify which file to @@ -3052,7 +2642,6 @@ modify instead of the default ".dir-locals.el". ** Connection local variables -+++ *** New macros 'connection-local-p' and 'connection-local-value'. The former macro returns non-nil if a variable has a connection-local binding. The latter macro returns the connection-local value of a @@ -3060,14 +2649,12 @@ variable if any, or its current value. ** Hash tables -+++ *** ':rehash-size' and ':rehash-threshold' args no longer have any effect. These keyword arguments are now ignored by 'make-hash-table'. Emacs manages the memory for all hash table objects in the same way. The functions 'hash-table-rehash-size' and 'hash-table-rehash-threshold' remain for compatibility but now always return the old default values. -+++ *** The printed representation has been shrunk and simplified. The 'test' parameter is omitted if it is 'eql' (the default), as is 'data' if empty. 'rehash-size', 'rehash-threshold' and 'size' are @@ -3075,7 +2662,6 @@ always omitted, and ignored if present when the object is read back in. ** Obarrays -+++ *** New obarray type. Obarrays are now represented by an opaque type instead of using vectors. They are created by 'obarray-make' and manage their internal storage @@ -3091,14 +2677,11 @@ with something other than 0, as in '(make-vector N nil)', will no longer work, and should be rewritten to use 'obarray-make'. Alternatively, you can fill the vector with 0. -+++ *** New function 'obarray-clear' removes all symbols from an obarray. ---- *** 'obarray-size' and 'obarray-default-size' are now obsolete. They pertained to the internal storage size which is now irrelevant. -+++ ** 'treesit-install-language-grammar' can handle local directory instead of URL. It is now possible to pass a directory of a local repository as URL inside 'treesit-language-source-alist', so that calling @@ -3106,22 +2689,18 @@ inside 'treesit-language-source-alist', so that calling It may be useful, for example, for the purposes of bisecting a treesitter grammar. -+++ ** New buffer-local variable 'tabulated-list-groups'. It controls display and separate sorting of groups of entries. By default no grouping or sorting is done. -+++ ** New variable 'revert-buffer-restore-functions'. It helps to preserve various states after reverting the buffer. ---- ** New text property 'context-menu-functions'. Like the variable with the same name, it adds menus from the list that is the value of the property to context menus shown when clicking on the text which as this property. ---- ** Detecting the end of an iteration of a keyboard macro. 'read-event', 'read-char', and 'read-char-exclusive' no longer return -1 when called at the end of an iteration of the execution of a keyboard @@ -3133,7 +2712,6 @@ aforementioned functions: (and (arrayp executing-kbd-macro) (>= executing-kbd-macro-index (length executing-kbd-macro))) -+++ ** 'vtable-update-object' updates an existing object with just two arguments. It is now possible to update the representation of an object in a vtable by calling 'vtable-update-object' with just the vtable and the object as @@ -3142,7 +2720,6 @@ this case, would mean repeating the object in the argument list.) When replacing an object with a different one, passing both the new and old objects is still necessary. -+++ ** 'vtable-insert-object' can insert "before" or at an index. The signature of 'vtable-insert-object' has changed and is now: @@ -3155,7 +2732,6 @@ this was not possible.) In addition, LOCATION can be an integer, a (zero-based) index into the table at which the new object is inserted (BEFORE is ignored in this case). -+++ ** New function 'sqlite-execute-batch'. This function lets the user execute multiple SQL statements in one go. It is useful, for example, when a Lisp program needs to evaluate an @@ -3163,45 +2739,37 @@ entire SQL file. ** JSON -+++ *** 'json-serialize' now always returns a unibyte string. This is appropriate since it is an encoding operation. In the unlikely event that a multibyte string is needed, the result can be decoded using (decode-coding-string RESULT 'utf-8) ---- *** The parser keeps duplicated object keys in alist and plist output. A JSON object such as '{"a":1,"a":2}' will now be translated into the Lisp values '((a . 1) (a . 2))' or '(:a 1 :a 2)' if alist or plist object types are requested. ---- *** The parser sometimes signals different types of errors. It will now signal 'json-utf8-decode-error' for inputs that are not correctly UTF-8 encoded. ---- *** The parser and encoder now accept arbitrarily large integers. Previously, they were limited to the range of signed 64-bit integers. ** New tree-sitter functions and variables for defining and using "things" -+++ *** New variable 'treesit-thing-settings'. It allows modes to define "things" like 'defun', 'text', 'sexp', and 'sentence' for navigation commands and tree-traversal functions. -+++ *** New functions for navigating "things". There are new navigation functions 'treesit-thing-prev', 'treesit-thing-next', 'treesit-navigate-thing', 'treesit-beginning-of-thing', and 'treesit-end-of-thing'. -+++ *** New functions 'treesit-thing-at', 'treesit-thing-at-point'. -+++ *** Tree-traversing functions. The functions 'treesit-search-subtree', 'treesit-search-forward', 'treesit-search-forward-goto', and 'treesit-induce-sparse-tree' now @@ -3211,14 +2779,12 @@ for the predicate argument. ** Other tree-sitter function and variable changes -+++ *** 'treesit-parser-list' now takes additional optional arguments. The additional arguments are LANGUAGE and TAG. If LANGUAGE is given, only return parsers for that language. If TAG is given, only return parsers with that tag. Note that passing nil as tag doesn't mean return all parsers, but rather "all parsers with no tags". -+++ *** New variable 'treesit-primary-parser'. This variable should be set by multi-langauge major modes before calling 'treesit-major-mode-setup', in order for tree-sitter integration @@ -3229,7 +2795,6 @@ functionalities to operate correctly. ** MS-Windows -+++ *** You can now opt out of following MS-Windows' Dark mode. By default, Emacs on MS-Windows follows the system's Dark mode for its title bars' and scroll bars' appearance. If the new user option @@ -3237,7 +2802,6 @@ title bars' and scroll bars' appearance. If the new user option will disregard the system's Dark mode and will always use the default Light mode. ---- *** You can now use Image-Dired even if the 'convert' program is not installed. If you don't have GraphicsMagick or ImageMagick installed, and thus the 'gm convert'/'convert' program is not available, Emacs on MS-Windows @@ -3246,7 +2810,6 @@ thumbnail images and show them in the thumbnail buffer. Unlike with using 'convert', this fallback method is synchronous, so Emacs will wait until all the thumbnails are created and displayed, before showing them. ---- *** Emacs on MS-Windows now supports the ':stipple' face attribute. From fdd23023c84f873984aed62ef58699c09ee5ef20 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 21:52:21 +0100 Subject: [PATCH 005/279] ; * admin/MAINTAINERS: Sort external packages alphabetically. --- admin/MAINTAINERS | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index 2317337303b..8841dc0905b 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -386,25 +386,6 @@ Spencer Baugh 3. Externally maintained packages. ============================================================================== -Tramp - Maintainer: Michael Albinus - Repository: https://git.savannah.gnu.org/git/tramp.git - Mailing List: tramp-devel@gnu.org - Bug Reports: M-x tramp-bug - Notes: For backward compatibility requirements, see - lisp/net/trampver.el. - - lisp/net/tramp*.el - doc/misc/tramp*.texi - test/lisp/net/tramp*-tests.el - -Transient - Maintainer: Jonas Bernoulli - Repository: https://github.com/magit/transient - - lisp/transient.el - doc/misc/transient.texi - Modus themes Maintainer: Protesilaos Stavrou Repository: https://github.com/protesilaos/modus-themes @@ -429,6 +410,25 @@ Org Mode doc/misc/org.org doc/misc/org-setup.org +Tramp + Maintainer: Michael Albinus + Repository: https://git.savannah.gnu.org/git/tramp.git + Mailing List: tramp-devel@gnu.org + Bug Reports: M-x tramp-bug + Notes: For backward compatibility requirements, see + lisp/net/trampver.el. + + lisp/net/tramp*.el + doc/misc/tramp*.texi + test/lisp/net/tramp*-tests.el + +Transient + Maintainer: Jonas Bernoulli + Repository: https://github.com/magit/transient + + lisp/transient.el + doc/misc/transient.texi + ;;; Local Variables: ;;; coding: utf-8 From 5617b07a45bedcaa94591e941d06a3255e06302f Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 22:39:10 +0100 Subject: [PATCH 006/279] ; Prefer HTTPS to HTTP in docs * doc/emacs/android.texi (Android Software): * doc/lispref/frames.texi (X Selections): * doc/misc/cc-mode.texi (Custom Filling and Breaking): * doc/misc/efaq.texi (Basic editing): * doc/misc/gnus.texi (Propagating marks, Spam Statistics Package): * doc/misc/org.org (External Links, Images in HTML export) (LaTeX Export, LaTeX math snippets): Prefer HTTPS to HTTP. Fix or mark some broken links while we're at it. --- doc/emacs/android.texi | 2 +- doc/lispref/frames.texi | 2 +- doc/misc/cc-mode.texi | 2 +- doc/misc/efaq.texi | 2 +- doc/misc/gnus.texi | 3 ++- doc/misc/org.org | 8 ++++---- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi index 53c53723074..a1801d378ea 100644 --- a/doc/emacs/android.texi +++ b/doc/emacs/android.texi @@ -1179,7 +1179,7 @@ from improved reproductions of Unix command-line utilities to package repositories providing extensive collections of free GNU and Unix software. - @uref{http://busybox.net, Busybox} provides Unix utilities and + @uref{https://busybox.net, Busybox} provides Unix utilities and limited replicas of certain popular GNU programs such as @command{wget} in a single statically-linked Linux binary, which is capable of running under Android. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 53cc73a1650..2426c9c890f 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4222,7 +4222,7 @@ selection targets that the owner supports, and @code{MULTIPLE}, used for internal purposes by X clients. A selection owner may support any number of other targets, some of which may be standardized by the X Consortium's -@url{http://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html, +@url{https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html, Inter-Client Communication Conventions Manual}, while others, such as @code{UTF8_STRING}, were meant to be standardized by the XFree86 Project, but their standardization was never completed. diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index 65f178c2fa5..abfcf03d08f 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -3189,7 +3189,7 @@ margins of the texts kept intact: @cindex Filladapt mode It's also possible to use other adaptive filling packages, notably Kyle E. Jones' Filladapt package@footnote{It's available from -@uref{http://www.wonderworks.com/}. As of version 2.12, it does however +@uref{https://elpa.gnu.org/packages/filladapt.html}. As of version 2.12, it does however lack a feature that makes it work suboptimally when @code{c-comment-prefix-regexp} matches the empty string (which it does by default). A patch for that is available from diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi index 5e4117d4898..4f936014ed1 100644 --- a/doc/misc/efaq.texi +++ b/doc/misc/efaq.texi @@ -481,7 +481,7 @@ Emacs help works best if it is invoked by a single key whose value should be stored in the variable @code{help-char}. Some Emacs slides and tutorials can be found at -@uref{http://web.psung.name/emacs/}. +@uref{https://web.psung.name/emacs/}. @node Learning how to do something @section How do I find out how to do something in Emacs? diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 7bfe580f768..4d278dc3754 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -22380,6 +22380,7 @@ First of: you really need a patched mairix binary for using the marks propagation feature efficiently. Otherwise, you would have to update the mairix database all the time. You can get the patch at +@c FIXME: This link is broken as of 2025-01-26. @uref{http://www.randomsample.de/mairix-maildir-patch.tar} You need the mairix v0.21 source code for this patch; everything else @@ -26049,7 +26050,7 @@ never install such a back end. @cindex spam filtering, naive Bayesian Paul Graham has written an excellent essay about spam filtering using -statistics: @uref{http://www.paulgraham.com/spam.html,A Plan for +statistics: @uref{https://www.paulgraham.com/spam.html,A Plan for Spam}. In it he describes the inherent deficiency of rule-based filtering as used by SpamAssassin, for example: Somebody has to write the rules, and everybody else has to install these rules. You are diff --git a/doc/misc/org.org b/doc/misc/org.org index 98c416c5da4..363a95fa65c 100644 --- a/doc/misc/org.org +++ b/doc/misc/org.org @@ -3403,7 +3403,7 @@ options: | Link Type | Example | |------------+--------------------------------------------------------------------| -| http | =http://staff.science.uva.nl/c.dominik/= | +| http | =https://staff.science.uva.nl/c.dominik/= | | https | =https://orgmode.org/= | | doi | =doi:10.1000/182= | | file | =file:/home/dominik/images/jupiter.jpg= | @@ -13633,7 +13633,7 @@ backend by default in-lines that image. For example: ~org-html-inline-images~. On the other hand, if the description part of the Org link is itself -another link, such as =file:= or =http:= URL pointing to an image, the +another link, such as =file:= or =https:= URL pointing to an image, the HTML export backend in-lines this image and links to the main image. This Org syntax enables the backend to link low-resolution thumbnail to the high-resolution version of the image, as shown in this example: @@ -13938,7 +13938,7 @@ terminology. You may refer to https://tug.org/begin.html to get familiar with LaTeX basics. Users with LaTeX installed may also run =texdoc latex= from terminal to open LaTeX introduction [fn:: The command will open a PDF file, which is also available for download -from http://mirrors.ctan.org/info/latex-doc-ptr/latex-doc-ptr.pdf] +from https://mirrors.ctan.org/info/latex-doc-ptr/latex-doc-ptr.pdf] *** LaTeX/PDF export commands :PROPERTIES: @@ -15220,7 +15220,7 @@ document in one of the following ways: ~org-latex-to-mathml-jar-file~. If you prefer to use MathToWeb[fn:: See - [[http://www.mathtoweb.com/cgi-bin/mathtoweb_home.pl][MathToWeb]].] + [[https://mathtoweb.sourceforge.io/][MathToWeb]].] as your converter, you can configure the above variables as shown below. From 84595cbcc78b1ea44302f22b83a7d722940c6e49 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Sun, 26 Jan 2025 08:56:15 +0100 Subject: [PATCH 007/279] ; (let-alist): Document double-dot escape syntax. (Bug#75852) --- lisp/emacs-lisp/let-alist.el | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lisp/emacs-lisp/let-alist.el b/lisp/emacs-lisp/let-alist.el index 27ce3e5c137..15a9bb89a42 100644 --- a/lisp/emacs-lisp/let-alist.el +++ b/lisp/emacs-lisp/let-alist.el @@ -141,6 +141,12 @@ the variables of the outer one. You can, however, access alists inside the original alist by using dots inside the symbol, as displayed in the example above. +To refer to a non-`let-alist' variable starting with a dot in BODY, use +two dots instead of one. For example, in the following form `..foo' +refers to the variable `.foo' bound outside of the `let-alist': + + (let ((.foo 42)) (let-alist \\='((foo . nil)) ..foo)) + Note that there is no way to differentiate the case where a key is missing from when it is present, but its value is nil. Thus, the following form evaluates to nil: From 5d021a711a9885100e4ab9d5bb286505a2a16827 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 27 Jan 2025 15:19:06 +0200 Subject: [PATCH 008/279] ; Improve documentation of '.dir-locals.el' * doc/lispref/variables.texi (Directory Local Variables): * doc/emacs/custom.texi (Directory Variables): Document that '.dir-locals-2.el' must be in the same directory as '.dir-locals.el'. (Bug#75890) --- doc/emacs/custom.texi | 9 +++++---- doc/lispref/variables.texi | 5 +++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 22c8bf417e3..4432a0834aa 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -1421,10 +1421,11 @@ this search is skipped for remote files. If needed, the search can be extended for remote files by setting the variable @code{enable-remote-dir-locals} to @code{t}. - You can also use @file{.dir-locals-2.el}; if found, Emacs loads it -in addition to @file{.dir-locals.el}. This is useful when -@file{.dir-locals.el} is under version control in a shared repository -and can't be used for personal customizations. + You can also use @file{.dir-locals-2.el}; if found in the same +directory as @file{.dir-locals.el}, Emacs loads it in addition to +@file{.dir-locals.el}. This is useful when @file{.dir-locals.el} is +under version control in a shared repository and can't be used for +personal customizations. The @file{.dir-locals.el} file should hold a specially-constructed list, which maps major mode names (symbols) to alists diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index 106a7a592b9..b56dfb6077b 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -2205,8 +2205,9 @@ If some of the subdirectories have their own @file{.dir-locals.el} files, Emacs uses the settings from the deepest file it finds starting from the file's directory and moving up the directory tree. This constant is also used to derive the name of a second dir-locals file -@file{.dir-locals-2.el}. If this second dir-locals file is present, -then that is loaded in addition to @file{.dir-locals.el}. This is useful +@file{.dir-locals-2.el}. If this second dir-locals file is present in +the same directory as @file{.dir-locals.el}, then it will be loaded in +addition to @file{.dir-locals.el}. This is useful when @file{.dir-locals.el} is under version control in a shared repository and cannot be used for personal customizations. The file specifies local variables as a specially formatted list; see From a9cde2463abd6677e9d44d306473beef00983aad Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Mon, 20 Jan 2025 20:36:41 -0800 Subject: [PATCH 009/279] Don't signal an error in treesit-node-at * lisp/treesit.el (treesit-node-at): Wrap treesit-buffer-root-node within condition-case. --- lisp/treesit.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 2887521110b..2aa49a596d8 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -213,9 +213,11 @@ language and doesn't match the language of the local parser." (car (treesit-local-parsers-at pos parser-or-lang)))) (treesit-parser-root-node parser)) - (treesit-buffer-root-node - (or parser-or-lang - (treesit-language-at pos)))))) + (condition-case nil + (treesit-buffer-root-node + (or parser-or-lang + (treesit-language-at pos))) + (treesit-no-parser nil))))) (node root) (node-before root) (pos-1 (max (1- pos) (point-min))) From e74efd9a428491288be46ce56f1d6f4f7cf79ed9 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 28 Jan 2025 10:12:09 +0100 Subject: [PATCH 010/279] * CONTRIBUTE: Recommend running the unit test prior to committing. --- CONTRIBUTE | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTE b/CONTRIBUTE index e03674e5d14..2b5c438c055 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -157,8 +157,8 @@ If your test lasts longer than some few seconds, mark it in its 'ert-deftest' definition with ":tags '(:expensive-test)". To run tests on the entire Emacs tree, run "make check" from the -top-level directory. Most tests are in the directory "test/". From -the "test/" directory, run "make " to run the tests for +top-level directory. Most tests are in the directory "test/". From the +"test/" directory, run "make -tests" to run the tests for .el(c). See "test/README" for more information. If you're making changes that involve the Emacs build system, please @@ -169,6 +169,12 @@ test 'out-of-tree' builds as well, i.e.: ../path-to-emacs-sources/configure make +It is a good practice to run the unit test of a change prior to committing. +If you have changed, e.g., the file "xt-mouse.el", you can run the unit +tests via + + make && make -C test xt-mouse-tests + ** Commit messages Ordinarily, a changeset you commit should contain a description of the From 05ee2b741f074b64c46a1063ec331e111099fc31 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 28 Jan 2025 16:57:47 +0200 Subject: [PATCH 011/279] ; * CONTRIBUTE: Suggest to run more tests sometimes. --- CONTRIBUTE | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTE b/CONTRIBUTE index 2b5c438c055..aa6a59cd432 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -175,6 +175,19 @@ tests via make && make -C test xt-mouse-tests +Changes in code that implements infrastructure capabilities might affect +many tests in the test suite, not just the tests for the source files +you changed. For such changes, we recommend running unit tests that +invoke the functions you have changed. You can search for the tests +that might be affected using tools like Grep. For example, suppose you +make a change in the 'rename-file' primitive. Then + + grep -Rl rename-file test --include="*.el" + +will show all the unit tests which invoke rename-file; run them all to +be sure your changes didn't break the test suite. If in doubt, run the +entire suite. + ** Commit messages Ordinarily, a changeset you commit should contain a description of the From 17ef46e849dd1073fc4445834519f983985135fa Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 22:58:13 +0100 Subject: [PATCH 012/279] ; * etc/NEWS: Note CVE-2024-53920 further up also. --- etc/NEWS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index 53f75d120d2..fbfb9086430 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -188,10 +188,13 @@ expectations. This option lists those files and directories whose content Emacs should consider as sufficiently trusted to run any part of the code contained therein even without any explicit user request. + For example, Flymake's backend for Emacs Lisp consults this option and disables itself with an "untrusted content" warning if the file is not listed. +This option is used to fix CVE-2024-53920. See below for details. + ** Emacs now supports Unicode Standard version 15.1. ** Emacs now comes with Org v9.7. From 486d5d524ca116a2aaed3069536a2372497551b9 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 21:57:34 +0100 Subject: [PATCH 013/279] Update cc-mode URL to point to nongnu.org * doc/misc/cc-mode.texi (Getting Started) (Custom Filling and Breaking, Updating CC Mode) (Mailing Lists and Bug Reports): * lisp/progmodes/cc-mode.el: Update cc-mode URL to point to nongnu.org, instead of old URL on SourceForge. --- doc/misc/cc-mode.texi | 8 ++++---- lisp/progmodes/cc-mode.el | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index abfcf03d08f..9c3e1a85fb1 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -581,7 +581,7 @@ you are going to be editing AWK files, @file{README} describes how to configure your (X)Emacs so that @ccmode{} will supersede the obsolete @code{awk-mode.el} which might have been supplied with your (X)Emacs. @ccmode{} might not work with older versions of Emacs or XEmacs. See -the @ccmode{} release notes at @uref{https://cc-mode.sourceforge.net} +the @ccmode{} release notes at @uref{https://www.nongnu.org/cc-mode/} for the latest information on Emacs version and package compatibility (@pxref{Updating CC Mode}). @@ -3193,7 +3193,7 @@ E. Jones' Filladapt package@footnote{It's available from lack a feature that makes it work suboptimally when @code{c-comment-prefix-regexp} matches the empty string (which it does by default). A patch for that is available from -@uref{https://cc-mode.sourceforge.net/,, the CC Mode web site}.}, +@uref{https://www.nongnu.org/cc-mode/,, the CC Mode web site}.}, @c 2005/11/22: The above is still believed to be the case. which handles things like bulleted lists nicely. There's a convenience function @code{c-setup-filladapt} that tunes the relevant variables in @@ -7660,7 +7660,7 @@ have old versions of @ccmode{} and so should be upgraded. Access to the compatibility, etc.@: are all available on the web site: @quotation -@uref{https://cc-mode.sourceforge.net/} +@uref{https://www.nongnu.org/cc-mode/} @end quotation @@ -7694,7 +7694,7 @@ the GNU Bug Tracker at @url{https://debbugs.gnu.org}, then sends it on to @email{bug-cc-mode@@gnu.org}. You can also send reports, other questions, and suggestions (kudos?@: @t{;-)} to that address. It's a mailing list which you can join or browse an archive of; see the web site at -@uref{https://cc-mode.sourceforge.net/} for further details. +@uref{https://www.nongnu.org/cc-mode/} for further details. @cindex announcement mailing list If you want to get announcements of new @ccmode{} releases, send the diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index b1b2f6268e9..992f7878a8b 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -66,7 +66,7 @@ ;; You can get the latest version of CC Mode, including PostScript ;; documentation and separate individual files from: ;; -;; https://cc-mode.sourceforge.net/ +;; https://www.nongnu.org/cc-mode/ ;; ;; You can join a moderated CC Mode announcement-only mailing list by ;; visiting @@ -172,8 +172,8 @@ ;; `c-font-lock-init' too to set up CC Mode's font lock support. ;; ;; See cc-langs.el for further info. A small example of a derived mode -;; is also available at . +;; is also available at +;; . (defun c-leave-cc-mode-mode () (when c-buffer-is-cc-mode From 6447634f1714cbf4211b682a62915e72c934af6b Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 22:02:07 +0100 Subject: [PATCH 014/279] ; * admin/MAINTAINERS: Add CC Mode. --- admin/MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index 8841dc0905b..5060fc20506 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -386,6 +386,14 @@ Spencer Baugh 3. Externally maintained packages. ============================================================================== +CC Mode + Maintainer: Alan Mackenzie + Website: https://www.nongnu.org/cc-mode + Repository: https://hg.savannah.nongnu.org/hgweb/cc-mode/ + Bug reports: bug-cc-mode@gnu.org + + lisp/progmodes/cc-*.el + Modus themes Maintainer: Protesilaos Stavrou Repository: https://github.com/protesilaos/modus-themes From 1969c2c3eda4af152037a5a7fdf82a834541db41 Mon Sep 17 00:00:00 2001 From: Bastien Guerry Date: Tue, 28 Jan 2025 14:25:22 +0100 Subject: [PATCH 015/279] ; * admin/MAINTAINERS: Remove Bastien Guerry. (cherry picked from commit eb73dd0d45126e693645ead7a34f113217fa48bb) --- admin/MAINTAINERS | 5 ----- 1 file changed, 5 deletions(-) diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index 5060fc20506..0851aa94674 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -52,11 +52,6 @@ Stefan Monnier minibuffer completion lisp/outline.el -Bastien Guerry - Org - lisp/org/* - doc/misc/org.texi - Artur Malabarba lisp/emacs-lisp/let-alist.el From d0907a43888ea531a94d46d4fdbb45df9a23cc95 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Tue, 28 Jan 2025 18:45:52 +0100 Subject: [PATCH 016/279] ; * admin/MAINTAINERS: Prefer "website" to "home page". --- admin/MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index 0851aa94674..a47af03eeee 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -397,8 +397,8 @@ Modus themes etc/themes/modus*.el Org Mode - Home Page: https://orgmode.org/ Maintainer: Org Mode developers + Website: https://orgmode.org/ Repository: https://git.savannah.gnu.org/git/emacs/org-mode.git Mailing list: emacs-orgmode@gnu.org Bug Reports: M-x org-submit-bug-report From 0c6aa27cde5dc911cfd3646d5789124fecb06f46 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 29 Jan 2025 17:55:58 +0200 Subject: [PATCH 017/279] ; Fix Cygw32 build (bug#75926) (cherry picked from commit cb62a47896bb21420a709c655034e8acfcb08082) --- src/treesit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/treesit.c b/src/treesit.c index 2805fa69aed..655eab8af8a 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -4374,7 +4374,7 @@ the symbol of that THING. For example, (or sexp sentence). */); defsubr (&Streesit_subtree_stat); #endif /* HAVE_TREE_SITTER */ defsubr (&Streesit_available_p); -#ifdef WINDOWSNT +#ifdef HAVE_NTGUI DEFSYM (Qtree_sitter__library_abi, "tree-sitter--library-abi"); Fset (Qtree_sitter__library_abi, #if HAVE_TREE_SITTER From 0b3e050c6ce07e7b87aaab1185f605a1d8c16ba1 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 30 Jan 2025 08:38:05 +0200 Subject: [PATCH 018/279] * src/puresize.h (BASE_PURESIZE): Increase (bug#75907). --- src/puresize.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/puresize.h b/src/puresize.h index e9cbdd86022..f2576666a66 100644 --- a/src/puresize.h +++ b/src/puresize.h @@ -47,7 +47,7 @@ INLINE_HEADER_BEGIN #endif #ifndef BASE_PURESIZE -#define BASE_PURESIZE (3000000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) +#define BASE_PURESIZE (3400000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) #endif /* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ From d11488fd6fb72acd9f9356b95b2f905c59a1095d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 30 Jan 2025 11:37:40 +0200 Subject: [PATCH 019/279] ; * lisp/subr.el (sit-for): Doc fix. --- lisp/subr.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index 9666cc09a5c..7aca542dab4 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3529,13 +3529,15 @@ causes it to evaluate `help-form' and display the result." char)) (defun sit-for (seconds &optional nodisp) - "Redisplay, then wait for SECONDS seconds. Stop when input is available. + "Redisplay, then wait for SECONDS seconds; stop when input is available. SECONDS may be a floating-point value. \(On operating systems that do not support waiting for fractions of a second, floating-point values are rounded down to the nearest integer.) -If optional arg NODISP is t, don't redisplay, just wait for input. -Redisplay does not happen if input is available before it starts. +If there's pending input, return nil immediately without redisplaying +and without waiting. +If optional arg NODISP is t, don't redisplay, just wait for input (but +still return nil immediately if there's pending input). Value is t if waited the full time with no input arriving, and nil otherwise." ;; This used to be implemented in C until the following discussion: From 5485ea6aef91c65a0ce300347db3c0ac138ad550 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sun, 26 Jan 2025 14:53:49 +0100 Subject: [PATCH 020/279] Do not set `trusted-content` in major modes * lisp/progmodes/elisp-mode.el (lisp-interaction-mode): * lisp/ielm.el (inferior-emacs-lisp-mode): Do not set `trusted-content. * lisp/ielm.el (ielm): * lisp/simple.el (get-scratch-buffer-create): Set `trusted-content` here instead. * lisp/files.el (trusted-content): Doc fix; warn against setting this option to :all in a major or mode mode. Problem reported by Max Nikulin . --- etc/NEWS | 3 +++ lisp/files.el | 5 +++-- lisp/ielm.el | 4 ++-- lisp/progmodes/elisp-mode.el | 3 +-- lisp/simple.el | 4 +++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index fbfb9086430..da3a1d670e7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -193,6 +193,9 @@ For example, Flymake's backend for Emacs Lisp consults this option and disables itself with an "untrusted content" warning if the file is not listed. +Emacs Lisp authors should note that a major or minor mode must never set +this variable to the ':all' value. + This option is used to fix CVE-2024-53920. See below for details. ** Emacs now supports Unicode Standard version 15.1. diff --git a/lisp/files.el b/lisp/files.el index b64935e8d9e..380721f1fe2 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -724,11 +724,12 @@ enabled (for example, when it is added to a mode hook). Each element of the list should be a string: - If it ends in \"/\", it is considered as a directory name and means that Emacs should trust all the files whose name has this directory as a prefix. -- else it is considered as a file name. +- Otherwise, it is considered a file name. Use abbreviated file names. For example, an entry \"~/mycode/\" means that Emacs will trust all the files in your directory \"mycode\". This variable can also be set to `:all', in which case Emacs will trust -all files, which opens a gaping security hole." +all files, which opens a gaping security hole. Emacs Lisp authors +should note that this value must never be set by a major or minor mode." :type '(choice (repeat :tag "List" file) (const :tag "Trust everything (DANGEROUS!)" :all)) :version "30.1") diff --git a/lisp/ielm.el b/lisp/ielm.el index 561185a738a..b3cd02b4dc0 100644 --- a/lisp/ielm.el +++ b/lisp/ielm.el @@ -580,7 +580,6 @@ Customized bindings may be defined in `ielm-map', which currently contains: ielm-fontify-input-enable (comint-fontify-input-mode)) - (setq-local trusted-content :all) (setq comint-prompt-regexp (concat "^" (regexp-quote ielm-prompt))) (setq-local paragraph-separate "\\'") (setq-local paragraph-start comint-prompt-regexp) @@ -684,7 +683,8 @@ See `inferior-emacs-lisp-mode' for details." (unless (comint-check-proc buf-name) (with-current-buffer (get-buffer-create buf-name) (unless (zerop (buffer-size)) (setq old-point (point))) - (inferior-emacs-lisp-mode))) + (inferior-emacs-lisp-mode) + (setq-local trusted-content :all))) (pop-to-buffer-same-window buf-name) (when old-point (push-mark old-point)))) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 59c33c09f0f..a573d9ef864 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1337,8 +1337,7 @@ Semicolons start comments. \\{lisp-interaction-mode-map}" :abbrev-table nil - (setq-local lexical-binding t) - (setq-local trusted-content :all)) + (setq-local lexical-binding t)) ;;; Emacs Lisp Byte-Code mode diff --git a/lisp/simple.el b/lisp/simple.el index da4d20e4f78..152a8c451ac 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -11154,7 +11154,9 @@ too short to have a dst element. (when initial-scratch-message (insert (substitute-command-keys initial-scratch-message)) (set-buffer-modified-p nil)) - (funcall initial-major-mode)) + (funcall initial-major-mode) + (when (eq initial-major-mode 'lisp-interaction-mode) + (setq-local trusted-content :all))) scratch))) (defun scratch-buffer () From 87be3aa1491d5016da8ddb2e896720c53d153643 Mon Sep 17 00:00:00 2001 From: Damien Cassou Date: Thu, 30 Jan 2025 21:44:31 +0100 Subject: [PATCH 021/279] eglot: Allow omnisharp binary to be capitalized "OmniSharp" Some distributors (e.g. nixpkgs) provide a binary "OmniSharp" instead of "omnisharp", which breaks on case-sensitive file-systems. * lisp/progmodes/eglot.el (eglot-server-programs): Add "OmniSharp" as a valid binary name to search for. (Bug#75954) --- lisp/progmodes/eglot.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 9eb28e34faf..45e0e7d16cd 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -327,6 +327,7 @@ automatically)." ((csharp-mode csharp-ts-mode) . ,(eglot-alternatives '(("omnisharp" "-lsp") + ("OmniSharp" "-lsp") ("csharp-ls")))) (purescript-mode . ("purescript-language-server" "--stdio")) ((perl-mode cperl-mode) From 6441b9ea7af143a882fc1222be345b9260d5bbae Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Fri, 31 Jan 2025 19:25:03 +0100 Subject: [PATCH 022/279] Fix typo in Gnus manual * doc/misc/gnus.texi (Comparing Mail Back Ends): Fix a missing verb. (Bug#75974) --- doc/misc/gnus.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 4d278dc3754..1eace0d5b5a 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -17204,7 +17204,7 @@ filename is unrelated to the article number in Gnus. @code{nnmaildir} also stores the equivalent of @code{nnml}'s overview files in one file per article, so it uses about twice as many inodes as @code{nnml}. (Use @code{df -i} to see how plentiful your inode supply is.) If this -slows you down or takes up very much space, a non-block-structured +slows you down or takes up very much space, use a non-block-structured file system. Since maildirs don't require locking for delivery, the maildirs you use From 3bccd04c5c659307231f9e03895d71d26c1d5f8f Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 1 Feb 2025 04:08:43 +0100 Subject: [PATCH 023/279] Improve wording in symbols.texi * doc/lispref/symbols.texi (Symbol Components): Improve wording (Bug#75512). Reported by Matt Trzcinski . --- doc/lispref/symbols.texi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi index 24b4e892024..2fd3da9812d 100644 --- a/doc/lispref/symbols.texi +++ b/doc/lispref/symbols.texi @@ -106,11 +106,11 @@ reference any object. (This is not the same thing as holding the symbol a value cell that is void results in an error, such as @samp{Symbol's value as variable is void}. - Because each symbol has separate value and function cells, variables -names and function names do not conflict. For example, the symbol -@code{buffer-file-name} has a value (the name of the file being -visited in the current buffer) as well as a function definition (a -primitive function that returns the name of the file): + Because each symbol has separate value and function cells, the names +of variables and functions do not conflict. For example, the symbol +@code{buffer-file-name} has a value (the name of the file being visited +in the current buffer) as well as a function definition (a primitive +function that returns the name of the file): @example buffer-file-name From fdc6842a44e76db35432305455a05f2125962a62 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 11:33:34 +0200 Subject: [PATCH 024/279] Remove bookmark fringe marks when deleting all bookmarks * lisp/bookmark.el (bookmark-delete-all): Remove fringe marks for all the bookmarks. (Bug#75953) --- lisp/bookmark.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lisp/bookmark.el b/lisp/bookmark.el index cd59293e0a4..153646c1fff 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -1584,6 +1584,8 @@ confirmation." (when (or no-confirm (yes-or-no-p "Permanently delete all bookmarks? ")) (bookmark-maybe-load-default-file) + (dolist (bm bookmark-alist) + (bookmark--remove-fringe-mark bm)) (setq bookmark-alist-modification-count (+ bookmark-alist-modification-count (length bookmark-alist))) (setq bookmark-alist nil) From 22ab03e155adc4df0623e3ee9c2cc56a228e148a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 12:21:51 +0200 Subject: [PATCH 025/279] ; Avoid compiler warnings in the MS-Windows build * src/w32heap.c: Remove unused variables, to avoid compilation warnings. This removes variables that were used only in the unexec build. --- src/w32heap.c | 45 --------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/src/w32heap.c b/src/w32heap.c index 2ba36f01751..f767e5781bf 100644 --- a/src/w32heap.c +++ b/src/w32heap.c @@ -89,51 +89,6 @@ typedef struct _RTL_HEAP_PARAMETERS { /* Info for keeping track of our dynamic heap used after dumping. */ unsigned char *data_region_base = NULL; unsigned char *data_region_end = NULL; -static DWORD_PTR committed = 0; - -/* The maximum block size that can be handled by a non-growable w32 - heap is limited by the MaxBlockSize value below. - - This point deserves an explanation. - - The W32 heap allocator can be used for a growable heap or a - non-growable one. - - A growable heap is not compatible with a fixed base address for the - heap. Only a non-growable one is. One drawback of non-growable - heaps is that they can hold only objects smaller than a certain - size (the one defined below). Most of the larger blocks are GC'ed - before dumping. In any case, and to be safe, we implement a simple - first-fit allocation algorithm starting at the end of the - dumped_data[] array as depicted below: - - ---------------------------------------------- - | | | | - | Private heap |-> <-| Big chunks | - | | | | - ---------------------------------------------- - ^ ^ ^ - dumped_data dumped_data bc_limit - + committed - -*/ - -/* Info for managing our preload heap, which is essentially a fixed size - data area in the executable. */ -#define PAGE_SIZE 0x1000 -#define MaxBlockSize (0x80000 - PAGE_SIZE) - -#define MAX_BLOCKS 0x40 - -static struct -{ - unsigned char *address; - size_t size; - DWORD occupied; -} blocks[MAX_BLOCKS]; - -static DWORD blocks_number = 0; -static unsigned char *bc_limit; /* Handle for the private heap: - inside the dumped_data[] array before dump with unexec, From e067f2763fd52b78342b5c759205032227e82ebe Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 12:22:13 +0200 Subject: [PATCH 026/279] Rename a recently-added variable (bug#56197) * lisp/emacs-lisp/lisp-mode.el (lisp-fill-paragraphs-as-doc-string): Renamed from 'lisp-fill-paragraph-as-displayed' and default value reversed. (lisp-fill-paragraph): Adjust to the change. * test/lisp/emacs-lisp/lisp-mode-tests.el (lisp-fill-paragraph-as-displayed): Likewise. --- lisp/emacs-lisp/lisp-mode.el | 13 +++++++------ test/lisp/emacs-lisp/lisp-mode-tests.el | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 3b1d34bf7cd..1349a5212ed 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -1431,16 +1431,17 @@ Any non-integer value means do not use a different value of :group 'lisp :version "30.1") -(defvar lisp-fill-paragraph-as-displayed nil - "Modify the behavior of `lisp-fill-paragraph'. +(defvar lisp-fill-paragraphs-as-doc-string t + "Whether `lisp-fill-paragraph' should fill strings as ELisp doc strings. The default behavior of `lisp-fill-paragraph' is tuned for filling Emacs Lisp doc strings, with their special treatment for the first line. -Particularly, strings are filled in a narrowed context to avoid filling +Specifically, strings are filled in a narrowed context to avoid filling surrounding code, which means any leading indent is disregarded, which can cause the filled string to extend passed the configured `fill-column' variable value. If you would rather fill the string in -its original context and ensure the `fill-column' value is more strictly -respected, set this variable to true. Doing so makes +its original context, disregarding the special conventions of ELisp doc +strings, and want to ensure the `fill-column' value is more strictly +respected, set this variable to nil. Doing so makes `lisp-fill-paragraph' behave as it used to in Emacs 27 and prior versions.") @@ -1506,7 +1507,7 @@ and initial semicolons." ;; code. (if (not string-start) (lisp--fill-line-simple) - (unless lisp-fill-paragraph-as-displayed + (when lisp-fill-paragraphs-as-doc-string ;; If we're in a string, then narrow (roughly) to that ;; string before filling. This avoids filling Lisp ;; statements that follow the string. diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el index 96e37114276..676d4f2ab4a 100644 --- a/test/lisp/emacs-lisp/lisp-mode-tests.el +++ b/test/lisp/emacs-lisp/lisp-mode-tests.el @@ -333,7 +333,7 @@ Here is some more text.\" (ert-deftest lisp-fill-paragraph-as-displayed () "Test bug#56197 -- more specifically, validate that a leading indentation for a string is preserved in the filled string." - (let ((lisp-fill-paragraph-as-displayed t) ;variable under test + (let ((lisp-fill-paragraphs-as-doc-string nil) ;variable under test ;; The following is a contrived example that demonstrates the ;; fill-column problem when the string to fill is indented. (source "\ From 004600e0142fb6f9c7ab492f855ee9668bb0421e Mon Sep 17 00:00:00 2001 From: shipmints Date: Mon, 27 Jan 2025 11:16:04 -0500 Subject: [PATCH 027/279] Add new user option bookmark-bmenu-type-column-width * lisp/bookmark.el (bookmark-bmenu-mode): Add new user option bookmark-bmenu-type-column-width, defaulting to 8 for backwards compatibility, and use it when creating the tabulated bookmark list. (Bug#75826) --- etc/NEWS | 8 ++++++++ lisp/bookmark.el | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index 5b9e356737e..05008a5524b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -451,6 +451,14 @@ Such bindings make it possible to compute which function to bind to FUNC. If 'whitespace-style' includes 'missing-newline-at-eof' (which is the default), the 'whitespace-cleanup' function will now add the newline. +** Bookmark + +--- +*** New user option 'bookmark-bmenu-type-column-width'. +This user option controls the width of the type column on the bookmark +menu 'bookmark-bmenu-list'. The default value is 8 which is backwards +compatible. + ** Gnus --- diff --git a/lisp/bookmark.el b/lisp/bookmark.el index d68e9308208..c86101217d6 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -165,6 +165,10 @@ This includes the annotations column.") You can toggle whether files are shown with \\\\[bookmark-bmenu-toggle-filenames]." :type 'natnum) +(defcustom bookmark-bmenu-type-column-width 8 + "Column width for bookmark type in a buffer listing bookmarks." + :type 'natnum + :version "31.1") (defcustom bookmark-bmenu-toggle-filenames t "Non-nil means show filenames when listing bookmarks. @@ -2061,7 +2065,7 @@ At any time you may use \\[revert-buffer] to go back to sorting by creation orde `[("" 1) ;; Space to add "*" for bookmark with annotation ("Bookmark Name" ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate) - ("Type" 8 bookmark-bmenu--type-predicate) + ("Type" ,bookmark-bmenu-type-column-width bookmark-bmenu--type-predicate) ,@(if bookmark-bmenu-toggle-filenames '(("File" 0 bookmark-bmenu--file-predicate)))]) (setq tabulated-list-padding bookmark-bmenu-marks-width) From ed0ca7c23e60696148b986ac15fb20e40aec7dea Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 12:34:26 +0200 Subject: [PATCH 028/279] * etc/NEWS: Fix punctuation. --- etc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index 05008a5524b..4859ac414e3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -456,7 +456,7 @@ default), the 'whitespace-cleanup' function will now add the newline. --- *** New user option 'bookmark-bmenu-type-column-width'. This user option controls the width of the type column on the bookmark -menu 'bookmark-bmenu-list'. The default value is 8 which is backwards +menu 'bookmark-bmenu-list'. The default value is 8 which is backwards compatible. ** Gnus From f40aff4c5d2d8dc83074addc568abcdf564e6b01 Mon Sep 17 00:00:00 2001 From: Pengji Zhang Date: Mon, 27 Jan 2025 19:42:00 +0800 Subject: [PATCH 029/279] New user option 'Buffer-menu-human-readable-sizes' * lisp/buff-menu.el (Buffer-menu-human-readable-sizes): New user option. (list-buffers--refresh): Use it. * etc/NEWS: Announce the new user option. (Bug#75825) --- etc/NEWS | 6 ++++++ lisp/buff-menu.el | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index 4859ac414e3..fd0d3ece5eb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -402,6 +402,12 @@ set to 'title'. *** New user option 'ibuffer-human-readable-size'. When non-nil, buffer sizes are shown in human readable format. +--- +** Buffer Menu +*** New user option 'Buffer-menu-human-readable-sizes'. +When non-nil, buffer sizes are shown in human readable format. The +default is nil, which retains the old format. + ** Smerge *** New command 'smerge-extend' extends a conflict over surrounding lines. diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el index 4418db01724..36268b3512a 100644 --- a/lisp/buff-menu.el +++ b/lisp/buff-menu.el @@ -135,6 +135,14 @@ If this is nil, group names are unsorted." :group 'Buffer-menu :version "30.1") +(defcustom Buffer-menu-human-readable-sizes nil + "If non-nil, show buffer sizes in human-readable format. +That means to use `file-size-human-readable' (which see) to format the +buffer sizes in the buffer size column." + :type 'boolean + :group 'Buffer-menu + :version "31.1") + (defvar-local Buffer-menu-files-only nil "Non-nil if the current Buffer Menu lists only file buffers. This is set by the prefix argument to `buffer-menu' and related @@ -831,7 +839,10 @@ See more at `Buffer-menu-filter-predicate'." (if buffer-read-only "%" " ") (if (buffer-modified-p) "*" " ") (Buffer-menu--pretty-name name) - (number-to-string (buffer-size)) + (funcall (if Buffer-menu-human-readable-sizes + #'file-size-human-readable + #'number-to-string) + (buffer-size)) (concat (format-mode-line mode-name nil nil buffer) (if mode-line-process From 4aa53f293455e690a9aa07eac13011020b887e0e Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 1 Feb 2025 06:07:24 -0500 Subject: [PATCH 030/279] (defcustom): Improve doc of `:group` * lisp/custom.el (defcustom): Mention the use of a default group and the fact that `:group` can be repeated. --- lisp/custom.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/custom.el b/lisp/custom.el index 3abc326e674..9e6eb930467 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -306,7 +306,8 @@ The following keywords are meaningful: The following common keywords are also meaningful. :group VALUE should be a customization group. - Add SYMBOL (or FACE with `defface') to that group. + Add SYMBOL (or FACE with `defface') to that group instead of + the default group. Can be repeated. :link LINK-DATA Include an external link after the documentation string for this item. This is a sentence containing an active field which From 89eac993c76b58384e1e5d5ffb7402a8bcdb6290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rudolf=20Adamkovi=C4=8D?= Date: Sat, 25 Jan 2025 11:24:34 +0100 Subject: [PATCH 031/279] Ispell: Increase help timeout * lisp/textmodes/ispell.el (ispell-help-timeout): Increase the timeout from 5 to 30 seconds to allow users, especially new users, read the Ispell help menu comfortably and act confidently (bug#75804). --- lisp/textmodes/ispell.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index abe3abefc26..fbd1746b96e 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -402,7 +402,7 @@ re-start Emacs." (const :tag "default" nil)) (coding-system :tag "Coding System")))) -(defcustom ispell-help-timeout 5 +(defcustom ispell-help-timeout 30 "The number of seconds to display the help text." :type 'number :version "28.1") From ba2719389515cee54874588d76b9244c17f568d5 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 1 Feb 2025 12:24:27 +0100 Subject: [PATCH 032/279] ; * etc/NEWS: Fix wording. --- etc/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index da3a1d670e7..ec14e447859 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -194,7 +194,7 @@ and disables itself with an "untrusted content" warning if the file is not listed. Emacs Lisp authors should note that a major or minor mode must never set -this variable to the ':all' value. +this option to the ':all' value. This option is used to fix CVE-2024-53920. See below for details. From 3a5aba81ca0739ff3f877a77c41cc0cd5a3c8fc7 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 13:26:06 +0200 Subject: [PATCH 033/279] ; Fix last change * etc/NEWS: Announce the change in 'ispell-help-timeout'. * lisp/textmodes/ispell.el (ispell-help-timeout): Change :version. (Bug#75804) --- etc/NEWS | 7 +++++++ lisp/textmodes/ispell.el | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index fd0d3ece5eb..93e2d0ebc65 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -733,6 +733,13 @@ the 'mutool' program after their initial conversion to PDF format. The name of the 'djvused' program can be customized by changing the user option 'doc-view-djvused-program'. +** Ispell + +--- +*** The default value of 'ispell-help-timeout' has changed. +The default value is now 30 seconds, as the old value was too short to +allow reading the help text. + ** Flyspell --- diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index fbd1746b96e..f53732098ea 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -405,7 +405,7 @@ re-start Emacs." (defcustom ispell-help-timeout 30 "The number of seconds to display the help text." :type 'number - :version "28.1") + :version "31.1") (defvar ispell-dictionary-base-alist '((nil ; default From 0ef78b131b4e232f064e370699a7ae2413715a44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jostein=20Kj=C3=B8nigsen?= Date: Mon, 6 Jan 2025 15:08:36 +0100 Subject: [PATCH 034/279] lisp/progmodes/csharp-mode.el: Fix fontification of typeof (bug#75406). --- lisp/progmodes/csharp-mode.el | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 3e07da40cdd..9d19456179b 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -748,6 +748,12 @@ compilation and evaluation time conflicts." (treesit-query-compile 'c-sharp "(type_of_expression)" t) t)) +(defun csharp-ts-mode--test-typeof-expression () + "Return non-nil if (type_of_expression) is in the grammar." + (ignore-errors + (treesit-query-compile 'c-sharp "(typeof_expression)" t) + t)) + (defun csharp-ts-mode--test-name-equals () "Return non-nil if (name_equals) is in the grammar." (ignore-errors @@ -871,7 +877,9 @@ compilation and evaluation time conflicts." (type_parameter_constraint (type type: (generic_name (identifier) @font-lock-type-face))))) ,@(when (csharp-ts-mode--test-type-of-expression) - '((type_of_expression (identifier) @font-lock-type-face)) + '((type_of_expression (identifier) @font-lock-type-face))) + + ,@(when (csharp-ts-mode--test-typeof-expression) '((typeof_expression (identifier) @font-lock-type-face))) (object_creation_expression From 532ff6e29df87b9fdc84c56cddd9c587c5895e48 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 1 Feb 2025 20:59:24 +0800 Subject: [PATCH 035/279] Fix compilation warnings on Android * src/alloc.c (pointer_align): Only define if !USE_ALIGNED_ALLOC. --- src/alloc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index 40a59854a87..c39459e1f2e 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -501,14 +501,6 @@ Lisp_Object const *staticvec[NSTATICS]; int staticidx; -#ifndef HAVE_ALIGNED_ALLOC -static void * -pointer_align (void *ptr, int alignment) -{ - return (void *) ROUNDUP ((uintptr_t) ptr, alignment); -} -#endif - /* Extract the pointer hidden within O. */ static ATTRIBUTE_NO_SANITIZE_UNDEFINED void * @@ -1095,6 +1087,16 @@ struct ablocks /* The list of free ablock. */ static struct ablock *free_ablock; +#if !USE_ALIGNED_ALLOC + +static void * +pointer_align (void *ptr, int alignment) +{ + return (void *) ROUNDUP ((uintptr_t) ptr, alignment); +} + +#endif /* !USE_ALIGNED_ALLOC */ + /* Allocate an aligned block of nbytes. Alignment is on a multiple of BLOCK_ALIGN and `nbytes' has to be smaller or equal to BLOCK_BYTES. */ From eb12b6d153b8ad3f9e3fe23761a98021d8071293 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Thu, 30 Jan 2025 17:09:48 +0300 Subject: [PATCH 036/279] Avoid infinite questions if TAGS file was removed When the visited TAGS file was removed, commands that depend on TAGS, such as auto-completion, may invoke an interactive question whether a user wants to re-read the file. From that point on, the question will be asked over and over, because the file no longer exists, which results in mtime mismatch and inability to "fix the mismatch" by reading from the file. Fix that by simply ignoring the mismatch if the file no longer exists. * lisp/progmodes/etags.el (tags-verify-table): Avoid infinite questions if TAGS file was removed. (Bug#75946) --- lisp/progmodes/etags.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index b322b35ed63..22f946c5698 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -445,6 +445,9 @@ Returns non-nil if it is a valid table." (set-buffer (get-file-buffer file)) (or verify-tags-table-function (tags-table-mode)) (unless (or (verify-visited-file-modtime (current-buffer)) + ;; Avoid an infinte loop of questions about + ;; re-reading content if file was removed. + (not (file-exists-p file)) ;; Decide whether to revert the file. ;; revert-without-query can say to revert ;; or the user can say to revert. From 20e3959dc37685334579394b320ab93f751243fb Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 15:44:47 +0200 Subject: [PATCH 037/279] ; * lisp/progmodes/etags.el (tags-verify-table): Improve comment (bug#75946). --- lisp/progmodes/etags.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index 22f946c5698..42057a3aacb 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -445,8 +445,9 @@ Returns non-nil if it is a valid table." (set-buffer (get-file-buffer file)) (or verify-tags-table-function (tags-table-mode)) (unless (or (verify-visited-file-modtime (current-buffer)) - ;; Avoid an infinte loop of questions about - ;; re-reading content if file was removed. + ;; 'verify-visited-file-modtime' return non-nil if + ;; the tags table file was meanwhile deleted. Avoid + ;; asking the question below again if so. (not (file-exists-p file)) ;; Decide whether to revert the file. ;; revert-without-query can say to revert From 4eabfd68c91185909be307435e5db8b8f0fb4102 Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Sat, 18 Jan 2025 20:55:18 +0000 Subject: [PATCH 038/279] Use #$ for lambda fixups in native compilation data vectors The "#$" syntax is recognized by Fread, which substitutes Vload_file_name in its place. If Vload_file_name is bound appropriately, no other value can produce an object EQ to the one produced by "#$". We use this to check the data vector for entries that we know should have been initialized: if the value is still equal to what we bound Vload_file_name to when it was read, it wasn't initialized, and we abort. * lisp/emacs-lisp/comp.el (comp--#$): New defvar. (comp--finalize-container): Use it. * src/comp.c (ABI_VERSION): Bump. (emit_static_object): Ensure 'comp--#$' prints as "#$". (load_static_obj): Ensure '#$' reads as Vcomp__hashdollar. (check_comp_unit_relocs): Adjust assertion. (syms_of_comp): Define 'comp--#$'. * src/pdumper.c (dump_do_dump_relocation): Adjust assertion. --- lisp/emacs-lisp/comp.el | 8 ++++---- src/comp.c | 26 +++++++++++++++++++++----- src/pdumper.c | 2 +- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index dd94e75966c..0da007afebb 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -42,6 +42,7 @@ (defvar comp-subr-arities-h) (defvar native-comp-eln-load-path) (defvar native-comp-enable-subr-trampolines) +(defvar comp--\#$) (declare-function comp--compile-ctxt-to-file0 "comp.c") (declare-function comp--init-ctxt "comp.c") @@ -3254,10 +3255,9 @@ Set it into the `type' slot." ;; from the corresponding m-var. collect (if (gethash obj (comp-ctxt-byte-func-to-func-h comp-ctxt)) - ;; Hack not to have `--lambda-fixup' in - ;; data relocations as it would trigger the - ;; check in 'check_comp_unit_relocs'. - (intern (concat (make-string 1 ?-) "-lambda-fixup")) + ;; This prints as #$, so we can assert this + ;; value does not remain in the data vector + comp--\#$ obj)))) (defun comp--finalize-relocs () diff --git a/src/comp.c b/src/comp.c index 2b2ac073214..692b28e00cb 100644 --- a/src/comp.c +++ b/src/comp.c @@ -468,7 +468,7 @@ load_gccjit_if_necessary (bool mandatory) /* Increase this number to force a new Vcomp_abi_hash to be generated. */ -#define ABI_VERSION "9" +#define ABI_VERSION "10" /* Length of the hashes used for eln file naming. */ #define HASH_LENGTH 8 @@ -2666,6 +2666,12 @@ emit_static_object (const char *name, Lisp_Object obj) specbind (intern_c_string ("print-quoted"), Qt); specbind (intern_c_string ("print-gensym"), Qt); specbind (intern_c_string ("print-circle"), Qt); + /* Bind print-number-table and print-continuous-numbering so comp--#$ + prints as #$. */ + Lisp_Object print_number_table = CALLN (Fmake_hash_table, QCtest, Qeq); + Fputhash (Vcomp__hashdollar, build_string ("#$") , print_number_table); + specbind (intern_c_string ("print-number-table"), print_number_table); + specbind (intern_c_string ("print-continuous-numbering"), Qt); Lisp_Object str = Fprin1_to_string (obj, Qnil, Qnil); unbind_to (count, Qnil); @@ -5129,18 +5135,25 @@ typedef char *(*comp_lit_str_func) (void); static Lisp_Object load_static_obj (struct Lisp_Native_Comp_Unit *comp_u, const char *name) { + specpdl_ref count = SPECPDL_INDEX (); static_obj_t *blob = dynlib_sym (comp_u->handle, format_string ("%s_blob", name)); + /* Special value so we can recognize #$, which is used for entries in + the static vector that must be overwritten at load time. This is a + specific string that contains "#$", which is not EQ to any + legitimate object returned by Fread. */ + specbind (intern_c_string ("load-file-name"), + Vcomp__hashdollar); if (blob) /* New blob format. */ - return Fread (make_string (blob->data, blob->len)); + return unbind_to (count, Fread (make_string (blob->data, blob->len))); static_obj_t *(*f)(void) = dynlib_sym (comp_u->handle, name); if (!f) xsignal1 (Qnative_lisp_file_inconsistent, comp_u->file); blob = f (); - return Fread (make_string (blob->data, blob->len)); + return unbind_to (count, Fread (make_string (blob->data, blob->len))); } @@ -5157,7 +5170,7 @@ check_comp_unit_relocs (struct Lisp_Native_Comp_Unit *comp_u) for (ptrdiff_t i = 0; i < d_vec_len; i++) { Lisp_Object x = data_relocs[i]; - if (EQ (x, Q__lambda_fixup)) + if (EQ (x, Vcomp__hashdollar)) return false; else if (NATIVE_COMP_FUNCTIONP (x)) { @@ -5610,7 +5623,6 @@ natively-compiled one. */); DEFSYM (Qfixnum, "fixnum"); DEFSYM (Qscratch, "scratch"); DEFSYM (Qlate, "late"); - DEFSYM (Q__lambda_fixup, "--lambda-fixup"); DEFSYM (Qgccjit, "gccjit"); DEFSYM (Qcomp_subr_trampoline_install, "comp-subr-trampoline-install"); DEFSYM (Qnative_comp_warning_on_missing_source, @@ -5792,6 +5804,10 @@ This is intended to be used only for development and verification of the native compiler. */); comp_sanitizer_active = false; + DEFVAR_LISP ("comp--#$", Vcomp__hashdollar, + doc: /* Special value which will print as "#$". */); + Vcomp__hashdollar = build_string ("#$"); + Fprovide (intern_c_string ("native-compile"), Qnil); #endif /* #ifdef HAVE_NATIVE_COMP */ diff --git a/src/pdumper.c b/src/pdumper.c index b2ceea2f8bd..20f2c426c53 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -5513,7 +5513,7 @@ dump_do_dump_relocation (const uintptr_t dump_base, XSETSUBR (tem, subr); Lisp_Object *fixup = &(comp_u->data_relocs[XFIXNUM (lambda_data_idx)]); - eassert (EQ (*fixup, Q__lambda_fixup)); + eassert (EQ (*fixup, Vcomp__hashdollar)); *fixup = tem; Fputhash (tem, Qt, comp_u->lambda_gc_guard_h); } From 5a5706f943ae2677c6d73fed8de11affd3ef04aa Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Sat, 1 Feb 2025 17:08:27 +0000 Subject: [PATCH 039/279] ; src/pdumper.c (dump_hash_table): Bump CHECK_STRUCTS hash. --- src/pdumper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pdumper.c b/src/pdumper.c index 20f2c426c53..dee13fb9a81 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2737,7 +2737,7 @@ dump_hash_table_contents (struct dump_context *ctx, struct Lisp_Hash_Table *h) static dump_off dump_hash_table (struct dump_context *ctx, Lisp_Object object) { -#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_267C58D687 +#if CHECK_STRUCTS && !defined HASH_Lisp_Hash_Table_2A3C3E2B62 # error "Lisp_Hash_Table changed. See CHECK_STRUCTS comment in config.h." #endif const struct Lisp_Hash_Table *hash_in = XHASH_TABLE (object); From 3a86774ce55e9dc4dc6de01f6aca19fcaa41a5d3 Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Sat, 1 Feb 2025 18:14:47 +0100 Subject: [PATCH 040/279] Update to Transient v0.8.4-7-gabee7353 --- doc/misc/transient.texi | 138 ++++++++++++++++++++++-- lisp/transient.el | 227 ++++++++++++++++++++++++++++------------ 2 files changed, 292 insertions(+), 73 deletions(-) diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index fb8b6da145c..4740663e987 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -31,7 +31,7 @@ General Public License for more details. @finalout @titlepage @title Transient User and Developer Manual -@subtitle for version 0.8.3 +@subtitle for version 0.8.4 @author Jonas Bernoulli @page @vskip 0pt plus 1filll @@ -53,7 +53,7 @@ resource to get over that hurdle is Psionic K's interactive tutorial, available at @uref{https://github.com/positron-solutions/transient-showcase}. @noindent -This manual is for Transient version 0.8.3. +This manual is for Transient version 0.8.4. @insertcopying @end ifnottex @@ -93,6 +93,7 @@ Defining New Commands * Binding Suffix and Infix Commands:: * Defining Suffix and Infix Commands:: * Using Infix Arguments:: +* Using Prefix Scope:: * Current Suffix Command:: * Current Prefix Command:: * Transient State:: @@ -553,6 +554,48 @@ the level specified by @code{transient-default-level} are temporarily available anyway. @end table +@defun transient-set-default-level suffix level +This function sets the default level of the suffix COMMAND to LEVEL@. + +If a suffix command appears in multiple menus, it may make sense to +consistently change its level in all those menus at once. For +example, the @code{--gpg-sign} argument (which is implemented using the +command @code{magit:--gpg-sign}), is bound in all of Magit's menu which +create commits. Users who sometimes sign their commits would want +that argument to be available in all of these menus, while for users +who never sign it is just unnecessary noise in any menus. + +To always make @code{--gpg-sign} available, use: + +@lisp +(transient-set-default-level 'magit:--gpg-sign 1) +@end lisp + +To never make @code{--gpg-sign} available, use: + +@lisp +(transient-set-default-level 'magit:--gpg-sign 0) +@end lisp + +This sets the level in the suffix prototype object for this command. +Commands only have a suffix prototype if they were defined using one +of @code{transient-define-argument}, @code{transient-define-infix} and +@code{transient-define-suffix}. For all other commands this would signal +an error. (This is one of the reasons why package authors should +use one of these functions to define shared suffix commands, and +especially shared arguments.) + +If the user changes the level of a suffix in a particular menu, +using @kbd{C-x l} as shown above, then that obviously shadows the default. + +It is also possible to set the level of a suffix binding in a +particular menu, either when defining the menu using +@code{transient-define-prefix,} or later using @code{transient-insert-suffix}. If +such bindings specify a level, then that also overrides the default. +(Per-suffix default levels is a new feature, so you might encounter +this quite often.) +@end defun + @node Other Commands @section Other Commands @@ -1017,6 +1060,7 @@ signal an error. * Binding Suffix and Infix Commands:: * Defining Suffix and Infix Commands:: * Using Infix Arguments:: +* Using Prefix Scope:: * Current Suffix Command:: * Current Prefix Command:: * Transient State:: @@ -1323,6 +1367,13 @@ be replaced with an error. The boolean @code{:pad-keys} argument controls whether keys of all suffixes contained in a group are right padded, effectively aligning the descriptions. + +@item +If a keyword argument accepts a function as value, you an use a +@code{lambda} expression. As a special case, the @code{##} macro (which returns a +@code{lambda} expression and is implemented in the @code{llama} package) is also +supported. Inside group specifications, the use of @code{##} is not +supported anywhere but directly following a keyword symbol. @end itemize The @var{ELEMENT}s are either all subgroups, or all suffixes and strings. @@ -1446,6 +1497,12 @@ Finally, details can be specified using optional @var{KEYWORD}-@var{VALUE} pairs Each keyword has to be a keyword symbol, either @code{:class} or a keyword argument supported by the constructor of that class. @xref{Suffix Slots}. +If a keyword argument accepts a function as value, you an use a @code{lambda} +expression. As a special case, the @code{##} macro (which returns a @code{lambda} +expression and is implemented in the @code{llama} package) is also supported. +Inside suffix bindings, the use of @code{##} is not supported anywhere but +directly following a keyword symbol. + @node Defining Suffix and Infix Commands @section Defining Suffix and Infix Commands @@ -1568,6 +1625,55 @@ used if you need the objects (as opposed to just their values) and if the current command is not being invoked from @var{PREFIX}. @end defun +@node Using Prefix Scope +@section Using Prefix Scope + +Some transients have a sort of secondary value, called a scope. A +prefix's scope can be accessed using @code{transient-scope}; similar to how +its value can be accessed using @code{transient-args}. + +@defun transient-scope prefixes classes +This function returns the scope of the active or current transient +prefix command. + +If optional PREFIXES and CLASSES are both nil, return the scope of +the prefix currently being setup, making this variation useful, e.g., +in @code{:if*} predicates. If no prefix is being setup, but the current +command was invoked from some prefix, then return the scope of that. + +If PREFIXES is non-nil, it must be a prefix command or a list of such +commands. If CLASSES is non-nil, it must be a prefix class or a list +of such classes. When this function is called from the body or the +@code{interactive} form of a suffix command, PREFIXES and/or CLASSES should +be non-nil. If either is non-nil, try the following in order: + +@itemize +@item +If the current suffix command was invoked from a prefix, which +appears in PREFIXES, return the scope of that prefix. + +@item +If the current suffix command was invoked from a prefix, and its +class derives from one of the CLASSES, return the scope of that +prefix. + +@item +If a prefix is being setup and it appears in PREFIXES, return its +scope. + +@item +If a prefix is being setup and its class derives from one of the +CLASSES, return its scope. + +@item +Finally try to return the default scope of the first command in +PREFIXES@. This only works if that slot is set in the respective +class definition or using its `transient-init-scope' method. +@end itemize + +If no prefix matches, return nil. +@end defun + @node Current Suffix Command @section Current Suffix Command @@ -2458,8 +2564,9 @@ being initialized. This slot is still experimental. @code{transient-mode-line-format}. It should have the same type. @item -@code{column-width} is only respected inside @code{transient-columns} groups and -allows aligning columns across separate instances of that. +@code{column-widths} is only respected inside @code{transient-columns} groups and +allows aligning columns across separate instances of that. A list +of integers. @item @code{variable-pitch} controls whether alignment is done pixel-wise to @@ -2535,8 +2642,9 @@ Also see @ref{Suffix Classes}. @subheading Slots of @code{transient-child} This is the abstract superclass of @code{transient-suffix} and @code{transient-group}. -This is where the shared @code{if*} and @code{inapt-if*} slots (see @ref{Predicate Slots}) -and the @code{level} slot (see @ref{Enabling and Disabling Suffixes}) are defined. +This is where the shared @code{if*} and @code{inapt-if*} slots (see @ref{Predicate Slots}), +the @code{level} slot (see @ref{Enabling and Disabling Suffixes}), and the @code{advice} +and @code{advice*} slots (see @ref{Slots of @code{transient-suffix}}) are defined. @itemize @item @@ -2595,6 +2703,24 @@ for details. defining a command using @code{transient-define-suffix}. @end itemize +The following two slots are experimental. They can also be set for a +group, in which case they apply to all suffixes in that group, except +for suffixes that set the same slot to a non-nil value. + +@itemize +@item +@code{advice} A function used to advise the command. The advise is called +using @code{(apply advice command args)}, i.e., it behaves like an "around" +advice. + +@item +@code{advice*} A function used to advise the command. Unlike @code{advice}, this +advises not only the command body but also its @code{interactive} spec. If +both slots are non-nil, @code{advice} is used for the body and @code{advice*} is +used for the @code{interactive} form. When advising the @code{interactive} spec, +called using @code{(funcall advice #'advice-eval-interactive-spec spec)}. +@end itemize + @anchor{Slots of @code{transient-infix}} @subheading Slots of @code{transient-infix} diff --git a/lisp/transient.el b/lisp/transient.el index 24ab56e830b..610e5871ccc 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -5,7 +5,7 @@ ;; Author: Jonas Bernoulli ;; URL: https://github.com/magit/transient ;; Keywords: extensions -;; Version: 0.8.3 +;; Version: 0.8.4 ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -32,7 +32,7 @@ ;;; Code: -(defconst transient-version "v0.8.3-2-gf0478b29-builtin") +(defconst transient-version "v0.8.4-7-gabee7353-builtin") (require 'cl-lib) (require 'eieio) @@ -281,6 +281,20 @@ number is positive, or hide the menu if it is negative." :format "\n %t: %v" :value -20))) +(defcustom transient-show-docstring-format "%s" + "How to display suffix docstrings. + +The command `transient-toggle-docstrings' toggles between showing suffix +descriptions as usual, and instead or additionally displaying the suffix +docstrings. The format specified here controls how that is done. %c is +the description and %s is the docstring. Use \"%-14c %s\" or similar to +display both. + +This command is not bound by default, see its docstring for instructions." + :package-version '(transient . "0.8.4") + :group 'transient + :type 'string) + (defcustom transient-read-with-initial-input nil "Whether to use the last history element as initial minibuffer input." :package-version '(transient . "0.2.0") @@ -709,7 +723,7 @@ the prototype is stored in the clone's `prototype' slot.") :documentation "The parent group object.") (level :initarg :level - :initform (symbol-value 'transient--default-child-level) + :initform nil :documentation "Enable if level of prefix is equal or greater.") (if :initarg :if @@ -779,7 +793,15 @@ the prototype is stored in the clone's `prototype' slot.") (inapt-if-not-derived :initarg :inapt-if-not-derived :initform nil - :documentation "Inapt if major-mode does not derive from value.")) + :documentation "Inapt if major-mode does not derive from value.") + (advice + :initarg :advice + :initform nil + :documentation "Advise applied to the command body.") + (advice* + :initarg :advice* + :initform nil + :documentation "Advise applied to the command body and interactive spec.")) "Abstract superclass for group and suffix classes. It is undefined which predicates are used if more than one `if*' @@ -1188,14 +1210,15 @@ commands are aliases for." (cond ((eq key :class) (setq class val)) ((or (symbolp val) - (and (listp val) (not (eq (car val) 'lambda)))) + (and (listp val) + (not (memq (car val) (list 'lambda (intern "")))))) (setq args (plist-put args key (macroexp-quote val)))) ((setq args (plist-put args key val)))))) (unless (or spec class (not (plist-get args :setup-children))) (message "WARNING: %s: When %s is used, %s must also be specified" 'transient-define-prefix :setup-children :class)) (list 'vector - (or level transient--default-child-level) + level (list 'quote (cond (class) ((cl-typep (car spec) @@ -1286,7 +1309,8 @@ commands are aliases for." ((guard (eq (car-safe val) '\,)) (use key (cadr val))) ((guard (or (symbolp val) - (and (listp val) (not (eq (car val) 'lambda))))) + (and (listp val) + (not (memq (car val) (list 'lambda (intern ""))))))) (use key (macroexp-quote val))) (_ (use key val))))) (when spec @@ -1295,7 +1319,7 @@ commands are aliases for." (shortarg (plist-get args :shortarg))) (use :key shortarg))) (list 'list - (or level transient--default-child-level) + level (macroexp-quote (or class 'transient-suffix)) (cons 'list args)))) @@ -1530,6 +1554,21 @@ See info node `(transient)Modifying Existing Transients'." (defun transient--nthcdr (n list) (nthcdr (if (< n 0) (- (length list) (abs n)) n) list)) +(defun transient-set-default-level (command level) + "Set the default level of suffix COMMAND to LEVEL. + +The default level is shadowed if the binding of the suffix in a +prefix menu specifies a level, and also if the user changes the +level of such a binding. + +The default level can only be set for commands that were defined +using `transient-define-suffix', `transient-define-infix' or +`transient-define-argument'." + (if-let ((proto (transient--suffix-prototype command))) + (oset proto level level) + (user-error "Cannot set level for `%s'; no prototype object exists" + command))) + ;;; Variables (defvar transient-current-prefix nil @@ -2216,7 +2255,8 @@ value. Otherwise return CHILDREN as is.") (string (list spec)))) (defun transient--init-group (levels spec parent) - (pcase-let ((`(,level ,class ,args ,children) (append spec nil))) + (pcase-let* ((`(,level ,class ,args ,children) (append spec nil)) + (level (or level transient--default-child-level))) (and-let* (((transient--use-level-p level)) (obj (apply class :parent parent :level level args)) ((transient--use-suffix-p obj)) @@ -2233,9 +2273,12 @@ value. Otherwise return CHILDREN as is.") (pcase-let* ((`(,level ,class ,args) spec) (cmd (plist-get args :command)) (key (transient--kbd (plist-get args :key))) + (proto (and cmd (transient--suffix-prototype cmd))) (level (or (alist-get (cons cmd key) levels nil nil #'equal) (alist-get cmd levels) - level))) + level + (and proto (oref proto level)) + transient--default-child-level))) (let ((fn (and (symbolp cmd) (symbol-function cmd)))) (when (autoloadp fn) @@ -2246,7 +2289,7 @@ value. Otherwise return CHILDREN as is.") (apply class :parent parent :level level args) (unless (and cmd (symbolp cmd)) (error "BUG: Non-symbolic suffix command: %s" cmd)) - (if-let* ((proto (and cmd (transient--suffix-prototype cmd)))) + (if proto (apply #'clone proto :level level args) (apply class :command cmd :parent parent :level level args))))) @@ -2436,6 +2479,8 @@ value. Otherwise return CHILDREN as is.") (setq transient--redisplay-map nil) (setq transient--redisplay-key nil) (setq transient--helpp nil) + (unless (eq transient--docsp 'permanent) + (setq transient--docsp nil)) (setq transient--editp nil) (setq transient--prefix nil) (setq transient--layout nil) @@ -2563,7 +2608,13 @@ value. Otherwise return CHILDREN as is.") (let ((abort t)) (unwind-protect (prog1 (let ((debugger #'transient--exit-and-debug)) - (advice-eval-interactive-spec spec)) + (if-let* ((obj (transient-suffix-object suffix)) + (grp (oref obj parent)) + (adv (or (oref obj advice*) + (oref grp advice*)))) + (funcall + adv #'advice-eval-interactive-spec spec) + (advice-eval-interactive-spec spec))) (setq abort nil)) (when abort (when-let* ((unwind (oref prefix unwind-suffix))) @@ -2573,7 +2624,14 @@ value. Otherwise return CHILDREN as is.") (oset prefix unwind-suffix nil)))))) (unwind-protect (let ((debugger #'transient--exit-and-debug)) - (apply fn args)) + (if-let* ((obj (transient-suffix-object suffix)) + (grp (oref obj parent)) + (adv (or (oref obj advice) + (oref grp advice) + (oref obj advice*) + (oref grp advice*)))) + (apply adv fn args) + (apply fn args))) (when-let* ((unwind (oref prefix unwind-suffix))) (transient--debug 'unwind-command) (funcall unwind suffix)) @@ -3212,12 +3270,21 @@ For example: (interactive) (setq transient-show-common-commands (not transient-show-common-commands))) -(transient-define-suffix transient-toggle-docstrings () +(transient-define-suffix transient-toggle-docstrings (&optional permanent) "Toggle whether to show docstrings instead of suffix descriptions. -To make this available in all menus, bind it in `transient-map'." + +By default this is only enabled temporarily for the current transient +menu invocation. With a prefix argument, enable this until explicitly +disabled again. + +Infix arguments are not affected by this, because otherwise many menus +would likely become unreadable. To make this command available in all +menus, bind it in `transient-map'. `transient-show-docstring-format' +controls how the docstrings are displayed and whether descriptions are +also displayed." :transient t - (interactive) - (setq transient--docsp (not transient--docsp))) + (interactive (list current-prefix-arg)) + (setq transient--docsp (if permanent 'permanent (not transient--docsp)))) (defun transient-toggle-debug () "Toggle debugging statements for transient commands." @@ -3789,37 +3856,48 @@ a default implementation, which is a noop.") ;;;; Get -(defun transient-scope (&optional prefixes) +(defun transient-scope (&optional prefixes classes) "Return the scope of the active or current transient prefix command. -If optional PREFIXES is nil, return the scope of the prefix currently -being setup, making this variant useful, e.g., in `:if*' predicates. -If no prefix is being setup, but the current command was invoked from -some prefix, then return the scope of that. - -When this function is called from the body or `interactive' form of a -suffix command, PREFIXES should be non-nil. +If optional PREFIXES and CLASSES are both nil, return the scope of +the prefix currently being setup, making this variation useful, e.g., +in `:if*' predicates. If no prefix is being setup, but the current +command was invoked from some prefix, then return the scope of that. If PREFIXES is non-nil, it must be a prefix command or a list of such -commands. In this case try the following in order: +commands. If CLASSES is non-nil, it must be a prefix class or a list +of such classes. When this function is called from the body or the +`interactive' form of a suffix command, PREFIXES and/or CLASSES should +be non-nil. If either is non-nil, try the following in order: - If the current suffix command was invoked from a prefix, which - appears in PREFIXES, then return the scope of that prefix. + appears in PREFIXES, return the scope of that prefix. -- If a prefix is being setup and it appears in PREFIXES, then return - its scope. +- If the current suffix command was invoked from a prefix, and its + class derives from one of the CLASSES, return the scope of that + prefix. -- Finally try to return the default scope of the first prefix in +- If a prefix is being setup and it appears in PREFIXES, return its + scope. + +- If a prefix is being setup and its class derives from one of the + CLASSES, return its scope. + +- Finally try to return the default scope of the first command in PREFIXES. This only works if that slot is set in the respective class definition or using its `transient-init-scope' method. If no prefix matches, return nil." - (if prefixes - (let ((prefixes (ensure-list prefixes))) - (if-let* ((obj (or (and-let* ((obj transient-current-prefix)) - (and (memq (oref obj command) prefixes) obj)) - (and-let* ((obj transient--prefix)) - (and (memq (oref obj command) prefixes) obj))))) + (if (or prefixes classes) + (let ((prefixes (ensure-list prefixes)) + (type (if (symbolp classes) classes (cons 'or classes)))) + (if-let ((obj (cl-flet ((match (obj) + (and obj + (or (memq (oref obj command) prefixes) + (cl-typep obj type)) + obj))) + (or (match transient-current-prefix) + (match transient--prefix))))) (oref obj scope) (and (get (car prefixes) 'transient--prefix) (oref (transient--init-prefix (car prefixes)) scope)))) @@ -4247,16 +4325,21 @@ face `transient-heading' to the complete string." If the result is nil, then use \"(BUG: no description)\" as the description. If the OBJ's `key' is currently unreachable, then apply the face `transient-unreachable' to the complete string." - (let ((desc (if-let* ((transient--docsp) - (cmd (oref obj command)) - (doc (ignore-errors (documentation cmd))) - ((not (equal doc (documentation - 'transient--default-infix-command))))) - (substring doc 0 (string-match "\\.?\n" doc)) - (or (cl-call-next-method obj) - (and (slot-boundp transient--prefix 'suffix-description) - (funcall (oref transient--prefix suffix-description) - obj)))))) + (let ((desc (or (cl-call-next-method obj) + (and (slot-boundp transient--prefix 'suffix-description) + (funcall (oref transient--prefix suffix-description) + obj))))) + (when-let* ((transient--docsp) + (cmd (oref obj command)) + ((not (memq 'transient--default-infix-command + (function-alias-p cmd)))) + (docstr (ignore-errors (documentation cmd))) + (docstr (string-trim + (substring docstr 0 (string-match "\\.?\n" docstr)))) + ((not (equal docstr "")))) + (setq desc (format-spec transient-show-docstring-format + `((?c . ,desc) + (?s . ,docstr))))) (if desc (when-let* ((face (transient--get-face obj 'face))) (setq desc (transient--add-face desc face t))) @@ -4568,34 +4651,44 @@ Select the help window, and make the help buffer current and return it." (insert "\n")) (when transient--helpp (insert - (format (propertize "\ + (format + (propertize "\ Type a %s to show help for that suffix command, or %s to show manual. Type %s to exit help.\n" - 'face 'transient-heading) - (propertize "" 'face 'transient-key) - (propertize "?" 'face 'transient-key) - (propertize "C-g" 'face 'transient-key)))) + 'face 'transient-heading) + (propertize "" 'face 'transient-key) + (propertize "?" 'face 'transient-key) + (propertize "C-g" 'face 'transient-key)))) (when transient--editp (unless transient--helpp (insert - (format (propertize "\ -Type a %s to set level for that suffix command. -Type %s to set what levels are available for this prefix command.\n" - 'face 'transient-heading) - (propertize "" 'face 'transient-key) - (propertize "C-x l" 'face 'transient-key)))) + (format + (propertize "\ +Type %s and then %s to put the respective suffix command on level %s. +Type %s and then %s to display suffixes up to level %s in this menu. +Type %s and then %s to describe the respective suffix command.\n" + 'face 'transient-heading) + (propertize "" 'face 'transient-key) + (propertize "" 'face 'transient-key) + (propertize " N " 'face 'transient-enabled-suffix) + (propertize "C-x l" 'face 'transient-key) + (propertize "" 'face 'transient-key) + (propertize " N " 'face 'transient-enabled-suffix) + (propertize "C-h" 'face 'transient-key) + (propertize "" 'face 'transient-key)))) (with-slots (level) transient--prefix (insert - (format (propertize " -Suffixes on levels %s are available. -Suffixes on levels %s and %s are unavailable.\n" - 'face 'transient-heading) - (propertize (format "1-%s" level) - 'face 'transient-enabled-suffix) - (propertize " 0 " - 'face 'transient-disabled-suffix) - (propertize (format ">=%s" (1+ level)) - 'face 'transient-disabled-suffix)))))) + (format + (propertize " +The current level of this menu is %s, so + commands on levels %s are displayed, and + commands on levels %s and %s are not displayed.\n" + 'face 'transient-heading) + (propertize (format " %s " level) 'face 'transient-enabled-suffix) + (propertize (format " 1..%s " level) 'face 'transient-enabled-suffix) + (propertize (format " >= %s " (1+ level)) + 'face 'transient-disabled-suffix) + (propertize " 0 " 'face 'transient-disabled-suffix)))))) (cl-defgeneric transient-show-summary (obj &optional return) "Show brief summary about the command at point in the echo area. From c5731a74c73678de34ccbacf6977a0e55a239bc8 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 1 Feb 2025 18:52:13 +0100 Subject: [PATCH 041/279] Minor Tramp changes * doc/misc/tramp.texi (External methods): Precise remark on rsync speed. * lisp/net/tramp-cache.el (tramp-connection-properties): Add link to the Tramp manual in the docstring. --- doc/misc/tramp.texi | 3 ++- lisp/net/tramp-cache.el | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 9aad087c510..86ffba29744 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -1154,7 +1154,8 @@ command to transfer is similar to the @option{scp} method. @command{rsync} performs much better than @command{scp} when transferring files that exist on both hosts. However, this advantage -is lost if the file exists only on one side of the connection. +is lost if the file exists only on one side of the connection, during +the first file transfer. This method supports the @samp{-p} argument. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index 37c82e4922b..a5245deaf2b 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -98,8 +98,11 @@ Every entry has the form (REGEXP PROPERTY VALUE). The regexp matches remote file names. It can be nil. PROPERTY is a string, and VALUE the corresponding value. They are used, if there is no -matching entry for PROPERTY in `tramp-cache-data'. For more -details see the info pages." +matching entry for PROPERTY in `tramp-cache-data'. + +PROPERTY can also be a string representing a parameter in +`tramp-methods'. For more details see the Info node `(tramp) Predefined +connection information'." :group 'tramp :version "24.4" :type '(repeat (list (choice :tag "File Name regexp" regexp (const nil)) From 1292b64216f636bacea7fedf578b373f03affdd8 Mon Sep 17 00:00:00 2001 From: shipmints Date: Sat, 25 Jan 2025 14:04:51 -0500 Subject: [PATCH 042/279] Add auto save timer to save-place (bug#75837) * lisp/saveplace.el (save-place-autosave-interval): New user option 'save-place-autosave-interval' which defaults to nil, and has a custom :set to manage the timer. Add 'save-place--manage-timer' to enable or cancel the timer if the mode is enabled and 'save-place-autosave-interval' is non-nil. Amend 'save-place-mode' to invoke save-place--manage-timer. Add 'save-place--cancel-timer'. Add 'save-place--autosave'. --- etc/NEWS | 19 +++++++++++++++++++ lisp/saveplace.el | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 93e2d0ebc65..259b6e03549 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -465,6 +465,25 @@ This user option controls the width of the type column on the bookmark menu 'bookmark-bmenu-list'. The default value is 8 which is backwards compatible. +** Saveplace + +--- +*** You can now regularly auto-save places. +Customize 'save-place-autosave-interval' to the number of seconds +between auto saving places. For example, to save places every 5 +minutes: + + M-x customize-option RET save-place-autosave-interval RET and set to + 300 seconds. + +Or in elisp: + + (setopt save-place-autosave-interval (* 60 5)) + +If 'save-place-autosave-interval' is nil, auto saving is disabled; this +is the default. As before, saved places are scheduled to be saved at +Emacs exit. + ** Gnus --- diff --git a/lisp/saveplace.el b/lisp/saveplace.el index c2e68f39730..37b657073cc 100644 --- a/lisp/saveplace.el +++ b/lisp/saveplace.el @@ -208,6 +208,45 @@ disabled, i.e., no files are excluded." (declare-function dired-current-directory "dired" (&optional localp)) +(defvar save-place--autosave-timer nil) + +(defun save-place--cancel-timer () + "Cancel `save-place-autosave' timer, if set." + (when (timerp save-place--autosave-timer) + (cancel-timer save-place--autosave-timer)) + (setq save-place--autosave-timer nil)) + +(defvar save-place-autosave-interval) + +(defun save-place--manage-timer () + "Set or cancel an invocation of `save-place--autosave' on a timer. +If `save-place-mode' is enabled, set the timer, otherwise cancel the timer." + (if (and save-place-mode + save-place-autosave-interval + (null save-place--autosave-timer)) + (setq save-place--autosave-timer + (run-with-timer + save-place-autosave-interval + save-place-autosave-interval #'save-place--autosave)) + (save-place--cancel-timer))) + +(defcustom save-place-autosave-interval nil + "The interval between auto saves of buffer places. +If set to nil, disables timer-based auto saving. +Use `setopt' or Customize commands to set this option." + :type '(choice (const :tag "Disabled" nil) + (integer :tag "Seconds")) + :version "31.1" + :set (lambda (sym val) + (set-default sym val) + (save-place--cancel-timer) + (save-place--manage-timer))) + +(defun save-place--autosave () + "Called by `save-place--autosave-timer'." + (save-places-to-alist) + (save-place-alist-to-file)) + (defun save-place--setup-hooks (add) (cond (add @@ -235,7 +274,8 @@ This means when you visit a file, point goes to the last place where it was when you previously visited the same file." :global t :group 'save-place - (save-place--setup-hooks save-place-mode)) + (save-place--setup-hooks save-place-mode) + (save-place--manage-timer)) (make-variable-buffer-local 'save-place-mode) @@ -258,7 +298,8 @@ file: dired-subdir-alist (dired-current-directory)))) (message "Buffer `%s' not visiting a file or directory" (buffer-name)) - (save-place--setup-hooks save-place-mode))) + (save-place--setup-hooks save-place-mode) + (save-place--manage-timer))) (declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep)) From c7889d0545d5e684fc5cec5d50e249ab9c24da44 Mon Sep 17 00:00:00 2001 From: shipmints Date: Sat, 25 Jan 2025 13:12:56 -0500 Subject: [PATCH 043/279] Add missing custom :set to 'savehist-autosave-interval' * lisp/savehist.el (savehist-autosave-interval): Correctly reset 'savehist-timer' when 'savehist-autosave-interval' changes via setopt or a Customize command. (Bug#75834) --- lisp/savehist.el | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/lisp/savehist.el b/lisp/savehist.el index 153e2db8706..7d755bc5047 100644 --- a/lisp/savehist.el +++ b/lisp/savehist.el @@ -96,11 +96,37 @@ the user's privacy." :type '(choice (natnum :tag "Specify") (const :tag "Use default" :value nil))) +(defvar savehist-timer nil) + +(defun savehist--cancel-timer () + "Cancel `savehist-autosave' timer, if set." + (when (timerp savehist-timer) + (cancel-timer savehist-timer)) + (setq savehist-timer nil)) + +(defun savehist--manage-timer () + "Set or cancel an invocation of `savehist-autosave' on a timer. +If `savehist-mode' is enabled, set the timer, otherwise cancel the timer. +This should not cause noticeable delays for users -- `savehist-autosave' +executes in under 5 ms on my system." + (if (and savehist-mode + savehist-autosave-interval + (null savehist-timer)) + (setq savehist-timer + (run-with-timer savehist-autosave-interval + savehist-autosave-interval #'savehist-autosave)) + (savehist--cancel-timer))) + (defcustom savehist-autosave-interval (* 5 60) "The interval between autosaves of minibuffer history. -If set to nil, disables timer-based autosaving." +If set to nil, disables timer-based autosaving. +Use `setopt' or Customize commands to set this option." :type '(choice (const :tag "Disabled" nil) - (integer :tag "Seconds"))) + (integer :tag "Seconds")) + :set (lambda (sym val) + (set-default sym val) + (savehist--cancel-timer) + (savehist--manage-timer))) (defcustom savehist-mode-hook nil "Hook called when Savehist mode is turned on." @@ -122,8 +148,6 @@ unwise, unless you know what you are doing.") ;; Internal variables. -(defvar savehist-timer nil) - (defvar savehist-last-checksum nil) (defvar savehist-minibuffer-history-variables nil @@ -197,23 +221,14 @@ Installs `savehist-autosave' in `kill-emacs-hook' and on a timer. To undo this, call `savehist-uninstall'." (add-hook 'minibuffer-setup-hook #'savehist-minibuffer-hook) (add-hook 'kill-emacs-hook #'savehist-autosave) - ;; Install an invocation of savehist-autosave on a timer. This - ;; should not cause noticeable delays for users -- savehist-autosave - ;; executes in under 5 ms on my system. - (when (and savehist-autosave-interval - (null savehist-timer)) - (setq savehist-timer - (run-with-timer savehist-autosave-interval - savehist-autosave-interval #'savehist-autosave)))) + (savehist--manage-timer)) (defun savehist-uninstall () "Undo installing savehist. Normally invoked by calling `savehist-mode' to unset the minor mode." (remove-hook 'minibuffer-setup-hook #'savehist-minibuffer-hook) (remove-hook 'kill-emacs-hook #'savehist-autosave) - (when savehist-timer - (cancel-timer savehist-timer) - (setq savehist-timer nil))) + (savehist--manage-timer)) (defvar savehist--has-given-file-warning nil) (defun savehist-save (&optional auto-save) From 3ae7c9069fa9320ce2cff5b421dc8d9d4c4b8430 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 1 Feb 2025 22:08:38 +0200 Subject: [PATCH 044/279] ; Fix last change. --- lisp/savehist.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lisp/savehist.el b/lisp/savehist.el index 7d755bc5047..7cfb358dd6d 100644 --- a/lisp/savehist.el +++ b/lisp/savehist.el @@ -104,6 +104,8 @@ the user's privacy." (cancel-timer savehist-timer)) (setq savehist-timer nil)) +(defvar savehist-autosave-interval) + (defun savehist--manage-timer () "Set or cancel an invocation of `savehist-autosave' on a timer. If `savehist-mode' is enabled, set the timer, otherwise cancel the timer. From c91c591f0f0cc774647c32bdcf05bb3a9551e340 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 1 Feb 2025 14:09:06 -0800 Subject: [PATCH 045/279] =?UTF-8?q?Omit=202=20=E2=80=98volatile=E2=80=99s?= =?UTF-8?q?=20in=20internal=5Flisp=5Fcondition=5Fcase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * src/eval.c (internal_lisp_condition_case): Omit an unnecessary ‘volatile’ and an unnecessary pointer-to-volatile local var. Perhaps these were needed in previous versions of Emacs, or to pacify older versions of GCC when using --enable-gcc-warnings, but they are not needed to pacify current GCC. --- src/eval.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/eval.c b/src/eval.c index 666d49f03fe..70f533842b9 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1478,7 +1478,7 @@ Lisp_Object internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, Lisp_Object handlers) { - struct handler *volatile oldhandlerlist = handlerlist; + struct handler *oldhandlerlist = handlerlist; /* The number of non-success handlers, plus 1 for a sentinel. */ ptrdiff_t clausenb = 1; @@ -1543,12 +1543,11 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, if (!CONSP (condition)) condition = list1 (condition); struct handler *c = push_handler (condition, CONDITION_CASE); - Lisp_Object volatile *clauses_volatile = clauses; if (sys_setjmp (c->jmp)) { var = var_volatile; val = handlerlist->val; - Lisp_Object volatile *chosen_clause = clauses_volatile; + Lisp_Object volatile *chosen_clause = clauses; struct handler *oldh = oldhandlerlist; for (struct handler *h = handlerlist->next; h != oldh; h = h->next) chosen_clause++; From 42f1318e6579f94b90ef101f3f03ca65fb229262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= Date: Sun, 2 Feb 2025 05:39:47 +0100 Subject: [PATCH 046/279] Fix hiding tty cursor for overlapping children * src/dispnew.c (is_cursor_obscured): If selected frame is in the z-order of the root frame, use that, otherwise use the root frame. --- src/dispnew.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dispnew.c b/src/dispnew.c index 35c8d347616..c062ea42f3d 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -3909,10 +3909,12 @@ frame_selected_window_frame (struct frame *f) static bool is_cursor_obscured (struct frame *root) { - /* Determine in which frame on ROOT the cursor could be. */ - struct frame *sf = frame_selected_window_frame (root); - if (sf == NULL) - return false; + /* Which frame contains the cursor? If the selected frame is in + root's z-order, it's the selected frame. Otherwise fall back to + the root itself. */ + struct frame *sf = (frame_ancestor_p (root, SELECTED_FRAME ()) + ? SELECTED_FRAME () + : root); /* Give up if we can't tell where the cursor currently is. */ int x, y; From 354b2907fce6a4ce9f5e8ea0faf69974e21e749b Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 2 Feb 2025 08:23:02 +0200 Subject: [PATCH 047/279] Fix mouse pointer inside mouse-face on text with 'pointer' property * src/dispnew.c (gui_update_window_end): Don't consider mouse face overwritten. * src/xdisp.c (show_mouse_face): Accept an additional argument; redefine the mouse cursor only if that argument is 'true'. All callers changed. (Bug#75931) --- src/dispnew.c | 3 --- src/xdisp.c | 35 ++++++++++++++++++----------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/dispnew.c b/src/dispnew.c index c062ea42f3d..5f5575d484b 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -4597,9 +4597,6 @@ gui_update_window_end (struct window *w, bool cursor_on_p, w->output_cursor.hpos, w->output_cursor.vpos, w->output_cursor.x, w->output_cursor.y); - if (cursor_in_mouse_face_p (w) && cursor_on_p) - mouse_face_overwritten_p = 1; - if (draw_window_fringes (w, true)) { if (WINDOW_RIGHT_DIVIDER_WIDTH (w)) diff --git a/src/xdisp.c b/src/xdisp.c index 0b8dbf514c1..36e82f873ab 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1229,7 +1229,7 @@ static void get_cursor_offset_for_mouse_face (struct window *w, static void produce_special_glyphs (struct it *, enum display_element_type); static void pad_mode_line (struct it *, bool); -static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face); +static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face, bool); static bool coords_in_mouse_face_p (struct window *, int, int); static void reset_box_start_end_flags (struct it *); @@ -15052,14 +15052,14 @@ handle_tab_bar_click (struct frame *f, int x, int y, bool down_p, { /* Show the clicked button in pressed state. */ if (!NILP (Vmouse_highlight)) - show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); + show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN, true); f->last_tab_bar_item = prop_idx; /* record the pressed tab */ } else { /* Show item in released state. */ if (!NILP (Vmouse_highlight)) - show_mouse_face (hlinfo, DRAW_IMAGE_RAISED); + show_mouse_face (hlinfo, DRAW_IMAGE_RAISED, true); f->last_tab_bar_item = -1; } @@ -15157,7 +15157,7 @@ note_tab_bar_highlight (struct frame *f, int x, int y) hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID; /* Display it as active. */ - show_mouse_face (hlinfo, draw); + show_mouse_face (hlinfo, draw, true); } set_help_echo: @@ -16074,7 +16074,7 @@ handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p, { /* Show item in pressed state. */ if (!NILP (Vmouse_highlight)) - show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN); + show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN, true); f->last_tool_bar_item = prop_idx; } else @@ -16085,7 +16085,7 @@ handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p, /* Show item in released state. */ if (!NILP (Vmouse_highlight)) - show_mouse_face (hlinfo, DRAW_IMAGE_RAISED); + show_mouse_face (hlinfo, DRAW_IMAGE_RAISED, true); key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY); @@ -16181,7 +16181,7 @@ note_tool_bar_highlight (struct frame *f, int x, int y) hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID; /* Display it as active. */ - show_mouse_face (hlinfo, draw); + show_mouse_face (hlinfo, draw, true); } set_help_echo: @@ -34196,12 +34196,13 @@ erase_phys_cursor (struct window *w) /* Since erasing the phys cursor will probably lead to corruption of the mouse face display if the glyph's pixel_width is not kept up to date with the :box property of the mouse face, just redraw the - mouse face. */ + mouse face, but leave the mouse cursor as it was. */ if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p) { w->phys_cursor_on_p = false; w->phys_cursor_type = NO_CURSOR; - show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE); + show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE, + false); return; } #endif @@ -34462,7 +34463,8 @@ draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row, /* Display the active region described by mouse_face_* according to DRAW. */ static void -show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) +show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw, + bool define_mouse_cursor) { /* Don't bother doing anything if the mouse-face window is not set up. */ @@ -34604,7 +34606,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) #ifdef HAVE_WINDOW_SYSTEM /* Change the mouse cursor. */ - if (FRAME_WINDOW_P (f) && NILP (track_mouse)) + if (FRAME_WINDOW_P (f) && NILP (track_mouse) && define_mouse_cursor) { if (draw == DRAW_NORMAL_TEXT #ifndef HAVE_EXT_TOOL_BAR @@ -34612,8 +34614,7 @@ show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw) #endif && !EQ (hlinfo->mouse_face_window, f->tab_bar_window)) FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor); - else - if (draw == DRAW_MOUSE_FACE) + else if (draw == DRAW_MOUSE_FACE) FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor); else FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor); @@ -34632,7 +34633,7 @@ clear_mouse_face (Mouse_HLInfo *hlinfo) bool cleared = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window); if (cleared) - show_mouse_face (hlinfo, DRAW_NORMAL_TEXT); + show_mouse_face (hlinfo, DRAW_NORMAL_TEXT, true); hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; hlinfo->mouse_face_window = Qnil; @@ -35199,7 +35200,7 @@ mouse_face_from_buffer_pos (Lisp_Object window, = face_at_buffer_position (w, mouse_charpos, &ignore, mouse_charpos + 1, !hlinfo->mouse_face_hidden, -1, 0); - show_mouse_face (hlinfo, DRAW_MOUSE_FACE); + show_mouse_face (hlinfo, DRAW_MOUSE_FACE, true); } /* The following function is not used anymore (replaced with @@ -35909,7 +35910,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, face_at_string_position (w, string, charpos, 0, &ignore, glyph->face_id, true, 0); - show_mouse_face (hlinfo, DRAW_MOUSE_FACE); + show_mouse_face (hlinfo, DRAW_MOUSE_FACE, true); mouse_face_shown = true; if (NILP (pointer)) @@ -36448,7 +36449,7 @@ note_mouse_highlight (struct frame *f, int x, int y) hlinfo->mouse_face_face_id = face_at_string_position (w, object, pos, 0, &ignore, glyph->face_id, true, 0); - show_mouse_face (hlinfo, DRAW_MOUSE_FACE); + show_mouse_face (hlinfo, DRAW_MOUSE_FACE, true); cursor = No_Cursor; } else From 7ac05c33b182ce3f3bd26b730a9c87ad4ec8cdd5 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 1 Feb 2025 22:20:04 -0800 Subject: [PATCH 048/279] Improve malloc Lisp alignment commentary Prompted by a private email from Pip Cet. --- src/alloc.c | 32 +++++++++++++++++++------------- src/lisp.h | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/alloc.c b/src/alloc.c index c39459e1f2e..7fa05e54202 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -608,23 +608,28 @@ buffer_memory_full (ptrdiff_t nbytes) #define COMMON_MULTIPLE(a, b) \ ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) -/* Alignment needed for memory blocks that are allocated via malloc - and that contain Lisp objects. */ +/* Alignment needed for memory blocks managed by the garbage collector. */ enum { LISP_ALIGNMENT = alignof (union { union emacs_align_type x; GCALIGNED_UNION_MEMBER }) }; static_assert (LISP_ALIGNMENT % GCALIGNMENT == 0); -/* Verify Emacs's assumption that malloc (N) returns storage suitably - aligned for Lisp objects whenever N is a multiple of LISP_ALIGNMENT. - This assumption holds for current Emacs porting targets; - if the assumption fails on a new platform, this check should - cause compilation to fail and some porting work will need to be done. +/* Emacs assumes that malloc (N) returns storage suitably aligned for + any Lisp object whenever N is a multiple of LISP_ALIGNMENT. + This Emacs assumption holds for current Emacs porting targets. - In practice the assumption holds when alignof (max_align_t) is also a - multiple of LISP_ALIGNMENT. This works even for buggy platforms - like MinGW circa 2020, where alignof (max_align_t) is 16 even though - the malloc alignment is only 8, and where Emacs still works because - it never does anything that requires an alignment of 16. */ + On all current Emacs porting targets, it also happens that + alignof (max_align_t) is a multiple of LISP_ALIGNMENT. + Check this with a static_assert. If the static_assert fails on an + unusual platform, Emacs may well not work, so inspect this module's + source code carefully with the unusual platform's quirks in mind. + + In practice the static_assert works even for buggy platforms where + malloc can yield an unaligned address if given a large but unaligned + size; Emacs avoids the bug because it aligns the size before calling + malloc. The static_assert also works for MinGW circa 2020, where + alignof (max_align_t) is 16 even though the malloc alignment is only 8; + Emacs avoids the bug because on this platform it never does anything + that requires an alignment of 16. */ enum { MALLOC_IS_LISP_ALIGNED = alignof (max_align_t) % LISP_ALIGNMENT == 0 }; static_assert (MALLOC_IS_LISP_ALIGNED); @@ -900,7 +905,8 @@ void *lisp_malloc_loser EXTERNALLY_VISIBLE; #endif /* Allocate memory for Lisp data. - NBYTES is the number of bytes to allocate; it must be Lisp-aligned. + NBYTES is the number of bytes to allocate; + it must be a multiple of LISP_ALIGNMENT. If CLEARIT, arrange for the allocated memory to be cleared by using calloc, which can be faster than malloc+memset. TYPE describes the intended use of the allocated memory block diff --git a/src/lisp.h b/src/lisp.h index 5595038f7c7..6aea51f8322 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -257,7 +257,7 @@ DEFINE_GDB_SYMBOL_END (VALMASK) # define alignas(a) #endif -/* Minimum alignment requirement for Lisp objects, imposed by the +/* The minimum alignment requirement for Lisp objects that is imposed by the internal representation of tagged pointers. It is 2**GCTYPEBITS if USE_LSB_TAG, 1 otherwise. It must be a literal integer constant, for older versions of GCC (through at least 4.9). */ From 6b40dbda6ad6d677c69263785ff4db7010840b6e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 1 Feb 2025 22:20:04 -0800 Subject: [PATCH 049/279] Improve format-seconds on negative args * lisp/calendar/time-date.el (format-seconds): Work better with negative seconds (Bug#75849). * test/lisp/calendar/time-date-tests.el (test-format-seconds): Test it. --- lisp/calendar/time-date.el | 13 ++++---- test/lisp/calendar/time-date-tests.el | 43 ++++++++++++++++----------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el index 09b4cfb0edf..1d792952f98 100644 --- a/lisp/calendar/time-date.el +++ b/lisp/calendar/time-date.el @@ -305,7 +305,7 @@ right of \"%x\", trailing zero units are not output." ("x"))) (case-fold-search t) spec match usedunits zeroflag larger prev name unit num - leading-zeropos trailing-zeropos fraction + leading-zeropos trailing-zeropos fraction minus chop-leading chop-trailing) (while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start) (setq start (match-end 0) @@ -327,8 +327,11 @@ right of \"%x\", trailing zero units are not output." (error "Units are not in decreasing order of size")) (unless (numberp seconds) (setq seconds (float-time seconds))) - (setq fraction (mod seconds 1) - seconds (round seconds)) + (setq minus (when (< seconds 0) "-") ; Treat -0.0 like 0.0. + seconds (abs seconds) + seconds (let ((s (floor seconds))) + (setq fraction (- seconds s)) + s)) (dolist (u units) (setq spec (car u) name (cadr u) @@ -392,8 +395,8 @@ right of \"%x\", trailing zero units are not output." ;; string in full. (when (equal string "") (setq string pre))) - (setq string (replace-regexp-in-string "%[zx]" "" string))) - (string-trim (string-replace "%%" "%" string))) + (setq string (replace-regexp-in-string "%[zx]" "" string)) + (concat minus (string-trim (string-replace "%%" "%" string))))) (defvar seconds-to-string (list (list 1 "ms" 0.001) diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el index 3a69a0c7b18..b8d3381528e 100644 --- a/test/lisp/calendar/time-date-tests.el +++ b/test/lisp/calendar/time-date-tests.el @@ -106,24 +106,31 @@ (should-error (date-days-in-month 2020 'foo))) (ert-deftest test-format-seconds () - (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %")) - (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %")) - (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) "1 %")) - (should (equal (format-seconds "%mm %ss" 66) "1m 6s")) - (should (equal (format-seconds "%mm %5ss" 66) "1m 6s")) - (should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s")) - - (should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s")) - (should (equal (format-seconds "%mm %5,1ss" 66.4) "1m 6.4s")) - (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s")) - - (should (equal (format-seconds "%hh %z%x%mm %ss" (* 60 2)) "2m")) - (should (equal (format-seconds "%hh %z%mm %ss" (* 60 2)) "2m 0s")) - (should (equal (format-seconds "%hh %x%mm %ss" (* 60 2)) "0h 2m")) - (should (equal (format-seconds "%hh %x%mm %ss" 0) "0h 0m 0s")) - ;; Bug#70322 - (should (equal (format-seconds "%y %z%d %h %m %s %%" 9999999) "115 17 46 39 %")) - (should (equal (format-seconds "%Y, %D, %H, %M, %z%S" 0) "0 seconds"))) + (let ((format-seconds-list + '(("%y %d %h %m %s %%" 0 "0 0 0 0 0 %") + ("%y %d %h %m %s %%" 0 "0 0 0 0 0 %") + ("%y %d %h %m %s %%" 9999999 "0 115 17 46 39 %") + ("%y %d %h %m %z %s %%" 1 "1 %") + ("%mm %ss" 66 "1m 6s") + ("%mm %5ss" 66 "1m 6s") + ("%mm %.5ss" 66.4 "1m 00006s") + ("%mm %,1ss" 66.4 "1m 6.4s") + ("%mm %5,1ss" 66.4 "1m 6.4s") + ("%mm %.5,1ss" 66.4 "1m 006.4s") + ("%hh %z%x%mm %ss" 120 "2m") + ("%hh %z%mm %ss" 120 "2m 0s") + ("%hh %x%mm %ss" 120 "0h 2m") + ("%hh %x%mm %ss" 0 "0h 0m 0s") + ("%y %z%d %h %m %s %%" 9999999 "115 17 46 39 %") + ("%Y, %D, %H, %M, %z%S" 0 "0 seconds")))) + (dolist (fs format-seconds-list) + (let ((string (nth 0 fs)) + (seconds (nth 1 fs)) + (expected (nth 2 fs))) + (should (equal (format-seconds string seconds) expected)) + (when (< 0 seconds) + (should (equal (format-seconds string (- seconds)) + (concat "-" expected)))))))) (ert-deftest test-ordinal () (should (equal (date-ordinal-to-time 2008 271) From 6d7e7899d84600de3aa4bb5e4cb4013e48f7a8b5 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 2 Feb 2025 15:58:18 +0200 Subject: [PATCH 050/279] Improve documentation of 'display-monitor-attributes- * doc/lispref/frames.texi (Multiple Terminals): * lisp/frame.el (display-monitor-attributes-list): Better documentation of what the 'source' key means on X. (Bug#75936) --- doc/lispref/frames.texi | 7 ++++++- lisp/frame.el | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 2426c9c890f..39bfed48e4e 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -420,7 +420,12 @@ Name of the physical monitor as @var{string}. @item source Source of the multi-monitor information as @var{string}; -e.g., @samp{XRandR 1.5}, @samp{XRandr} or @samp{Xinerama}. +on X, it could be @samp{XRandR 1.5}, @samp{XRandr}, @samp{Xinerama}, +@samp{Gdk}, or @samp{fallback}. The last value of @samp{source} means +that Emacs was built without GTK and without XRandR or Xinerama +extensions, in which case the information about multiple physical +monitors will be provided as if they all as a whole formed a single +monitor. @end table @var{x}, @var{y}, @var{width}, and @var{height} are integers. diff --git a/lisp/frame.el b/lisp/frame.el index 64b9f6acff8..ec3d38fa3fa 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2465,6 +2465,10 @@ details depend on the platform and environment. The `source' attribute describes the source from which the information was obtained. On X, this may be one of: \"Gdk\", \"XRandR 1.5\", \"XRandr\", \"Xinerama\", or \"fallback\". +If it is \"fallback\", it means Emacs was built without GTK +and without XrandR or Xinerama extensions, in which case the +information about multiple physical monitors will be provided +as if they all as a whole formed a single monitor. A frame is dominated by a physical monitor when either the largest area of the frame resides in the monitor, or the monitor From 669bb2eaf535728c58899ab56f0f7d5bdd3747c0 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 2 Feb 2025 16:06:04 +0200 Subject: [PATCH 051/279] Announce XINERAM and XRANDR in 'system-configuration-features' * configure.ac (emacs_config_features): Add XINERAMA and XRANDR. (Bug#75936) --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 9db1f07d7fc..7b4c03c0908 100644 --- a/configure.ac +++ b/configure.ac @@ -7481,8 +7481,8 @@ for opt in ACL BE_APP CAIRO DBUS FREETYPE GCONF GIF GLIB GMP GNUTLS GPM GSETTING HARFBUZZ IMAGEMAGICK JPEG LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 \ M17N_FLT MODULES NATIVE_COMP NOTIFY NS OLDXMENU PDUMPER PGTK PNG RSVG SECCOMP \ SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER \ - UNEXEC WEBP X11 XAW3D XDBE XFT XIM XINPUT2 XPM XWIDGETS X_TOOLKIT \ - ZLIB; do + UNEXEC WEBP X11 XAW3D XDBE XFT XIM XINERAMA XINPUT2 XPM XRANDR XWIDGETS \ + X_TOOLKIT ZLIB; do case $opt in PDUMPER) val=${with_pdumper} ;; From fb53de0c06651ed9662610790b3c2938a314c468 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sat, 1 Feb 2025 17:57:56 -0800 Subject: [PATCH 052/279] ; Remove obsolete :options value from erc-mode-hook * lisp/erc/erc.el (erc-mode-hook): Remove `erc-add-scroll-to-bottom' from :options list because the function has been deprecated. --- lisp/erc/erc.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 72335a444cb..afa8e0a7b72 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1272,10 +1272,11 @@ particular sessions and/or `let'-bound for spells." :group 'erc) (defcustom erc-mode-hook nil - "Hook run after `erc-mode' setup is finished." + "Hook run after `erc-mode' setup is finished. +Members should be robust enough to run in any order and not depend on +hook depth." :group 'erc-hooks - :type 'hook - :options '(erc-add-scroll-to-bottom)) + :type 'hook) (defcustom erc-timer-hook nil "Abnormal hook run after each response handler. From a62a26239780684d481533a57d12de520b737f9b Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Thu, 30 Jan 2025 19:07:00 -0800 Subject: [PATCH 053/279] Run erc-services-regain-mode callback on a timer * lisp/erc/erc-services.el (erc-services-regain-timeout-seconds): New variable. (erc-services-regain-mode): Mention CertFP in doc string. (erc--nickname-in-use-make-request): Ensure the 900 RPL_LOGGEDIN callback always runs after `erc-services-regain-timeout-seconds', even when SASL isn't being used. * test/lisp/erc/erc-scenarios-services-misc.el (erc-scenarios-services-misc--regain-command/oftc): New test. * test/lisp/erc/resources/services/regain/taken-regain-oftc.eld: New file. --- lisp/erc/erc-services.el | 25 ++++++++--- test/lisp/erc/erc-scenarios-services-misc.el | 25 +++++++++++ .../services/regain/taken-regain-oftc.eld | 42 +++++++++++++++++++ 3 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 test/lisp/erc/resources/services/regain/taken-regain-oftc.eld diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el index d16aa8c54d8..429424117eb 100644 --- a/lisp/erc/erc-services.el +++ b/lisp/erc/erc-services.el @@ -548,6 +548,9 @@ for details and use cases." (function-item erc-services-issue-ghost-and-retry-nick) function))) +(defvar erc-services-regain-timeout-seconds 5 + "Seconds after which to run callbacks if necessary.") + (defun erc-services-retry-nick-on-connect (want) "Try at most once to grab nickname WANT after reconnecting. Expect to be used when automatically reconnecting to servers @@ -608,8 +611,8 @@ consider its main option, `erc-services-regain-alist': In practical terms, this means that this module, which is still somewhat experimental, is likely only useful in conjunction with -SASL authentication rather than the traditional approach provided -by the `services' module it shares a library with (see Info +SASL authentication or CertFP rather than the traditional approach +provided by the `services' module it shares a library with (see Info node `(erc) SASL' for more)." nil nil localp) @@ -632,11 +635,21 @@ one." (funcall found want)))) (on-900 (lambda (_ parsed) + (cancel-timer timer) (remove-hook 'erc-server-900-functions on-900 t) - (unless erc-server-connected - (when (equal (car (erc-response.command-args parsed)) temp) - (add-hook 'erc-after-connect after-connect nil t))) - nil))) + (unless (equal want (erc-current-nick)) + (if erc-server-connected + (funcall after-connect nil temp) + (when (or (eq parsed 'forcep) + (equal (car (erc-response.command-args parsed)) temp)) + (add-hook 'erc-after-connect after-connect nil t)))) + nil)) + (timer (run-at-time erc-services-regain-timeout-seconds + nil (lambda (buffer) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (funcall on-900 nil 'forcep)))) + (current-buffer)))) (add-hook 'erc-server-900-functions on-900 nil t)) (cl-call-next-method)) diff --git a/test/lisp/erc/erc-scenarios-services-misc.el b/test/lisp/erc/erc-scenarios-services-misc.el index 823c97dd96b..13d66a54d3a 100644 --- a/test/lisp/erc/erc-scenarios-services-misc.el +++ b/test/lisp/erc/erc-scenarios-services-misc.el @@ -223,6 +223,31 @@ ;; Works with "given" `:id'. (should (and (erc-network) (not (eq (erc-network) 'ExampleNet))))))) +(ert-deftest erc-scenarios-services-misc--regain-command/oftc () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-server-flood-penalty 0.1) + (erc-scenarios-common-dialog "services/regain") + (dumb-server (erc-d-run "localhost" t 'taken-regain-oftc)) + (port (process-contact dumb-server :service)) + (erc-modules `(services-regain ,@erc-modules)) + (erc-services-regain-timeout-seconds 1) + (use-id-p (cl-evenp (truncate (float-time)))) + (erc-services-regain-alist (list (cons (if use-id-p 'oftc 'OFTC) + #'erc-services-issue-regain))) + (expect (erc-d-t-make-expecter))) + + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "dummy" + :user "tester" + :full-name "tester" + :id (and use-id-p 'oftc)) + (funcall expect 10 "Nickname dummy is already in use, trying dummy`") + (funcall expect 10 "-NickServ- REGAIN succeed on nickname") + (funcall expect 10 "*** Your new nickname is dummy") + (funcall expect 10 "*** dummy has changed mode for dummy to +R")))) + (ert-deftest erc-scenarios-services-misc--ghost-and-retry-nick () :tags '(:expensive-test) (erc-scenarios-common-with-cleanup diff --git a/test/lisp/erc/resources/services/regain/taken-regain-oftc.eld b/test/lisp/erc/resources/services/regain/taken-regain-oftc.eld new file mode 100644 index 00000000000..c6fa09dc45c --- /dev/null +++ b/test/lisp/erc/resources/services/regain/taken-regain-oftc.eld @@ -0,0 +1,42 @@ +;; -*- mode: lisp-data; -*- +((nick 10 "NICK dummy")) +((user 10 "USER tester 0 * :tester") + (0.09 ":reflection.oftc.net NOTICE AUTH :*** Looking up your hostname...") + (0.03 ":reflection.oftc.net NOTICE AUTH :*** Checking Ident") + (0.02 ":reflection.oftc.net NOTICE AUTH :*** Found your hostname") + (0.01 ":reflection.oftc.net NOTICE AUTH :*** No Ident response") + (0.01 ":reflection.oftc.net 433 * dummy :Nickname is already in use.")) +((nick 10 "NICK dummy`") + (0.09 ":reflection.oftc.net NOTICE dummy` :*** Connected securely via TLSv1.3 TLS_AES_256_GCM_SHA384-256") + (0.03 ":reflection.oftc.net NOTICE dummy` :*** Your client certificate fingerprint is 4F6DDB61A5CFFA42719D39E3819B45DC58E4E307") + (0.01 ":reflection.oftc.net 001 dummy` :Welcome to the OFTC Internet Relay Chat Network dummy`") + (0.01 ":reflection.oftc.net 002 dummy` :Your host is reflection.oftc.net[64.86.243.183/6697], running version hybrid-7.2.2+oftc1.7.3") + (0.01 ":reflection.oftc.net 003 dummy` :This server was created Nov 1 2023 at 10:10:46") + (0.00 ":reflection.oftc.net 004 dummy` reflection.oftc.net hybrid-7.2.2+oftc1.7.3 CDGPRSabcdfgijklnorsuwxyz bciklmnopstvzeIMRS bkloveI") + (0.01 ":reflection.oftc.net 005 dummy` CALLERID CASEMAPPING=rfc1459 DEAF=D KICKLEN=160 MODES=4 NICKLEN=30 PREFIX=(ov)@+ STATUSMSG=@+ TOPICLEN=391 NETWORK=OFTC MAXLIST=beI:100 MAXTARGETS=1 CHANTYPES=# :are supported by this server") + (0.03 ":reflection.oftc.net 005 dummy` CHANLIMIT=#:250 CHANNELLEN=50 CHANMODES=eIqb,k,l,cimnpstzMRS AWAYLEN=160 KNOCK ELIST=CMNTU SAFELIST EXCEPTS=e INVEX=I :are supported by this server") + (0.01 ":reflection.oftc.net 042 dummy` 8L3AAEM45 :your unique ID") + (0.00 ":reflection.oftc.net 251 dummy` :There are 31 users and 16297 invisible on 19 servers") + (0.00 ":reflection.oftc.net 252 dummy` 20 :IRC Operators online") + (0.00 ":reflection.oftc.net 253 dummy` 25 :unknown connection(s)") + (0.00 ":reflection.oftc.net 254 dummy` 4118 :channels formed") + (0.00 ":reflection.oftc.net 255 dummy` :I have 1245 clients and 1 servers") + (0.00 ":reflection.oftc.net 265 dummy` :Current local users: 1245 Max: 1782") + (0.00 ":reflection.oftc.net 266 dummy` :Current global users: 16328 Max: 19479") + (0.00 ":reflection.oftc.net 250 dummy` :Highest connection count: 1783 (1782 clients) (203288 connections received)") + (0.03 ":reflection.oftc.net 375 dummy` :- reflection.oftc.net Message of the Day - ") + (0.00 ":reflection.oftc.net 372 dummy` :- O") + (0.00 ":reflection.oftc.net 372 dummy` :- Thanks and enjoy your stay! The OFTC team.") + (0.00 ":reflection.oftc.net 376 dummy` :End of /MOTD command.") + (0.03 ":dummy`!~tester@static-198-54-134-141.cust.tzulo.com MODE dummy` :+i")) +((mode 10 "MODE dummy` +i") + (0.00 ":CTCPServ!services@services.oftc.net PRIVMSG dummy` :\1VERSION\1")) +((~notice 10 "NOTICE CTCPServ :\1VERSION \2ERC\2")) +((privmsg 10 "PRIVMSG NickServ :REGAIN dummy") + (0.01 ":NickServ!services@services.oftc.net NOTICE dummy` :REGAIN succeed on nickname \2dummy\2. You have been changed to your nickname.") + (0.05 ":dummy`!~tester@static-198-54-134-141.cust.tzulo.com NICK :dummy") + (0.01 ":dummy MODE dummy :+R") + (0.04 ":dummy MODE dummy :-R") + (0.01 ":dummy MODE dummy :+R")) +((quit 10 "QUIT :\2ERC\2 5") + (0.08 "ERROR :Closing Link: static-198-54-134-141.cust.tzulo.com ()")) From 7f10d2680be16219cbde78434836b0befce3a0b3 Mon Sep 17 00:00:00 2001 From: Stephen Gildea Date: Sun, 2 Feb 2025 20:14:40 -0800 Subject: [PATCH 054/279] ; time-stamp: documentation, tests, NEWS * lisp/time-stamp.el (time-stamp-pattern, time-stamp-count): Document how to update different time stamps on multiple lines. * doc/emacs/files.texi (Time stamps): Add an example showing a time stamp at the end of a file. * etc/NEWS: Announce time-stamp format additions. * test/lisp/time-stamp-tests.el: More title-case tests. --- doc/emacs/files.texi | 16 +++++++++++++++ etc/NEWS | 24 +++++++++++++++++++++++ lisp/time-stamp.el | 30 ++++++++++++++++++---------- test/lisp/time-stamp-tests.el | 37 +++++++++++++++++++++++------------ 4 files changed, 84 insertions(+), 23 deletions(-) diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 3db291d68e9..3bc7d6ea24a 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1072,6 +1072,22 @@ identify and update that custom template: @end group @end example +Here is another example, with the time stamp inserted into the last +paragraph of an HTML document. The @code{%%} in the pattern asks for +the default format. + +@example +@r{@dots{}} +

Last modified:

+ + + +@end example + @vindex time-stamp-format By default the time stamp is formatted according to your locale setting (@pxref{Environment}) and diff --git a/etc/NEWS b/etc/NEWS index 259b6e03549..8cf86d1375d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -901,6 +901,30 @@ the 'grep' results editable. The edits will be reflected in the buffer visiting the originating file. Typing 'C-c C-c' will leave the Grep Edit mode. +** time-stamp + +--- +*** 'time-stamp' can up-case, capitalize and down-case date words. +This control can be useful in languages in which days of the week and/or +month names are capitalized only at the beginning of a sentence. For +details, see the built-in documentation for variable 'time-stamp-format'. + +Because this feature is new in Emacs 31.1, do not use it in the local +variables section of any file that might be edited by an older version +of Emacs. + +--- +*** Some historical 'time-stamp' conversions now warn. +'time-stamp-pattern' and 'time-stamp-format' had quietly +accepted several 'time-stamp' conversions (e.g., "%:y") that +have been deprecated since Emacs 27.1 (released in 2020). +These now generate a warning with a suggested migration. + +Merely having "(add-hook 'before-save-hook 'time-stamp)" +in your Emacs init file does not expose you to this change. +However, if you set 'time-stamp-format' or 'time-stamp-pattern' +with a file-local variable, you may be asked to update the value. + ** TeX modes +++ diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index a2e91246ae2..ad356eb2bd6 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el @@ -248,7 +248,11 @@ your init file, you would be incompatible with other people's files.") (defvar time-stamp-count 1 ;Do not change! "How many templates \\[time-stamp] will look for in a buffer. -The same time stamp will be written in each case. + +If the value is greater than 1, the same time stamp will be written in +each case. If you want to insert different text on different lines, +then instead of changing this variable, include a newline (written as +\"\\n\") in `time-stamp-format' or the format part of `time-stamp-pattern'. `time-stamp-count' is best changed with a file-local variable. If you were to change it in your init file, you would be incompatible @@ -259,26 +263,27 @@ with other people's files.") (defvar time-stamp-pattern nil ;Do not change! "Convenience variable setting all `time-stamp' location and format values. This string has four parts, each of which is optional. -These four parts set `time-stamp-line-limit', `time-stamp-start', -`time-stamp-format', and `time-stamp-end'. See the documentation -for each of these variables for details. +These four parts override `time-stamp-line-limit', `time-stamp-start', +`time-stamp-format' and `time-stamp-end', respectively. See the +documentation for each of these variables for details. The first part is a number followed by a slash; the number sets the number of lines at the beginning (negative counts from end) of the file searched for the time stamp. The number and the slash may be omitted to use the -normal value. +value of `time-stamp-line-limit' as the number. The second part is a regexp identifying the pattern preceding the time stamp. -This part may be omitted to use the normal pattern. +This part may be omitted to use the value of `time-stamp-start'. -The third part specifies the format of the time stamp inserted. See -the documentation for `time-stamp-format' for details. Specify this -part as \"%%\" to use the normal format. +The third part specifies the format of the time stamp inserted. Specify +this part as \"%%\" to use the value of `time-stamp-format'. The fourth part is a regexp identifying the pattern following the time stamp. -This part may be omitted to use the normal pattern. +This part may be omitted to use the value of `time-stamp-end'. The pattern does not need to match the entire line of the time stamp. +The pattern will update time stamp information on multiple lines if the +pattern includes newlines, written as \"\\n\". These variables are best changed with file-local variables. If you were to change `time-stamp-pattern', `time-stamp-line-limit', @@ -299,6 +304,11 @@ Examples: %% time-stamp-pattern: \"newcommand{\\\\\\\\timestamp}{%%}\" (sets `time-stamp-start' and `time-stamp-end') +// time-stamp-pattern: \"10/Author %L\\nRevised %-d %b %Y$\" + (sets all four variables and updates text on two lines) + +See Info node `Time Stamps' for more examples. + See also `time-stamp-count' and `time-stamp-inserts-lines'.") ;;;###autoload(put 'time-stamp-pattern 'safe-local-variable 'stringp) diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el index c59ae9f5356..a7aa00dc267 100644 --- a/test/lisp/time-stamp-tests.el +++ b/test/lisp/time-stamp-tests.el @@ -344,13 +344,12 @@ ;; broken in 2019, changed in 2024 (should (equal (time-stamp-string "%-A" ref-time1) Monday)) (should (equal (time-stamp-string "%_A" ref-time1) Monday)) - ;; allowed but not recommended since 2019 (warned 1997-2019) - (should (equal (time-stamp-string "%^A" ref-time1) MONDAY)) ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%a" ref-time1) Mon)) (should (equal (time-stamp-string "%4a" ref-time1) p4-Mon)) (should (equal (time-stamp-string "%04a" ref-time1) p4-Mon)) (should (equal (time-stamp-string "%A" ref-time1) Monday)) + (should (equal (time-stamp-string "%^A" ref-time1) MONDAY)) ;; warned 1997-2019, changed in 2019 (should (equal (time-stamp-string "%^a" ref-time1) MON)) (should (equal (time-stamp-string "%^4a" ref-time1) p4-MON)) @@ -401,13 +400,12 @@ ;; broken in 2019, changed in 2024 (should (equal (time-stamp-string "%-B" ref-time1) January)) (should (equal (time-stamp-string "%_B" ref-time1) January)) - ;; allowed but not recommended since 2019 (warned 1997-2019) - (should (equal (time-stamp-string "%^B" ref-time1) JANUARY)) ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%b" ref-time1) Jan)) (should (equal (time-stamp-string "%4b" ref-time1) p4-Jan)) (should (equal (time-stamp-string "%04b" ref-time1) p4-Jan)) (should (equal (time-stamp-string "%B" ref-time1) January)) + (should (equal (time-stamp-string "%^B" ref-time1) JANUARY)) ;; warned 1997-2019, changed in 2019 (should (equal (time-stamp-string "%^b" ref-time1) JAN)) (should (equal (time-stamp-string "%^4b" ref-time1) p4-JAN)) @@ -490,7 +488,7 @@ (should (equal (time-stamp-string "%:I" ref-time1) "3")) ;PM (should (equal (time-stamp-string "%:I" ref-time2) "12")) ;PM (should (equal (time-stamp-string "%:I" ref-time3) "6")) ;AM - ;; implemented since 1997, recommended since 2019 + ;; implemented since 1997, recommended 2019-2024 (should (equal (time-stamp-string "%1I" ref-time1) "3")) (should (equal (time-stamp-string "%1I" ref-time2) "12")) (should (equal (time-stamp-string "%1I" ref-time3) "6")) @@ -517,7 +515,7 @@ ;; recommended 1997-2019 (should (equal (time-stamp-string "%:m" ref-time1) "1")) (should (equal (time-stamp-string "%:m" ref-time2) "11")) - ;; implemented since 1997, recommended since 2019 + ;; implemented since 1997, recommended 2019-2024 (should (equal (time-stamp-string "%1m" ref-time1) "1")) (should (equal (time-stamp-string "%1m" ref-time2) "11")) ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 @@ -540,7 +538,7 @@ ;; recommended 1997-2019 (should (equal (time-stamp-string "%:M" ref-time1) "4")) (should (equal (time-stamp-string "%:M" ref-time2) "14")) - ;; implemented since 1997, recommended since 2019 + ;; implemented since 1997, recommended 2019-2024 (should (equal (time-stamp-string "%1M" ref-time1) "4")) (should (equal (time-stamp-string "%1M" ref-time2) "14")) ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 @@ -563,7 +561,7 @@ ;; recommended 1997-2019 (should (equal (time-stamp-string "%:S" ref-time1) "5")) (should (equal (time-stamp-string "%:S" ref-time2) "15")) - ;; implemented since 1997, recommended since 2019 + ;; implemented since 1997, recommended 2019-2024 (should (equal (time-stamp-string "%1S" ref-time1) "5")) (should (equal (time-stamp-string "%1S" ref-time2) "15")) ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 @@ -586,10 +584,12 @@ (should (equal (time-stamp-string "%:y" ref-time1) "2006"))) (time-stamp-should-warn (should (equal (time-stamp-string "%:y" ref-time2) "2016"))) - ;; warned 1997-2019, changed in 2019 - ;; (We don't expect the %-y or %_y form to be useful, - ;; but we test both so that we can confidently state that - ;; `-' and `_' affect all 2-digit conversions identically.) + ;; %-y and %_y warned 1997-2019, changed in 2019 + ;; (We don't expect these forms to be useful, + ;; but we test here so that we can confidently state that + ;; all 2-digit conversions behave identically.) + (should (equal (time-stamp-string "%1y" ref-time1) "6")) + (should (equal (time-stamp-string "%1y" ref-time2) "16")) (should (equal (time-stamp-string "%-y" ref-time1) "6")) (should (equal (time-stamp-string "%-y" ref-time2) "16")) (should (equal (time-stamp-string "%_y" ref-time1) " 6")) @@ -619,6 +619,8 @@ (am (format-time-string "%P" ref-time3 t)) (Pm (format-time-string "%p" ref-time1 t)) (Am (format-time-string "%p" ref-time3 t)) + (Pm-tc (capitalize (format-time-string "%p" ref-time1 t))) + (Am-tc (capitalize (format-time-string "%p" ref-time3 t))) (PM (format-time-string "%^p" ref-time1 t)) (AM (format-time-string "%^p" ref-time3 t))) ;; implemented and recommended since 1997 @@ -644,6 +646,11 @@ (should (equal (time-stamp-string "%^#P" ref-time3) am)) (should (equal (time-stamp-string "%^P" ref-time1) "")) (should (equal (time-stamp-string "%^P" ref-time3) "")) + ;; implemented since 2025 + (should (equal (time-stamp-string "%*p" ref-time1) Pm-tc)) + (should (equal (time-stamp-string "%*p" ref-time3) Am-tc)) + (should (equal (time-stamp-string "%*P" ref-time1) Pm-tc)) + (should (equal (time-stamp-string "%*P" ref-time3) Am-tc)) ;; reserved for possible adding or removing periods (dots) (should (equal (time-stamp-string "%:p" ref-time1) Pm)) (should (equal (time-stamp-string "%#:p" ref-time1) pm)) @@ -667,6 +674,7 @@ "Test `time-stamp' format %Z." (with-time-stamp-test-env (let ((UTC-abbr (format-time-string "%Z" ref-time1 t)) + (Utc-abbr (capitalize (format-time-string "%Z" ref-time1 t))) (utc-abbr (format-time-string "%#Z" ref-time1 t))) ;; implemented and recommended since 1995 (should (equal (time-stamp-string "%Z" ref-time1) UTC-abbr)) @@ -674,7 +682,10 @@ (should (equal (time-stamp-string "%#Z" ref-time1) utc-abbr)) ;; ^ accepted and ignored since 1995/1997, test for consistency with %p (should (equal (time-stamp-string "%^Z" ref-time1) UTC-abbr)) - (should (equal (time-stamp-string "%^#Z" ref-time1) utc-abbr))))) + (should (equal (time-stamp-string "%^#Z" ref-time1) utc-abbr)) + ;; implemented since 2025 + (should (equal (time-stamp-string "%*Z" ref-time1) Utc-abbr)) + ))) (ert-deftest time-stamp-format-time-zone-offset () "Test `time-stamp' legacy format %z and spot-test new offset format %5z." From a8e85243790b6ab9b9e261c77ddfdc65a9867069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= Date: Sun, 2 Feb 2025 15:09:52 +0100 Subject: [PATCH 055/279] Handle mouse highlighting in the presence of tty child frames * src/term.c (tty_draw_row_with_mouse_face): Draw only parts of the highlighted text that are not covered by other frames. --- src/term.c | 93 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/src/term.c b/src/term.c index f307d709316..fd95e75a007 100644 --- a/src/term.c +++ b/src/term.c @@ -2559,36 +2559,89 @@ A value of zero means TTY uses the system's default value. */) #if !defined DOS_NT && !defined HAVE_ANDROID /* Implementation of draw_row_with_mouse_face for TTY/GPM and macOS. */ + void -tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, - int start_hpos, int end_hpos, +tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *window_row, + int window_start_x, + int window_end_x, enum draw_glyphs_face draw) { - int nglyphs = end_hpos - start_hpos; - struct frame *f = XFRAME (WINDOW_FRAME (w)); - struct tty_display_info *tty = FRAME_TTY (f); - int face_id = tty->mouse_highlight.mouse_face_face_id; + struct frame *f = XFRAME (w->frame); + struct frame *root = root_frame (f); - if (end_hpos >= row->used[TEXT_AREA]) - nglyphs = row->used[TEXT_AREA] - start_hpos; + /* Window coordinates are relative to the text area. Make + them relative to the window's left edge, */ + window_end_x = min (window_end_x, window_row->used[TEXT_AREA]); + window_start_x += window_row->used[LEFT_MARGIN_AREA]; + window_end_x += window_row->used[LEFT_MARGIN_AREA]; - int pos_y = row->y + WINDOW_TOP_EDGE_Y (w); - int pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); + /* Translate from window to window's frame. */ + int frame_start_x = WINDOW_LEFT_EDGE_X (w) + window_start_x; + int frame_end_x = WINDOW_LEFT_EDGE_X (w) + window_end_x; + int frame_y = window_row->y + WINDOW_TOP_EDGE_Y (w); - /* Save current cursor coordinates. */ - int save_y = curY (tty); + /* Translate from (possible) child frame to root frame. */ + int root_start_x, root_end_x, root_y; + root_xy (f, frame_start_x, frame_y, &root_start_x, &root_y); + root_xy (f, frame_end_x, frame_y, &root_end_x, &root_y); + struct glyph_row *root_row = MATRIX_ROW (root->current_matrix, root_y); + + /* Remember current cursor coordinates so that we can restore + them at the end. */ + struct tty_display_info *tty = FRAME_TTY (root); int save_x = curX (tty); - cursor_to (f, pos_y, pos_x); + int save_y = curY (tty); - if (draw == DRAW_MOUSE_FACE) + /* If the root frame displays child frames, we cannot naively + write to the terminal what the window thinks should be drawn. + Instead, write only those parts that are not obscured by + other frames. */ + for (int root_x = root_start_x; root_x < root_end_x; ) { - struct glyph *glyph = row->glyphs[TEXT_AREA] + start_hpos; - struct face *face = FACE_FROM_ID (f, face_id); - tty_write_glyphs_with_face (f, glyph, nglyphs, face); - } - else if (draw == DRAW_NORMAL_TEXT) - write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); + /* Find the start of a run of glyphs from frame F. */ + struct glyph *root_start = root_row->glyphs[TEXT_AREA] + root_x; + while (root_x < root_end_x && root_start->frame != f) + ++root_x, ++root_start; + /* If start of a run of glyphs from F found. */ + int root_run_start_x = root_x; + if (root_run_start_x < root_end_x) + { + /* Find the end of the run of glyphs from frame F. */ + struct glyph *root_end = root_start; + while (root_x < root_end_x && root_end->frame == f) + ++root_x, ++root_end; + + /* If we have a run glyphs to output, do it. */ + if (root_end > root_start) + { + cursor_to (root, root_y, root_run_start_x); + ptrdiff_t n = root_end - root_start; + switch (draw) + { + case DRAW_NORMAL_TEXT: + write_glyphs (f, root_start, n); + break; + + case DRAW_MOUSE_FACE: + { + int face_id = tty->mouse_highlight.mouse_face_face_id; + struct face *face = FACE_FROM_ID (f, face_id); + tty_write_glyphs_with_face (f, root_start, n, face); + } + break; + + case DRAW_INVERSE_VIDEO: + case DRAW_CURSOR: + case DRAW_IMAGE_RAISED: + case DRAW_IMAGE_SUNKEN: + emacs_abort (); + } + } + } + } + + /* Restore cursor where it was before. */ cursor_to (f, save_y, save_x); } From a7f34a532cf7d99dac58bd7187f7ad82c1e4d789 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Sun, 2 Feb 2025 13:33:37 +0100 Subject: [PATCH 056/279] Fix padding when using which-key-setup-side-window-right * lisp/which-key.el (which-key--pad-column): Insert zero padding spaces when the description string is longer than the column width. (Bug#75765) --- lisp/which-key.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/which-key.el b/lisp/which-key.el index d33e8b1a3bb..6ae8dcbb1f0 100644 --- a/lisp/which-key.el +++ b/lisp/which-key.el @@ -2038,7 +2038,7 @@ that width." (mapcar (pcase-lambda (`(,key ,sep ,desc ,_doc)) (concat (format col-format key sep desc) - (make-string (- col-desc-width (string-width desc)) ?\s))) + (make-string (max (- col-desc-width (string-width desc)) 0) ?\s))) col-keys)))) (defun which-key--partition-list (n list) From fbc13ba9ccf4590ccd15dafa35d3872807af9cbd Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Mon, 3 Feb 2025 12:51:48 +0100 Subject: [PATCH 057/279] Better NaN handling in proced-tests.el * test/lisp/proced-tests.el (proced--cpu-at-point): Make it more robust. (proced--assert-process-valid-cpu-refinement): Handle `ert-test-skipped' signal. --- test/lisp/proced-tests.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/lisp/proced-tests.el b/test/lisp/proced-tests.el index e24163c3884..ecf23c5d037 100644 --- a/test/lisp/proced-tests.el +++ b/test/lisp/proced-tests.el @@ -38,10 +38,10 @@ (defun proced--cpu-at-point () "Return as an integer the current CPU value at point." (if (string-suffix-p "nan" (thing-at-point 'sexp)) - (let ((pid (proced-pid-at-point))) - (ert-skip - (format - "Found NaN value for %%CPU at point for process with PID %d" pid))) + (ert-skip + (format + "Found NaN value for %%CPU at point for process with PID %s" + (substring-no-properties (thing-at-point 'sexp)))) (thing-at-point 'number))) (defun proced--assert-emacs-pid-in-buffer () @@ -61,6 +61,7 @@ (proced--move-to-column "%CPU") (condition-case err (>= (proced--cpu-at-point) cpu) + (ert-test-skipped (signal (car err) (cdr err))) (error (ert-fail (list err (proced--assert-process-valid-cpu-refinement-explainer cpu)))))) From 1639ad2814ae100c9f878a1388eb9ffc9d208b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulrich=20M=C3=BCller?= Date: Sat, 1 Feb 2025 23:10:53 +0100 Subject: [PATCH 058/279] Avoid ln(10) expression in calc units definition * lisp/calc/calc-ext.el (calc-init-extensions): Autoload calc-math for math-ln-10. * lisp/calc/calc-units.el (math-standard-units): Use new ln10 constant instead of ln(10) in the decibel definition. (math-find-base-units-rec): Allow ln10 in expression. (math-to-standard-rec): Recognize the ln10 constant. (Bug#75861) --- lisp/calc/calc-ext.el | 2 +- lisp/calc/calc-units.el | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lisp/calc/calc-ext.el b/lisp/calc/calc-ext.el index 4ec96d3ef53..060d352fe66 100644 --- a/lisp/calc/calc-ext.el +++ b/lisp/calc/calc-ext.el @@ -877,7 +877,7 @@ calcFunc-tanh math-arccos-raw math-arcsin-raw math-arctan-raw math-arctan2-raw math-cos-raw math-cot-raw math-csc-raw math-exp-minus-1-raw math-exp-raw math-from-radians math-from-radians-2 math-hypot math-infinite-dir -math-ln-raw math-nearly-equal math-nearly-equal-float +math-ln-10 math-ln-raw math-nearly-equal math-nearly-equal-float math-nearly-zerop math-nearly-zerop-float math-nth-root math-sin-cos-raw math-sin-raw math-sqrt math-sqrt-float math-sqrt-raw math-tan-raw math-to-radians math-to-radians-2) diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el index d2396a9b262..4a638e66132 100644 --- a/lisp/calc/calc-units.el +++ b/lisp/calc/calc-units.el @@ -314,7 +314,8 @@ ;; Logarithmic units ( Np nil "*Neper") - ( dB "(ln(10)/20) Np" "decibel")) + ( dB "(ln10/20) Np" "Decibel" nil + "(ln(10)/20) Np")) "List of predefined units for Calc. Each element is (NAME DEF DESC TEMP-UNIT HUMAN-DEF), where: @@ -948,10 +949,9 @@ If COMP or STD is non-nil, put that in the units table instead." ((eq (car expr) '+) (math-find-base-units-rec (nth 1 expr) pow)) ((eq (car expr) 'var) - (or (eq (nth 1 expr) 'pi) + (or (memq (nth 1 expr) '(pi ln10)) (error "Unknown name %s in defining expression for unit %s" (nth 1 expr) (car math-fbu-entry)))) - ((equal expr '(calcFunc-ln 10))) (t (error "Malformed defining expression for unit %s" (car math-fbu-entry)))))) @@ -1055,9 +1055,9 @@ If COMP or STD is non-nil, put that in the units table instead." math-unit-prefixes)) expr))) expr) - (if (eq base 'pi) - (math-pi) - expr))) + (cond ((eq base 'pi) (math-pi)) + ((eq base 'ln10) (math-ln-10)) + (t expr)))) (if (or (Math-primp expr) (and (eq (car-safe expr) 'calcFunc-subscr) From a3b3083081299049b2ac2333d078c9cac62f2be4 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 3 Feb 2025 12:37:06 +0100 Subject: [PATCH 059/279] ; Don't use HTTPS in HTTP-specific example * doc/misc/org.org (External Links): Change HTTP example to use HTTP. Changing it to HTTPS has been done before, but it's a mistake. To avoid making this mistake again, change the URL to orgmode.org to make it more similar to the example on the next line, thereby contrasting the two. --- doc/misc/org.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/misc/org.org b/doc/misc/org.org index 363a95fa65c..26cb46cf13c 100644 --- a/doc/misc/org.org +++ b/doc/misc/org.org @@ -3403,7 +3403,7 @@ options: | Link Type | Example | |------------+--------------------------------------------------------------------| -| http | =https://staff.science.uva.nl/c.dominik/= | +| http | =http://orgmode.org/= | | https | =https://orgmode.org/= | | doi | =doi:10.1000/182= | | file | =file:/home/dominik/images/jupiter.jpg= | From a22e971a119dfd1385fe38d6f594bccfe8911152 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 3 Feb 2025 18:36:11 +0200 Subject: [PATCH 060/279] Fix -nw sessions on MS-Windows * src/w32console.c (w32con_clear_end_of_line): Set the space glyphs' frame to NULL. (w32con_write_glyphs): Handle face_id_frame == NULL, when called from 'w32con_clear_end_of_line'. (tty_draw_row_with_mouse_face): Adjust to changes in term.c. --- src/w32console.c | 98 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 21 deletions(-) diff --git a/src/w32console.c b/src/w32console.c index 9cfedde3b3f..b18eda437ad 100644 --- a/src/w32console.c +++ b/src/w32console.c @@ -167,7 +167,7 @@ w32con_clear_end_of_line (struct frame *f, int end) for (i = 0; i < glyphs_len; i++) { memcpy (&glyphs[i], &space_glyph, sizeof (struct glyph)); - glyphs[i].frame = f; + glyphs[i].frame = NULL; } ceol_initialized = TRUE; } @@ -339,8 +339,10 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string, && string[n].frame == face_id_frame)) break; + /* w32con_clear_end_of_line sets frame of glyphs to NULL. */ + struct frame *attr_frame = face_id_frame ? face_id_frame : f; /* Turn appearance modes of the face of the run on. */ - char_attr = w32_face_attributes (face_id_frame, face_id); + char_attr = w32_face_attributes (attr_frame, face_id); if (n == len) /* This is the last run. */ @@ -425,34 +427,88 @@ w32con_write_glyphs_with_face (struct frame *f, register int x, register int y, /* Implementation of draw_row_with_mouse_face for W32 console. */ void -tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row, - int start_hpos, int end_hpos, +tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *window_row, + int window_start_x, int window_end_x, enum draw_glyphs_face draw) { - int nglyphs = end_hpos - start_hpos; struct frame *f = XFRAME (WINDOW_FRAME (w)); - struct tty_display_info *tty = FRAME_TTY (f); - int face_id = tty->mouse_highlight.mouse_face_face_id; - int pos_x, pos_y; + struct frame *root = root_frame (f); - if (end_hpos >= row->used[TEXT_AREA]) - nglyphs = row->used[TEXT_AREA] - start_hpos; + /* Window coordinates are relative to the text area. Make + them relative to the window's left edge, */ + window_end_x = min (window_end_x, window_row->used[TEXT_AREA]); + window_start_x += window_row->used[LEFT_MARGIN_AREA]; + window_end_x += window_row->used[LEFT_MARGIN_AREA]; - pos_y = row->y + WINDOW_TOP_EDGE_Y (w); - pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w); + /* Translate from window to window's frame. */ + int frame_start_x = WINDOW_LEFT_EDGE_X (w) + window_start_x; + int frame_end_x = WINDOW_LEFT_EDGE_X (w) + window_end_x; + int frame_y = window_row->y + WINDOW_TOP_EDGE_Y (w); - if (draw == DRAW_MOUSE_FACE) - w32con_write_glyphs_with_face (f, pos_x, pos_y, - row->glyphs[TEXT_AREA] + start_hpos, - nglyphs, face_id); - else if (draw == DRAW_NORMAL_TEXT) + /* Translate from (possible) child frame to root frame. */ + int root_start_x, root_end_x, root_y; + root_xy (f, frame_start_x, frame_y, &root_start_x, &root_y); + root_xy (f, frame_end_x, frame_y, &root_end_x, &root_y); + struct glyph_row *root_row = MATRIX_ROW (root->current_matrix, root_y); + + /* Remember current cursor coordinates so that we can restore + them at the end. */ + COORD save_coords = cursor_coords; + + /* If the root frame displays child frames, we cannot naively + write to the terminal what the window thinks should be drawn. + Instead, write only those parts that are not obscured by + other frames. */ + for (int root_x = root_start_x; root_x < root_end_x; ) { - COORD save_coords = cursor_coords; + /* Find the start of a run of glyphs from frame F. */ + struct glyph *root_start = root_row->glyphs[TEXT_AREA] + root_x; + while (root_x < root_end_x && root_start->frame != f) + ++root_x, ++root_start; - w32con_move_cursor (f, pos_y, pos_x); - write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs); - w32con_move_cursor (f, save_coords.Y, save_coords.X); + /* If start of a run of glyphs from F found. */ + int root_run_start_x = root_x; + if (root_run_start_x < root_end_x) + { + /* Find the end of the run of glyphs from frame F. */ + struct glyph *root_end = root_start; + while (root_x < root_end_x && root_end->frame == f) + ++root_x, ++root_end; + + /* If we have a run glyphs to output, do it. */ + if (root_end > root_start) + { + w32con_move_cursor (root, root_y, root_run_start_x); + + ptrdiff_t nglyphs = root_end - root_start; + switch (draw) + { + case DRAW_NORMAL_TEXT: + write_glyphs (f, root_start, nglyphs); + break; + + case DRAW_MOUSE_FACE: + { + struct tty_display_info *tty = FRAME_TTY (f); + int face_id = tty->mouse_highlight.mouse_face_face_id; + w32con_write_glyphs_with_face (f, root_run_start_x, root_y, + root_start, nglyphs, + face_id); + } + break; + + case DRAW_INVERSE_VIDEO: + case DRAW_CURSOR: + case DRAW_IMAGE_RAISED: + case DRAW_IMAGE_SUNKEN: + emacs_abort (); + } + } + } } + + /* Restore cursor where it was before. */ + w32con_move_cursor (f, save_coords.Y, save_coords.X); } static void From b5316e1ddb728ab7502e2b2fffcc84e9c47316dd Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Mon, 3 Feb 2025 09:54:47 +0100 Subject: [PATCH 061/279] read-face-name: Build common completion table for CR and CRM * lisp/faces.el (read-face-name): Build a common completion table for both `completing-read' and `completing-read-multiple' with completion metadata (bug#74865). --- lisp/faces.el | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/lisp/faces.el b/lisp/faces.el index 5fe3ab1a294..dd8c24f5001 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -1137,19 +1137,30 @@ returned. Otherwise, DEFAULT is returned verbatim." (let ((prompt (if default (format-prompt prompt default) (format "%s: " prompt))) - aliasfaces nonaliasfaces faces) + aliasfaces nonaliasfaces table) ;; Build up the completion tables. (mapatoms (lambda (s) (if (facep s) (if (get s 'face-alias) (push (symbol-name s) aliasfaces) (push (symbol-name s) nonaliasfaces))))) + (setq table + (completion-table-with-metadata + (completion-table-in-turn nonaliasfaces aliasfaces) + `((affixation-function + . ,(lambda (faces) + (mapcar + (lambda (face) + (list face + (concat (propertize read-face-name-sample-text + 'face face) + "\t") + "")) + faces)))))) (if multiple - (progn - (dolist (face (completing-read-multiple - prompt - (completion-table-in-turn nonaliasfaces aliasfaces) - nil t nil 'face-name-history default)) + (let (faces) + (dolist (face (completing-read-multiple prompt table nil t nil + 'face-name-history default)) ;; Ignore elements that are not faces ;; (for example, because DEFAULT was "all faces") (if (facep face) (push (if (stringp face) @@ -1157,21 +1168,8 @@ returned. Otherwise, DEFAULT is returned verbatim." face) faces))) (nreverse faces)) - (let ((face (completing-read - prompt - (completion-table-with-metadata - (completion-table-in-turn nonaliasfaces aliasfaces) - `((affixation-function - . ,(lambda (faces) - (mapcar - (lambda (face) - (list face - (concat (propertize read-face-name-sample-text - 'face face) - "\t") - "")) - faces))))) - nil t nil 'face-name-history defaults))) + (let ((face (completing-read prompt table nil t nil + 'face-name-history defaults))) (when (facep face) (if (stringp face) (intern face) face))))))) From 1c3a8bc9b51cf89fc1eff181d39941d7f0c7b2e2 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 3 Feb 2025 15:50:36 -0500 Subject: [PATCH 062/279] * lisp/emacs-lisp/track-changes.el (track-changes-fetch): Fix bug#75906 --- lisp/emacs-lisp/track-changes.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el index 3f3b8d7bed9..1aac53b5f33 100644 --- a/lisp/emacs-lisp/track-changes.el +++ b/lisp/emacs-lisp/track-changes.el @@ -364,7 +364,9 @@ and re-enable the TRACKER corresponding to ID." track-changes--state)) ;; Nothing to do. nil) - (cl-assert (not (memq id track-changes--clean-trackers))) + ;; ID may still be in `track-changes--clean-trackers' if + ;; `after-change-functions' was skipped. + ;;(cl-assert (not (memq id track-changes--clean-trackers))) (cl-assert (<= (point-min) beg end (point-max))) ;; Update the tracker's state *before* running `func' so we don't risk ;; mistakenly replaying the changes in case `func' exits non-locally. From 14ebe4d5dbd4e6637de227c8561aab22cf4b632c Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Mon, 3 Feb 2025 20:40:34 +0000 Subject: [PATCH 063/279] Fix GC-related crashes in styled_format (bug#75754) This approach ensures we don't use an SSDATA pointer after GC, and that no Lisp callback code can modify the format string while we're working on it. * src/editfns.c (styled_format): Operate on a copy of the format string rather than the original. Ensure final NUL byte is copied. --- src/editfns.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/editfns.c b/src/editfns.c index 4ba356d627c..f9258392146 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -3442,9 +3442,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) } *info; CHECK_STRING (args[0]); - char *format_start = SSDATA (args[0]); bool multibyte_format = STRING_MULTIBYTE (args[0]); ptrdiff_t formatlen = SBYTES (args[0]); + char *format_start = SAFE_ALLOCA (formatlen + 1); + memcpy (format_start, SSDATA (args[0]), formatlen + 1); bool fmt_props = !!string_intervals (args[0]); /* Upper bound on number of format specs. Each uses at least 2 chars. */ From f3ac16b3cc5778041332bb46f819a51e8b697099 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 3 Feb 2025 16:33:39 -0500 Subject: [PATCH 064/279] (save-place-abbreviate-file-names): Don't eagerly load alist (bug#75730) Change the way we handle `save-place-abbreviate-file-names` such that this preference is applied lazily when we load the alist, rather than eagerly when we define it (which forced the alist to be loaded before we needed it). * lisp/saveplace.el (save-place-load-alist-from-file): Use `unless`, `when`, and `with-temp-buffer` to hopefully help readability. Call `save-place--normalize-alist`. (save-place--normalize-alist): New function extracted from the setter of `save-place-abbreviate-file-names`. (save-place-abbreviate-file-names): Use it. (save-place-alist-to-file): Use `with-temp-buffer`. --- lisp/saveplace.el | 127 +++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/lisp/saveplace.el b/lisp/saveplace.el index 37b657073cc..b6c57d2da80 100644 --- a/lisp/saveplace.el +++ b/lisp/saveplace.el @@ -101,47 +101,44 @@ this happens automatically before saving `save-place-alist' to :type 'boolean) (defun save-place-load-alist-from-file () - (if (not save-place-loaded) - (progn - (setq save-place-loaded t) - (let ((file (expand-file-name save-place-file))) - ;; make sure that the alist does not get overwritten, and then - ;; load it if it exists: - (if (file-readable-p file) - ;; don't want to use find-file because we have been - ;; adding hooks to it. - (with-current-buffer (get-buffer-create " *Saved Places*") - (delete-region (point-min) (point-max)) - ;; Make sure our 'coding:' cookie in the save-place - ;; file will take effect, in case the caller binds - ;; coding-system-for-read. - (let (coding-system-for-read) - (insert-file-contents file)) - (goto-char (point-min)) - (setq save-place-alist - (with-demoted-errors "Error reading save-place-file: %S" - (car (read-from-string - (buffer-substring (point-min) (point-max)))))) + (unless save-place-loaded + (setq save-place-loaded t) + ;; FIXME: Obey `save-place-abbreviate-file-names'? + (let ((file (expand-file-name save-place-file))) + ;; make sure that the alist does not get overwritten, and then + ;; load it if it exists: + (when (file-readable-p file) + ;; don't want to use find-file because we have been + ;; adding hooks to it. + (with-temp-buffer + ;; Make sure our 'coding:' cookie in the save-place + ;; file will take effect, in case the caller binds + ;; coding-system-for-read. + (let (coding-system-for-read) + (insert-file-contents file)) + (goto-char (point-min)) + (setq save-place-alist + (with-demoted-errors "Error reading save-place-file: %S" + (car (read-from-string + (buffer-substring (point-min) (point-max)))))) - ;; If there is a limit, and we're over it, then we'll - ;; have to truncate the end of the list: - (if save-place-limit - (if (<= save-place-limit 0) - ;; Zero gets special cased. I'm not thrilled - ;; with this, but the loop for >= 1 is tight. - (setq save-place-alist nil) - ;; Else the limit is >= 1, so enforce it by - ;; counting and then `setcdr'ing. - (let ((s save-place-alist) - (count 1)) - (while s - (if (>= count save-place-limit) - (setcdr s nil) - (setq count (1+ count))) - (setq s (cdr s)))))) - - (kill-buffer (current-buffer)))) - nil)))) + ;; If there is a limit, and we're over it, then we'll + ;; have to truncate the end of the list: + (if save-place-limit + (if (<= save-place-limit 0) + ;; Zero gets special cased. I'm not thrilled + ;; with this, but the loop for >= 1 is tight. + (setq save-place-alist nil) + ;; Else the limit is >= 1, so enforce it by + ;; counting and then `setcdr'ing. + (let ((s save-place-alist) + (count 1)) + (while s + (if (>= count save-place-limit) + (setcdr s nil) + (setq count (1+ count))) + (setq s (cdr s)))))))) + (save-place--normalize-alist)))) (defcustom save-place-abbreviate-file-names nil "If non-nil, abbreviate file names before saving them. @@ -154,27 +151,32 @@ just using `setq' may cause out-of-sync problems. You should use either `setopt' or \\[customize-variable] to set this option." :type 'boolean :set (lambda (sym val) - (set-default sym val) - (or save-place-loaded (save-place-load-alist-from-file)) - (let ((fun (if val #'abbreviate-file-name #'expand-file-name)) - ;; Don't expand file names for non-existing remote connections. - (non-essential t)) - (setq save-place-alist - (cl-delete-duplicates - (cl-loop for (k . v) in save-place-alist - collect - (cons (funcall fun k) - (if (listp v) - (cl-loop for (k1 . v1) in v - collect - (cons k1 (funcall fun v1))) - v))) - :key #'car - :from-end t - :test #'equal))) - val) + (let ((old (if (default-boundp sym) (default-value sym)))) + (set-default sym val) + (if (or (equal old val) (not save-place-loaded)) + nil ;Nothing to do. + (save-place--normalize-alist)))) :version "28.1") +(defun save-place--normalize-alist () + (let ((fun (if save-place-abbreviate-file-names + #'abbreviate-file-name #'expand-file-name)) + ;; Don't expand file names for non-existing remote connections. + (non-essential t)) + (setq save-place-alist + (cl-delete-duplicates + (cl-loop for (k . v) in save-place-alist + collect + (cons (funcall fun k) + (if (listp v) + (cl-loop for (k1 . v1) in v + collect + (cons k1 (funcall fun v1))) + v))) + :key #'car + :from-end t + :test #'equal)))) + (defcustom save-place-save-skipped t "If non-nil, remember files matching `save-place-skip-check-regexp'. @@ -273,7 +275,6 @@ Use `setopt' or Customize commands to set this option." This means when you visit a file, point goes to the last place where it was when you previously visited the same file." :global t - :group 'save-place (save-place--setup-hooks save-place-mode) (save-place--manage-timer)) @@ -383,8 +384,7 @@ may have changed) back to `save-place-alist'." (defun save-place-alist-to-file () (let ((file (expand-file-name save-place-file)) (coding-system-for-write 'utf-8)) - (with-current-buffer (get-buffer-create " *Saved Places*") - (delete-region (point-min) (point-max)) + (with-temp-buffer (when save-place-forget-unreadable-files (save-place-forget-unreadable-files)) (insert (format ";;; -*- coding: %s; mode: lisp-data -*-\n" @@ -402,8 +402,7 @@ may have changed) back to `save-place-alist'." (condition-case nil ;; Don't use write-file; we don't want this buffer to visit it. (write-region (point-min) (point-max) file) - (file-error (message "Saving places: can't write %s" file))) - (kill-buffer (current-buffer)))))) + (file-error (message "Saving places: can't write %s" file))))))) (defun save-places-to-alist () ;; go through buffer-list, saving places to alist if save-place-mode From c4a67a405072601b9d7dd95dc94c0b402e1e0ae6 Mon Sep 17 00:00:00 2001 From: Manuel Giraud Date: Mon, 3 Feb 2025 16:57:58 +0100 Subject: [PATCH 065/279] Fix OpenBSD compilation (bug#76009) * configure.ac: Remove a bogus LD_SWITCH_SYSTEM for OpenBSD. --- configure.ac | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 7b4c03c0908..33d04a5bdb9 100644 --- a/configure.ac +++ b/configure.ac @@ -2161,9 +2161,7 @@ case "$opsys" in ;; openbsd) - ## Han Boetes says this is necessary, - ## otherwise Emacs dumps core on elf systems. - LD_SWITCH_SYSTEM="-Z" + : ;; esac AC_SUBST([LD_SWITCH_SYSTEM]) From 73a45ce7206a107695b2b4d9761e249edd7502e9 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Mon, 3 Feb 2025 23:51:15 +0100 Subject: [PATCH 066/279] ; Update link to picons database * lisp/gnus/gnus-art.el (gnus-picon-databases): Fix broken link. --- lisp/gnus/gnus-art.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 218cf319448..eb4263812ea 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -981,11 +981,11 @@ be controlled by `gnus-treat-body-boundary'." "/usr/share/picons") "Defines the location of the faces database. For information on obtaining this database of pretty pictures, please -see http://www.cs.indiana.edu/picons/ftp/index.html" +see https://kinzler.com/ftp/faces/picons/" :version "22.1" :type '(repeat directory) :link '(url-link :tag "download" - "http://www.cs.indiana.edu/picons/ftp/index.html") + "https://kinzler.com/ftp/faces/picons/") :link '(custom-manual "(gnus)Picons") :group 'gnus-picon) From 164da071e07cf162bfe166908dedc82da44ef634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Tue, 4 Feb 2025 12:02:06 +0000 Subject: [PATCH 067/279] Eglot: avoid 'null' as params to 'shutdown' request (bug#66144) Doing so confuses some servers. It used to be needed for the gopls server, but according to https://debbugs.gnu.org/cgi/bugreport.cgi?bug=66144#32 that has been fixed. Thanks to Javier Olaechea * lisp/progmodes/eglot.el (eglot-shutdown): Use eglot--{}. --- lisp/progmodes/eglot.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 4114f21bc75..4a174d5db5c 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1246,7 +1246,7 @@ SERVER." (unwind-protect (progn (setf (eglot--shutdown-requested server) t) - (eglot--request server :shutdown nil :timeout (or timeout 1.5)) + (eglot--request server :shutdown eglot--{} :timeout (or timeout 1.5)) (jsonrpc-notify server :exit nil)) ;; Now ask jsonrpc.el to shut down the server. (jsonrpc-shutdown server (not preserve-buffers)) From 40e38a681dafb02f71d741338e9c3c5ff99c734e Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 4 Feb 2025 14:18:38 +0200 Subject: [PATCH 068/279] ; * test/src/editfns-tests.el (editfns-tests-styled-print): New test. --- test/src/editfns-tests.el | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 9fff4255b57..b18111ad119 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -534,4 +534,15 @@ 'utf-8 nil (current-buffer)) (should (null (sanity-check-change-functions-errors)))))) +(ert-deftest editfns-tests-styled-print () + "Test bug#75754." + :expected-result :failed + (let* ((print-unreadable-function + (lambda (&rest _args) + (garbage-collect) + (make-string 100 ?Ā t))) + (str "\"[1] ĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀĀ\"")) + (should (string= (format "%S" (format "%S %S" [1] (symbol-function '+))) + str)))) + ;;; editfns-tests.el ends here From 9597881592049509d62f91139316ac0eba2fb19d Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 4 Feb 2025 14:09:52 +0100 Subject: [PATCH 069/279] Add inhibit-auto-revert macro * doc/lispref/backups.texi (Reverting): Add inhibit-auto-revert-buffers and inhibit-auto-revert. * etc/NEWS: Add inhibit-auto-revert-buffers and inhibit-auto-revert. Fix typos. * lisp/autorevert.el (inhibit-auto-revert-buffers): New variable. (inhibit-auto-revert): New macro. (auto-revert-active-p, auto-revert-handler): Check `inhibit-auto-revert-buffers'. * lisp/dired.el (dired--inhibit-auto-revert): Remove. (dired-buffer-stale-p): Don't set it. (dired-map-over-marks, dired-internal-do-deletions): Use `inhibit-auto-revert. * test/lisp/autorevert-tests.el (auto-revert-test08-auto-revert-inhibit-auto-revert) (auto-revert-test08-auto-revert-inhibit-auto-revert-remote): New tests. --- doc/lispref/backups.texi | 24 ++++++ etc/NEWS | 91 +++++++++++++---------- lisp/autorevert.el | 47 +++++++++--- lisp/dired.el | 133 ++++++++++++++++------------------ test/lisp/autorevert-tests.el | 35 +++++++++ 5 files changed, 210 insertions(+), 120 deletions(-) diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi index 50c7ace253c..f3f0902f364 100644 --- a/doc/lispref/backups.texi +++ b/doc/lispref/backups.texi @@ -852,6 +852,30 @@ It is important to assure that point does not continuously jump around as a consequence of auto-reverting. Of course, moving point might be inevitable if the buffer radically changes. +@defvar inhibit-auto-revert-buffers +When the current buffer is member of this variable (a list of buffers), +auto-reverting is suppressed for that buffer. This is useful if serious +changes are applied to that buffer which would be poisoned by an +unexpected auto-revert. After the change is finished, the buffer shall +be removed from @code{inhibit-auto-revert-buffers}. + +The check of membership in @code{inhibit-auto-revert-buffers} is applied +prior to the call of @code{buffer-stale-function}; any heavy check in +that function is avoided, therefore. + +If auto-reverting is triggered by file notification while +@code{inhibit-auto-revert-buffers} prevents this, auto-revert will +happen next time the buffer is polled for changes, unless +@code{auto-revert-avoid-polling} is non-@code{nil}. @pxref{(emacs) Auto +Revert}. +@end defvar + +@defmac inhibit-auto-revert &rest body +This macro adds the current buffer to +@code{inhibit-auto-revert-buffers}, runs @var{body}, and removes the +current buffer from @code{inhibit-auto-revert-buffers} afterwards. +@end defmac + You should make sure that the @code{revert-buffer-function} does not print messages that unnecessarily duplicate Auto Revert's own messages, displayed if @code{auto-revert-verbose} is @code{t}, and effectively diff --git a/etc/NEWS b/etc/NEWS index 8cf86d1375d..2464598c6d1 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -41,12 +41,12 @@ incorrectly in rare cases. ** In compatible terminals, 'xterm-mouse-mode' is turned on by default. For these terminals the mouse will work by default. A compatible -terminal is one that supports Emacs seting and getting the OS selection +terminal is one that supports Emacs setting and getting the OS selection data (a.k.a. the clipboard) and mouse button and motion events. With -xterm-mouse-mode enabled, you must use Emacs keybindings to copy to the +'xterm-mouse-mode' enabled, you must use Emacs keybindings to copy to the OS selection instead of terminal-specific keybindings. -You can keep the old behavior by putting `(xterm-mouse-mode -1)' in your +You can keep the old behavior by putting '(xterm-mouse-mode -1)' in your init file. @@ -75,7 +75,7 @@ In particular: To enable tooltips on TTY frames, call 'tty-tip-mode'. The presence of child frame support on TTY frames can be checked with -`(featurep 'tty-child-frames)'. +'(featurep 'tty-child-frames)'. Recent versions of Posframe and Corfu are known to use child frames on TTYs if they are supported. @@ -108,7 +108,7 @@ instead of its now-obsolete variable. ** Network Security Manager (NSM) is now more strict. *** NSM warns about TLS 1.1 by default. -It has been deprecated by RFC8996, published in 2021. +It has been deprecated by RFC 8996, published in 2021. *** NSM warns about DHE and RSA key exchange by default. Emacs now warns about ephemeral Diffie-Hellman key exchange, and static @@ -181,13 +181,9 @@ the "*Completions*" buffer is hidden. +++ *** New functions to modify window layout. Several functions to modify the window layout have been added: -'rotate-window-layout-clockwise' -'rotate-window-layout-anticlockwise' -'flip-window-layout-vertically' -'flip-window-layout-horizontally' -'transpose-window-layout' -'rotate-windows' -'rotate-windows-back' +'rotate-window-layout-clockwise', 'rotate-window-layout-anticlockwise', +'flip-window-layout-vertically', 'flip-window-layout-horizontally', +'transpose-window-layout', 'rotate-windows', and 'rotate-windows-back'. +++ *** New hook 'window-deletable-functions'. @@ -254,11 +250,11 @@ adjustment when a tab is restored, and avoids advice. *** New user option 'tab-bar-define-keys'. This controls which key bindings tab-bar creates. Values are t, the default, which defines all keys and is backwards compatible, 'numeric' -(tab number selection only), 'tab' (TAB and SHIFT-TAB keys only), nil +(tab number selection only), 'tab' ('TAB' and 'S-TAB' keys only), nil (which defines none). This is useful to avoid key binding conflicts, such as when folding in -outline mode using TAB keys, or when a user wants to define her own +outline mode using 'TAB' keys, or when a user wants to define her own tab-bar keys without first having to remove the defaults. --- @@ -386,13 +382,15 @@ modal editing packages. --- ** ASM mode + *** 'asm-mode-set-comment-hook' is obsolete. You can now set `asm-comment-char' from 'asm-mode-hook' instead. --- ** Ibuffer + *** New column 'recency' in Ibuffer display. -The variable 'ibuffer-formats' configures the Ibuffer formats. Add +The user option 'ibuffer-formats' configures the Ibuffer formats. Add 'recency' to the format to display the column. *** New value 'title' for the user option 'ibuffer-use-header-line'. @@ -404,11 +402,13 @@ When non-nil, buffer sizes are shown in human readable format. --- ** Buffer Menu + *** New user option 'Buffer-menu-human-readable-sizes'. When non-nil, buffer sizes are shown in human readable format. The default is nil, which retains the old format. ** Smerge + *** New command 'smerge-extend' extends a conflict over surrounding lines. ** Image Dired @@ -430,7 +430,7 @@ a web browser to load them. For example, it could be used like this: For better integration with the Qutebrowser, set 'browse-url(-secondary)-browser-function' to 'browse-url-qutebrowser'. -*** New GTK-native launch mode +*** New GTK-native launch mode. For better Wayland support, the pgtk toolkit exposes a new 'x-gtk-launch-uri' browse-url handler and uses it by default when URLs are browsed from a PGTK frame. For other frames, we fall back to the @@ -469,16 +469,15 @@ compatible. --- *** You can now regularly auto-save places. -Customize 'save-place-autosave-interval' to the number of seconds -between auto saving places. For example, to save places every 5 +Customize user option 'save-place-autosave-interval' to the number of +seconds between auto saving places. For example, to save places every 5 minutes: - M-x customize-option RET save-place-autosave-interval RET and set to - 300 seconds. + M-x customize-option RET save-place-autosave-interval RET 300 -Or in elisp: +Or in Elisp: - (setopt save-place-autosave-interval (* 60 5)) + (setopt save-place-autosave-interval (* 60 5)) If 'save-place-autosave-interval' is nil, auto saving is disabled; this is the default. As before, saved places are scheduled to be saved at @@ -680,7 +679,6 @@ build tags for the test commands. The 'go-ts-mode-test-flags' user option is available to set a list of additional flags to pass to the go test command line. - ** C-ts mode +++ @@ -901,13 +899,13 @@ the 'grep' results editable. The edits will be reflected in the buffer visiting the originating file. Typing 'C-c C-c' will leave the Grep Edit mode. -** time-stamp +** Time Stamp --- *** 'time-stamp' can up-case, capitalize and down-case date words. This control can be useful in languages in which days of the week and/or month names are capitalized only at the beginning of a sentence. For -details, see the built-in documentation for variable 'time-stamp-format'. +details, see the built-in documentation for user option 'time-stamp-format'. Because this feature is new in Emacs 31.1, do not use it in the local variables section of any file that might be edited by an older version @@ -915,12 +913,12 @@ of Emacs. --- *** Some historical 'time-stamp' conversions now warn. -'time-stamp-pattern' and 'time-stamp-format' had quietly -accepted several 'time-stamp' conversions (e.g., "%:y") that -have been deprecated since Emacs 27.1 (released in 2020). -These now generate a warning with a suggested migration. +'time-stamp-pattern' and 'time-stamp-format' had quietly accepted +several 'time-stamp' conversions (e.g., "%:y") that have been deprecated +since Emacs 27.1. These now generate a warning with a suggested +migration. -Merely having "(add-hook 'before-save-hook 'time-stamp)" +Merely having '(add-hook 'before-save-hook 'time-stamp)' in your Emacs init file does not expose you to this change. However, if you set 'time-stamp-format' or 'time-stamp-pattern' with a file-local variable, you may be asked to update the value. @@ -1076,6 +1074,19 @@ destination window is chosen using 'display-buffer-alist'. Example: display-buffer-use-some-window) (some-window . mru)))) +** Autorevert + ++++ +*** New variable 'inhibit-auto-revert-buffers'. +While a buffer is member of this variable, a list of buffers, +auto-reverting of this buffer is suppressed. + ++++ +*** New macro 'inhibit-auto-revert'. +This macro adds the current buffer to 'inhibit-auto-revert-buffers', +runs its body, and removes the current buffer from +'inhibit-auto-revert-buffers' afterwards. + * New Modes and Packages in Emacs 31.1 @@ -1085,7 +1096,7 @@ destination window is chosen using 'display-buffer-alist'. Example: ** Nested backquotes are not supported any more in Pcase patterns. --- -** The obsolete variable `redisplay-dont-pause' has been removed. +** The obsolete variable 'redisplay-dont-pause' has been removed. ** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. An old alternative name (without the first 'e') has been removed. @@ -1161,7 +1172,7 @@ authorize the invoked D-Bus method (for example via polkit). ** The customization group 'wp' has been removed. It has been obsolete since Emacs 26.1. Use the group 'text' instead. -** Changes in tree-sitter modes. +** Changes in tree-sitter modes +++ *** Indirect buffers can have their own parser list. @@ -1186,7 +1197,7 @@ override flag by 'treesit-font-lock-setting-query', 'treesit-font-lock-setting-feature', 'treesit-font-lock-setting-enable', and 'treesit-font-lock-setting-override'. -*** New treesit thing 'list'. +*** New tree-sitter thing 'list'. Unlike the existing thing 'sexp' that defines both lists and atoms, 'list' defines only lists to be navigated by 'forward-sexp'. The new function 'treesit-forward-sexp-list' uses 'list' @@ -1209,9 +1220,9 @@ used to communicate the tree-sitter parsing results to *** Tree-sitter enabled modes now properly support 'hs-minor-mode'. All commands from hideshow.el can selectively display blocks -defined by the new treesit thing 'list'. +defined by the new tree-sitter thing 'list'. -*** New treesit thing 'comment'. +*** New tree-sitter thing 'comment'. The new variable 'forward-comment-function' is set to the new function 'treesit-forward-comment' if a major mode defines the thing 'comment'. @@ -1223,26 +1234,26 @@ variable 'treesit-language-display-name-alist' holds the translations of language symbols where that translation is not trivial. +++ -*** New command 'treesit-explore' +*** New command 'treesit-explore'. This command replaces 'treesit-explore-mode'. It turns on 'treesit-explore-mode' if it’s not on, and pops up the explorer buffer if it’s already on. +++ -*** 'treesit-explore-mode' now supports local parsers +*** 'treesit-explore-mode' now supports local parsers. Now 'treesit-explore-mode' (or 'treesit-explore') prompts for a parser rather than a language, and it’s now possible to select a local parser at point to explore. +++ -*** New variable 'treesit-aggregated-simple-imenu-settings' +*** New variable 'treesit-aggregated-simple-imenu-settings'. This variable allows major modes to setup Imenu for multiple languages. -*** New function 'treesit-add-simple-indent-rules' +*** New function 'treesit-add-simple-indent-rules'. This new function makes it easier to customize indent rules for tree-sitter modes. -*** New variable 'treesit-simple-indent-override-rules' +*** New variable 'treesit-simple-indent-override-rules'. Users can customize this variable to add simple custom indentation rules for tree-sitter major modes. diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 1dcfe8e911f..b6dd9fb9015 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -772,11 +772,37 @@ If the buffer needs to be reverted, do it now." (when auto-revert-notify-modified-p (auto-revert-handler))))) +;;;###autoload +(progn + (defvar inhibit-auto-revert-buffers nil + "A list of buffers with suppressed auto-revert.") + + (defmacro inhibit-auto-revert (&rest body) + "Deactivate auto-reverting of current buffer temporarily. +Run BODY." + (declare (indent 0) (debug ((form body) body))) + `(progn + ;; Cleanup. + (dolist (buf inhibit-auto-revert-buffers) + (unless (buffer-live-p buf) + (setq inhibit-auto-revert-buffers + (delq buf inhibit-auto-revert-buffers)))) + (let ((buf (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (current-buffer)))) + (unwind-protect + (progn + (when buf (add-to-list 'inhibit-auto-revert-buffers buf)) + ,@body) + (when buf + (setq inhibit-auto-revert-buffers + (delq buf inhibit-auto-revert-buffers)))))))) + (defun auto-revert-active-p () "Check if auto-revert is active in current buffer." - (or auto-revert-mode - auto-revert-tail-mode - auto-revert--global-mode)) + (and (or auto-revert-mode + auto-revert-tail-mode + auto-revert--global-mode) + (not (memq (current-buffer) inhibit-auto-revert-buffers)))) (defun auto-revert-handler () "Revert current buffer, if appropriate. @@ -798,14 +824,17 @@ This is an internal function used by Auto-Revert Mode." (setq size (file-attribute-size (file-attributes buffer-file-name))))) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t))) + (and (not (memq (current-buffer) + inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t)))) (and (or auto-revert-mode global-auto-revert-non-file-buffers) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t)))) + (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t))))) eob eoblist) (setq auto-revert-notify-modified-p nil auto-revert--last-time (current-time)) diff --git a/lisp/dired.el b/lisp/dired.el index 2eb6546107a..91163186443 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -944,9 +944,6 @@ Return value is the number of files marked, or nil if none were marked." "")))) (and (> count 0) count))) -(defvar-local dired--inhibit-auto-revert nil - "A non-nil value prevents `auto-revert-mode' from reverting the buffer.") - (defmacro dired-map-over-marks (body arg &optional show-progress distinguish-one-marked) "Eval BODY with point on each marked line. Return a list of BODY's results. @@ -983,48 +980,48 @@ marked file, return (t FILENAME) instead of (FILENAME)." ;;endless loop. ;;This warning should not apply any longer, sk 2-Sep-1991 14:10. `(prog1 - (let ((dired--inhibit-auto-revert t) - (inhibit-read-only t) - case-fold-search found results) - (if (and ,arg (not (eq ,arg 'marked))) - (if (integerp ,arg) - (progn ;; no save-excursion, want to move point. - (dired-repeat-over-lines - ,arg - (lambda () - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results)))) - (when (< ,arg 0) - (setq results (nreverse results))) - results) - ;; non-nil, non-integer, non-marked ARG means use current file: - (list ,body)) - (let ((regexp (dired-marker-regexp)) next-position) - (save-excursion - (goto-char (point-min)) - ;; remember position of next marked file before BODY - ;; can insert lines before the just found file, - ;; confusing us by finding the same marked file again - ;; and again and... - (setq next-position (and (re-search-forward regexp nil t) - (point-marker)) - found (not (null next-position))) - (while next-position - (goto-char next-position) - (if ,show-progress (sit-for 0)) - (setq results (cons ,body results)) - ;; move after last match - (goto-char next-position) - (forward-line 1) - (set-marker next-position nil) - (setq next-position (and (re-search-forward regexp nil t) - (point-marker))))) - (if (and ,distinguish-one-marked (= (length results) 1)) - (setq results (cons t results))) - (if found - results - (unless (eq ,arg 'marked) - (list ,body)))))) + (inhibit-auto-revert + (let ((inhibit-read-only t) + case-fold-search found results) + (if (and ,arg (not (eq ,arg 'marked))) + (if (integerp ,arg) + (progn ;; no save-excursion, want to move point. + (dired-repeat-over-lines + ,arg + (lambda () + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)))) + (when (< ,arg 0) + (setq results (nreverse results))) + results) + ;; non-nil, non-integer, non-marked ARG means use current file: + (list ,body)) + (let ((regexp (dired-marker-regexp)) next-position) + (save-excursion + (goto-char (point-min)) + ;; remember position of next marked file before BODY + ;; can insert lines before the just found file, + ;; confusing us by finding the same marked file again + ;; and again and... + (setq next-position (and (re-search-forward regexp nil t) + (point-marker)) + found (not (null next-position))) + (while next-position + (goto-char next-position) + (if ,show-progress (sit-for 0)) + (setq results (cons ,body results)) + ;; move after last match + (goto-char next-position) + (forward-line 1) + (set-marker next-position nil) + (setq next-position (and (re-search-forward regexp nil t) + (point-marker))))) + (if (and ,distinguish-one-marked (= (length results) 1)) + (setq results (cons t results))) + (if found + results + (unless (eq ,arg 'marked) + (list ,body))))))) ;; save-excursion loses, again (dired-move-to-filename))) @@ -1294,12 +1291,6 @@ This feature is used by Auto Revert mode." ;; Do not auto-revert when the dired buffer can be currently ;; written by the user as in `wdired-mode'. buffer-read-only - ;; When a dired operation using dired-map-over-marks is in - ;; progress, dired--inhibit-auto-revert is bound to some - ;; non-nil value and we must not auto-revert because that could - ;; change the order of files leading to skipping or - ;; double-processing (see bug#75626). - (not dired--inhibit-auto-revert) (dired-directory-changed-p dirname)))) (defcustom dired-auto-revert-buffer nil @@ -4089,26 +4080,26 @@ non-empty directories is allowed." (while l (goto-char (marker-position (cdr (car l)))) (dired-move-to-filename) - (let ((inhibit-read-only t) - ;; Temporarily prevent auto-revert while deleting - ;; entry in the dired buffer (bug#71264). - (dired--inhibit-auto-revert t)) - (condition-case err - (let ((fn (car (car l)))) - (dired-delete-file fn dired-recursive-deletes trash) - ;; if we get here, removing worked - (setq succ (1+ succ)) - (progress-reporter-update progress-reporter succ) - (dired-fun-in-all-buffers - (file-name-directory fn) (file-name-nondirectory fn) - #'dired-delete-entry fn) - ;; For when FN's directory name is different - ;; from the current buffer's dired-directory. - (dired-delete-entry fn)) - (quit (throw '--delete-cancel (message "OK, canceled"))) - (error ;; catch errors from failed deletions - (dired-log "%s: %s\n" (car err) (error-message-string err)) - (setq failures (cons (car (car l)) failures))))) + ;; Temporarily prevent auto-revert while deleting entry in + ;; the dired buffer (bug#71264). + (inhibit-auto-revert + (let ((inhibit-read-only t)) + (condition-case err + (let ((fn (car (car l)))) + (dired-delete-file fn dired-recursive-deletes trash) + ;; if we get here, removing worked + (setq succ (1+ succ)) + (progress-reporter-update progress-reporter succ) + (dired-fun-in-all-buffers + (file-name-directory fn) (file-name-nondirectory fn) + #'dired-delete-entry fn) + ;; For when FN's directory name is different + ;; from the current buffer's dired-directory. + (dired-delete-entry fn)) + (quit (throw '--delete-cancel (message "OK, canceled"))) + (error ;; catch errors from failed deletions + (dired-log "%s: %s\n" (car err) (error-message-string err)) + (setq failures (cons (car (car l)) failures)))))) (setq l (cdr l))) (if (not failures) (progress-reporter-done progress-reporter) diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el index 5e46216cc42..319f3285d2d 100644 --- a/test/lisp/autorevert-tests.el +++ b/test/lisp/autorevert-tests.el @@ -687,6 +687,41 @@ This expects `auto-revert--messages' to be bound by (auto-revert--deftest-remote auto-revert-test07-auto-revert-several-buffers "Check autorevert for several buffers visiting the same remote file.") +(ert-deftest auto-revert-test08-auto-revert-inhibit-auto-revert () + "Check the power of `inhibit-auto-revert'." + ;; `auto-revert-buffers' runs every 5". And we must wait, until the + ;; file has been reverted. + (with-auto-revert-test + (ert-with-temp-file tmpfile + (let ((times '(60 30 15)) + buf) + (unwind-protect + (progn + (auto-revert-tests--write-file "any text" tmpfile (pop times)) + (setq buf (find-file-noselect tmpfile)) + (with-current-buffer buf + (ert-with-message-capture auto-revert--messages + (inhibit-auto-revert + (auto-revert-mode 1) + (should auto-revert-mode) + + (auto-revert-tests--write-file "another text" tmpfile (pop times)) + ;; Check, that the buffer hasn't been reverted. + (auto-revert--wait-for-revert buf) + (should-not (string-match "another text" (buffer-string)))) + + ;; Check, that the buffer has been reverted. + (auto-revert--wait-for-revert buf) + (should (string-match "another text" (buffer-string)))))) + + ;; Exit. + (ignore-errors + (with-current-buffer buf (set-buffer-modified-p nil)) + (kill-buffer buf))))))) + +(auto-revert--deftest-remote auto-revert-test08-auto-revert-inhibit-auto-revert + "Check the power of `inhibit-auto-revert' on a remote file.") + ;; Mark all tests as unstable on Cygwin (bug#49665). (when (eq system-type 'cygwin) (dolist (test (apropos-internal "^auto-revert" #'ert-test-boundp)) From 2eb6171ec96eac0c78cf20b3003fcbcb1206c8c7 Mon Sep 17 00:00:00 2001 From: Andrew G Cohen Date: Wed, 5 Jul 2023 15:21:16 +0800 Subject: [PATCH 070/279] Don't use obsolete In-Reply-To format in messages (Bug#64454) When creating a new message, message-send-mail uses an obsolete format for the In-Reply-To header that includes additional information about the originating message. This patch changes the default to use the rfc5322 approved format, but allow the obsolete format through a defcustom. * lisp/gnus/message.el (message-make-in-reply-to): Return only the message-id of the originating message (the default) unless the new custom variable message-header-use-obsolete-in-reply-to is non-nil. * doc/misc/message.texi: Document the new custom variable message-header-use-obsolete-in-reply-to. * etc/NEWS: Update NEWS. --- doc/misc/message.texi | 6 ++++ etc/NEWS | 10 +++++++ lisp/gnus/message.el | 66 +++++++++++++++++++++++++------------------ 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/doc/misc/message.texi b/doc/misc/message.texi index bd20aec5bc6..509bbd5b575 100644 --- a/doc/misc/message.texi +++ b/doc/misc/message.texi @@ -1791,6 +1791,12 @@ member list with elements @code{CC} and @code{To}, then @code{message-carefully-insert-headers} will not insert a @code{To} header when the message is already @code{CC}ed to the recipient. +@item message-header-use-obsolete-in-reply-to +@vindex message-header-use-obsolete-in-reply-to +When non-@code{nil}, use an obsolete form of the @code{In-Reply-To} +header that includes a parenthetical phrase with details of the +originating email following the message id. The default is @code{nil}. + @item message-syntax-checks @vindex message-syntax-checks Controls what syntax checks should not be performed on outgoing posts. diff --git a/etc/NEWS b/etc/NEWS index 8cf86d1375d..2e5022b4955 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -484,6 +484,16 @@ If 'save-place-autosave-interval' is nil, auto saving is disabled; this is the default. As before, saved places are scheduled to be saved at Emacs exit. +** Message + +--- +*** In-Reply-To header contains only a message id. +The In-Reply-To header created when replying to a message now contains +only the originating message's id, conforming to RFC5322. The previous +behavior included additional information about the originating message. +The new variable 'message-header-use-obsolete-in-reply-to', nil by +default, can be set to a non-nil value to restore the previous behavior. + ** Gnus --- diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index b552b211eb8..7a84d6366db 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -113,6 +113,13 @@ :group 'message :group 'faces) +(defcustom message-header-use-obsolete-in-reply-to nil + "Include extra information in the In-Reply-To header. +This form has been obsolete since RFC 2822." + :group 'message-headers + :version "31.1" + :type 'boolean) + (defcustom message-directory "~/Mail/" "Directory from which all other mail file variables are derived." :group 'message-various @@ -5993,35 +6000,38 @@ In posting styles use `(\"Expires\" (make-expires-date 30))'." "Return the In-Reply-To header for this message." (when message-reply-headers (let ((from (mail-header-from message-reply-headers)) - (date (mail-header-date message-reply-headers)) - (msg-id (mail-header-id message-reply-headers))) + (date (mail-header-date message-reply-headers)) + (msg-id (mail-header-id message-reply-headers))) (when from - (let ((name (mail-extract-address-components from))) - (concat - msg-id (if msg-id " (") - (if (car name) - (if (string-match "[^[:ascii:]]" (car name)) - ;; Quote a string containing non-ASCII characters. - ;; It will make the RFC2047 encoder cause an error - ;; if there are special characters. - (mm-with-multibyte-buffer - (insert (car name)) - (goto-char (point-min)) - (while (search-forward "\"" nil t) - (when (prog2 - (backward-char) - (zerop (% (skip-chars-backward "\\\\") 2)) - (goto-char (match-beginning 0))) - (insert "\\")) - (forward-char)) - ;; Those quotes will be removed by the RFC2047 encoder. - (concat "\"" (buffer-string) "\"")) - (car name)) - (nth 1 name)) - "'s message of \"" - (if (or (not date) (string= date "")) - "(unknown date)" date) - "\"" (if msg-id ")"))))))) + (let ((name (mail-extract-address-components from))) + (concat + msg-id + (when message-header-use-obsolete-in-reply-to + (concat + (if msg-id " (") + (if (car name) + (if (string-match "[^[:ascii:]]" (car name)) + ;; Quote a string containing non-ASCII characters. + ;; It will make the RFC2047 encoder cause an error + ;; if there are special characters. + (mm-with-multibyte-buffer + (insert (car name)) + (goto-char (point-min)) + (while (search-forward "\"" nil t) + (when (prog2 + (backward-char) + (zerop (% (skip-chars-backward "\\\\") 2)) + (goto-char (match-beginning 0))) + (insert "\\")) + (forward-char)) + ;; Those quotes will be removed by the RFC2047 encoder. + (concat "\"" (buffer-string) "\"")) + (car name)) + (nth 1 name)) + "'s message of \"" + (if (or (not date) (string= date "")) + "(unknown date)" date) + "\"" (if msg-id ")"))))))))) (defun message-make-distribution () "Make a Distribution header." From 2b1c25e62b3ff1718cfebda9d0e6b670c903b4cd Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 4 Feb 2025 14:32:46 +0100 Subject: [PATCH 071/279] Fix some checks in autorevert.el * lisp/autorevert.el (auto-revert-handler): Rework checks. (auto-revert-handler): Don't run `vc-refresh-state' in `auto-revert-tail-mode'. --- lisp/autorevert.el | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index b6dd9fb9015..ddb116bb828 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -818,23 +818,22 @@ This is an internal function used by Auto-Revert Mode." (not (file-remote-p buffer-file-name))) (or (not auto-revert-notify-watch-descriptor) auto-revert-notify-modified-p) + (not (memq (current-buffer) inhibit-auto-revert-buffers)) (if auto-revert-tail-mode (and (file-readable-p buffer-file-name) (/= auto-revert-tail-pos (setq size (file-attribute-size (file-attributes buffer-file-name))))) - (and (not (memq (current-buffer) - inhibit-auto-revert-buffers)) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t)))) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t))) (and (or auto-revert-mode global-auto-revert-non-file-buffers) - (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) - (funcall (or buffer-stale-function - #'buffer-stale--default-function) - t))))) + (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (funcall (or buffer-stale-function + #'buffer-stale--default-function) + t)))) eob eoblist) (setq auto-revert-notify-modified-p nil auto-revert--last-time (current-time)) @@ -869,7 +868,7 @@ This is an internal function used by Auto-Revert Mode." (set-window-point window (point-max))))) ;; `preserve-modes' avoids changing the (minor) modes. But we do ;; want to reset the mode for VC, so we do it manually. - (when (or revert auto-revert-check-vc-info) + (when (and (not auto-revert-tail-mode) (or revert auto-revert-check-vc-info)) (let ((revert-buffer-in-progress-p t)) (vc-refresh-state))))) From 4212b2630f7a9d754810c8c9641e766534b44098 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 4 Feb 2025 16:01:47 +0200 Subject: [PATCH 072/279] ; * test/src/editfns-tests.el (editfns-tests-styled-print): Fix last change. --- test/src/editfns-tests.el | 1 - 1 file changed, 1 deletion(-) diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index b18111ad119..8d4e7bc48fa 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -536,7 +536,6 @@ (ert-deftest editfns-tests-styled-print () "Test bug#75754." - :expected-result :failed (let* ((print-unreadable-function (lambda (&rest _args) (garbage-collect) From 5c36b4126533764bb8b90413f274d766e1a6f0d6 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 4 Feb 2025 16:06:36 +0200 Subject: [PATCH 073/279] * src/fileio.c (Fsubstitute_in_file_name): Doc fix (bug#76023). --- src/fileio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fileio.c b/src/fileio.c index e522dd93cd6..7042dbca258 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2050,7 +2050,9 @@ the value of this function. If `/~' appears, all of FILENAME through that `/' is discarded. If `//' appears, everything up to and including the first of -those `/' is discarded. */) +those `/' is discarded. More generally, if a variable substitution +produces an absolute file name, everything before that file name +is discarded. */) (Lisp_Object filename) { char *nm, *p, *x, *endp; From 1e01ae335dda0ebcbca71c50c066a3072dd9d022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= Date: Mon, 27 Jan 2025 08:58:30 +0100 Subject: [PATCH 074/279] Use read-key in read-multiple-choice (bug#75886) * lisp/emacs-lisp/rmc.el (read-multiple-choice--short-answers): Use read-key instead of read-event because read-event doesn't use input-decode-map. * test/lisp/emacs-lisp/rmc-tests.el: Use read-key instead of read-event. --- lisp/emacs-lisp/rmc.el | 10 ++++++++-- test/lisp/emacs-lisp/rmc-tests.el | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el index 27e5d6c612b..c4df8cf2f98 100644 --- a/lisp/emacs-lisp/rmc.el +++ b/lisp/emacs-lisp/rmc.el @@ -216,8 +216,14 @@ Usage example: (car elem))) prompt-choices))) (condition-case nil - (let ((cursor-in-echo-area t)) - (read-event)) + (let ((cursor-in-echo-area t) + ;; Do NOT use read-event here. That + ;; function does not consult + ;; input-decode-map (bug#75886). + (key (read-key))) + (when (eq key ?\C-g) + (signal 'quit nil)) + key) (error nil)))) (if (memq (car-safe tchar) '(touchscreen-begin touchscreen-end diff --git a/test/lisp/emacs-lisp/rmc-tests.el b/test/lisp/emacs-lisp/rmc-tests.el index 1bc8c90cad6..0237bc3f9e5 100644 --- a/test/lisp/emacs-lisp/rmc-tests.el +++ b/test/lisp/emacs-lisp/rmc-tests.el @@ -61,7 +61,7 @@ (ert-deftest test-read-multiple-choice () (dolist (char '(?y ?n)) - (cl-letf* (((symbol-function #'read-event) (lambda () char)) + (cl-letf* (((symbol-function #'read-key) (lambda () char)) (str (if (eq char ?y) "yes" "no"))) (should (equal (list char str) (read-multiple-choice "Do it? " '((?y "yes") (?n "no")))))))) @@ -69,7 +69,7 @@ (ert-deftest test-read-multiple-choice-help () (let ((chars '(?o ?a)) help) - (cl-letf* (((symbol-function #'read-event) + (cl-letf* (((symbol-function #'read-key) (lambda () (message "chars %S" chars) (when (= 1 (length chars)) From f9a1f449d9cbe57f7312a5327d08e28e71c16882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= Date: Tue, 4 Feb 2025 06:09:52 +0100 Subject: [PATCH 075/279] Fix min-width display spec handling (bug#76014) * src/xdisp.c (display_min_width): Take into account that the output may already be longer than the specified min-width. --- src/xdisp.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index 36e82f873ab..804a19e048f 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5646,7 +5646,7 @@ get_display_property (ptrdiff_t charpos, Lisp_Object prop, Lisp_Object object) /* Handle 'display' property '(min-width (WIDTH))' at CHARPOS in OBJECT. OBJECT can be a buffer (or nil, which means the current buffer) or a - string. MIN_WIDTH is the value of min-width spec that we expect to + string. WIDTH_SPEC is the value of min-width spec that we expect to process. */ static void display_min_width (struct it *it, ptrdiff_t charpos, @@ -5692,8 +5692,9 @@ display_min_width (struct it *it, ptrdiff_t charpos, a stretch that ends beyond the visible portion of the window if we are truncating screen lines. If we are requested to do that, some Lisp program went awry. */ - if (!(it->line_wrap == TRUNCATE - && it->current_x + width > it->last_visible_x)) + if (width > 0 + && !(it->line_wrap == TRUNCATE + && it->current_x + width > it->last_visible_x)) w = list1 (make_int (width)); } else @@ -5704,8 +5705,9 @@ display_min_width (struct it *it, ptrdiff_t charpos, NULL, true, NULL); width -= (it->current_x - it->min_width_start) / FRAME_COLUMN_WIDTH (it->f); - if (!(it->line_wrap == TRUNCATE - && it->current_x + width > it->last_visible_x)) + if (width > 0 + && !(it->line_wrap == TRUNCATE + && it->current_x + width > it->last_visible_x)) w = make_int (width); } From b685b21a33423018f3da7695919a4d1b1ef2c9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Tue, 4 Feb 2025 14:43:48 +0000 Subject: [PATCH 076/279] Eglot: protect against nil jit-lock-context-unfontify-pos * lisp/progmodes/eglot.el (eglot-shutdown, eglot--update-hints): Rework. Github-reference: https://github.com/joaotavora/eglot/pull/1370 --- lisp/progmodes/eglot.el | 70 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 4a174d5db5c..7b1c174c4d7 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -4247,47 +4247,47 @@ If NOERROR, return predicate, else erroring function." (defvar-local eglot--outstanding-inlay-regions-timer nil "Helper timer for `eglot--update-hints'.") -(defun eglot--update-hints (from to) +(cl-defun eglot--update-hints (from to) "Jit-lock function for Eglot inlay hints." + ;; XXX: We're relying on knowledge of jit-lock internals here. + ;; Comparing `jit-lock-context-unfontify-pos' (if non-nil) to + ;; `point-max' tells us whether this call to `jit-lock-functions' + ;; happens after `jit-lock-context-timer' has just run. + (when (and jit-lock-context-unfontify-pos + (/= jit-lock-context-unfontify-pos (point-max))) + (cl-return-from eglot--update-hints)) (cl-symbol-macrolet ((region eglot--outstanding-inlay-hints-region) (last-region eglot--outstanding-inlay-hints-last-region) (timer eglot--outstanding-inlay-regions-timer)) (setcar region (min (or (car region) (point-max)) from)) (setcdr region (max (or (cdr region) (point-min)) to)) - ;; HACK: We're relying on knowledge of jit-lock internals here. The - ;; condition comparing `jit-lock-context-unfontify-pos' to - ;; `point-max' is a heuristic for telling whether this call to - ;; `jit-lock-functions' happens after `jit-lock-context-timer' has - ;; just run. Only after this delay should we start the smoothing - ;; timer that will eventually call `eglot--update-hints-1' with the - ;; coalesced region. I wish we didn't need the timer, but sometimes - ;; a lot of "non-contextual" calls come in all at once and do verify - ;; the condition. Notice it is a 0 second timer though, so we're - ;; not introducing any more delay over jit-lock's timers. - (when (= jit-lock-context-unfontify-pos (point-max)) - (if timer (cancel-timer timer)) - (let ((buf (current-buffer))) - (setq timer (run-at-time - 0 nil - (lambda () - (eglot--when-live-buffer buf - ;; HACK: In some pathological situations - ;; (Emacs's own coding.c, for example), - ;; jit-lock is calling `eglot--update-hints' - ;; repeatedly with same sequence of - ;; arguments, which leads to - ;; `eglot--update-hints-1' being called with - ;; the same region repeatedly. This happens - ;; even if the hint-painting code does - ;; nothing else other than widen, narrow, - ;; move point then restore these things. - ;; Possible Emacs bug, but this fixes it. - (unless (equal last-region region) - (eglot--update-hints-1 (max (car region) (point-min)) - (min (cdr region) (point-max))) - (setq last-region region)) - (setq region (cons nil nil) - timer nil))))))))) + ;; XXX: Then there is a smoothing timer. I wish we didn't need it, + ;; but sometimes a lot of calls come in all at once and do make it + ;; past the check above. Notice it is a 0 second timer though, so + ;; we're not introducing any more delay over jit-lock's timers. + (when timer (cancel-timer timer)) + (setq timer (run-at-time + 0 nil + (lambda (buf) + (eglot--when-live-buffer buf + ;; HACK: In some pathological situations + ;; (Emacs's own coding.c, for example), + ;; jit-lock is calling `eglot--update-hints' + ;; repeatedly with same sequence of + ;; arguments, which leads to + ;; `eglot--update-hints-1' being called with + ;; the same region repeatedly. This happens + ;; even if the hint-painting code does + ;; nothing else other than widen, narrow, + ;; move point then restore these things. + ;; Possible Emacs bug, but this fixes it. + (unless (equal last-region region) + (eglot--update-hints-1 (max (car region) (point-min)) + (min (cdr region) (point-max))) + (setq last-region region)) + (setq region (cons nil nil) + timer nil))) + (current-buffer))))) (defun eglot--update-hints-1 (from to) "Do most work for `eglot--update-hints', including LSP request." From 6842415577405adafcba16f8cbff02f35b5583f9 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Tue, 4 Feb 2025 09:25:17 -0800 Subject: [PATCH 077/279] Improve calculation of indent prefixes when using text scaling Previously, the display spec for the "average space" was wrong. It used a plain number for the width of the specified space, which means "N times the normal character width for the buffer", but we want "N times the normal character width for the *current face*" (bug#76008). * lisp/visual-wrap.el (visual-wrap--content-prefix): Specify the width of the "average space" in terms of the average width of the current face. * lisp/net/shr.el (shr-indent): As above, and call 'string-pixel-width' without specifying the buffer, to match 'shr-string-pixel-width'. --- lisp/net/shr.el | 6 +++--- lisp/visual-wrap.el | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 8cc95ea6966..b25b6783066 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -1052,15 +1052,15 @@ When `shr-fill-text' is nil, only indent." (insert-char ?\s shr-indentation) (insert ?\s) ;; Set the specified space width in units of the average-width - ;; of the current font, like (N . width). That way, the + ;; of the current face, like (N . width). That way, the ;; indentation is calculated correctly when using ;; `text-scale-adjust'. (let ((avg-space (propertize (buffer-substring (1- (point)) (point)) - 'display '(space :width 1)))) + 'display '(space :width (1 . width))))) (put-text-property (1- (point)) (point) 'display `(space :width (,(/ (float shr-indentation) - (string-pixel-width avg-space (current-buffer))) + (string-pixel-width avg-space)) . width))))) (put-text-property start (+ (point) prefix) 'shr-prefix-length (+ prefix (- (point) start)))))) diff --git a/lisp/visual-wrap.el b/lisp/visual-wrap.el index 1691ba9c500..f2a186ce320 100644 --- a/lisp/visual-wrap.el +++ b/lisp/visual-wrap.el @@ -164,7 +164,7 @@ PREFIX was empty." ;; units of the font's average-width) large enough to fit the ;; first-line prefix. (let ((avg-space (propertize (buffer-substring position (1+ position)) - 'display '(space :width 1)))) + 'display '(space :width (1 . width))))) ;; Remove any `min-width' display specs since we'll replace with ;; our own later in `visual-wrap--apply-to-line' (bug#73882). (add-display-text-property 0 (length prefix) 'min-width nil prefix) From 782ec71053d8535511522f27f28c11682ca0f40b Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 4 Feb 2025 11:43:58 -0800 Subject: [PATCH 078/279] Improve bidi_get_time runtime checking * src/bidi.c (bidi_get_type): Improve runtime checking, by also aborting if the bidi_type_table entry is not a bidi_type_t value. --- src/bidi.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/bidi.c b/src/bidi.c index d8754e2db73..fd0bebb85e0 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -282,12 +282,6 @@ bidi_get_type (int ch, bidi_dir_t override) emacs_abort (); default_type = (bidi_type_t) XFIXNUM (CHAR_TABLE_REF (bidi_type_table, ch)); - /* Every valid character code, even those that are unassigned by the - UCD, have some bidi-class property, according to - DerivedBidiClass.txt file. Therefore, if we ever get UNKNOWN_BT - (= zero) code from CHAR_TABLE_REF, that's a bug. */ - if (default_type == UNKNOWN_BT) - emacs_abort (); switch (default_type) { @@ -303,13 +297,26 @@ bidi_get_type (int ch, bidi_dir_t override) case FSI: case PDI: return default_type; - default: + + case STRONG_L: case STRONG_R: + case WEAK_EN: case WEAK_AN: + case STRONG_AL: + case WEAK_ES: case WEAK_ET: case WEAK_CS: case WEAK_NSM: + case NEUTRAL_S: case NEUTRAL_WS: case NEUTRAL_ON: if (override == L2R) return STRONG_L; else if (override == R2L) return STRONG_R; else return default_type; + + case UNKNOWN_BT: + default: + /* Every valid character code, even those unassigned by the UCD, + have some bidi-class property, according to DerivedBidiClass.txt. + Therefore, if we ever get UNKNOWN_BT (= zero) or some unknown + code from CHAR_TABLE_REF, that's a bug. */ + emacs_abort (); } } From 7d85f678f33029cc874da2aaa89cf95a45403146 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Tue, 4 Feb 2025 02:53:53 +0100 Subject: [PATCH 079/279] Avoid overly short timeout in ispell-help * lisp/textmodes/ispell.el (ispell-help): Avoid too short timeout by using at least 0.5 seconds. --- lisp/textmodes/ispell.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index f53732098ea..24d09c3e9bc 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -2512,7 +2512,7 @@ Selections are: (with-current-buffer buffer (insert (concat help-1 "\n" help-2 "\n" help-3))) (ispell-display-buffer buffer) - (sit-for ispell-help-timeout) + (sit-for (max 0.5 ispell-help-timeout)) (kill-buffer "*Ispell Help*")) (unwind-protect (let ((resize-mini-windows 'grow-only)) @@ -2522,7 +2522,7 @@ Selections are: ;;(set-minibuffer-window (selected-window)) (enlarge-window 2) (insert (concat help-1 "\n" help-2 "\n" help-3)) - (sit-for ispell-help-timeout)) + (sit-for (max 0.5 ispell-help-timeout))) (erase-buffer))))))) (define-obsolete-function-alias 'lookup-words 'ispell-lookup-words "24.4") From 999d054dc1e265f1a39c10035a3a3f7f75de8445 Mon Sep 17 00:00:00 2001 From: kobarity Date: Wed, 5 Feb 2025 00:02:05 +0900 Subject: [PATCH 080/279] Make it configurable to highlight Python 2 builtins By default, Python 2-only builtins are not highlighted. * lisp/progmodes/python.el (python-2-support): New defcustom. (python-font-lock-builtin-types) (python-font-lock-builtins-python3) (python-font-lock-builtins-python2) (python-font-lock-builtins) (python-font-lock-special-attributes) (python-font-lock-builtin-exceptions-python3) (python-font-lock-builtin-exceptions-python2) (python-font-lock-builtin-exceptions): New variables. (python-font-lock-keywords-level-2) (python-font-lock-keywords-maximum-decoration) (python--treesit-builtin-types) (python--treesit-builtins) (python--treesit-special-attributes) (python--treesit-exceptions): Use new variables. Co-authored-by: Konstantin Kharlamov Co-authored-by: Stefan Kangas --- etc/NEWS | 8 ++ lisp/progmodes/python.el | 197 ++++++++++++++++++--------------------- 2 files changed, 99 insertions(+), 106 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 82e2462df6b..ade635aa924 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -988,6 +988,14 @@ exist. If "python" points to Python 2 on your system, you now have to customize these variables to "python3" if you want to use Python 3 instead. +--- +*** Python 2 support is now optional and disabled by default. +Since Python 2 EOL was over 5 years ago, this release removes Python +2-only builtins such as "file" from the default highlighting in +'python-mode' and 'python-ts-mode'. If you would like them highlighted, +customize the new user option `python-2-support' to a non-nil value and +restart Emacs. + --- *** Support of 'electric-layout-mode' added. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 3a297a3979c..8a99ff0434d 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -316,6 +316,16 @@ To customize the Python interpreter for interactive use, modify :version "30.1" :type 'string) +(defcustom python-2-support nil + "If non-nil, enable Python 2 support. +Currently only affects highlighting. + +After customizing this variable, you must restart Emacs for it to take +effect." + :version "31.1" + :type 'boolean + :safe 'booleanp) + ;;; Bindings @@ -689,6 +699,40 @@ the {...} holes that appear within f-strings." This is the minimum decoration level, including function and class declarations.") +(defvar python-font-lock-builtin-types + '("bool" "bytearray" "bytes" "complex" "dict" "float" "frozenset" + "int" "list" "memoryview" "range" "set" "str" "tuple")) + +(defvar python-font-lock-builtins-python3 + '("abs" "aiter" "all" "anext" "any" "ascii" "bin" "breakpoint" + "callable" "chr" "classmethod" "compile" "delattr" "dir" "divmod" + "enumerate" "eval" "exec" "filter" "format" "getattr" "globals" + "hasattr" "hash" "help" "hex" "id" "input" "isinstance" + "issubclass" "iter" "len" "locals" "map" "max" "min" "next" + "object" "oct" "open" "ord" "pow" "print" "property" "repr" + "reversed" "round" "setattr" "slice" "sorted" "staticmethod" "sum" + "super" "type" "vars" "zip" "__import__")) + +(defvar python-font-lock-builtins-python2 + '("basestring" "cmp" "execfile" "file" "long" "raw_input" "reduce" + "reload" "unichr" "unicode" "xrange" "apply" "buffer" "coerce" + "intern")) + +(defvar python-font-lock-builtins + (append python-font-lock-builtins-python3 + (when python-2-support + python-font-lock-builtins-python2))) + +(defvar python-font-lock-special-attributes + '(;; https://docs.python.org/3/reference/datamodel.html + "__annotations__" "__bases__" "__closure__" "__code__" + "__defaults__" "__dict__" "__doc__" "__firstlineno__" + "__globals__" "__kwdefaults__" "__name__" "__module__" + "__mro__" "__package__" "__qualname__" + "__static_attributes__" "__type_params__" + ;; Extras: + "__all__")) + (defvar python-font-lock-keywords-level-2 `(,@python-font-lock-keywords-level-1 ,(rx symbol-start @@ -711,33 +755,11 @@ class declarations.") "self") symbol-end) ;; Builtins - (,(rx symbol-start - (or - "abs" "all" "any" "bin" "bool" "callable" "chr" "classmethod" - "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" - "eval" "filter" "float" "format" "frozenset" "getattr" "globals" - "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance" - "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview" - "min" "next" "object" "oct" "open" "ord" "pow" "print" "property" - "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted" - "staticmethod" "str" "sum" "super" "tuple" "type" "vars" "zip" - "__import__" - ;; Python 2: - "basestring" "cmp" "execfile" "file" "long" "raw_input" "reduce" - "reload" "unichr" "unicode" "xrange" "apply" "buffer" "coerce" - "intern" - ;; Python 3: - "aiter" "anext" "ascii" "breakpoint" "bytearray" "bytes" "exec" - ;; Special attributes: - ;; https://docs.python.org/3/reference/datamodel.html - "__annotations__" "__bases__" "__closure__" "__code__" - "__defaults__" "__dict__" "__doc__" "__firstlineno__" - "__globals__" "__kwdefaults__" "__name__" "__module__" - "__mro__" "__package__" "__qualname__" - "__static_attributes__" "__type_params__" - ;; Extras: - "__all__") - symbol-end) . font-lock-builtin-face)) + (,(rx-to-string `(seq symbol-start + (or ,@(append python-font-lock-builtin-types + python-font-lock-builtins + python-font-lock-special-attributes)) + symbol-end)) . font-lock-builtin-face)) "Font lock keywords to use in `python-mode' for level 2 decoration. This is the medium decoration level, including everything in @@ -759,6 +781,41 @@ sign in chained assignment." (equal (char-after) ?=)) return (progn (backward-char) t)))) +(defvar python-font-lock-builtin-exceptions-python3 + '(;; Python 2 and 3: + "ArithmeticError" "AssertionError" "AttributeError" "BaseException" + "BufferError" "BytesWarning" "DeprecationWarning" "EOFError" + "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning" + "GeneratorExit" "IOError" "ImportError" "ImportWarning" + "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt" + "LookupError" "MemoryError" "NameError" "NotImplementedError" + "OSError" "OverflowError" "PendingDeprecationWarning" + "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration" + "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError" + "TypeError" "UnboundLocalError" "UnicodeDecodeError" + "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError" + "UnicodeWarning" "UserWarning" "ValueError" "Warning" + "ZeroDivisionError" + ;; Python 3: + "BlockingIOError" "BrokenPipeError" "ChildProcessError" + "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError" + "ConnectionResetError" "EncodingWarning" "FileExistsError" + "FileNotFoundError" "InterruptedError" "IsADirectoryError" + "NotADirectoryError" "ModuleNotFoundError" "PermissionError" + "ProcessLookupError" "PythonFinalizationError" "RecursionError" + "ResourceWarning" "StopAsyncIteration" "TimeoutError" + "BaseExceptionGroup" "ExceptionGroup" + ;; OS specific + "VMSError" "WindowsError")) + +(defvar python-font-lock-builtin-exceptions-python2 + '("StandardError")) + +(defvar python-font-lock-builtin-exceptions + (append python-font-lock-builtin-exceptions-python3 + (when python-2-support + python-font-lock-builtin-exceptions-python2))) + (defvar python-font-lock-keywords-maximum-decoration `((python--font-lock-f-strings) ,@python-font-lock-keywords-level-2 @@ -776,38 +833,9 @@ sign in chained assignment." (0+ "." (1+ (or word ?_))))) (1 font-lock-type-face)) ;; Builtin Exceptions - (,(rx symbol-start - (or - ;; Python 2 and 3: - "ArithmeticError" "AssertionError" "AttributeError" "BaseException" - "BufferError" "BytesWarning" "DeprecationWarning" "EOFError" - "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning" - "GeneratorExit" "IOError" "ImportError" "ImportWarning" - "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt" - "LookupError" "MemoryError" "NameError" "NotImplementedError" - "OSError" "OverflowError" "PendingDeprecationWarning" - "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration" - "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError" - "TypeError" "UnboundLocalError" "UnicodeDecodeError" - "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError" - "UnicodeWarning" "UserWarning" "ValueError" "Warning" - "ZeroDivisionError" - ;; Python 2: - "StandardError" - ;; Python 3: - "BlockingIOError" "BrokenPipeError" "ChildProcessError" - "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError" - "ConnectionResetError" "EncodingWarning" "FileExistsError" - "FileNotFoundError" "InterruptedError" "IsADirectoryError" - "NotADirectoryError" "ModuleNotFoundError" "PermissionError" - "ProcessLookupError" "PythonFinalizationError" "RecursionError" - "ResourceWarning" "StopAsyncIteration" "TimeoutError" - "BaseExceptionGroup" "ExceptionGroup" - ;; OS specific - "VMSError" "WindowsError" - ) - symbol-end) - . font-lock-type-face) + (,(rx-to-string `(seq symbol-start + (or ,@python-font-lock-builtin-exceptions) + symbol-end)) . font-lock-type-face) ;; single assignment with/without type hints, e.g. ;; a: int = 5 ;; b: Tuple[Optional[int], Union[Sequence[str], str]] = (None, 'foo') @@ -1015,8 +1043,7 @@ It makes underscores and dots word constituent chars.") "and" "in" "is" "not" "or" "not in" "is not")) (defvar python--treesit-builtin-types - '("int" "float" "complex" "bool" "list" "tuple" "range" "str" - "bytes" "bytearray" "memoryview" "set" "frozenset" "dict")) + python-font-lock-builtin-types) (defvar python--treesit-type-regex (rx-to-string `(seq bol (or @@ -1025,17 +1052,7 @@ It makes underscores and dots word constituent chars.") eol))) (defvar python--treesit-builtins - (append python--treesit-builtin-types - '("abs" "aiter" "all" "anext" "any" "ascii" "bin" "breakpoint" - "callable" "chr" "classmethod" "compile" - "delattr" "dir" "divmod" "enumerate" "eval" "exec" - "filter" "format" "getattr" "globals" - "hasattr" "hash" "help" "hex" "id" "input" "isinstance" - "issubclass" "iter" "len" "locals" "map" "max" - "min" "next" "object" "oct" "open" "ord" "pow" - "print" "property" "repr" "reversed" "round" - "setattr" "slice" "sorted" "staticmethod" "sum" "super" - "type" "vars" "zip" "__import__"))) + python-font-lock-builtins) (defvar python--treesit-constants '("Ellipsis" "False" "None" "NotImplemented" "True" "__debug__" @@ -1047,42 +1064,10 @@ It makes underscores and dots word constituent chars.") ">>" ">>=" "|" "|=" "~" "@" "@=")) (defvar python--treesit-special-attributes - '("__annotations__" "__bases__" "__closure__" "__code__" - "__defaults__" "__dict__" "__doc__" "__firstlineno__" - "__globals__" "__kwdefaults__" "__name__" "__module__" - "__mro__" "__package__" "__qualname__" - "__static_attributes__" "__type_params__" - "__all__")) + python-font-lock-special-attributes) (defvar python--treesit-exceptions - '(;; Python 2 and 3: - "ArithmeticError" "AssertionError" "AttributeError" "BaseException" - "BufferError" "BytesWarning" "DeprecationWarning" "EOFError" - "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning" - "GeneratorExit" "IOError" "ImportError" "ImportWarning" - "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt" - "LookupError" "MemoryError" "NameError" "NotImplementedError" - "OSError" "OverflowError" "PendingDeprecationWarning" - "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration" - "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError" - "TypeError" "UnboundLocalError" "UnicodeDecodeError" - "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError" - "UnicodeWarning" "UserWarning" "ValueError" "Warning" - "ZeroDivisionError" - ;; Python 2: - "StandardError" - ;; Python 3: - "BlockingIOError" "BrokenPipeError" "ChildProcessError" - "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError" - "ConnectionResetError" "EncodingWarning" "FileExistsError" - "FileNotFoundError" "InterruptedError" "IsADirectoryError" - "NotADirectoryError" "ModuleNotFoundError" "PermissionError" - "ProcessLookupError" "PythonFinalizationError" "RecursionError" - "ResourceWarning" "StopAsyncIteration" "TimeoutError" - "BaseExceptionGroup" "ExceptionGroup" - ;; OS specific - "VMSError" "WindowsError" - )) + python-font-lock-builtin-exceptions) (defun python--treesit-fontify-string (node override start end &rest _) "Fontify string. From 4aab2f45b3dc39f4ebe4e09fd4e3b56b757843aa Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 4 Feb 2025 16:56:56 -0800 Subject: [PATCH 081/279] Remove no-longer-needed delete_frame UNINIT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * src/frame.c (delete_frame): Remove a local with UNINIT that is no longer needed now that GCC bug#85563 is fixed, as we don’t need to worry about porting --enable-gcc-warnings to older GCC. This change reverts this part of my commit “Port --enable-gcc-warnings to GCC 8” 8c3215e7a47e3caaa005bf573765ed63e0739b89 dated Sat Apr 28 16:49:24 2018 -0700. --- src/frame.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/frame.c b/src/frame.c index cac9b0a4acd..6e125b9561c 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2481,7 +2481,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force) else { Lisp_Object tail; - Lisp_Object frame1 UNINIT; /* This line works around GCC bug 85563. */ eassume (CONSP (Vframe_list)); /* Look for another visible frame on the same terminal. From 12a3145b3b9480e5e5993dac28df52a36cc7b95d Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Tue, 4 Feb 2025 23:35:37 -0800 Subject: [PATCH 082/279] Make treesit-node-at more readable * lisp/treesit.el (treesit-node-at): Make the logic for finding the parser (and the root node) more explicit and straightforward. Don't use treesit-buffer-root-node; instead, find the parser and use treesit-parser-root-node directly. --- lisp/treesit.el | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index e2fdfb7c1ef..9e3c75519f9 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -226,17 +226,35 @@ is nil, try to guess the language at POS using `treesit-language-at'. If there's a local parser at POS, the local parser takes priority unless PARSER-OR-LANG is a parser, or PARSER-OR-LANG is a language and doesn't match the language of the local parser." - (let* ((root (if (treesit-parser-p parser-or-lang) - (treesit-parser-root-node parser-or-lang) - (or (when-let* ((parser - (car (treesit-local-parsers-at - pos parser-or-lang)))) - (treesit-parser-root-node parser)) - (condition-case nil - (treesit-buffer-root-node - (or parser-or-lang - (treesit-language-at pos))) - (treesit-no-parser nil))))) + (let* ((root + ;; 1. Given a parser, just use the parser's root node. + (cond ((treesit-parser-p parser-or-lang) + (treesit-parser-root-node parser-or-lang)) + ;; 2. Given a language, try local parser, then global + ;; parser. + (parser-or-lang + (let* ((local-parser (car (treesit-local-parsers-at + pos parser-or-lang))) + (global-parser (car (treesit-parser-list + nil parser-or-lang))) + (parser (or local-parser global-parser))) + (when parser + (treesit-parser-root-node parser)))) + ;; 3. No given language, try to get a language at point. + ;; If we got a language, only use parser of that + ;; language, otherwise use any parser we can find. When + ;; finding parser, try local parser first, then global + ;; parser. + (t + ;; LANG can be nil. + (let* ((lang (treesit-language-at pos)) + (local-parser (car (treesit-local-parsers-at + pos lang))) + (global-parser (car (treesit-parser-list + nil lang))) + (parser (or local-parser global-parser))) + (when parser + (treesit-parser-root-node parser)))))) (node root) (node-before root) (pos-1 (max (1- pos) (point-min))) From 4396f6414c2fb82cb8cee68420b658e376bb4e01 Mon Sep 17 00:00:00 2001 From: Vincenzo Pupillo Date: Mon, 3 Feb 2025 22:14:44 +0100 Subject: [PATCH 083/279] Correctly handled the local parser for jsdoc (bug#75456) As a result of recent patches to treesitter, local parsers must now be recognized by 'treesit-language-at-point' and have their own indentation rules. * lisp/progmodes/js.el (js--treesit-indent-rules): New rule for jsdoc. (js--treesit-language-at-point): New function. (js-ts-mode): Use the new function. --- lisp/progmodes/js.el | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 8029a304757..3168395acf1 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3490,7 +3490,10 @@ Check if a node type is available, then return the right indent rules." ((match "/" "jsx_self_closing_element") parent 0) ((parent-is "jsx_self_closing_element") parent js-indent-level) ;; FIXME(Theo): This no-node catch-all should be removed. When is it needed? - (no-node parent-bol 0))))) + (no-node parent-bol 0)) + (jsdoc + ((and (parent-is "document") c-ts-common-looking-at-star) + c-ts-common-comment-start-after-first-star -1))))) (defvar js--treesit-keywords '("as" "async" "await" "break" "case" "catch" "class" "const" "continue" @@ -3718,6 +3721,22 @@ Return nil if there is no name or if NODE is not a defun node." ("lexical_declaration" (treesit-node-top-level node)) (_ t))) +(defun js--treesit-language-at-point (point) + "Return the language at POINT." + (let* ((node (treesit-node-at point 'javascript)) + (node-type (treesit-node-type node)) + (node-start (treesit-node-start node)) + (node-end (treesit-node-end node))) + (if (not (treesit-ready-p 'jsdoc t)) + 'javascript + (if (equal node-type "comment") + (save-excursion + (goto-char node-start) + (if (search-forward "/**" node-end t) + 'jsdoc + 'javascript)) + 'javascript)))) + ;;; Main Function ;;;###autoload @@ -3927,6 +3946,7 @@ See `treesit-thing-settings' for more information.") ;; Tree-sitter setup. (setq-local treesit-primary-parser (treesit-parser-create 'javascript)) + (setq-local treesit-language-at-point-function #'js--treesit-language-at-point) ;; Indent. (setq-local treesit-simple-indent-rules js--treesit-indent-rules) From a476295620a692657f7febd4630cf67f128c4c65 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Wed, 5 Feb 2025 09:41:49 +0100 Subject: [PATCH 084/279] * lisp/autorevert.el (defvar): Fix debug declaration. --- lisp/autorevert.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index ddb116bb828..aeb80ff7884 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -780,7 +780,7 @@ If the buffer needs to be reverted, do it now." (defmacro inhibit-auto-revert (&rest body) "Deactivate auto-reverting of current buffer temporarily. Run BODY." - (declare (indent 0) (debug ((form body) body))) + (declare (indent 0) (debug (body))) `(progn ;; Cleanup. (dolist (buf inhibit-auto-revert-buffers) From a1f2f5995d69db646f58a7203ab6208556f0df4b Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 5 Feb 2025 14:44:01 +0200 Subject: [PATCH 085/279] Revert "Improve bidi_get_time runtime checking" This reverts commit 782ec71053d8535511522f27f28c11682ca0f40b. It makes the code less readable and less future-proof, so a net loss. (Bug#75964) --- src/bidi.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/bidi.c b/src/bidi.c index fd0bebb85e0..d8754e2db73 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -282,6 +282,12 @@ bidi_get_type (int ch, bidi_dir_t override) emacs_abort (); default_type = (bidi_type_t) XFIXNUM (CHAR_TABLE_REF (bidi_type_table, ch)); + /* Every valid character code, even those that are unassigned by the + UCD, have some bidi-class property, according to + DerivedBidiClass.txt file. Therefore, if we ever get UNKNOWN_BT + (= zero) code from CHAR_TABLE_REF, that's a bug. */ + if (default_type == UNKNOWN_BT) + emacs_abort (); switch (default_type) { @@ -297,26 +303,13 @@ bidi_get_type (int ch, bidi_dir_t override) case FSI: case PDI: return default_type; - - case STRONG_L: case STRONG_R: - case WEAK_EN: case WEAK_AN: - case STRONG_AL: - case WEAK_ES: case WEAK_ET: case WEAK_CS: case WEAK_NSM: - case NEUTRAL_S: case NEUTRAL_WS: case NEUTRAL_ON: + default: if (override == L2R) return STRONG_L; else if (override == R2L) return STRONG_R; else return default_type; - - case UNKNOWN_BT: - default: - /* Every valid character code, even those unassigned by the UCD, - have some bidi-class property, according to DerivedBidiClass.txt. - Therefore, if we ever get UNKNOWN_BT (= zero) or some unknown - code from CHAR_TABLE_REF, that's a bug. */ - emacs_abort (); } } From 85113fcda97970bc2468f409278e27d6570fc76f Mon Sep 17 00:00:00 2001 From: Mauro Aranda Date: Fri, 17 Jan 2025 17:12:08 -0300 Subject: [PATCH 086/279] Prepare markers for insertions inside of a widget Recreating child widgets without recreating the parent widget may lead to situations where the parent widget doesn't cover its children or buttons entirely anymore. This bug manifests as a faulty fontification of children or buttons, for example. (Bug#69941) * lisp/wid-edit.el (widget--prepare-markers-for-inside-insertion) (widget--prepare-markers-for-outside-insertion): New functions. (widget-default-create): Use them. * test/lisp/wid-edit-tests.el (widget-test-insertion-at-parent-markers) (widget-test-insertion-at-parent-markers-2): New tests. --- lisp/wid-edit.el | 49 +++++++++++++++++++++++++++++++++-- test/lisp/wid-edit-tests.el | 51 +++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 7260f60196a..a1d4c4850ae 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -1730,6 +1730,49 @@ The value of the :type attribute should be an unconverted widget type." (call-interactively (widget-get widget :complete-function)))))))) +(defun widget--prepare-markers-for-inside-insertion (widget) + "Prepare the WIDGET's parent for insertions inside it, if necessary. + +Usually, the :from marker has type t, while the :to marker has type nil. +When recreating a child or a button inside a composite widget right at these +markers, they have to be changed to nil and t respectively, +so that the WIDGET's parent (if any), properly contains all of its +recreated children and buttons. + +Prepares also the markers of the WIDGET's grandparent, if necessary. + +Returns a list of the markers that had its type changed, for later resetting." + (let* ((parent (widget-get widget :parent)) + (parent-from-marker (and parent (widget-get parent :from))) + (parent-to-marker (and parent (widget-get parent :to))) + (lst nil) + (pos (point))) + (when (and parent-from-marker + (eq pos (marker-position parent-from-marker)) + (marker-insertion-type parent-from-marker)) + (set-marker-insertion-type parent-from-marker nil) + (push (cons parent-from-marker t) lst)) + (when (and parent-to-marker + (eq pos (marker-position parent-to-marker)) + (not (marker-insertion-type parent-to-marker))) + (set-marker-insertion-type parent-to-marker t) + (push (cons parent-to-marker nil) lst)) + (when lst + (nconc lst (widget--prepare-markers-for-inside-insertion parent))))) + +(defun widget--revert-markers-for-outside-insertion (markers) + "Revert MARKERS for insertions that do not belong to a widget. + +MARKERS is a list of the form (MARKER . NEW-TYPE), as returned by +`widget--prepare-markers-for-inside-insertion' and this function sets MARKER +to NEW-TYPE. + +Coupled with `widget--prepare-parent-for-inside-insertion', this has the effect +of setting markers back to the type needed for insertions that do not belong +to a given widget." + (dolist (marker markers) + (set-marker-insertion-type (car marker) (cdr marker)))) + (defun widget-default-create (widget) "Create WIDGET at point in the current buffer." (widget-specify-insert @@ -1737,7 +1780,8 @@ The value of the :type attribute should be an unconverted widget type." button-begin button-end sample-begin sample-end doc-begin doc-end - value-pos) + value-pos + (markers (widget--prepare-markers-for-inside-insertion widget))) (insert (widget-get widget :format)) (goto-char from) ;; Parse escapes in format. @@ -1797,7 +1841,8 @@ The value of the :type attribute should be an unconverted widget type." (widget-specify-doc widget doc-begin doc-end)) (when value-pos (goto-char value-pos) - (widget-apply widget :value-create))) + (widget-apply widget :value-create)) + (widget--revert-markers-for-outside-insertion markers)) (let ((from (point-min-marker)) (to (point-max-marker))) (set-marker-insertion-type from t) diff --git a/test/lisp/wid-edit-tests.el b/test/lisp/wid-edit-tests.el index c18e6d14c4c..e34aa64f8d1 100644 --- a/test/lisp/wid-edit-tests.el +++ b/test/lisp/wid-edit-tests.el @@ -430,4 +430,55 @@ return nil, even with a non-nil bubblep argument." (should-not (overlay-buffer field-overlay)) (should-not (overlay-buffer field-end-overlay))))) +;; The following two tests are for Bug#69941. Markers need to be prepared +;; against "inside" insertions at them. That is, a recreated child should +;; still be covered by the parent's :from and :to markers. +(ert-deftest widget-test-insertion-at-parent-markers () + "Test that recreating a child keeps the parent's markers covering it. + +Test the most common situation, where only one parent needs to be adjusted." + (with-temp-buffer + (let* ((group (widget-create 'group + :format "%v" + '(item :value 1 :format "%v"))) + (item (car (widget-get group :children))) + (ofrom (marker-position (widget-get group :from))) + (oto (marker-position (widget-get group :to)))) + (widget-insert "\n") + (widget-setup) + ;; Change item, without recreating the group. This causes changes + ;; right at the :from and :to markers, and if they don't have + ;; the right type, the group's :from-:to span won't include its + ;; child, the item widget, anymore. + (widget-value-set item 2) + ;; The positions should be the same as they were when the group + ;; widget was first created. + (should (= ofrom (widget-get group :from))) + (should (= oto (widget-get group :to)))))) + +(ert-deftest widget-test-insertion-at-parent-markers-2 () + "Test that recreating a child keeps the parent's marker covering it. + +Test the uncommon situation in which we might need to prepare the grandparent's +markers (and so on) as well." + (with-temp-buffer + (let* ((group (widget-create '(group + :format "%v" + (group + :format "%v" + (item :value 1 :format "%v"))))) + (group2 (car (widget-get group :children))) + (item (car (widget-get group2 :children))) + (ofrom (marker-position (widget-get group :from))) + (oto (marker-position (widget-get group :to))) + (ofrom2 (marker-position (widget-get group2 :from))) + (oto2 (marker-position (widget-get group2 :to)))) + (widget-insert "\n") + (widget-setup) + (widget-value-set item 2) + (should (= ofrom (widget-get group :from))) + (should (= oto (widget-get group :to))) + (should (= ofrom2 (widget-get group2 :from))) + (should (= oto2 (widget-get group2 :to)))))) + ;;; wid-edit-tests.el ends here From bfc8540da4521d460b72fdbc20edb3a0488c23c2 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Wed, 5 Feb 2025 15:48:49 +0200 Subject: [PATCH 087/279] * lisp/dired-x.el (dired-omit-expunge): Escape '%' (bug#75877). --- lisp/dired-x.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 4a05f609b2b..89390a482f0 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -498,8 +498,10 @@ status message." nil (if dired-omit-verbose (format "Omitted %%d line%%s in %s" - (abbreviate-file-name - dired-directory)) + (replace-regexp-in-string + "%" "%%" + (abbreviate-file-name + dired-directory))) "") init-count))) (force-mode-line-update)))) From 4be087f1e12afb2ea4de1a5686d14a28a9a20940 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Wed, 5 Feb 2025 19:43:45 -0500 Subject: [PATCH 088/279] (font-ccl-encoder-alist): Delete variable, unused * src/ccl.c (syms_of_ccl): Remove `font-ccl-encoder-alist`. * lisp/language/ethiopic.el (ccl-encode-ethio-font): Delete CCL program. (font-ccl-encoder-alist): Don't modify it. --- lisp/language/ethiopic.el | 22 ---------------------- src/ccl.c | 13 ------------- 2 files changed, 35 deletions(-) diff --git a/lisp/language/ethiopic.el b/lisp/language/ethiopic.el index 14098c7e470..9c254cbfc6e 100644 --- a/lisp/language/ethiopic.el +++ b/lisp/language/ethiopic.el @@ -36,28 +36,6 @@ ;;; Code: -(define-ccl-program ccl-encode-ethio-font - '(0 - ;; In: R0:ethiopic (not checked) - ;; R1:position code 1 - ;; R2:position code 2 - ;; Out: R1:font code point 1 - ;; R2:font code point 2 - ((r1 -= 33) - (r2 -= 33) - (r1 *= 94) - (r2 += r1) - (if (r2 < 256) - (r1 = #x12) - (if (r2 < 448) - ((r1 = #x13) (r2 -= 256)) - ((r1 = #xfd) (r2 -= 208)) - )))) - "CCL program to encode an Ethiopic code to code point of Ethiopic font.") - -(setq font-ccl-encoder-alist - (cons (cons "ethiopic" ccl-encode-ethio-font) font-ccl-encoder-alist)) - (set-language-info-alist "Ethiopic" '((setup-function . setup-ethiopic-environment-internal) (exit-function . exit-ethiopic-environment) diff --git a/src/ccl.c b/src/ccl.c index 78845ebaf65..a45fe0439c4 100644 --- a/src/ccl.c +++ b/src/ccl.c @@ -2379,19 +2379,6 @@ syms_of_ccl (void) doc: /* Vector of code conversion maps. */); Vcode_conversion_map_vector = make_nil_vector (16); - DEFVAR_LISP ("font-ccl-encoder-alist", Vfont_ccl_encoder_alist, - doc: /* Alist of fontname patterns vs corresponding CCL program. -Each element looks like (REGEXP . CCL-CODE), - where CCL-CODE is a compiled CCL program. -When a font whose name matches REGEXP is used for displaying a character, - CCL-CODE is executed to calculate the code point in the font - from the charset number and position code(s) of the character which are set - in CCL registers R0, R1, and R2 before the execution. -The code point in the font is set in CCL registers R1 and R2 - when the execution terminated. - If the font is single-byte font, the register R2 is not used. */); - Vfont_ccl_encoder_alist = Qnil; - DEFVAR_LISP ("translation-hash-table-vector", Vtranslation_hash_table_vector, doc: /* Vector containing all translation hash tables ever defined. Comprises pairs (SYMBOL . TABLE) where SYMBOL and TABLE were set up by calls From d10acd16c90afe9fc8534fcd174397b7c403eda9 Mon Sep 17 00:00:00 2001 From: Antero Mejr Date: Sat, 18 Jan 2025 22:35:39 -0500 Subject: [PATCH 089/279] Add scheme-mode indentation for SRFI 64, R7RS guard * lisp/progmodes/scheme.el: Add properties for SRFI 64 and R7RS guard identifiers. (Bug#75999) --- lisp/progmodes/scheme.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el index 8896c2547c8..6fa92164f43 100644 --- a/lisp/progmodes/scheme.el +++ b/lisp/progmodes/scheme.el @@ -681,10 +681,15 @@ indentation." (put 'define-values 'scheme-indent-function 1) (put 'define-record-type 'scheme-indent-function 1) ;; is 1 correct? (put 'define-library 'scheme-indent-function 1) +(put 'guard 'scheme-indent-function 1) ;; SRFI-8 (put 'receive 'scheme-indent-function 2) +;; SRFI 64 +(put 'test-group 'scheme-indent-function 1) +(put 'test-group-with-cleanup 'scheme-indent-function 1) + ;; SRFI-204 (withdrawn, but provided in many implementations, see the SRFI text) (put 'match 'scheme-indent-function 1) (put 'match-lambda 'scheme-indent-function 0) From ea04dd8ca93d609c0ee475c4acf58a56dfc0f1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= Date: Thu, 6 Feb 2025 05:31:38 +0100 Subject: [PATCH 090/279] Use read-key in amp-y-or-n-p (bug#75886) * lisp/emacs-lisp/map-ynp.el (map-y-or-n-p): Use read-key so that C-g in recognized when defined in input-decode-map. --- lisp/emacs-lisp/map-ynp.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/map-ynp.el b/lisp/emacs-lisp/map-ynp.el index 14cbbfda033..18277b60fb8 100644 --- a/lisp/emacs-lisp/map-ynp.el +++ b/lisp/emacs-lisp/map-ynp.el @@ -185,7 +185,12 @@ The function's value is the number of actions taken." (let ((overriding-text-conversion-style nil)) (when (fboundp 'set-text-conversion-style) (set-text-conversion-style text-conversion-style)) - (setq char (read-event))) + ;; Do NOT use read-event here. That + ;; function does not consult + ;; input-decode-map (bug#75886). + (setq char (read-key)) + (when (eq char ?\C-g) + (signal 'quit nil))) (when (fboundp 'set-text-conversion-style) (set-text-conversion-style text-conversion-style))) ;; Show the answer to the question. From 143f1096daa686841f1409bd63835167bb7e8aca Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 6 Feb 2025 10:42:04 +0200 Subject: [PATCH 091/279] Improve documentation of 'file-name-concat' * doc/lispref/files.texi (Directory Names): * src/fileio.c (Ffile_name_concat): Advise not to use 'file-name-concat' unless necessary. (Bug#76023) --- doc/lispref/files.texi | 8 ++++++++ src/fileio.c | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 97ad7c6b7fa..c285cd1c683 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -2459,6 +2459,14 @@ results in any way. This is almost the same as using @code{concat}, but @var{dirname} (and the non-final components) may or may not end with slash characters, and this function will not double those characters. + +In most cases, one or more calls to @code{expand-file-name} (@pxref{File +Name Expansion} are better suited for the job of generating file names +with leading directories than this function. Use this function only if +some of the special features of @code{expand-file-name} get in the way +of what your program needs to do. For example, the special handling by +@code{expand-file-name} of @file{~}, @file{~@var{user}}, and @code{nil}, +or the removal of @file{.} and @file{..} might not be what you want. @end defun To convert a directory name to its abbreviation, use this diff --git a/src/fileio.c b/src/fileio.c index 7042dbca258..66aef91d9e7 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -847,6 +847,10 @@ Each element in COMPONENTS must be a string or nil. DIRECTORY or the non-final elements in COMPONENTS may or may not end with a slash -- if they don't end with a slash, a slash will be inserted before concatenating. +In most cases, one or more calls to `expand-file-name' are better +suited for the job than this function. Use this function only if +some of the special expansions done by `expand-file-name' get in +the way of what your program needs to do. usage: (file-name-concat DIRECTORY &rest COMPONENTS) */) (ptrdiff_t nargs, Lisp_Object *args) { From 811d575336942b1cd1e1c6fb50620babdf9cc82c Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Thu, 6 Feb 2025 16:56:07 +0100 Subject: [PATCH 092/279] ; Rename internal variable in inhibit-auto-revert * lisp/autorevert.el (inhibit-auto-revert): Call internal variable `iar-buf' in order not to mismatch with variables outside the macro. --- lisp/autorevert.el | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index aeb80ff7884..315100885be 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -787,15 +787,16 @@ Run BODY." (unless (buffer-live-p buf) (setq inhibit-auto-revert-buffers (delq buf inhibit-auto-revert-buffers)))) - (let ((buf (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) - (current-buffer)))) + (let ((iar-buf + (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (current-buffer)))) (unwind-protect (progn - (when buf (add-to-list 'inhibit-auto-revert-buffers buf)) + (when iar-buf (add-to-list 'inhibit-auto-revert-buffers iar-buf)) ,@body) - (when buf + (when iar-buf (setq inhibit-auto-revert-buffers - (delq buf inhibit-auto-revert-buffers)))))))) + (delq iar-buf inhibit-auto-revert-buffers)))))))) (defun auto-revert-active-p () "Check if auto-revert is active in current buffer." From be316dc1c74fc547fe83c0426fdec3ffd4e5fb1f Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Thu, 6 Feb 2025 20:07:09 +0100 Subject: [PATCH 093/279] ; Use an uninterned symbol in the inhibit-auto-revert expansion. --- lisp/autorevert.el | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 315100885be..e6a12d37ad1 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -781,22 +781,23 @@ If the buffer needs to be reverted, do it now." "Deactivate auto-reverting of current buffer temporarily. Run BODY." (declare (indent 0) (debug (body))) - `(progn - ;; Cleanup. - (dolist (buf inhibit-auto-revert-buffers) - (unless (buffer-live-p buf) - (setq inhibit-auto-revert-buffers - (delq buf inhibit-auto-revert-buffers)))) - (let ((iar-buf - (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) - (current-buffer)))) - (unwind-protect - (progn - (when iar-buf (add-to-list 'inhibit-auto-revert-buffers iar-buf)) - ,@body) - (when iar-buf + (let ((buf (make-symbol "buf"))) + `(progn + ;; Cleanup. + (dolist (,buf inhibit-auto-revert-buffers) + (unless (buffer-live-p ,buf) (setq inhibit-auto-revert-buffers - (delq iar-buf inhibit-auto-revert-buffers)))))))) + (delq ,buf inhibit-auto-revert-buffers)))) + (let ((,buf + (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) + (current-buffer)))) + (unwind-protect + (progn + (when ,buf (add-to-list 'inhibit-auto-revert-buffers ,buf)) + ,@body) + (when ,buf + (setq inhibit-auto-revert-buffers + (delq ,buf inhibit-auto-revert-buffers))))))))) (defun auto-revert-active-p () "Check if auto-revert is active in current buffer." From 1751739152149608d28853782ce53b0b9a749bb2 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 7 Feb 2025 11:11:51 +0800 Subject: [PATCH 094/279] Prevent crash when requesting storage permissions on Android * java/org/gnu/emacs/EmacsService.java (requestStorageAccess30): Handle ActivityNotFoundException. --- java/org/gnu/emacs/EmacsService.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 04563590dc4..5225337a826 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java @@ -54,6 +54,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.content.ActivityNotFoundException; import android.content.ClipboardManager; import android.content.Context; import android.content.ContentResolver; @@ -2092,7 +2093,15 @@ public final class EmacsService extends Service /* Now request these permissions. */ - activity.startActivity (intent); + try + { + activity.startActivity (intent); + } + catch (ActivityNotFoundException exception) + { + Log.w (TAG, "Failed to request storage access permissions: "); + exception.printStackTrace (); + } } }; From f6e6585f5751852dbdc972fef8fc5a3ccc6e4573 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Fri, 7 Feb 2025 09:47:41 +0200 Subject: [PATCH 095/279] * lisp/progmodes/sh-script.el (bash-ts-mode): Improve treesit settings. Add 'list' and 'sentence' things to treesit-thing-settings, and move mistakenly added 'sentence' to 'text' (bug#73404). Set 'treesit-defun-name-function' and 'treesit-simple-imenu-settings'. Reset 'outline-regexp'. --- lisp/progmodes/sh-script.el | 41 ++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 3a41ef297ef..c4b7d0837a4 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -1646,10 +1646,45 @@ not written in Bash or sh." sh-mode--treesit-settings) (setq-local treesit-thing-settings `((bash - (sentence ,(regexp-opt '("comment" - "heredoc_start" - "heredoc_body")))))) + (list + ,(rx bos (or "do_group" + "if_statement" + "case_statement" + "compound_statement" + "subshell" + "test_command" + "parenthesized_expression" + "arithmetic_expansion" + "brace_expression" + "string" + "array" + "expansion" ;; but not "simple_expansion" + "command_substitution" + "process_substitution") + eos)) + (sentence + ,(rx bos (or "redirected_statement" + "declaration_command" + "unset_command" + "command" + "variable_assignment") + eos)) + (text + ,(rx bos (or "comment" + "heredoc_body") + eos))))) (setq-local treesit-defun-type-regexp "function_definition") + (setq-local treesit-defun-name-function + (lambda (node) + (treesit-node-text + (treesit-node-child-by-field-name node "name") + t))) + (setq-local treesit-simple-imenu-settings + '((nil "\\`function_definition\\'" nil nil))) + ;; Override regexp-based outline variable from `sh-base-mode' + ;; to use `treesit-simple-imenu-settings' for outlines: + (kill-local-variable 'outline-regexp) + (treesit-major-mode-setup))) (derived-mode-add-parents 'bash-ts-mode '(sh-mode)) From 92aecdfd9fda59f3ea66c5709f0bc7af882a0c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerd=20M=C3=B6llmann?= Date: Fri, 7 Feb 2025 11:27:06 +0100 Subject: [PATCH 096/279] ; Fix files-tests * test/lisp/files-tests.el (files-tests--with-buffer-offer-save): Override symbol function of read-key instead of read-event. --- test/lisp/files-tests.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index e085d052e1c..5e2c4eb2669 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1973,7 +1973,7 @@ FN-TEST is the function to test: either `save-some-buffers' or `save-some-buffers-default-predicate' let-bound to a value specified inside ARGS-RESULTS. -During the call to FN-TEST,`read-event' is overridden with a function that +During the call to FN-TEST,`read-key' is overridden with a function that just returns `n' and `kill-emacs' is overridden to do nothing. ARGS-RESULTS is a list of elements (FN-ARGS CALLERS-DIR EXPECTED), where @@ -2004,7 +2004,7 @@ CALLERS-DIR specifies the value to let-bind (setq nb-saved-buffers 0) (with-current-buffer (car buffers) (cl-letf - (((symbol-function 'read-event) + (((symbol-function 'read-key) ;; Increase counter and answer 'n' when prompted ;; to save a buffer. (lambda (&rest _) (cl-incf nb-saved-buffers) ?n)) From d41178368eb73873f34c15b58062a7447802c914 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Fri, 7 Feb 2025 12:04:05 +0100 Subject: [PATCH 097/279] New function insert-special-event and special event sleep-event * doc/lispref/commands.texi (Misc Events): Add sleep-event. (Special Events): New function insert-special-event. * etc/NEWS: New function insert-special-event. New event 'sleep-event'. Fix typos. * src/keyboard.c (Finsert_special_event): New defun. (syms_of_keyboard): Declare Qsleep_event. Define subroutine Sinsert_special_event. Add sleep-event to Vspecial_event_map. (Bug#63620) (kbd_buffer_get_event, make_lispy_event) (init_while_no_input_ignore_events, is_ignored_event): * src/termhooks.h (event_kind): Add SLEEP_EVENT. --- doc/lispref/commands.texi | 32 +++++++++++++++++++ etc/NEWS | 19 ++++++++--- src/keyboard.c | 67 +++++++++++++++++++++++++++++++++++++++ src/termhooks.h | 3 ++ 4 files changed, 117 insertions(+), 4 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 39514145a1e..c3891b70406 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2756,6 +2756,14 @@ To test the signal handler, you can make Emacs send a signal to itself: (signal-process (emacs-pid) 'sigusr1) @end smallexample +@cindex @code{sleep-event} event +@item (sleep-event @var{sleep-wake}) +This event is injected when the device Emacs is running on enters or +leaves the sleep state. A non-@code{nil} @var{sleep-wake} indicates +entering the sleep state. + +This is implemented only on GNU/Linux. + @cindex @code{language-change} event @item language-change This kind of event is generated on MS-Windows when the input language @@ -4029,6 +4037,30 @@ The keymap which defines how to handle special events---and which events are special---is in the variable @code{special-event-map} (@pxref{Controlling Active Maps}). +@defun insert-special-event +@cindex inserting special events +This function inserts a special event into the input event queue. Only +event types which are contained in the @code{special-event-map} keymap +are accepted. As a result, the handler specified in the keymap is +invoked. + +The function returns @code{nil}. Example: + +@example +(defun my-event-handler (event) + (interactive "e") + (message "Event arrived: %S" event)) +@result{} my-event-handler + +(keymap-set special-event-map "" #'my-event-handler) +@result{} my-event-handler + +(insert-special-event '(sleep-event t)) +@result{} nil +@result{} "Event arrived: (sleep-event t)" +@end example +@end defun + @node Waiting @section Waiting for Elapsed Time or Input @cindex waiting diff --git a/etc/NEWS b/etc/NEWS index ade635aa924..df1aff9213e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -486,9 +486,9 @@ Emacs exit. ** Message --- -*** In-Reply-To header contains only a message id. -The In-Reply-To header created when replying to a message now contains -only the originating message's id, conforming to RFC5322. The previous +*** "In-Reply-To" header contains only a message id. +The "In-Reply-To" header created when replying to a message now contains +only the originating message's id, conforming to RFC 5322. The previous behavior included additional information about the originating message. The new variable 'message-header-use-obsolete-in-reply-to', nil by default, can be set to a non-nil value to restore the previous behavior. @@ -993,7 +993,7 @@ instead. Since Python 2 EOL was over 5 years ago, this release removes Python 2-only builtins such as "file" from the default highlighting in 'python-mode' and 'python-ts-mode'. If you would like them highlighted, -customize the new user option `python-2-support' to a non-nil value and +customize the new user option 'python-2-support' to a non-nil value and restart Emacs. --- @@ -1354,6 +1354,17 @@ provide instructions for finding the definition. New convenience function 'find-function-update-type-alist' offers a concise way to update a symbol's 'find-function-type-alist' property. +** Special Events + ++++ +*** New primitive 'insert-special-event'. +This function inserts the special EVENT into the input event queue. + ++++ +*** New event type 'sleep-event'. +This event is sent when the device running Emacs enters or leaves the +sleep state. + * Changes in Emacs 31.1 on Non-Free Operating Systems diff --git a/src/keyboard.c b/src/keyboard.c index 2d8c45c05ee..ace5e1e3fef 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4273,6 +4273,7 @@ kbd_buffer_get_event (KBOARD **kbp, case CONFIG_CHANGED_EVENT: case FOCUS_OUT_EVENT: case SELECT_WINDOW_EVENT: + case SLEEP_EVENT: { obj = make_lispy_event (&event->ie); kbd_fetch_ptr = next_kbd_event (event); @@ -7110,6 +7111,9 @@ make_lispy_event (struct input_event *event) #endif #endif /* USE_FILE_NOTIFY */ + case SLEEP_EVENT: + return Fcons (Qsleep_event, event->arg); + case CONFIG_CHANGED_EVENT: return list3 (Qconfig_changed_event, event->arg, event->frame_or_window); @@ -11631,6 +11635,63 @@ If CHECK-TIMERS is non-nil, timers that are ready to run will do so. */) ? Qt : Qnil); } +DEFUN ("insert-special-event", Finsert_special_event, Sinsert_special_event, + 1, 1, 0, + doc: /* Insert the special EVENT into the input event queue. +Only 'input_event' slots KIND and ARG are set. */) + (Lisp_Object event) +{ + /* Check, that it is a special event. */ + CHECK_CONS (event); + if (NILP (access_keymap + (get_keymap (Vspecial_event_map, 0, 1), event, 0, 0, 1))) + signal_error ("Invalid event kind", XCAR (event)); + + /* Construct an input event. */ + struct input_event ie; + EVENT_INIT (ie); + ie.kind = + (EQ (XCAR (event), Qdelete_frame) ? DELETE_WINDOW_EVENT +#ifdef HAVE_NTGUI + : EQ (XCAR (event), Qend_session) ? END_SESSION_EVENT +#endif +#ifdef HAVE_NS + : EQ (XCAR (event), Qns_put_working_text) ? KEY_NS_PUT_WORKING_TEXT +#endif +#ifdef HAVE_NS + : EQ (XCAR (event), Qns_unput_working_text) ? KEY_NS_UNPUT_WORKING_TEXT +#endif + : EQ (XCAR (event), Qiconify_frame) ? ICONIFY_EVENT + : EQ (XCAR (event), Qmake_frame_visible) ? DEICONIFY_EVENT + // : EQ (XCAR (event), Qselect_window) ? SELECT_WINDOW_EVENT + : EQ (XCAR (event), Qsave_session) ? SAVE_SESSION_EVENT +#ifdef HAVE_DBUS + : EQ (XCAR (event), Qdbus_event) ? DBUS_EVENT +#endif +#ifdef THREADS_ENABLED + : EQ (XCAR (event), Qthread_event) ? THREAD_EVENT +#endif +#ifdef USE_FILE_NOTIFY + : EQ (XCAR (event), Qfile_notify) ? FILE_NOTIFY_EVENT +#endif /* USE_FILE_NOTIFY */ + : EQ (XCAR (event), Qconfig_changed_event) ? CONFIG_CHANGED_EVENT +#if defined (WINDOWSNT) + : EQ (XCAR (event), Qlanguage_change) ? LANGUAGE_CHANGE_EVENT +#endif + : EQ (XCAR (event), Qfocus_in) ? FOCUS_IN_EVENT + : EQ (XCAR (event), Qfocus_out) ? FOCUS_OUT_EVENT + : EQ (XCAR (event), Qmove_frame) ? MOVE_FRAME_EVENT + : EQ (XCAR (event), Qsleep_event) ? SLEEP_EVENT + : NO_EVENT); + ie.frame_or_window = Qnil; + ie.arg = CDR (event); + + /* Store it into the input event queue. */ + kbd_buffer_store_event (&ie); + + return (Qnil); +} + /* Reallocate recent_keys copying the recorded keystrokes in the right order. */ static void @@ -12803,6 +12864,7 @@ init_while_no_input_ignore_events (void) #ifdef THREADS_ENABLED events = Fcons (Qthread_event, events); #endif + events = Fcons (Qsleep_event, events); return events; } @@ -12826,6 +12888,7 @@ is_ignored_event (union buffered_input_event *event) #ifdef HAVE_DBUS case DBUS_EVENT: ignore_event = Qdbus_event; break; #endif + case SLEEP_EVENT: ignore_event = Qsleep_event; break; default: ignore_event = Qnil; break; } @@ -12931,6 +12994,7 @@ syms_of_keyboard (void) #endif /* USE_FILE_NOTIFY */ DEFSYM (Qtouch_end, "touch-end"); + DEFSYM (Qsleep_event, "sleep-event"); /* Menu and tool bar item parts. */ DEFSYM (QCenable, ":enable"); @@ -13144,6 +13208,7 @@ syms_of_keyboard (void) defsubr (&Srecursive_edit); defsubr (&Sinternal_track_mouse); defsubr (&Sinput_pending_p); + defsubr (&Sinsert_special_event); defsubr (&Slossage_size); defsubr (&Srecent_keys); defsubr (&Sthis_command_keys); @@ -14017,6 +14082,8 @@ keys_of_keyboard (void) "handle-focus-out"); initial_define_lispy_key (Vspecial_event_map, "move-frame", "handle-move-frame"); + initial_define_lispy_key (Vspecial_event_map, "sleep-event", + "ignore"); } /* Mark the pointers in the kboard objects. diff --git a/src/termhooks.h b/src/termhooks.h index 0795148f1af..a77ca25e159 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -291,6 +291,9 @@ enum event_kind , FILE_NOTIFY_EVENT #endif + /* Sleep/wake event. */ + , SLEEP_EVENT + /* Pre-edit text was changed. */ , PREEDIT_TEXT_EVENT From f806b9cba6568433e36878ed005673a5788c004f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 7 Feb 2025 13:37:56 +0200 Subject: [PATCH 098/279] ; * src/keyboard.c (Finsert_special_event): Don't use "//". --- src/keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard.c b/src/keyboard.c index ace5e1e3fef..e91bd3d68b4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -11663,7 +11663,7 @@ Only 'input_event' slots KIND and ARG are set. */) #endif : EQ (XCAR (event), Qiconify_frame) ? ICONIFY_EVENT : EQ (XCAR (event), Qmake_frame_visible) ? DEICONIFY_EVENT - // : EQ (XCAR (event), Qselect_window) ? SELECT_WINDOW_EVENT + /* : EQ (XCAR (event), Qselect_window) ? SELECT_WINDOW_EVENT */ : EQ (XCAR (event), Qsave_session) ? SAVE_SESSION_EVENT #ifdef HAVE_DBUS : EQ (XCAR (event), Qdbus_event) ? DBUS_EVENT From 1ef9de69b3c3d8254ab58bf455137a4439dce516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Fri, 7 Feb 2025 11:08:29 +0000 Subject: [PATCH 099/279] Eglot: add support for call and type hierarchies * lisp/progmodes/eglot.el (eglot--lsp-interface-alist): Add new interfaces. (eglot-client-capabilities): Advertise support for callHierarchy and typeHierarchy. (eglot-ignored-server-capabilities): Add new providers. (eglot--goto): New helper. (eglot-menu): Add new menu items. (eglot-handle-request window/showDocument): Use eglot--goto. (button, tree-widget): Require them. (eglot--hierarchy-item): New button type. (eglot--hierarchy-interactive, eglot--hierarchy-children) (eglot--hierarchy-label, eglot--hierarchy-1, eglot--hierarchy-2): New internal functions. (eglot--define-hierarchy-command): New macro. (eglot-show-type-hierarchy, eglot-show-call-hierarchy) (eglot-hierarchy-center-on-node): New commands. (eglot--hierarchy-roots, eglot--hierarchy-specs): New local variables. (eglot-hierarchy-label-map): New keymap. (eglot-hierarchy-mode): New major mode. * doc/misc/eglot.texi (Eglot Commands, Eglot Features): Describe new feature. * etc/EGLOT-NEWS (Changes in upcoming Eglot): Mention new feature. --- doc/misc/eglot.texi | 15 +++ etc/EGLOT-NEWS | 7 ++ lisp/progmodes/eglot.el | 221 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 235 insertions(+), 8 deletions(-) diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi index 722766843ec..333e369e440 100644 --- a/doc/misc/eglot.texi +++ b/doc/misc/eglot.texi @@ -452,6 +452,11 @@ be it the type of a variable, or the name of a formal parameter in a function call. @xref{Eglot Commands} and the @code{eglot-inlay-hints-mode} minor mode. +@item +Display of function call and type hierarchies via the +@code{eglot-show-call-hierarchy} and @code{eglot-show-type-hierarchy} +commands (@pxref{Eglot Commands}). + @item Code reformatting via the @code{eglot-format} and related commands (@pxref{Eglot Commands}). Automatic reformatting of source code is also @@ -738,6 +743,16 @@ instead of indicating problems. For example, a C++ language server can serve hints about positional parameter names in function calls and a variable's automatically deduced type. Inlay hints help the user not have to remember these things by heart. + +@cindex type hierarchy +@item M-x eglot-show-type-hierarchy +Pop up a special buffer showing a interactive tree which represents a +hierarchy of subtypes and supertypes for the symbol at point. + +@cindex call hierarchy +@item M-x eglot-call-type-hierarchy +Pop up a special buffer showing a interactive tree which represents a +hierarchy of callers and callee for the symbol at point. @end ftable The following Eglot commands are used less commonly, mostly for diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index 02355e25f93..20a2e694426 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -20,6 +20,13 @@ https://github.com/joaotavora/eglot/issues/1234. * Changes in upcoming Eglot +** Support for call and type hierarchies + +The new commands 'eglot-show-type-hierarchy' and +'eglot-show-call-hierarchy', when invoked on a symbol, pop up a special +buffer showing an interactive tree which represents a hierarchy of sub- +and super-types or callers and callees for that symbol. + ** New 'eglot-advertise-cancellation' variable Tweaking this variable may help some LSP servers avoid doing costly but diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 7b1c174c4d7..502effd098d 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -566,7 +566,9 @@ under cursor." (const :tag "Decorate color references" :colorProvider) (const :tag "Fold regions of buffer" :foldingRangeProvider) (const :tag "Execute custom commands" :executeCommandProvider) - (const :tag "Inlay hints" :inlayHintProvider))) + (const :tag "Inlay hints" :inlayHintProvider) + (const :tag "Type hierarchies" :typeHierarchyProvider) + (const :tag "Call hierarchies" :callHierarchyProvider))) (defcustom eglot-advertise-cancellation nil "If non-nil, Eglot attemps to inform server of cancelled requests. @@ -717,7 +719,13 @@ This can be useful when using docker to run a language server.") (WorkspaceSymbol (:name :kind) (:containerName :location :data)) (InlayHint (:position :label) (:kind :textEdits :tooltip :paddingLeft :paddingRight :data)) - (InlayHintLabelPart (:value) (:tooltip :location :command))) + (InlayHintLabelPart (:value) (:tooltip :location :command)) + ;; HACK! 'HierarchyItem' doesn't exist, only `CallHierarchyItem' + ;; and `TypeHierarchyItem'. But they're the same, so no bother. + (HierarchyItem (:name :kind) + (:tags :detail :uri :range :selectionRange :data)) + (CallHierarchyIncomingCall (:from :fromRanges) ()) + (CallHierarchyOutgoingCall (:to :fromRanges) ())) "Alist (INTERFACE-NAME . INTERFACE) of known external LSP interfaces. INTERFACE-NAME is a symbol designated by the spec as @@ -1066,6 +1074,8 @@ object." :rangeFormatting `(:dynamicRegistration :json-false) :rename `(:dynamicRegistration :json-false) :inlayHint `(:dynamicRegistration :json-false) + :callHierarchy `(:dynamicRegistration :json-false) + :typeHierarchy `(:dynamicRegistration :json-false) :publishDiagnostics (list :relatedInformation :json-false ;; TODO: We can support :codeDescription after ;; adding an appropriate UI to @@ -1782,6 +1792,15 @@ in project `%s'." (let ((warning-minimum-level :error)) (display-warning 'eglot (apply #'eglot--format format args) :warning))) +(defun eglot--goto (range) + "Goto and momentarily highlight RANGE in current buffer." + (pcase-let ((`(,beg . ,end) (eglot-range-region range))) + ;; FIXME: it is very naughty to use someone else's `--' + ;; function, but `xref--goto-char' happens to have + ;; exactly the semantics we want vis-a-vis widening. + (xref--goto-char beg) + (pulse-momentary-highlight-region beg end 'highlight))) + (defalias 'eglot--bol (if (fboundp 'pos-bol) #'pos-bol (lambda (&optional n) (let ((inhibit-field-text-motion t)) @@ -2285,6 +2304,9 @@ If it is activated, also signal textDocument/didOpen." :visible (eglot-server-capable :codeActionProvider)] ["Quickfix" eglot-code-action-quickfix :visible (eglot-server-capable :codeActionProvider)] + "--" + ["Show type hierarchy" eglot-show-type-hierarchy] + ["Show call hierarchy" eglot-show-call-hierarchy] "--")) (easy-menu-define eglot-server-menu nil "Manage server communication" @@ -2699,12 +2721,7 @@ THINGS are either registrations or unregisterations (sic)." (select-frame-set-input-focus (selected-frame))) ((display-buffer (current-buffer)))) (when selection - (pcase-let ((`(,beg . ,end) (eglot-range-region selection))) - ;; FIXME: it is very naughty to use someone else's `--' - ;; function, but `xref--goto-char' happens to have - ;; exactly the semantics we want vis-a-vis widening. - (xref--goto-char beg) - (pulse-momentary-highlight-region beg end 'highlight))))))) + (eglot--goto selection)))))) (t (setq success :json-false))) `(:success ,success))) @@ -4369,6 +4386,194 @@ If NOERROR, return predicate, else erroring function." (jit-lock-unregister #'eglot--update-hints) (remove-overlays nil nil 'eglot--inlay-hint t)))) + +;;; Call and type hierarchies +(require 'button) +(require 'tree-widget) + +(define-button-type 'eglot--hierarchy-item + 'follow-link t + 'face 'font-lock-function-name-face) + +(defun eglot--hierarchy-interactive (specs) + (let ((ans + (completing-read "[eglot] Direction (default both)?" + (cons "both" (mapcar #'cl-fourth specs)) + nil t nil nil "both"))) + (list + (cond ((equal ans "both") t) + (t (cl-third (cl-find ans specs :key #'cl-fourth :test #'equal))))))) + +(defmacro eglot--define-hierarchy-command + (name kind feature preparer specs) + `(defun ,name (direction) + ,(concat + "Show " kind " hierarchy for symbol at point.\n" + "DIRECTION can be:\n" + (cl-loop for (_ _ d e) in specs + concat (format " - `%s' for %s;\n" d e)) + "or t, the default, to consider both.\n" + "Interactively with a prefix argument, prompt for DIRECTION.") + (interactive (if current-prefix-arg + (eglot--hierarchy-interactive ',specs) + (list t))) + (let* ((specs ',specs) + (specs (if (eq t direction) specs + (list + (cl-find direction specs :key #'cl-third))))) + (eglot--hierarchy-1 + (format "*EGLOT %s hierarchy for %s*" + ,kind + (eglot-project-nickname (eglot--current-server-or-lose))) + ,feature ,preparer specs)))) + +(eglot--define-hierarchy-command + eglot-show-type-hierarchy + "type" + :typeHierarchyProvider + :textDocument/prepareTypeHierarchy + ((:typeHierarchy/supertypes " ↑ " derived "supertypes" "derives from") + (:typeHierarchy/subtypes " ↓ " base "subtypes" "base of"))) + +(eglot--define-hierarchy-command + eglot-show-call-hierarchy + "call" + :callHierarchyProvider + :textDocument/prepareCallHierarchy + ((:callHierarchy/incomingCalls " ← " incoming "incoming calls" "called by" + :from :fromRanges) + (:callHierarchy/outgoingCalls " → " base "outgoing calls" "calls" + :to :fromRanges))) + +(defvar-local eglot--hierarchy-roots nil) +(defvar-local eglot--hierarchy-specs nil) + +(defun eglot--hierarchy-children (node) + (cl-flet ((get-them (method node) + (eglot--dbind ((HierarchyItem) name) node + (let* ((sym (intern (format "eglot--%s" method))) + (plist (text-properties-at 0 name)) + (probe (cl-getf plist sym :none))) + (cond ((eq probe :none) + (let ((v (ignore-errors (jsonrpc-request + (eglot--current-server-or-lose) method + `(:item ,node))))) + (put-text-property 0 1 sym v name) + v)) + (t probe)))))) + (cl-loop + with specs = eglot--hierarchy-specs + for (method bullet _ _ hint key ranges) in specs + for resp = (get-them method node) + for items = + (cl-loop for r across resp + for item = (if key (plist-get r key) r) + collect item + do (eglot--dbind ((HierarchyItem) name) item + (put-text-property 0 1 'eglot--hierarchy-method + method name) + (put-text-property 0 1 'eglot--hierarchy-bullet + (propertize bullet + 'help-echo hint) + name) + (when ranges + (put-text-property 0 1 'eglot--hierarchy-call-sites + (plist-get r ranges) + name)))) + append items))) + +(defvar eglot-hierarchy-label-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map button-map) + (define-key map [mouse-3] (eglot--mouse-call + #'eglot-hierarchy-center-on-node)) + map) + "Keymap active in labels Eglot hierarchy buffers.") + +(defun eglot--hierarchy-label (node) + (eglot--dbind ((HierarchyItem) name uri _detail ((:range item-range))) node + (with-temp-buffer + (insert (propertize + (or (get-text-property + 0 'eglot--hierarchy-bullet name) + " ∘ ") + 'face 'shadow)) + (insert-text-button + name + :type 'eglot--hierarchy-item + 'eglot--hierarchy-node node + 'help-echo "mouse-1, RET: goto definition, mouse-3: center on node" + 'keymap eglot-hierarchy-label-map + 'action + (lambda (_btn) + (pop-to-buffer (find-file-noselect (eglot-uri-to-path uri))) + (eglot--goto + (or + (elt + (get-text-property 0 'eglot--hierarchy-call-sites name) + 0) + item-range)))) + (buffer-string)))) + +(defun eglot--hierarchy-1 (name provider preparer specs) + (eglot-server-capable-or-lose provider) + (let* ((server (eglot-current-server)) + (roots (jsonrpc-request + server + preparer + (eglot--TextDocumentPositionParams)))) + (with-current-buffer (get-buffer-create name) + (eglot-hierarchy-mode) + (setq-local + eglot--hierarchy-roots roots + eglot--hierarchy-specs specs + eglot--cached-server server + buffer-read-only t + revert-buffer-function + (lambda (&rest _ignore) + ;; flush cache, would defeat purpose of a revert + (mapc (lambda (r) + (eglot--dbind ((HierarchyItem) name) r + (set-text-properties 0 1 nil name))) + eglot--hierarchy-roots) + (eglot--hierarchy-2))) + (eglot--hierarchy-2)))) + +(defun eglot--hierarchy-2 () + (cl-labels ((expander-for (node) + (lambda (_widget) + (mapcar + #'convert + (eglot--hierarchy-children node)))) + (convert (node) + (let ((w (widget-convert + 'tree-widget + :tag (eglot--hierarchy-label node) + :expander (expander-for node)))) + (widget-put w :empty-icon + (widget-get w :leaf-icon)) + w))) + (let ((inhibit-read-only t)) + (erase-buffer) + (mapc (lambda (r) + (widget-create (convert r))) + eglot--hierarchy-roots) + (goto-char (point-min)))) + (pop-to-buffer (current-buffer))) + +(define-derived-mode eglot-hierarchy-mode special-mode + "Eglot special" "Eglot mode for viewing hierarchies. +\\{eglot-hierarchy-mode-map}" + :interactive nil) + +(defun eglot-hierarchy-center-on-node () + "Refresh hierarchy, centering on node at point." + (interactive) + (setq-local eglot--hierarchy-roots + (list (get-text-property (point) + 'eglot--hierarchy-node))) + (eglot--hierarchy-2)) + ;;; Hacks ;;; From 8be3be7330953dd015df28369c1f071178248bb4 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Fri, 7 Feb 2025 14:41:58 +0100 Subject: [PATCH 100/279] Use insert-special-event in Tramp * lisp/net/tramp-gvfs.el (tramp-gvfs-monitor-process-filter): * lisp/net/tramp-sh.el (tramp-sh-gio-monitor-process-filter) (tramp-sh-inotifywait-process-filter): Use `insert-special-event' if possible. --- lisp/net/tramp-gvfs.el | 12 ++++++++---- lisp/net/tramp-sh.el | 22 ++++++++++++---------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index b31095fb914..53a6ffc48aa 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1569,11 +1569,15 @@ If FILE-SYSTEM is non-nil, return file system attributes." (when (and (member action '(moved deleted)) (string-equal file (process-get proc 'tramp-watch-name))) (delete-process proc)) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the callback directly. + ;; Add an Emacs event now. + ;; `insert-special-event' exists since Emacs 31. (when (member action events) - (file-notify-callback (list proc action file file1))))) + (tramp-compat-funcall + (if (fboundp 'insert-special-event) + 'insert-special-event + (lookup-key special-event-map [file-notify])) + `(file-notify + ,(list proc action file file1) file-notify-callback))))) ;; Save rest of the string. (when (string-empty-p string) (setq string nil)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 40013852153..e268489b7c8 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -3898,13 +3898,14 @@ Fall back to normal file name handler if no Tramp handler exists." (concat remote-prefix file) (when file1 (concat remote-prefix file1))))) (setq string (replace-match "" nil nil string)) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the handler directly. + ;; Add an Emacs event now. + ;; `insert-special-event' exists since Emacs 31. (when (member (cl-caadr object) events) (tramp-compat-funcall - (lookup-key special-event-map [file-notify]) - `(file-notify ,object file-notify-callback)))))) + (if (fboundp 'insert-special-event) + 'insert-special-event + (lookup-key special-event-map [file-notify])) + `(file-notify ,object file-notify-callback)))))) ;; Save rest of the string. (while (string-match (rx bol "\n") string) @@ -3934,13 +3935,14 @@ Fall back to normal file name handler if no Tramp handler exists." (or (match-string 2 line) (file-name-nondirectory (process-get proc 'tramp-watch-name)))))) - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the handler directly. + ;; Add an Emacs event now. + ;; `insert-special-event' exists since Emacs 31. (when (member (cl-caadr object) events) (tramp-compat-funcall - (lookup-key special-event-map [file-notify]) - `(file-notify ,object file-notify-callback))))))) + (if (fboundp 'insert-special-event) + 'insert-special-event + (lookup-key special-event-map [file-notify])) + `(file-notify ,object file-notify-callback))))))) (defun tramp-sh-handle-file-system-info (filename) "Like `file-system-info' for Tramp files." From 0065c9dbb8fb7d2b802e8f9a327f33049afec4ad Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Fri, 7 Feb 2025 15:14:47 +0100 Subject: [PATCH 101/279] Suppress unneded events in special-event-map * src/keyboard.c (keys_of_keyboard): Don't add ns-put-working-text and ns-unput-working-text to Vspecial_event_map unless on NS port. --- src/keyboard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/keyboard.c b/src/keyboard.c index e91bd3d68b4..2b904b64cbe 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -14014,10 +14014,12 @@ keys_of_keyboard (void) initial_define_lispy_key (Vspecial_event_map, "end-session", "kill-emacs"); #endif +#ifdef HAVE_NS initial_define_lispy_key (Vspecial_event_map, "ns-put-working-text", "ns-put-working-text"); initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text", "ns-unput-working-text"); +#endif /* Here we used to use `ignore-event' which would simple set prefix-arg to current-prefix-arg, as is done in `handle-switch-frame'. But `handle-switch-frame is not run from the special-map. From a62b58648ac54feb8fb81aefdb0461cb11bf6a81 Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Fri, 7 Feb 2025 15:48:47 +0100 Subject: [PATCH 102/279] ; * src/keyboard.c (syms_of_keyboard): Fix previous change. --- src/keyboard.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/keyboard.c b/src/keyboard.c index 2b904b64cbe..ac143af83f4 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -13965,7 +13965,10 @@ function is called to remap that sequence. */); pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper); DEFSYM (Qactivate_mark_hook, "activate-mark-hook"); +#ifdef HAVE_NS + DEFSYM (Qns_put_working_text, "ns-put-working-text"); DEFSYM (Qns_unput_working_text, "ns-unput-working-text"); +#endif DEFSYM (Qinternal_timer_start_idle, "internal-timer-start-idle"); DEFSYM (Qconcat, "concat"); DEFSYM (Qsuspend_hook, "suspend-hook"); From 280b25e0096bb97fb473a8da9b4635fb2d6e5385 Mon Sep 17 00:00:00 2001 From: Stephen Gildea Date: Fri, 7 Feb 2025 09:17:26 -0800 Subject: [PATCH 103/279] time-stamp: Better handling of some edge cases * lisp/time-stamp.el (time-stamp-count): Require confirmation if large. (time-stamp-once): Correctly handle a start regexp matching 0 chars. * test/lisp/time-stamp-tests.el (time-stamp-custom-start): New test. --- lisp/time-stamp.el | 20 +++++++++++-------- test/lisp/time-stamp-tests.el | 36 ++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index ad356eb2bd6..4117db71058 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el @@ -114,7 +114,7 @@ limit yourself to the formats recommended by that older version." (defcustom time-stamp-active t - "Non-nil to enable time-stamping of buffers by \\[time-stamp]. + "Non-nil enables time-stamping of buffers by \\[time-stamp]. Can be toggled by \\[time-stamp-toggle-active]. This option does not affect when `time-stamp' is run, only what it @@ -257,7 +257,7 @@ then instead of changing this variable, include a newline (written as `time-stamp-count' is best changed with a file-local variable. If you were to change it in your init file, you would be incompatible with other people's files.") -;;;###autoload(put 'time-stamp-count 'safe-local-variable 'integerp) +;;;###autoload(put 'time-stamp-count 'safe-local-variable (lambda (c) (and (integerp c) (< c 100)))) (defvar time-stamp-pattern nil ;Do not change! @@ -342,12 +342,11 @@ To enable automatic time-stamping for only a specific file, add this line to a local variables list near the end of the file: eval: (add-hook \\='before-save-hook \\='time-stamp nil t) -If the file has no time stamp template, this function does nothing. +If the file has no time stamp template or if `time-stamp-active' is nil, +this function does nothing. You can set `time-stamp-pattern' in a file's local variables list -to customize the information in the time stamp and where it is written. - -The time stamp is updated only if `time-stamp-active' is non-nil." +to customize the information in the time stamp and where it is written." (interactive) (let ((line-limit time-stamp-line-limit) (ts-start time-stamp-start) @@ -421,6 +420,7 @@ The time stamp is updated only if `time-stamp-active' is non-nil." Returns the end point, which is where `time-stamp' begins the next search." (let ((case-fold-search nil) (end nil) + (advance-nudge 0) end-search-start (end-length nil)) (save-excursion @@ -430,6 +430,9 @@ Returns the end point, which is where `time-stamp' begins the next search." (while (and (< (goto-char start) search-limit) (not end) (re-search-forward ts-start search-limit 'move)) + ;; Whether or not we find a template, we must + ;; advance through the buffer. + (setq advance-nudge (if (> (point) start) 0 1)) (setq start (point)) (if (not time-stamp-inserts-lines) (forward-line format-lines)) @@ -444,7 +447,8 @@ Returns the end point, which is where `time-stamp' begins the next search." (if (re-search-forward ts-end line-end t) (progn (setq end (match-beginning 0)) - (setq end-length (- (match-end 0) end)))))))))))) + (setq end-length (- (match-end 0) end))) + (setq start (+ start advance-nudge))))))))))) (if end (progn ;; do all warnings outside save-excursion @@ -478,7 +482,7 @@ Returns the end point, which is where `time-stamp' begins the next search." (setq end (point)))))))))))) ;; return the location after this time stamp, if there was one (and end end-length - (+ end end-length)))) + (+ end (max advance-nudge end-length))))) ;;;###autoload diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el index a7aa00dc267..f4fcce3e957 100644 --- a/test/lisp/time-stamp-tests.el +++ b/test/lisp/time-stamp-tests.el @@ -138,6 +138,31 @@ (iter-yield-from (time-stamp-test-pattern-sequential)) (iter-yield-from (time-stamp-test-pattern-multiply))) +(ert-deftest time-stamp-custom-start () + "Test that `time-stamp' isn't stuck by a start matching 0 characters." + (with-time-stamp-test-env + (with-time-stamp-test-time ref-time1 + (let ((time-stamp-pattern "^%Y-%m-%d<-TS")) ;start matches 0 chars + (with-temp-buffer + (insert "\n<-TS\n") + ;; we should advance to line 2 and find the template + (time-stamp) + (should (equal (buffer-string) "\n2006-01-02<-TS\n")))) + (let ((time-stamp-pattern "\\b%Y-%m-%d\\b") ;start and end match 0 chars + (time-stamp-count 2)) + (with-temp-buffer + (insert "..") + ;; the two time stamps should be in different places + (time-stamp) + (should (equal (buffer-string) "2006-01-02..2006-01-02")))) + (let ((time-stamp-pattern "::%S\\_>") ;end matches 0 chars + (time-stamp-count 2)) + (with-temp-buffer + (insert "::0::0") + ;; the second template should be found immediately after the first + (time-stamp) + (should (equal (buffer-string) "::05::05"))))))) + (ert-deftest time-stamp-custom-pattern () "Test that `time-stamp-pattern' is parsed correctly." (iter-do (pattern-parts (time-stamp-test-pattern-all)) @@ -246,17 +271,17 @@ (let ((time-stamp-start "TS: <") (time-stamp-format "%Y-%m-%d") (time-stamp-count 0) ;changed later in the test - (buffer-expected-once "TS: <2006-01-02>\nTS: <>") - (buffer-expected-twice "TS: <2006-01-02>\nTS: <2006-01-02>")) + (buffer-expected-once "TS: <2006-01-02>TS: <>") + (buffer-expected-twice "TS: <2006-01-02>TS: <2006-01-02>")) (with-time-stamp-test-time ref-time1 (with-temp-buffer - (insert "TS: <>\nTS: <>") + (insert "TS: <>TS: <>") (time-stamp) ;; even with count = 0, expect one time stamp (should (equal (buffer-string) buffer-expected-once))) (with-temp-buffer (setq time-stamp-count 1) - (insert "TS: <>\nTS: <>") + (insert "TS: <>TS: <>") (time-stamp) (should (equal (buffer-string) buffer-expected-once)) @@ -698,7 +723,7 @@ (should (equal (time-stamp-string "%5z" ref-time1) "+0000")) (let ((time-stamp-time-zone "PST8")) (should (equal (time-stamp-string "%5z" ref-time1) "-0800"))) - (let ((time-stamp-time-zone "HST10")) + (let ((time-stamp-time-zone '(-36000 "HST"))) (should (equal (time-stamp-string "%5z" ref-time1) "-1000"))) (let ((time-stamp-time-zone "CET-1")) (should (equal (time-stamp-string "%5z" ref-time1) "+0100"))) @@ -887,6 +912,7 @@ (should (safe-local-variable-p 'time-stamp-inserts-lines t)) (should-not (safe-local-variable-p 'time-stamp-inserts-lines 17)) (should (safe-local-variable-p 'time-stamp-count 2)) + (should-not (safe-local-variable-p 'time-stamp-count 100)) (should-not (safe-local-variable-p 'time-stamp-count t)) (should (safe-local-variable-p 'time-stamp-pattern "a string")) (should-not (safe-local-variable-p 'time-stamp-pattern 17))) From 0c0f5f5df24947f0658c274f9fa62829ef5401dd Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 7 Feb 2025 21:22:38 +0100 Subject: [PATCH 104/279] Mark IRIX support in GUD as obsolete * lisp/progmodes/gud.el (gud-irix-p, gud-dbx-use-stopformat-p) (gud-irixdbx-marker-filter): Mark as obsolete. We stopped supporting IRIX in Emacs 26.1 (commit 6bc8689c0428). * lisp/progmodes/gud.el (dbx): Suppress obsoletion warnings. --- lisp/progmodes/gud.el | 42 ++++++------------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index b63de1abff2..7ced54170ff 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -1261,42 +1261,16 @@ containing the executable being debugged." output)) -;; The dbx in IRIX is a pain. It doesn't print the file name when -;; stopping at a breakpoint (but you do get it from the `up' and -;; `down' commands...). The only way to extract the information seems -;; to be with a `file' command, although the current line number is -;; available in $curline. Thus we have to look for output which -;; appears to indicate a breakpoint. Then we prod the dbx sub-process -;; to output the information we want with a combination of the -;; `printf' and `file' commands as a pseudo marker which we can -;; recognize next time through the marker-filter. This would be like -;; the gdb marker but you can't get the file name without a newline... -;; Note that gud-remove won't work since Irix dbx expects a breakpoint -;; number rather than a line number etc. Maybe this could be made to -;; work by listing all the breakpoints and picking the one(s) with the -;; correct line number, but life's too short. -;; d.love@dl.ac.uk (Dave Love) can be blamed for this - (defvar gud-irix-p nil "Non-nil to assume the interface appropriate for IRIX dbx. This works in IRIX 4, 5 and 6, but `gud-dbx-use-stopformat-p' provides a better solution in 6.1 upwards.") +(make-obsolete-variable 'gud-irix-p nil "31.1") (defvar gud-dbx-use-stopformat-p nil "Non-nil to use the dbx feature present at least from Irix 6.1 whereby $stopformat=1 produces an output format compatible with `gud-dbx-marker-filter'.") -;; [Irix dbx seemed to be a moving target. The dbx output changed -;; subtly sometime between OS v4.0.5 and v5.2 so that, for instance, -;; the output from `up' is no longer spotted by gud (and it's probably -;; not distinctive enough to try to match it -- use C-<, C-> -;; exclusively) . For 5.3 and 6.0, the $curline variable changed to -;; `long long'(why?!), so the printf stuff needed changing. The line -;; number was cast to `long' as a compromise between the new `long -;; long' and the original `int'. This was reported not to work in 6.2, -;; so it's changed back to int -- don't make your sources too long. -;; From Irix6.1 (but not 6.0?) dbx supported an undocumented feature -;; whereby `set $stopformat=1' reportedly produces output compatible -;; with `gud-dbx-marker-filter', which we prefer. +(make-obsolete-variable 'gud-dbx-use-stopformat-p nil "31.1") (defvar-keymap gud-dbx-repeat-map :doc "Keymap to repeat `dbx' stepping instructions \\`C-x C-a C-n n n'. @@ -1313,13 +1287,8 @@ Used in `repeat-mode'." gud-irix-p) (keymap-set gud-dbx-repeat-map "f" #'gud-finish)) - -;; The process filter is also somewhat -;; unreliable, sometimes not spotting the markers; I don't know -;; whether there's anything that can be done about that.] - -;; this filter is influenced by the xdb one rather than the gdb one (defun gud-irixdbx-marker-filter (string) + (declare (obsolete nil "31.1")) (let (result (case-fold-search nil)) (if (or (string-match comint-prompt-regexp string) (string-match ".*\012" string)) @@ -1417,8 +1386,9 @@ and source-file directory for your debugger." (gud-mips-p (gud-common-init command-line nil 'gud-mipsdbx-marker-filter)) (gud-irix-p - (gud-common-init command-line 'gud-dbx-massage-args - 'gud-irixdbx-marker-filter)) + (with-suppressed-warnings ((obsolete gud-irixdbx-marker-filter)) + (gud-common-init command-line 'gud-dbx-massage-args + #'gud-irixdbx-marker-filter))) (t (gud-common-init command-line 'gud-dbx-massage-args 'gud-dbx-marker-filter))) From 7169a5d5636ddede2fe70a31de098031f20f70b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Fri, 7 Feb 2025 20:33:41 +0000 Subject: [PATCH 105/279] Eglot: fix bug in eglot--lookup-mode When lookup in eglot-server-programs fails, fall back to a half-decent (((foo-mode . "foo")) . nil) return value. This enables interactive M-x eglot for modes not yet registered in e-s-p. * lisp/progmodes/eglot.el (eglot--lookup-mode): Fallback when lookup fails. --- lisp/progmodes/eglot.el | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 502effd098d..728227f0e9a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1322,22 +1322,28 @@ in `eglot-server-programs' (which see). CONTACT-PROXY is the value of the corresponding `eglot-server-programs' entry." (cl-loop + with lang-from-sym = (lambda (sym &optional language-id) + (cons sym + (or language-id + (or (get sym 'eglot-language-id) + (replace-regexp-in-string + "\\(?:-ts\\)?-mode$" "" + (symbol-name sym)))))) for (modes . contact) in eglot-server-programs for llists = (mapcar #'eglot--ensure-list - (if (or (symbolp modes) (keywordp (cadr modes))) - (list modes) modes)) + (if (or (symbolp modes) (keywordp (cadr modes))) + (list modes) modes)) for normalized = (mapcar (jsonrpc-lambda (sym &key language-id &allow-other-keys) - (cons sym - (or language-id - (or (get sym 'eglot-language-id) - (replace-regexp-in-string - "\\(?:-ts\\)?-mode$" "" - (symbol-name sym)))))) + (funcall lang-from-sym sym language-id)) llists) when (cl-some (lambda (cell) (provided-mode-derived-p mode (car cell))) normalized) - return (cons normalized contact))) + return (cons normalized contact) + ;; If lookup fails at least return some suitable LANGUAGES. + finally (cl-return + (cons (list (funcall lang-from-sym major-mode)) + nil)))) (defun eglot--guess-contact (&optional interactive) "Helper for `eglot'. From be4cf26c16794021ae790f1eb82fccea6efaa354 Mon Sep 17 00:00:00 2001 From: Mauro Aranda Date: Fri, 7 Feb 2025 07:31:34 -0300 Subject: [PATCH 106/279] Fix gnus-score-find-score-files-function :type * lisp/gnus/gnus-score.el (gnus-score-find-score-files-function): Delete extra quotes. (Bug#76118) --- lisp/gnus/gnus-score.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el index ba5edd4bdc1..0551ca2676d 100644 --- a/lisp/gnus/gnus-score.el +++ b/lisp/gnus/gnus-score.el @@ -119,11 +119,11 @@ the `a' symbolic prefix to the score commands will always use (function-item gnus-score-find-hierarchical) (function-item gnus-score-find-bnews) (repeat :tag "List of functions" - (choice (function :tag "Other" :value 'ignore) + (choice (function :tag "Other" :value ignore) (function-item gnus-score-find-single) (function-item gnus-score-find-hierarchical) (function-item gnus-score-find-bnews))) - (function :tag "Other" :value 'ignore))) + (function :tag "Other" :value ignore))) (defcustom gnus-score-interactive-default-score 1000 "Scoring commands will raise/lower the score with this number as the default." From 93206cbcea31add3da76cc1025b2f148312fe6f1 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 23 Jan 2025 23:49:52 +0100 Subject: [PATCH 107/279] Remove leading '*' from docstrings in cc-vars.el * lisp/progmodes/cc-vars.el (c-make-font-lock-extra-types-blurb): Remove leading '*' from generated docstrings. (Bug#75793) --- lisp/progmodes/cc-vars.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el index 3c386eb07e9..0687801d69f 100644 --- a/lisp/progmodes/cc-vars.el +++ b/lisp/progmodes/cc-vars.el @@ -1566,7 +1566,7 @@ working due to this change." (defun c-make-font-lock-extra-types-blurb (mode1 mode2 example) (concat "\ -*List of extra types (aside from the type keywords) to recognize in " +List of extra types (aside from the type keywords) to recognize in " mode1 " mode. Each list item should be a regexp matching a single identifier. " example " From 0e4883f18eecea59e537e2368a0f5674888a1af7 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 7 Feb 2025 13:02:02 -0800 Subject: [PATCH 108/279] Update from Gnulib by running admin/merge-gnulib --- doc/misc/texinfo.tex | 825 ++++++++++++++++++++++++++----------------- lib/attribute.h | 8 +- lib/flexmember.h | 7 +- lib/gnulib.mk.in | 20 +- lib/intprops.h | 8 + m4/acl.m4 | 4 +- m4/gnulib-common.m4 | 10 +- m4/gnulib-comp.m4 | 32 +- 8 files changed, 569 insertions(+), 345 deletions(-) diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 456696f4c9e..faad184e345 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -3,9 +3,9 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2024-11-04.20} +\def\texinfoversion{2025-01-31.21} % -% Copyright 1985, 1986, 1988, 1990-2024 Free Software Foundation, Inc. +% Copyright 1985, 1986, 1988, 1990-2025 Free Software Foundation, Inc. % % This texinfo.tex file is free software: you can redistribute it and/or % modify it under the terms of the GNU General Public License as @@ -156,8 +156,9 @@ % Give the space character the catcode for a space. \def\spaceisspace{\catcode`\ =10\relax} -% Likewise for ^^M, the end of line character. -\def\endlineisspace{\catcode13=10\relax} +% Used to ignore an active newline that may appear immediately after +% a macro name. +{\catcode13=\active \gdef\ignoreactivenewline{\let^^M\empty}} \chardef\dashChar = `\- \chardef\slashChar = `\/ @@ -957,6 +958,10 @@ where each line of input produces a line of output.} \ifx\byeerror\relax\else\errmessage{\byeerror}\fi \tracingstats=1\ptexend} +% set in \donoderef below, but we need to define this here so that +% conditionals balance inside the large \ifpdf ... \fi blocks below. +\newif\ifnodeseen +\nodeseenfalse \message{pdf,} % adobe `portable' document format @@ -975,6 +980,11 @@ where each line of input produces a line of output.} \newif\ifpdf \newif\ifpdfmakepagedest +\newif\ifluatex +\ifx\luatexversion\thisisundefined\else + \luatextrue +\fi + % % For LuaTeX % @@ -982,8 +992,7 @@ where each line of input produces a line of output.} \newif\iftxiuseunicodedestname \txiuseunicodedestnamefalse % For pdfTeX etc. -\ifx\luatexversion\thisisundefined -\else +\ifluatex % Use Unicode destination names \txiuseunicodedestnametrue % Escape PDF strings with converting UTF-16 from UTF-8 @@ -1072,12 +1081,17 @@ where each line of input produces a line of output.} \fi \fi +\newif\ifxetex +\ifx\XeTeXrevision\thisisundefined\else + \xetextrue +\fi + \newif\ifpdforxetex \pdforxetexfalse \ifpdf \pdforxetextrue \fi -\ifx\XeTeXrevision\thisisundefined\else +\ifxetex \pdforxetextrue \fi @@ -1167,58 +1181,90 @@ with PDF output, and none of those formats could be found. (.eps cannot be supported due to the design of the PDF format; use regular TeX (DVI output) for that.)} +% definitions for pdftex or luatex with pdf output \ifpdf + % Strings in PDF outlines can either be ASCII, or encoded in UTF-16BE + % with BOM. Unfortunately there is no simple way with pdftex to output + % UTF-16, so we have to do some quite convoluted expansion games if we + % find the string contains a non-ASCII codepoint if we want these to + % display correctly. We generated the UTF-16 sequences in + % \DeclareUnicodeCharacter and we access them here. % - % Color manipulation macros using ideas from pdfcolor.tex, - % except using rgb instead of cmyk; the latter is said to render as a - % very dark gray on-screen and a very dark halftone in print, instead - % of actual black. The dark red here is dark enough to print on paper as - % nearly black, but still distinguishable for online viewing. We use - % black by default, though. - \def\rgbDarkRed{0.50 0.09 0.12} - \def\rgbBlack{0 0 0} + \def\defpdfoutlinetextunicode#1{% + \def\pdfoutlinetext{#1}% + % + % Make UTF-8 sequences expand to UTF-16 definitions. + \passthroughcharsfalse \utfbytespdftrue + \utfviiidefinedwarningfalse + % + % Completely expand, eliminating any control sequences such as \code, + % leaving only possibly \utfbytes. + \let\utfbytes\relax + \pdfaccentliterals + \xdef\pdfoutlinetextchecked{#1}% + \checkutfbytes + }% + % Check if \utfbytes occurs in expansion. + \def\checkutfbytes{% + \expandafter\checkutfbytesz\pdfoutlinetextchecked\utfbytes\finish + }% + \def\checkutfbytesz#1\utfbytes#2\finish{% + \def\after{#2}% + \ifx\after\empty + % No further action needed. Output ASCII string as-is, as converting + % to UTF-16 is somewhat slow (and uses more space). + \global\let\pdfoutlinetext\pdfoutlinetextchecked + \else + \passthroughcharstrue % pass UTF-8 sequences unaltered + \xdef\pdfoutlinetext{\pdfoutlinetext}% + \expandafter\expandutfsixteen\expandafter{\pdfoutlinetext}\pdfoutlinetext + \fi + }% + % + \catcode2=1 % begin-group character + \catcode3=2 % end-group character + % + % argument should be pure UTF-8 with no control sequences. convert to + % UTF-16BE by inserting null bytes before bytes < 128 and expanding + % UTF-8 multibyte sequences to saved UTF-16BE sequences. + \def\expandutfsixteen#1#2{% + \bgroup \asciitounicode + \passthroughcharsfalse + \let\utfbytes\asis + % + % for Byte Order Mark (BOM) + \catcode"FE=12 + \catcode"FF=12 + % + % we want to treat { and } in #1 as any other ASCII bytes. however, + % we need grouping characters for \scantokens and definitions/assignments, + % so define alternative grouping characters using control characters + % that are unlikely to occur. + % this does not affect 0x02 or 0x03 bytes arising from expansion as + % these are tokens with different catcodes. + \catcode"02=1 % begin-group character + \catcode"03=2 % end-group character + % + \expandafter\xdef\expandafter#2\scantokens{% + ^^02^^fe^^ff#1^^03}% + % NB we need \scantokens to provide both the open and close group tokens + % for \xdef otherwise there is an e-TeX error "File ended while + % scanning definition of..." + % NB \scantokens is a e-TeX command which is assumed to be provided by + % pdfTeX. + % + \egroup + }% + % + \catcode2=12 \catcode3=12 % defaults + % + % Color support % % rg sets the color for filling (usual text, etc.); % RG sets the color for stroking (thin rules, e.g., normal _'s). \def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}} % - % Set color, and create a mark which defines \thiscolor accordingly, - % so that \makeheadline knows which color to restore. - \def\curcolor{0 0 0}% - \def\setcolor#1{% - \ifx#1\curcolor\else - \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% - \domark - \pdfsetcolor{#1}% - \xdef\curcolor{#1}% - \fi - } - % - \let\maincolor\rgbBlack - \pdfsetcolor{\maincolor} - \edef\thiscolor{\maincolor} - \def\currentcolordefs{} - % - \def\makefootline{% - \baselineskip24pt - \line{\pdfsetcolor{\maincolor}\the\footline}% - } - % - \def\makeheadline{% - \vbox to 0pt{% - \vskip-22.5pt - \line{% - \vbox to8.5pt{}% - % Extract \thiscolor definition from the marks. - \getcolormarks - % Typeset the headline with \maincolor, then restore the color. - \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% - }% - \vss - }% - \nointerlineskip - } - % + % PDF outline support % \pdfcatalog{/PageMode /UseOutlines} % @@ -1315,18 +1361,15 @@ output) for that.)} \def\pdfoutlinetext{#1}% \else \ifx \declaredencoding \utfeight - \ifx\luatexversion\thisisundefined - % For pdfTeX with UTF-8. - % TODO: the PDF format can use UTF-16 in bookmark strings, - % but the code for this isn't done yet. - % Use ASCII approximations. - \passthroughcharsfalse - \def\pdfoutlinetext{#1}% - \else + \ifluatex % For LuaTeX with UTF-8. % Pass through Unicode characters for title texts. \passthroughcharstrue - \def\pdfoutlinetext{#1}% + \pdfaccentliterals + \xdef\pdfoutlinetext{#1}% + \else + % For pdfTeX with UTF-8. + \defpdfoutlinetextunicode{#1}% \fi \else % For non-Latin-1 or non-UTF-8 encodings. @@ -1348,11 +1391,6 @@ output) for that.)} % used to mark target names; must be expandable. \def\pdfmkpgn#1{#1} % - % by default, use black for everything. - \def\urlcolor{\rgbBlack} - \let\linkcolor\rgbBlack - \def\endlink{\setcolor{\maincolor}\pdfendlink} - % % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% @@ -1416,6 +1454,10 @@ output) for that.)} \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% + % + % Treat index initials like @section. Note that this is the wrong + % level if the index is not at the level of @appendix or @chapter. + \def\idxinitialentry{\numsecentry}% \readdatafile{toc}% % % Read toc second time, this time actually producing the outlines. @@ -1437,6 +1479,8 @@ output) for that.)} \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% + \def\idxinitialentry##1##2##3##4{% + \dopdfoutline{##1}{}{idx.##1.##2}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, @@ -1450,6 +1494,7 @@ output) for that.)} % we use for the index sort strings. % \indexnofonts + \ifnodeseen\else \dopdfoutlinecontents \fi % for @contents at beginning \setupdatafile % We can have normal brace characters in the PDF outlines, unlike % Texinfo index files. So set that up. @@ -1458,6 +1503,10 @@ output) for that.)} \catcode`\\=\active \otherbackslash \input \tocreadfilename \endgroup + \ifnodeseen \dopdfoutlinecontents \fi % for @contents at end + } + \def\dopdfoutlinecontents{% + \expandafter\dopdfoutline\expandafter{\putwordTOC}{}{txi.CONTENTS}{}% } {\catcode`[=1 \catcode`]=2 \catcode`{=\other \catcode`}=\other @@ -1484,55 +1533,16 @@ output) for that.)} \else \let \startlink \pdfstartlink \fi - % make a live url in pdf output. - \def\pdfurl#1{% - \begingroup - % it seems we really need yet another set of dummies; have not - % tried to figure out what each command should do in the context - % of @url. for now, just make @/ a no-op, that's the only one - % people have actually reported a problem with. - % - \normalturnoffactive - \def\@{@}% - \let\/=\empty - \makevalueexpandable - % do we want to go so far as to use \indexnofonts instead of just - % special-casing \var here? - \def\var##1{##1}% - % - \leavevmode\setcolor{\urlcolor}% - \startlink attr{/Border [0 0 0]}% - user{/Subtype /Link /A << /S /URI /URI (#1) >>}% - \endgroup} - % \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may - % be a simple number, or a list of numbers in the case of an index - % entry. - \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} - \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} - \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} - \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} - \def\maketoks{% - \expandafter\poptoks\the\toksA|ENDTOKS|\relax - \ifx\first0\adn0 - \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 - \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 - \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 - \else - \ifnum0=\countA\else\makelink\fi - \ifx\first.\let\next=\done\else - \let\next=\maketoks - \addtokens{\toksB}{\the\toksD} - \ifx\first,\addtokens{\toksB}{\space}\fi - \fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \next} - \def\makelink{\addtokens{\toksB}% - {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\pdfmakeurl#1{% + \startlink attr{/Border [0 0 0]}% + user{/Subtype /Link /A << /S /URI /URI (#1) >>}% + }% + \def\endlink{\setcolor{\maincolor}\pdfendlink} + % \def\pdflink#1{\pdflinkpage{#1}{#1}}% \def\pdflinkpage#1#2{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \setcolor{\linkcolor}#2\endlink} - \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else % non-pdf mode \let\pdfmkdest = \gobble @@ -1541,13 +1551,12 @@ output) for that.)} \let\setcolor = \gobble \let\pdfsetcolor = \gobble \let\pdfmakeoutlines = \relax -\fi % \ifx\pdfoutput +\fi % % For XeTeX % -\ifx\XeTeXrevision\thisisundefined -\else +\ifxetex % % XeTeX version check % @@ -1573,45 +1582,8 @@ output) for that.)} \fi % % Color support - % - \def\rgbDarkRed{0.50 0.09 0.12} - \def\rgbBlack{0 0 0} - % \def\pdfsetcolor#1{\special{pdf:scolor [#1]}} % - % Set color, and create a mark which defines \thiscolor accordingly, - % so that \makeheadline knows which color to restore. - \def\setcolor#1{% - \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% - \domark - \pdfsetcolor{#1}% - } - % - \def\maincolor{\rgbBlack} - \pdfsetcolor{\maincolor} - \edef\thiscolor{\maincolor} - \def\currentcolordefs{} - % - \def\makefootline{% - \baselineskip24pt - \line{\pdfsetcolor{\maincolor}\the\footline}% - } - % - \def\makeheadline{% - \vbox to 0pt{% - \vskip-22.5pt - \line{% - \vbox to8.5pt{}% - % Extract \thiscolor definition from the marks. - \getcolormarks - % Typeset the headline with \maincolor, then restore the color. - \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% - }% - \vss - }% - \nointerlineskip - } - % % PDF outline support % % Emulate pdfTeX primitive @@ -1649,11 +1621,6 @@ output) for that.)} \safewhatsit{\pdfdest name{\pdfdestname} xyz}% } % - % by default, use black for everything. - \def\urlcolor{\rgbBlack} - \def\linkcolor{\rgbBlack} - \def\endlink{\setcolor{\maincolor}\pdfendlink} - % \def\dopdfoutline#1#2#3#4{% \setpdfoutlinetext{#1} \setpdfdestname{#3} @@ -1667,7 +1634,6 @@ output) for that.)} % \def\pdfmakeoutlines{% \begingroup - % % For XeTeX, counts of subentries are not necessary. % Therefore, we read toc only once. % @@ -1686,6 +1652,11 @@ output) for that.)} \def\numsubsubsecentry##1##2##3##4{% \dopdfoutline{##1}{4}{##3}{##4}}% % + % Note this is at the wrong level unless the index is in an @appendix + % or @chapter. + \def\idxinitialentry##1##2##3##4{% + \dopdfoutline{##1}{2}{idx.##1.##2}{##4}}% + % \let\appentry\numchapentry% \let\appsecentry\numsecentry% \let\appsubsecentry\numsubsecentry% @@ -1700,15 +1671,23 @@ output) for that.)} % Therefore, the encoding and the language may not be considered. % \indexnofonts + \pdfaccentliterals + \ifnodeseen\else \dopdfoutlinecontents \fi % for @contents at beginning + % \setupdatafile % We can have normal brace characters in the PDF outlines, unlike % Texinfo index files. So set that up. \def\{{\lbracecharliteral}% \def\}{\rbracecharliteral}% \catcode`\\=\active \otherbackslash - \input \tocreadfilename + \input \tocreadfilename\relax + \ifnodeseen \dopdfoutlinecontents \fi % for @contents at end \endgroup } + \def\dopdfoutlinecontents{% + \expandafter\dopdfoutline\expandafter + {\putwordTOC}{1}{txi.CONTENTS}{txi.CONTENTS}% + } {\catcode`[=1 \catcode`]=2 \catcode`{=\other \catcode`}=\other \gdef\lbracecharliteral[{]% @@ -1721,7 +1700,7 @@ output) for that.)} % However, due to a UTF-16 conversion issue of xdvipdfmx 20150315, % ``\special{pdf:dest ...}'' cannot handle non-ASCII strings. % It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753). -% + % \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces @@ -1736,55 +1715,17 @@ output) for that.)} \edef\temp{#1}% \expandafter\skipspaces\temp|\relax } - % make a live url in pdf output. - \def\pdfurl#1{% - \begingroup - % it seems we really need yet another set of dummies; have not - % tried to figure out what each command should do in the context - % of @url. for now, just make @/ a no-op, that's the only one - % people have actually reported a problem with. - % - \normalturnoffactive - \def\@{@}% - \let\/=\empty - \makevalueexpandable - % do we want to go so far as to use \indexnofonts instead of just - % special-casing \var here? - \def\var##1{##1}% - % - \leavevmode\setcolor{\urlcolor}% - \special{pdf:bann << /Border [0 0 0] - /Subtype /Link /A << /S /URI /URI (#1) >> >>}% - \endgroup} + \def\pdfmakeurl#1{% + \special{pdf:bann << /Border [0 0 0] + /Subtype /Link /A << /S /URI /URI (#1) >> >>}% + } \def\endlink{\setcolor{\maincolor}\special{pdf:eann}} - \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} - \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} - \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} - \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} - \def\maketoks{% - \expandafter\poptoks\the\toksA|ENDTOKS|\relax - \ifx\first0\adn0 - \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 - \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 - \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 - \else - \ifnum0=\countA\else\makelink\fi - \ifx\first.\let\next=\done\else - \let\next=\maketoks - \addtokens{\toksB}{\the\toksD} - \ifx\first,\addtokens{\toksB}{\space}\fi - \fi - \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi - \next} - \def\makelink{\addtokens{\toksB}% - {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{\pdflinkpage{#1}{#1}}% \def\pdflinkpage#1#2{% \special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A << /S /GoTo /D (#1) >> >>}% \setcolor{\linkcolor}#2\endlink} - \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} -% + % % % @image support % @@ -1841,6 +1782,164 @@ output) for that.)} } \fi +% common definitions and code for pdftex, luatex and xetex +\ifpdforxetex + % The dark red here is dark enough to print on paper as + % nearly black, but still distinguishable for online viewing. We use + % black by default, though. + \def\rgbDarkRed{0.50 0.09 0.12} + \def\rgbBlack{0 0 0} + % + % Set color, and create a mark which defines \thiscolor accordingly, + % so that \makeheadline knows which color to restore. + \def\curcolor{0 0 0}% + \def\setcolor#1{% + \ifx#1\curcolor\else + \xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}% + \domark + \pdfsetcolor{#1}% + \xdef\curcolor{#1}% + \fi + } + % + \let\maincolor\rgbBlack + \pdfsetcolor{\maincolor} + \edef\thiscolor{\maincolor} + \def\currentcolordefs{} + % + \def\makefootline{% + \baselineskip24pt + \line{\pdfsetcolor{\maincolor}\the\footline}% + } + % + \def\makeheadline{% + \vbox to 0pt{% + \vskip-22.5pt + \line{% + \vbox to8.5pt{}% + % Extract \thiscolor definition from the marks. + \getcolormarks + % Typeset the headline with \maincolor, then restore the color. + \pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}% + }% + \vss + }% + \nointerlineskip + } + % + % by default, use black for everything. + \def\urlcolor{\rgbBlack} + \let\linkcolor\rgbBlack + % + % make a live url in pdf output. + \def\pdfurl#1{% + \begingroup + % it seems we really need yet another set of dummies; have not + % tried to figure out what each command should do in the context + % of @url. for now, just make @/ a no-op, that's the only one + % people have actually reported a problem with. + % + \normalturnoffactive + \def\@{@}% + \let\/=\empty + \makevalueexpandable + % do we want to go so far as to use \indexnofonts instead of just + % special-casing \var here? + \def\var##1{##1}% + % + \leavevmode\setcolor{\urlcolor}% + \pdfmakeurl{#1}% + \endgroup} + % + % \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may + % be a simple number, or a list of numbers in the case of an index + % entry. + \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} + \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} + \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} + \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} + \def\maketoks{% + \expandafter\poptoks\the\toksA|ENDTOKS|\relax + \ifx\first0\adn0 + \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 + \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 + \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 + \else + \ifnum0=\countA\else\makelink\fi + \ifx\first.\let\next=\done\else + \let\next=\maketoks + \addtokens{\toksB}{\the\toksD} + \ifx\first,\addtokens{\toksB}{\space}\fi + \fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \next} + \def\makelink{\addtokens{\toksB}% + {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} + \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} +\fi + +\ifpdforxetex + % for pdftex. + {\catcode`^^cc=13 + \gdef\pdfaccentliteralsutfviii{% + % For PDF outline only. Unicode combining accents follow the + % character they modify. Note we need at least the first byte + % of the UTF-8 sequences to have an active catcode to allow the + % definitions to do their magic. + \def\"##1{##1^^cc^^88}% U+0308 + \def\'##1{##1^^cc^^81}% U+0301 + \def\,##1{##1^^cc^^a7}% U+0327 + \def\=##1{##1^^cc^^85}% U+0305 + \def\^##1{##1^^cc^^82}% U+0302 + \def\`##1{##1^^cc^^80}% U+0300 + \def\~##1{##1^^cc^^83}% U+0303 + \def\dotaccent##1{##1^^cc^^87}% U+0307 + \def\H##1{##1^^cc^^8b}% U+030B + \def\ogonek##1{##1^^cc^^a8}% U+0328 + \def\ringaccent##1{##1^^cc^^8a}% U+030A + \def\u##1{##1^^cc^^8c}% U+0306 + \def\ubaraccent##1{##1^^cc^^b1}% U+0331 + \def\udotaccent##1{##1^^cc^^a3}% U+0323 + \def\v##1{##1^^cc^^8c}% U+030C + % this definition of @tieaccent will only work with exactly two characters + % in argument as we need to insert the combining character between them. + \def\tieaccent##1{\tieaccentz##1}% + \def\tieaccentz##1##2{##1^^cd^^a1##2} % U+0361 + }}% + % + % for xetex and luatex, which both support extended ^^^^ escapes and + % process the Unicode codepoint as a single token. + \gdef\pdfaccentliteralsnative{% + \def\"##1{##1^^^^0308}% + \def\'##1{##1^^^^0301}% + \def\,##1{##1^^^^0327}% + \def\=##1{##1^^^^0305}% + \def\^##1{##1^^^^0302}% + \def\`##1{##1^^^^0300}% + \def\~##1{##1^^^^0303}% + \def\dotaccent##1{##1^^^^0307}% + \def\H##1{##1^^^^030b}% + \def\ogonek##1{##1^^^^0328}% + \def\ringaccent##1{##1^^^^030a}% + \def\u##1{##1^^^^0306}% + \def\ubaraccent##1{##1^^^^0331}% + \def\udotaccent##1{##1^^^^0323}% + \def\v##1{##1^^^^030c}% + \def\tieaccent##1{\tieaccentz##1}% + \def\tieaccentz##1##2{##1^^^^0361##2} % U+0361 + }% + % + % use the appropriate definition + \ifluatex + \let\pdfaccentliterals\pdfaccentliteralsnative + \else + \ifxetex + \let\pdfaccentliterals\pdfaccentliteralsnative + \else + \let\pdfaccentliterals\pdfaccentliteralsutfviii + \fi + \fi +\fi % \message{fonts,} @@ -2772,15 +2871,15 @@ end % @cite unconditionally uses \sl with \smartitaliccorrection. \def\cite#1{{\sl #1}\smartitaliccorrection} -% @var unconditionally uses \sl. This gives consistency for -% parameter names whether they are in @def, @table @code or a -% regular paragraph. -% To get ttsl font for @var when used in code context, @set txicodevaristt. -% The \null is to reset \spacefactor. +% By default, use ttsl font for @var when used in code context. +% To unconditionally use \sl for @var, @clear txicodevaristt. This +% gives consistency for parameter names whether they are in @def, +% @table @code or a regular paragraph. \def\aftersmartic{} \def\var#1{% \let\saveaftersmartic = \aftersmartic \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% + % The \null is to reset \spacefactor. % \ifflagclear{txicodevaristt}% {\def\varnext{{{\sl #1}}\smartitaliccorrection}}% @@ -2788,7 +2887,6 @@ end \varnext } -% To be removed after next release \def\SETtxicodevaristt{}% @set txicodevaristt \let\i=\smartitalic @@ -2808,7 +2906,7 @@ end \def\ii#1{{\it #1}} % italic font % @b, explicit bold. Also @strong. -\def\b#1{{\bf #1}} +\def\b#1{{\bf \defcharsdefault #1}} \let\strong=\b % @sansserif, explicit sans. @@ -3039,9 +3137,7 @@ end \unhbox0\ (\urefcode{#1})% \fi \else - \ifx\XeTeXrevision\thisisundefined - \unhbox0\ (\urefcode{#1})% DVI, always show arg and url - \else + \ifxetex % For XeTeX \ifurefurlonlylink % PDF plus option to not display url, show just arg @@ -3051,6 +3147,8 @@ end % visibility, if the pdf is eventually used to print, etc. \unhbox0\ (\urefcode{#1})% \fi + \else + \unhbox0\ (\urefcode{#1})% DVI, always show arg and url \fi \fi \else @@ -3670,15 +3768,24 @@ $$% {\font\thisecfont = #1ctt\ecsize \space at \nominalsize}% % else {\ifx\curfontstyle\bfstylename - % bold: - \font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize + \etcfontbold{#1}% \else - % regular: - \font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space at \nominalsize + \ifrmisbold + \etcfontbold{#1}% + \else + % regular: + \font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space + at \nominalsize + \fi \fi}% \thisecfont } +\def\etcfontbold#1{% + % bold: + \font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize +} + % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. @@ -5528,7 +5635,6 @@ might help (with 'rm \jobname.?? \jobname.??s')% \def\initial{% \bgroup - \initialglyphs \initialx } @@ -5551,7 +5657,10 @@ might help (with 'rm \jobname.?? \jobname.??s')% % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus 1\baselineskip - \leftline{\secfonts \kern-0.05em \secbf #1}% + \doindexinitialentry{#1}% + \initialglyphs + \leftline{% + \secfonts \kern-0.05em \secbf #1}% % \secfonts is inside the argument of \leftline so that the change of % \baselineskip will not affect any glue inserted before the vbox that % \leftline creates. @@ -5561,6 +5670,32 @@ might help (with 'rm \jobname.?? \jobname.??s')% \egroup % \initialglyphs } +\def\doindexinitialentry#1{% + \ifpdforxetex + \global\advance\idxinitialno by 1 + \def\indexlbrace{\{} + \def\indexrbrace{\}} + \def\indexbackslash{\realbackslash} + \def\indexatchar{\@} + \writetocentry{idxinitial}{\asis #1}{IDX\the\idxinitialno}% + % The @asis removes a pair of braces around e.g. {@indexatchar} that + % are output by texindex. + % + \vbox to 0pt{}% + % This vbox fixes the \pdfdest location for double column formatting. + % Without it, the \pdfdest is output above topskip glue at the top + % of a column as this glue is not added until the first box. + \pdfmkdest{idx.\asis #1.IDX\the\idxinitialno}% + \fi +} + +% No listing in TOC +\def\idxinitialentry#1#2#3#4{} + +% For index initials. +\newcount\idxinitialno \idxinitialno=1 + + \newdimen\entryrightmargin \entryrightmargin=0pt @@ -6782,12 +6917,13 @@ might help (with 'rm \jobname.?? \jobname.??s')% % Prepare to read what we've written to \tocfile. % -\def\startcontents#1{% +\def\startcontents#1#2{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. \contentsalignmacro \immediate\closeout\tocfile % + #2% % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \chapmacro{#1}{Yomitfromtoc}{}% @@ -6818,7 +6954,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% % Normal (long) toc. % \def\contents{% - \startcontents{\putwordTOC}% + \startcontents{\putwordTOC}{\contentsmkdest}% \openin 1 \tocreadfilename\space \ifeof 1 \else \findsecnowidths @@ -6834,9 +6970,13 @@ might help (with 'rm \jobname.?? \jobname.??s')% \contentsendroman } +\def\contentsmkdest{% + \pdfmkdest{txi.CONTENTS}% +} + % And just the chapters. \def\summarycontents{% - \startcontents{\putwordShortTOC}% + \startcontents{\putwordShortTOC}{}% % \let\partentry = \shortpartentry \let\numchapentry = \shortchapentry @@ -7925,7 +8065,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% {\rm\enskip}% hskip 0.5 em of \rmfont }{}% % - \boldbrax + \parenbrackglyphs % arguments will be output next, if any. } @@ -7935,7 +8075,10 @@ might help (with 'rm \jobname.?? \jobname.??s')% \def\^^M{}% for line continuation \df \ifdoingtypefn \tt \else \sl \fi \ifflagclear{txicodevaristt}{}% - {\def\var##1{{\setregularquotes \ttsl ##1}}}% + % use \ttsl for @var in both @def* and @deftype*. + % the kern prevents an italic correction at end, which appears + % too much for ttsl. + {\def\var##1{{\setregularquotes \ttsl ##1\kern 0pt }}}% #1% \egroup } @@ -7952,8 +8095,9 @@ might help (with 'rm \jobname.?? \jobname.??s')% \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, -% if the fn name has parens in it, \boldbrax will not be in effect yet, -% so TeX would otherwise complain about undefined control sequence. +% if the fn name has parens in it, \parenbrackglyphs will not be in +% effect yet, so TeX would otherwise complain about undefined control +% sequence. { \activeparens \gdef\defcharsdefault{% @@ -7963,49 +8107,28 @@ might help (with 'rm \jobname.?? \jobname.??s')% } \globaldefs=1 \defcharsdefault - \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} + \gdef\parenbrackglyphs{\let(=\opnr\let)=\cpnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \let\ampchar\& +\def\amprm#1 {{\rm\ }} + \newcount\parencount - -% If we encounter &foo, then turn on ()-hacking afterwards -\newif\ifampseen -\def\amprm#1 {\ampseentrue{\rm\ }} - -\def\parenfont{% - \ifampseen - % At the first level, print parens in roman, - % otherwise use the default font. - \ifnum \parencount=1 \rm \fi - \else - % The \sf parens (in \boldbrax) actually are a little bolder than - % the contained text. This is especially needed for [ and ] . - \sf - \fi -} -\def\infirstlevel#1{% - \ifampseen - \ifnum\parencount=1 - #1% - \fi - \fi -} -\def\bfafterword#1 {#1 \bf} - +% opening and closing parentheses in roman font \def\opnr{% + \ptexslash % italic correction \global\advance\parencount by 1 - {\parenfont(}% - \infirstlevel \bfafterword + {\sf(}% } -\def\clnr{% - {\parenfont)}% - \infirstlevel \sl +\def\cpnr{% + \ptexslash % italic correction + {\sf)}% \global\advance\parencount by -1 } \newcount\brackcount +% left and right square brackets in bold font \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% @@ -8535,7 +8658,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \expandafter\xdef\csname\the\macname\endcsname{% \begingroup \noexpand\spaceisspace - \noexpand\endlineisspace + \noexpand\ignoreactivenewline \noexpand\expandafter % skip any whitespace after the macro name. \expandafter\noexpand\csname\the\macname @@@\endcsname}% \expandafter\xdef\csname\the\macname @@@\endcsname{% @@ -8836,8 +8959,13 @@ might help (with 'rm \jobname.?? \jobname.??s')% \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty + \setnodeseenonce \fi } +\def\setnodeseenonce{ + \global\nodeseentrue + \let\setnodeseenonce\relax +} % @nodedescription, @nodedescriptionblock - do nothing for TeX \parseargdef\nodedescription{} @@ -9575,7 +9703,9 @@ might help (with 'rm \jobname.?? \jobname.??s')% % For pdfTeX and LuaTeX <= 0.80 \dopdfimage{#1}{#2}{#3}% \else - \ifx\XeTeXrevision\thisisundefined + \ifxetex + \doxeteximage{#1}{#2}{#3}% + \else % For epsf.tex % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}% @@ -9583,9 +9713,6 @@ might help (with 'rm \jobname.?? \jobname.??s')% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% - \else - % For XeTeX - \doxeteximage{#1}{#2}{#3}% \fi \fi % @@ -9931,25 +10058,24 @@ directory should work if nowhere else does.} \newif\iftxinativeunicodecapable \newif\iftxiusebytewiseio -\ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined - \txinativeunicodecapablefalse - \txiusebytewiseiotrue - \else - \txinativeunicodecapabletrue - \txiusebytewiseiofalse - \fi -\else +\ifxetex \txinativeunicodecapabletrue \txiusebytewiseiofalse +\else + \ifluatex + \txinativeunicodecapabletrue + \txiusebytewiseiofalse + \else + \txinativeunicodecapablefalse + \txiusebytewiseiotrue + \fi \fi % Set I/O by bytes instead of UTF-8 sequence for XeTeX and LuaTex % for non-UTF-8 (byte-wise) encodings. % \def\setbytewiseio{% - \ifx\XeTeXrevision\thisisundefined - \else + \ifxetex \XeTeXdefaultencoding "bytes" % For subsequent files to be read \XeTeXinputencoding "bytes" % For document root file % Unfortunately, there seems to be no corresponding XeTeX command for @@ -9958,8 +10084,7 @@ directory should work if nowhere else does.} % place of non-ASCII characters. \fi - \ifx\luatexversion\thisisundefined - \else + \ifluatex \directlua{ local utf8_char, byte, gsub = unicode.utf8.char, string.byte, string.gsub local function convert_char (char) @@ -10068,8 +10193,7 @@ directory should work if nowhere else does.} \fi % lattwo \fi % ascii % - \ifx\XeTeXrevision\thisisundefined - \else + \ifxetex \ifx \declaredencoding \utfeight \else \ifx \declaredencoding \ascii @@ -10352,11 +10476,15 @@ directory should work if nowhere else does.} \gdef\UTFviiiDefined#1{% \ifx #1\relax - \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \ifutfviiidefinedwarning + \message{\linenumber Unicode char \string #1 not defined for Texinfo}% + \fi \else \expandafter #1% \fi } +\newif\ifutfviiidefinedwarning +\utfviiidefinedwarningtrue % Give non-ASCII bytes the active definitions for processing UTF-8 sequences \begingroup @@ -10366,8 +10494,8 @@ directory should work if nowhere else does.} % Loop from \countUTFx to \countUTFy, performing \UTFviiiTmp % substituting ~ and $ with a character token of that value. - \def\UTFviiiLoop{% - \global\catcode\countUTFx\active + \gdef\UTFviiiLoop{% + \catcode\countUTFx\active \uccode`\~\countUTFx \uccode`\$\countUTFx \uppercase\expandafter{\UTFviiiTmp}% @@ -10375,7 +10503,7 @@ directory should work if nowhere else does.} \ifnum\countUTFx < \countUTFy \expandafter\UTFviiiLoop \fi} - + % % For bytes other than the first in a UTF-8 sequence. Not expected to % be expanded except when writing to auxiliary files. \countUTFx = "80 @@ -10409,6 +10537,16 @@ directory should work if nowhere else does.} \else\expandafter\UTFviiiFourOctets\expandafter$\fi }}% \UTFviiiLoop + % + % for pdftex only, used to expand ASCII to UTF-16BE. + \gdef\asciitounicode{% + \countUTFx = "20 + \countUTFy = "80 + \def\UTFviiiTmp{% + \def~{\nullbyte $}}% + \UTFviiiLoop + } + {\catcode0=11 \gdef\nullbyte{^^00}}% \endgroup \def\globallet{\global\let} % save some \expandafter's below @@ -10433,8 +10571,8 @@ directory should work if nowhere else does.} \fi } -% These macros are used here to construct the name of a control -% sequence to be defined. +% These macros are used here to construct the names of macros +% that expand to the definitions for UTF-8 sequences. \def\UTFviiiTwoOctetsName#1#2{% \csname u8:#1\string #2\endcsname}% \def\UTFviiiThreeOctetsName#1#2#3{% @@ -10442,6 +10580,35 @@ directory should work if nowhere else does.} \def\UTFviiiFourOctetsName#1#2#3#4{% \csname u8:#1\string #2\string #3\string #4\endcsname}% +% generate UTF-16 from codepoint +\def\utfsixteentotoks#1#2{% + \countUTFz = "#2\relax + \ifnum \countUTFz > 65535 + % doesn't work for codepoints > U+FFFF + % we don't define glyphs for any of these anyway, so it doesn't matter + #1={U+#2}% + \else + \countUTFx = \countUTFz + \divide\countUTFx by 256 + \countUTFy = \countUTFx + \multiply\countUTFx by 256 + \advance\countUTFz by -\countUTFx + \uccode`,=\countUTFy + \uccode`;=\countUTFz + \ifnum\countUTFy = 0 + \uppercase{#1={\nullbyte\string;}}% + \else\ifnum\countUTFz = 0 + \uppercase{#1={\string,\nullbyte}}% + \else + \uppercase{#1={\string,\string;}}% + \fi\fi + % NB \uppercase cannot insert a null byte + \fi +} + +\newif\ifutfbytespdf +\utfbytespdffalse + % For UTF-8 byte sequences (TeX, e-TeX and pdfTeX), % provide a definition macro to replace a Unicode character; % this gets used by the @U command @@ -10458,18 +10625,22 @@ directory should work if nowhere else does.} \countUTFz = "#1\relax \begingroup \parseXMLCharref - - % Give \u8:... its definition. The sequence of seven \expandafter's - % expands after the \gdef three times, e.g. % + % Completely expand \UTFviiiTmp, which looks like: % 1. \UTFviiTwoOctetsName B1 B2 % 2. \csname u8:B1 \string B2 \endcsname % 3. \u8: B1 B2 (a single control sequence token) + \xdef\UTFviiiTmp{\UTFviiiTmp}% % - \expandafter\expandafter - \expandafter\expandafter - \expandafter\expandafter - \expandafter\gdef \UTFviiiTmp{#2}% + \ifpdf + \toksA={#2}% + \utfsixteentotoks\toksB{#1}% + \expandafter\xdef\UTFviiiTmp{% + \noexpand\ifutfbytespdf\noexpand\utfbytes{\the\toksB}% + \noexpand\else\the\toksA\noexpand\fi}% + \else + \expandafter\gdef\UTFviiiTmp{#2}% + \fi % \expandafter\ifx\csname uni:#1\endcsname \relax \else \message{Internal error, already defined: #1}% @@ -10479,8 +10650,9 @@ directory should work if nowhere else does.} \expandafter\globallet\csname uni:#1\endcsname \UTFviiiTmp \endgroup} % - % Given the value in \countUTFz as a Unicode code point, set \UTFviiiTmp - % to the corresponding UTF-8 sequence. + % Given the value in \countUTFz as a Unicode code point, set + % \UTFviiiTmp to one of the \UTVviii*OctetsName macros followed by + % the corresponding UTF-8 sequence. \gdef\parseXMLCharref{% \ifnum\countUTFz < "20\relax \errhelp = \EMsimple @@ -10540,7 +10712,7 @@ directory should work if nowhere else does.} } % Suppress ligature creation from adjacent characters. -\ifx\luatexversion\thisisundefined +\ifluatex \def\nolig{{}} \else % Braces do not suppress ligature creation in LuaTeX, e.g. in of{}fice @@ -11325,6 +11497,25 @@ directory should work if nowhere else does.} % \global\mathchardef\checkmark="1370% actually the square root sign \DeclareUnicodeCharacter{2713}{\ensuremath\checkmark}% + % + % These are all the combining accents. We need these empty definitions + % at present for the sake of PDF outlines. + \DeclareUnicodeCharacter{0300}{}% + \DeclareUnicodeCharacter{0301}{}% + \DeclareUnicodeCharacter{0302}{}% + \DeclareUnicodeCharacter{0303}{}% + \DeclareUnicodeCharacter{0305}{}% + \DeclareUnicodeCharacter{0306}{}% + \DeclareUnicodeCharacter{0307}{}% + \DeclareUnicodeCharacter{0308}{}% + \DeclareUnicodeCharacter{030A}{}% + \DeclareUnicodeCharacter{030B}{}% + \DeclareUnicodeCharacter{030C}{}% + \DeclareUnicodeCharacter{0323}{}% + \DeclareUnicodeCharacter{0327}{}% + \DeclareUnicodeCharacter{0328}{}% + \DeclareUnicodeCharacter{0331}{}% + \DeclareUnicodeCharacter{0361}{}% }% end of \unicodechardefs % UTF-8 byte sequence (pdfTeX) definitions (replacing and @U command) @@ -11463,12 +11654,12 @@ directory should work if nowhere else does.} \pdfhorigin = 1 true in \pdfvorigin = 1 true in \else - \ifx\XeTeXrevision\thisisundefined - \special{papersize=#8,#7}% - \else + \ifxetex \pdfpageheight #7\relax \pdfpagewidth #8\relax % XeTeX does not have \pdfhorigin and \pdfvorigin. + \else + \special{papersize=#8,#7}% \fi \fi % @@ -11668,21 +11859,21 @@ directory should work if nowhere else does.} #1#2#3=\countB\relax } -\ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined +\ifxetex % XeTeX + \mtsetprotcode\textrm + \def\mtfontexpand#1{} +\else + \ifluatex % LuaTeX + \mtsetprotcode\textrm + \def\mtfontexpand#1{\expandglyphsinfont#1 20 20 1\relax} + \else \ifpdf % pdfTeX \mtsetprotcode\textrm \def\mtfontexpand#1{\pdffontexpand#1 20 20 1 autoexpand\relax} \else % TeX \def\mtfontexpand#1{} \fi - \else % LuaTeX - \mtsetprotcode\textrm - \def\mtfontexpand#1{\expandglyphsinfont#1 20 20 1\relax} \fi -\else % XeTeX - \mtsetprotcode\textrm - \def\mtfontexpand#1{} \fi @@ -11691,18 +11882,18 @@ directory should work if nowhere else does.} \def\microtypeON{% \microtypetrue % - \ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined + \ifxetex % XeTeX + \XeTeXprotrudechars=2 + \else + \ifluatex % LuaTeX + \adjustspacing=2 + \protrudechars=2 + \else \ifpdf % pdfTeX \pdfadjustspacing=2 \pdfprotrudechars=2 \fi - \else % LuaTeX - \adjustspacing=2 - \protrudechars=2 \fi - \else % XeTeX - \XeTeXprotrudechars=2 \fi % \mtfontexpand\textrm @@ -11713,18 +11904,18 @@ directory should work if nowhere else does.} \def\microtypeOFF{% \microtypefalse % - \ifx\XeTeXrevision\thisisundefined - \ifx\luatexversion\thisisundefined + \ifxetex % XeTeX + \XeTeXprotrudechars=0 + \else + \ifluatex % LuaTeX + \adjustspacing=0 + \protrudechars=0 + \else \ifpdf % pdfTeX \pdfadjustspacing=0 \pdfprotrudechars=0 \fi - \else % LuaTeX - \adjustspacing=0 - \protrudechars=0 \fi - \else % XeTeX - \XeTeXprotrudechars=0 \fi } diff --git a/lib/attribute.h b/lib/attribute.h index 4939d776e72..625195c8565 100644 --- a/lib/attribute.h +++ b/lib/attribute.h @@ -257,7 +257,9 @@ because the function need not return exactly once and can depend on state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function type. */ #define UNSEQUENCED _GL_ATTRIBUTE_UNSEQUENCED @@ -284,7 +286,9 @@ because the function need not return exactly once and can affect state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function type. */ #define REPRODUCIBLE _GL_ATTRIBUTE_REPRODUCIBLE diff --git a/lib/flexmember.h b/lib/flexmember.h index 15ee4f5e281..b4d86c29fb5 100644 --- a/lib/flexmember.h +++ b/lib/flexmember.h @@ -28,11 +28,12 @@ #include /* Nonzero multiple of alignment of TYPE, suitable for FLEXSIZEOF below. - On older platforms without _Alignof, use a pessimistic bound that is + If _Alignof might not exist or might not work correctly on + structs with flexible array members, use a pessimistic bound that is safe in practice even if FLEXIBLE_ARRAY_MEMBER is 1. - On newer platforms, use _Alignof to get a tighter bound. */ + Otherwise, use _Alignof to get a tighter bound. */ -#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112 || defined _Alignof # define FLEXALIGNOF(type) (sizeof (type) & ~ (sizeof (type) - 1)) #else # define FLEXALIGNOF(type) _Alignof (type) diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 22d102b1d86..fa2250cf686 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -281,7 +281,6 @@ EXECINFO_H = @EXECINFO_H@ EXEEXT = @EXEEXT@ FILE_HAS_ACL_LIB = @FILE_HAS_ACL_LIB@ FIND_DELETE = @FIND_DELETE@ -FIRSTFILE_OBJ = @FIRSTFILE_OBJ@ FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ FONT_OBJ = @FONT_OBJ@ @@ -960,7 +959,6 @@ HAVE_WCHAR_H = @HAVE_WCHAR_H@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ HAVE_XSERVER = @HAVE_XSERVER@ HAVE__EXIT = @HAVE__EXIT@ -HYBRID_MALLOC = @HYBRID_MALLOC@ IEEE754_H = @IEEE754_H@ IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@ IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@ @@ -1137,7 +1135,6 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ -PAXCTL = @PAXCTL@ PAXCTL_dumped = @PAXCTL_dumped@ PAXCTL_notdumped = @PAXCTL_notdumped@ PGTK_LIBS = @PGTK_LIBS@ @@ -1147,10 +1144,8 @@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PNG_CFLAGS = @PNG_CFLAGS@ PNG_LIBS = @PNG_LIBS@ -POST_ALLOC_OBJ = @POST_ALLOC_OBJ@ PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ -PRE_ALLOC_OBJ = @PRE_ALLOC_OBJ@ PRIPTR_PREFIX = @PRIPTR_PREFIX@ PROFILING_CFLAGS = @PROFILING_CFLAGS@ PTHREAD_H_DEFINES_STRUCT_TIMESPEC = @PTHREAD_H_DEFINES_STRUCT_TIMESPEC@ @@ -1388,7 +1383,6 @@ TREE_SITTER_LIBS = @TREE_SITTER_LIBS@ UINT32_MAX_LT_UINTMAX_MAX = @UINT32_MAX_LT_UINTMAX_MAX@ UINT64_MAX_EQ_ULONG_MAX = @UINT64_MAX_EQ_ULONG_MAX@ UNDEFINE_STRTOK_R = @UNDEFINE_STRTOK_R@ -UNEXEC_OBJ = @UNEXEC_OBJ@ UNISTD_H_DEFINES_STRUCT_TIMESPEC = @UNISTD_H_DEFINES_STRUCT_TIMESPEC@ UNISTD_H_HAVE_SYS_RANDOM_H = @UNISTD_H_HAVE_SYS_RANDOM_H@ UNISTD_H_HAVE_WINSOCK2_H = @UNISTD_H_HAVE_WINSOCK2_H@ @@ -1501,10 +1495,16 @@ gl_GNULIB_ENABLED_verify_CONDITION = @gl_GNULIB_ENABLED_verify_CONDITION@ gl_LIBOBJDEPS = @gl_LIBOBJDEPS@ gl_LIBOBJS = @gl_LIBOBJS@ gl_LTLIBOBJS = @gl_LTLIBOBJS@ +gl_libgnu_LIBOBJDEPS = @gl_libgnu_LIBOBJDEPS@ +gl_libgnu_LIBOBJS = @gl_libgnu_LIBOBJS@ +gl_libgnu_LTLIBOBJS = @gl_libgnu_LTLIBOBJS@ gltests_LIBOBJDEPS = @gltests_LIBOBJDEPS@ gltests_LIBOBJS = @gltests_LIBOBJS@ gltests_LTLIBOBJS = @gltests_LTLIBOBJS@ gltests_WITNESS = @gltests_WITNESS@ +gltests_libgnu_LIBOBJDEPS = @gltests_libgnu_LIBOBJDEPS@ +gltests_libgnu_LIBOBJS = @gltests_libgnu_LIBOBJS@ +gltests_libgnu_LTLIBOBJS = @gltests_libgnu_LTLIBOBJS@ gsettingsschemadir = @gsettingsschemadir@ host = @host@ host_alias = @host_alias@ @@ -1552,9 +1552,9 @@ x_default_search_path = @x_default_search_path@ noinst_LIBRARIES += libgnu.a libgnu_a_SOURCES = -libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS) -libgnu_a_LIBADD = $(gl_LIBOBJS) -libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) +libgnu_a_CFLAGS = $(AM_CFLAGS) $(GL_CFLAG_GNULIB_WARNINGS) $(GL_CFLAG_ALLOW_WARNINGS) +libgnu_a_LIBADD = $(gl_libgnu_LIBOBJS) +libgnu_a_DEPENDENCIES = $(gl_libgnu_LIBOBJS) EXTRA_libgnu_a_SOURCES = ## begin gnulib module absolute-header @@ -4446,5 +4446,5 @@ mostlyclean-local: mostlyclean-generic : distclean-local: distclean-gnulib-libobjs distclean-gnulib-libobjs: - -rm -f @gl_LIBOBJDEPS@ + -rm -f @gl_libgnu_LIBOBJDEPS@ maintainer-clean-local: distclean-gnulib-libobjs diff --git a/lib/intprops.h b/lib/intprops.h index 92dfef2500a..83efe39910a 100644 --- a/lib/intprops.h +++ b/lib/intprops.h @@ -34,6 +34,14 @@ signed or floating type. Do not evaluate E. */ #define EXPR_SIGNED(e) _GL_EXPR_SIGNED (e) +/* The same value as as the arithmetic expression E, but with E's type + after integer promotions. For example, if E is of type 'enum {A, B}' + then 'switch (INT_PROMOTE (E))' pacifies gcc -Wswitch-enum if some + enum values are deliberately omitted from the switch's cases. + Here, unary + is safer than a cast or inline function, as unary + + does only integer promotions. */ +#define INT_PROMOTE(e) (+ (e)) + /* Minimum and maximum values for integer types and expressions. */ diff --git a/m4/acl.m4 b/m4/acl.m4 index c9cb6dd09ed..7e4b0e354d9 100644 --- a/m4/acl.m4 +++ b/m4/acl.m4 @@ -1,5 +1,5 @@ # acl.m4 -# serial 34 +# serial 35 dnl Copyright (C) 2002, 2004-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -18,7 +18,7 @@ AC_DEFUN([gl_FUNC_ACL_ARG], , [enable_acl=auto]) AC_ARG_WITH([libsmack], [AS_HELP_STRING([--without-libsmack], - [do not use libsmack, even on systems that have it])] + [do not use libsmack, even on systems that have it])], [], [with_libsmack=maybe]) ]) diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4 index b3b1391bd54..6eff85bea12 100644 --- a/m4/gnulib-common.m4 +++ b/m4/gnulib-common.m4 @@ -1,5 +1,5 @@ # gnulib-common.m4 -# serial 106 +# serial 107 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -753,7 +753,9 @@ AC_DEFUN([gl_COMMON_BODY], [ than _GL_ATTRIBUTE_PURE because the function need not return exactly once and can affect state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function types. */ #ifndef _GL_ATTRIBUTE_REPRODUCIBLE /* This may be revisited when gcc and clang support [[reproducible]] or possibly @@ -804,7 +806,9 @@ AC_DEFUN([gl_COMMON_BODY], [ _GL_ATTRIBUTE_CONST because the function need not return exactly once and can depend on state addressed by its arguments.) See also and - . */ + . + ATTENTION! Efforts are underway to change the meaning of this attribute. + See . */ /* Applies to: functions, pointer to functions, function types. */ #ifndef _GL_ATTRIBUTE_UNSEQUENCED /* This may be revisited when gcc and clang support [[unsequenced]] or possibly diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 980baf83998..42f67d0a42b 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -1057,27 +1057,35 @@ AC_DEFUN([gl_INIT], gl_libobjs= gl_ltlibobjs= gl_libobjdeps= + gl_libgnu_libobjs= + gl_libgnu_ltlibobjs= + gl_libgnu_libobjdeps= if test -n "$gl_LIBOBJS"; then # Remove the extension. changequote(,)dnl sed_drop_objext='s/\.o$//;s/\.obj$//' sed_dirname1='s,//*,/,g' sed_dirname2='s,\(.\)/$,\1,' - sed_dirname3='s,^[^/]*$,.,' - sed_dirname4='s,\(.\)/[^/]*$,\1,' + sed_dirname3='s,[^/]*$,,' sed_basename1='s,.*/,,' changequote([, ])dnl for i in `for i in $gl_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do gl_libobjs="$gl_libobjs $i.$ac_objext" gl_ltlibobjs="$gl_ltlibobjs $i.lo" - i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3" -e "$sed_dirname4"` + i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3"` i_base=`echo "$i" | sed -e "$sed_basename1"` - gl_libobjdeps="$gl_libobjdeps $i_dir/\$(DEPDIR)/$i_base.Po" + gl_libgnu_libobjs="$gl_libgnu_libobjs $i_dir""libgnu_a-$i_base.$ac_objext" + gl_libgnu_ltlibobjs="$gl_libgnu_ltlibobjs $i_dir""libgnu_la-$i_base.lo" + gl_libobjdeps="$gl_libobjdeps $i_dir\$(DEPDIR)/$i_base.Po" + gl_libgnu_libobjdeps="$gl_libgnu_libobjdeps $i_dir\$(DEPDIR)/libgnu_a-$i_base.Po" done fi AC_SUBST([gl_LIBOBJS], [$gl_libobjs]) AC_SUBST([gl_LTLIBOBJS], [$gl_ltlibobjs]) AC_SUBST([gl_LIBOBJDEPS], [$gl_libobjdeps]) + AC_SUBST([gl_libgnu_LIBOBJS], [$gl_libgnu_libobjs]) + AC_SUBST([gl_libgnu_LTLIBOBJS], [$gl_libgnu_ltlibobjs]) + AC_SUBST([gl_libgnu_LIBOBJDEPS], [$gl_libgnu_libobjdeps]) ]) gltests_libdeps= gltests_ltlibdeps= @@ -1121,27 +1129,35 @@ changequote([, ])dnl gltests_libobjs= gltests_ltlibobjs= gltests_libobjdeps= + gltests_libgnu_libobjs= + gltests_libgnu_ltlibobjs= + gltests_libgnu_libobjdeps= if test -n "$gltests_LIBOBJS"; then # Remove the extension. changequote(,)dnl sed_drop_objext='s/\.o$//;s/\.obj$//' sed_dirname1='s,//*,/,g' sed_dirname2='s,\(.\)/$,\1,' - sed_dirname3='s,^[^/]*$,.,' - sed_dirname4='s,\(.\)/[^/]*$,\1,' + sed_dirname3='s,[^/]*$,,' sed_basename1='s,.*/,,' changequote([, ])dnl for i in `for i in $gltests_LIBOBJS; do echo "$i"; done | sed -e "$sed_drop_objext" | sort | uniq`; do gltests_libobjs="$gltests_libobjs $i.$ac_objext" gltests_ltlibobjs="$gltests_ltlibobjs $i.lo" - i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3" -e "$sed_dirname4"` + i_dir=`echo "$i" | sed -e "$sed_dirname1" -e "$sed_dirname2" -e "$sed_dirname3"` i_base=`echo "$i" | sed -e "$sed_basename1"` - gltests_libobjdeps="$gltests_libobjdeps $i_dir/\$(DEPDIR)/$i_base.Po" + gltests_libgnu_libobjs="$gltests_libgnu_libobjs $i_dir""libgnu_a-$i_base.$ac_objext" + gltests_libgnu_ltlibobjs="$gltests_libgnu_ltlibobjs $i_dir""libgnu_la-$i_base.lo" + gltests_libobjdeps="$gltests_libobjdeps $i_dir\$(DEPDIR)/$i_base.Po" + gltests_libgnu_libobjdeps="$gltests_libgnu_libobjdeps $i_dir\$(DEPDIR)/libgnu_a-$i_base.Po" done fi AC_SUBST([gltests_LIBOBJS], [$gltests_libobjs]) AC_SUBST([gltests_LTLIBOBJS], [$gltests_ltlibobjs]) AC_SUBST([gltests_LIBOBJDEPS], [$gltests_libobjdeps]) + AC_SUBST([gltests_libgnu_LIBOBJS], [$gltests_libgnu_libobjs]) + AC_SUBST([gltests_libgnu_LTLIBOBJS], [$gltests_libgnu_ltlibobjs]) + AC_SUBST([gltests_libgnu_LIBOBJDEPS], [$gltests_libgnu_libobjdeps]) ]) AC_REQUIRE([gl_CC_GNULIB_WARNINGS]) LIBGNU_LIBDEPS="$gl_libdeps" From e9408918f4e7fe00eb4e25e1e5428fb26c4ad847 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Tue, 4 Feb 2025 06:11:50 -0800 Subject: [PATCH 109/279] More clearly define local module behavior in ERC * doc/misc/erc.texi (Modules): Label all local modules as being such. Move `querypoll' to the auxiliary section. Rework entire "Local Modules" portion. * lisp/erc/erc-goodies.el (erc-keep-place-indicator-mode) (erc-command-indicator-mode): Mention what buffer types they operate in. * lisp/erc/erc-nicks.el (erc-nicks-mode): Mention the mode is enabled in all buffers. * lisp/erc/erc-notify.el (erc-querypoll-mode): Mention which buffers it operates in. * lisp/erc/erc-sasl.el (erc-sasl-mode): Disable completely in target buffers so its mode variable is nil. * lisp/erc/erc-services.el (erc-services-regain-mode): Disable in target buffers. * lisp/erc/erc.el (erc-open): When activating local modules, skip those that have just been enabled by a fellow module. Do this even though their setup code is meant to be idempotent. * test/lisp/erc/erc-scenarios-base-local-modules.el (erc-scenarios-base-local-modules--toggle-helpers): Revise to assert current behavior. (Bug#57955) --- doc/misc/erc.texi | 125 +++++++++++------- lisp/erc/erc-goodies.el | 8 +- lisp/erc/erc-nicks.el | 4 +- lisp/erc/erc-notify.el | 6 +- lisp/erc/erc-sasl.el | 14 +- lisp/erc/erc-services.el | 6 +- lisp/erc/erc.el | 4 +- .../erc/erc-scenarios-base-local-modules.el | 16 ++- 8 files changed, 114 insertions(+), 69 deletions(-) diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 7c934d8bb3a..1c0afa3b300 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -452,7 +452,7 @@ Buttonize URLs, nicknames, and other text Mark unidentified users on freenode and other servers supporting CAPAB. @cindex modules, command-indicator -@item command-indicator +@item command-indicator (local) Echo command lines for ``slash commands'', like @kbd{/JOIN #erc} and @kbd{/HELP join} @@ -494,7 +494,7 @@ Display a menu in ERC buffers Detect netsplits @cindex modules, nicks -@item nicks +@item nicks (local) Automatically colorize nicks @cindex modules, nickbar @@ -519,10 +519,6 @@ or your nickname is mentioned @item page Process CTCP PAGE requests from IRC -@cindex modules, querypoll -@item querypoll -Update query participant data by continually polling the server - @cindex modules, readonly @item readonly Make displayed lines read-only @@ -536,7 +532,7 @@ Replace text in messages Enable an input history @cindex modules, sasl -@item sasl +@item sasl (local) Enable SASL authentication @cindex modules, scrolltobottom @@ -583,22 +579,26 @@ Translate morse code in messages For various reasons, the following modules aren't currently listed in the Custom interface for @code{erc-modules}, but feel free to add them -explicitly. They may be managed by another module or considered more -useful when toggled interactively or just deemed experimental. +explicitly. They may be managed by another module or just deemed too +niche or experimental. @table @code @cindex modules, fill-wrap -@item fill-wrap +@item fill-wrap (local) Wrap long lines using @code{visual-line-mode} @cindex modules, keep-place-indicator -@item keep-place-indicator +@item keep-place-indicator (local) Remember your place in buffers with a visible reminder; activated interactively or via something like @code{erc-join-hook} +@cindex modules, querypoll +@item querypoll (local) +Update query participant data by continually polling the server + @cindex modules, services-regain -@item services-regain +@item services-regain (local) Automatically ask NickServ to reclaim your nick when reconnecting; experimental as of ERC 5.6 @@ -618,51 +618,84 @@ always loads anyway. @subheading Local Modules @cindex local modules -All modules operate as minor modes under the hood, and some newer ones -may be defined as buffer-local. These so-called ``local modules'' are -a work in progress and their behavior and interface are subject to -change. As of ERC 5.5, the only practical differences are as follows: +@c Earlier language in code comments, commit messages, and tracker +@c discussions used to describe a local module as being "active" in a +@c buffer if it had a local binding but "disabled" if that binding's +@c value was nil. For better or worse, ERC has since abandoned that +@c distinction and now considers "active" to be synonymous with +@c "enabled". + +All modules operate as minor modes under the hood, and newer ones are +mostly defined as buffer-local. These so-called @dfn{local modules} are +a work in progress, and their behavior and interface are subject to +change. As of ERC 5.6, the only practical differences are as follows: @enumerate @item -``Control variables,'' like @code{erc-sasl-mode}, retain their values -across IRC sessions and override @code{erc-module} membership when -influencing module activation. +@dfn{Mode variables}, a.k.a. @dfn{control variables}, like +@code{erc-sasl-mode}, retain their values across IRC sessions. @item Removing a local module from @code{erc-modules} via Customize not only -disables its mode but also kills its control variable in all ERC -buffers. +disables its mode but also kills its mode variable in all ERC buffers. @item -``Mode toggles,'' like @code{erc-sasl-mode} and the complementary -@code{erc-sasl-enable}/@code{erc-sasl-disable} pairing, behave -differently than their global counterparts. +@dfn{Mode commands}, like @code{erc-sasl-mode} and its one-way variants +@code{erc-sasl-enable} and @code{erc-sasl-disable}, behave differently +than their global counterparts. @end enumerate -In target buffers, a local module's activation state survives -``reassociation'' by default, but modules themselves always have the -final say. For example, a module may reset all instances of itself in -its network context upon reconnecting. Moreover, the value of a mode -variable may be meaningless in buffers that its module has no interest -in. For example, the value of @code{erc-sasl-mode} doesn't matter in -target buffers and may even remain non-@code{nil} after SASL has been -disabled for the current connection (and vice versa). +To detect whether a module is local, examine its mode variable. For +example, if you run @kbd{C-h v erc-sasl-mode @key{RET}}, you'll notice +it says ``Automatically becomes buffer-local when set''. You can do the +same in Lisp code with @code{(local-variable-if-set-p 'erc-sasl-mode)}. -When it comes to server buffers, a module's activation state only -persists for sessions revived via the automatic reconnection mechanism -or a manual @samp{/reconnect} issued at the prompt. In other words, -this doesn't apply to sessions revived by an entry-point command, such -as @code{erc-tls}, because such commands always ensure a clean slate -by looking only to @code{erc-modules}. Although a session revived in -this manner may indeed harvest other information from a previous -server buffer, it simply doesn't care which modules might have been -active during that connection. +In an ERC buffer, a local module is either enabled or disabled if its +mode variable has a local binding. This @dfn{activation state} may +contradict a module's presence in @code{erc-modules}, namely, in buffers +where it isn't applicable or has otherwise been disabled. In fact, a +local module's membership in @code{erc-modules} does nothing more than +guarantee -Lastly, a local mode's toggle command, like @code{erc-sasl-mode}, only -affects the current buffer, but its ``non-mode'' cousins, like +@enumerate +@item +its setup code runs in @emph{new} buffers +@item +its mode variable has a local binding in all affected buffers +@end enumerate + +In keeping with this, all built-in local modules disable themselves in +nonapplicable buffers rather than remain no-ops. Some also take strides +to enable themselves elsewhere when needed or at least emit a helpful +error. For example, the @samp{nicks} module does both in server +buffers, where it shares resources among the target buffers it primarily +services. ERC expects third-party local modules to mimic this pattern +and to document what buffer types they operate in: server, query, or +channel. (In the case of @samp{nicks}, it would be all three: it's +@dfn{session-local}.) + +In ERC, you can think of an IRC session as a group of buffers sharing +the same connection to a server. After a connection ends, this +association endures so that ERC can revive the session when +reconnecting. As it does with connection parameters, ERC therefore +persists a local module's activation state through reconnections, +reenabling modules that were previously active while ensuring others are +disabled. A couple related things to note here are + +@enumerate +@item +each module must manage its own application data and restore or reset +its environment accordingly +@item +session persistence is less predictable if a user changes the makeup of +@code{erc-modules} between sessions +@end enumerate + +When it comes to a local module's various activation commands, the +primary mode command, like @code{erc-sasl-mode}, for example, only +affects the current buffer, but its unidirectional cousins, like @code{erc-sasl-enable} and @code{erc-sasl-disable}, operate on all -buffers belonging to their connection (when called interactively). -And unlike global toggles, none of these ever mutates -@code{erc-modules}. +buffers belonging to their connection (when called interactively). And +unlike global toggles, none of these ever mutates @code{erc-modules}. + @c FIXME add section to Advanced chapter for creating modules, and @c move this there. diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index cfd0d3415ea..24a3205e0cd 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -372,7 +372,9 @@ than the indicator's position." "Buffer-local `keep-place' with fringe arrow and/or highlighted face. Play nice with global module `keep-place' but don't depend on it. Expect that users may want different combinations of `keep-place' -and `keep-place-indicator' in different buffers." +and `keep-place-indicator' in different buffers. + +This module is local to individual buffers." ((cond (erc-keep-place-mode) ((memq 'keep-place erc-modules) (erc-keep-place-mode +1)) @@ -589,7 +591,9 @@ message's speaker." Skip those appearing in `erc-noncommands-list'. Users can run \\[erc-command-indicator-toggle-hidden] to hide and -reveal echoed command lines after they've been inserted." +reveal echoed command lines after they've been inserted. + +This module is local to individual buffers." ((add-hook 'erc--input-review-functions #'erc--command-indicator-permit-insertion 80 t) (erc-command-indicator-toggle-hidden -1)) diff --git a/lisp/erc/erc-nicks.el b/lisp/erc/erc-nicks.el index b0629f7754c..a3e9b1f7b46 100644 --- a/lisp/erc/erc-nicks.el +++ b/lisp/erc/erc-nicks.el @@ -541,7 +541,9 @@ Abandon search after examining LIMIT faces." nick-object) (define-erc-module nicks nil - "Uniquely colorize nicknames in target buffers." + "Uniquely colorize nicknames in target buffers. + +This module is local per connection." ((if erc--target (progn (erc-with-server-buffer diff --git a/lisp/erc/erc-notify.el b/lisp/erc/erc-notify.el index 82754cb1989..1e04c90177e 100644 --- a/lisp/erc/erc-notify.el +++ b/lisp/erc/erc-notify.el @@ -299,7 +299,8 @@ like `nickbar', to provide UI feedback when changes occur. Once ERC implements the `monitor' extension, this module will serve as an optional fallback for keeping query-participant rolls up to date on servers that lack support or are stingy with their allotments. Until -such time, this module should be considered experimental. +such time, this module should be considered experimental and only really +useful for bots and other non-interactive Lisp programs. This is a local ERC module, so selectively polling only a subset of query targets is possible but cumbersome. To do so, ensure @@ -307,7 +308,8 @@ query targets is possible but cumbersome. To do so, ensure as appropriate in desired query buffers. To stop polling for the current connection, toggle off the command \\[erc-querypoll-mode] from a server buffer, or run \\`M-x C-u erc-querypoll-disable RET' from a -target buffer." +target buffer. Note that this module's minor mode must remain active in +at least the server buffer." ((if erc--target (if (erc-query-buffer-p) (progn ; accommodate those who eschew `erc-modules' diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el index a16f554f2d1..5228fc5e5aa 100644 --- a/lisp/erc/erc-sasl.el +++ b/lisp/erc/erc-sasl.el @@ -34,13 +34,6 @@ ;; ;; - Implement a proxy mechanism that chooses the strongest available ;; mechanism for you. Requires CAP 3.2 (see bug#49860). -;; -;; - Integrate with whatever solution ERC eventually settles on to -;; handle user options for different network contexts. At the -;; moment, this does its own thing for stashing and restoring -;; session options, but ERC should make abstractions available for -;; all local modules to use, possibly based on connection-local -;; variables. ;;; Code: (require 'erc) @@ -315,9 +308,10 @@ If necessary, pass PROMPT to `read-passwd'." (define-erc-module sasl nil "Non-IRCv3 SASL support for ERC. -This doesn't solicit or validate a suite of supported mechanisms." - ;; See bug#49860 for a CAP 3.2-aware WIP implementation. - ((unless erc--target +This local module only enables its minor mode in server buffers, and it +doesn't currently solicit or validate supported mechanisms." + ((if erc--target + (erc-sasl-mode -1) (setq erc-sasl--state (make-erc-sasl--state)) ;; If the previous attempt failed during registration, this may be ;; non-nil and contain erroneous values, but how can we detect that? diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el index 429424117eb..25da873076e 100644 --- a/lisp/erc/erc-services.el +++ b/lisp/erc/erc-services.el @@ -613,8 +613,10 @@ In practical terms, this means that this module, which is still somewhat experimental, is likely only useful in conjunction with SASL authentication or CertFP rather than the traditional approach provided by the `services' module it shares a library with (see Info -node `(erc) SASL' for more)." - nil nil localp) +node `(erc) SASL' for more). + +This local module's minor mode is only active in server buffers." + ((when erc--target (erc-services-regain-mode -1))) nil localp) (cl-defmethod erc--nickname-in-use-make-request ((want string) temp &context (erc-server-connected null) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index afa8e0a7b72..0d72b46360e 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2662,7 +2662,9 @@ side effect of setting the current buffer to the one it returns. Use (erc--initialize-markers old-point continued-session) (erc-determine-parameters server port nick full-name user passwd) (save-excursion (run-mode-hooks) - (dolist (mod (car delayed-modules)) (funcall mod +1)) + (dolist (mod (car delayed-modules)) + (unless (and (boundp mod) (symbol-value mod)) + (funcall mod +1))) (dolist (var (cdr delayed-modules)) (set var nil))) ;; Saving log file on exit diff --git a/test/lisp/erc/erc-scenarios-base-local-modules.el b/test/lisp/erc/erc-scenarios-base-local-modules.el index 71923cc11f2..1d670b8f508 100644 --- a/test/lisp/erc/erc-scenarios-base-local-modules.el +++ b/test/lisp/erc/erc-scenarios-base-local-modules.el @@ -117,20 +117,25 @@ (erc-cmd-QUIT "") (funcall expect 10 "finished"))) - (ert-info ("Disabling works from a target buffer") + (ert-info ("Explicit disabling affects entire session") + ;; Even though the mode variable is nil (but locally bound) in + ;; this target buffer, disabling interactively with + ;; `erc-sasl-disable', deactivates the module session-wide. (with-current-buffer "#chan" - (should erc-sasl-mode) - (call-interactively #'erc-sasl-disable) (should-not erc-sasl-mode) (should (local-variable-p 'erc-sasl-mode)) + (should (buffer-local-value 'erc-sasl-mode (get-buffer "foonet"))) + (call-interactively #'erc-sasl-disable) (should-not (buffer-local-value 'erc-sasl-mode (get-buffer "foonet"))) + (should-not erc-sasl-mode) (erc-cmd-RECONNECT) (funcall expect 10 "Some enigma, some riddle") - (should-not erc-sasl-mode) ; regression + (should-not erc-sasl-mode) (should (local-variable-p 'erc-sasl-mode))) (with-current-buffer "foonet" (should (local-variable-p 'erc-sasl-mode)) + (should-not erc-sasl-mode) (funcall expect 10 "User modes for tester`") (erc-cmd-QUIT "") (funcall expect 10 "finished"))) @@ -139,7 +144,8 @@ (with-current-buffer "#chan" (call-interactively #'erc-sasl-enable) (should (local-variable-p 'erc-sasl-mode)) - (should erc-sasl-mode) + (should-not erc-sasl-mode) + (should (buffer-local-value 'erc-sasl-mode (get-buffer "foonet"))) (erc-cmd-RECONNECT) (funcall expect 10 "Well met; good morrow, Titus and Hortensius.") (erc-cmd-QUIT "")) From 028913c446b8f06288f2e17be91aef701dc58ba4 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 7 Feb 2025 18:54:22 -0800 Subject: [PATCH 110/279] ; Make ERC test fixture more robust * test/lisp/erc/erc-tests.el (erc-tests--assert-printed-in-subprocess): Scan for sentinel before reading. (erc--find-mode, erc--essential-hook-ordering): Use contrived :result protocol expected by `erc-tests--assert-printed-in-subprocess'. * test/lisp/erc/resources/erc-tests-common.el (erc-tests-common-create-subprocess): Divert stderr to messages buffer. --- test/lisp/erc/erc-tests.el | 37 +++++++++++++-------- test/lisp/erc/resources/erc-tests-common.el | 20 ++++++----- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index df9e4d52f77..2279496e600 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -3558,12 +3558,23 @@ (should (eq (erc--normalize-module-symbol 'nickserv) 'services))) (defun erc-tests--assert-printed-in-subprocess (code expected) - (let ((proc (erc-tests-common-create-subprocess code '("-batch") nil))) - (while (accept-process-output proc 10)) - (goto-char (point-min)) - (unless (equal (read (current-buffer)) expected) - (message "Expected: %S\nGot: %s" expected (buffer-string)) - (ert-fail "Mismatch")))) + "Assert result emitted to standard output from CODE matches EXPECTED. +Expect CODE to print result using `prin1' as a list beginning with the +keyword :result." + (with-current-buffer + (get-buffer-create + (concat "*" (symbol-name (ert-test-name (ert-running-test))) "*")) + (unwind-protect + (let ((proc (erc-tests-common-create-subprocess code '("-batch") nil))) + (while (accept-process-output proc 10)) + (goto-char (point-min)) + (search-forward "(:result " nil t) + (unless (equal (ignore-errors (read (current-buffer))) expected) + (ert-fail (list "Mismatch" + :expected expected + :buffer-string (buffer-string))))) + (when noninteractive + (kill-buffer))))) ;; Worrying about which library a module comes from is mostly not ;; worth the hassle so long as ERC can find its minor mode. However, @@ -3573,25 +3584,25 @@ (ert-deftest erc--find-mode () (erc-tests--assert-printed-in-subprocess - `(let ((mods (mapcar #'cadddr (cdddr (get 'erc-modules 'custom-type)))) + '(let ((mods (mapcar #'cadddr (cdddr (get 'erc-modules 'custom-type)))) moded) (setq mods (sort mods (lambda (a b) (if (zerop (random 2)) a b)))) (dolist (mod mods) (unless (keywordp mod) (push (if-let* ((mode (erc--find-mode mod))) mod (list :missing mod)) moded))) - (message "%S" - (sort moded (lambda (a b) - (string< (symbol-name a) (symbol-name b)))))) + (prin1 (list :result + (sort moded (lambda (a b) + (string< (symbol-name a) (symbol-name b))))))) erc-tests--modules)) (ert-deftest erc--essential-hook-ordering () (erc-tests--assert-printed-in-subprocess '(progn (erc-update-modules) - (message "%S" - (list :erc-insert-modify-hook erc-insert-modify-hook - :erc-send-modify-hook erc-send-modify-hook))) + (prin1 (list :result + (list :erc-insert-modify-hook erc-insert-modify-hook + :erc-send-modify-hook erc-send-modify-hook)))) '( :erc-insert-modify-hook (erc-controls-highlight ; 0 erc-button-add-buttons ; 30 diff --git a/test/lisp/erc/resources/erc-tests-common.el b/test/lisp/erc/resources/erc-tests-common.el index 236fac84132..eedea8c44de 100644 --- a/test/lisp/erc/resources/erc-tests-common.el +++ b/test/lisp/erc/resources/erc-tests-common.el @@ -356,15 +356,17 @@ interspersing \"-l\" between members." (require 'erc) (cl-assert (equal erc-version ,erc-version) t) ,code)) - (proc (apply #'start-process - (symbol-name (ert-test-name (ert-running-test))) - (current-buffer) - (concat invocation-directory invocation-name) - `(,@(or init '("-Q")) - ,@switches - ,@(mapcan (lambda (f) (list "-l" f)) libs) - "-eval" ,(format "%S" prog))))) - (set-process-query-on-exit-flag proc t) + (proc (make-process + :name (symbol-name (ert-test-name (ert-running-test))) + :buffer (current-buffer) + :command `(,(concat invocation-directory invocation-name) + ,@(or init '("-Q")) + ,@switches + ,@(mapcan (lambda (f) (list "-l" f)) libs) + "-eval" ,(format "%S" prog)) + :connection-type 'pipe + :stderr (messages-buffer) + :noquery t))) proc)) (declare-function erc-track--setup "erc-track" ()) From 77ff0df588b6691db38be810210225e84d15eca3 Mon Sep 17 00:00:00 2001 From: Nicolas Despres Date: Sat, 21 Dec 2024 12:45:12 +0100 Subject: [PATCH 111/279] Prioritize split along the longest edge by default. Currently, `split-window-sensibly' prefers to try to split vertically first, disregarding the actual shape of the frame or the user preferences. This is a good default when Emacs is taller than wider. However, when Emacs is in full-screen (landscape screen layout), trying to split vertically may not be what the user expected, since there is plenty of space available on the right. Typical scenario: Emacs is in landscape layout, one buffer is open in a window covering the entire frame. Another buffer is opened in a second window (C-x 4 f). Both splits are feasible but users may prefer the horizontal one. This patch preserves the behavior of the `split-height-threshold' and `split-width-threshold' variables. Splitting continues not to be permitted if the edge length is below the threshold. * lisp/window.el (split-window-sensibly): First tried split direction follows user preferences. * etc/NEWS: Add an entry for new variable `split-window-preferred-direction'. * doc/emacs/windows.texi: Document new variable. --- doc/emacs/windows.texi | 5 ++- etc/NEWS | 8 ++++ lisp/window.el | 90 +++++++++++++++++++++++++++++++----------- 3 files changed, 78 insertions(+), 25 deletions(-) diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index a992f26fcdd..a4941435073 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -511,6 +511,7 @@ selected frame, and display the buffer in that new window. @vindex split-height-threshold @vindex split-width-threshold +@vindex split-window-preferred-direction The split can be either vertical or horizontal, depending on the variables @code{split-height-threshold} and @code{split-width-threshold}. These variables should have integer @@ -519,7 +520,9 @@ window's height, the split puts the new window below. Otherwise, if @code{split-width-threshold} is smaller than the window's width, the split puts the new window on the right. If neither condition holds, Emacs tries to split so that the new window is below---but only if the -window was not split before (to avoid excessive splitting). +window was not split before (to avoid excessive splitting). Whether +Emacs tries first to split vertically or horizontally, is +determined by the value of @code{split-window-preferred-direction}. @item Otherwise, display the buffer in a window previously showing it. diff --git a/etc/NEWS b/etc/NEWS index df1aff9213e..191b5235bde 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -226,6 +226,14 @@ It has been obsolete since Emacs 30.1. Use '(category . comint)' instead. Another user option 'display-tex-shell-buffer-action' has been removed too for which you can use '(category . tex-shell)'. ++++ +*** New user option 'split-window-preferred-direction'. +Users can now choose in which direction Emacs tries to split first: +vertical or horizontal. With this new setting, when the frame is in +landscape shape for instance, Emacs could split horizontally before +splitting vertically. The default setting preserves Emacs historical +behavior to try to split vertically first. + ** Frames +++ diff --git a/lisp/window.el b/lisp/window.el index 74bb2985254..ab15979baed 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7394,20 +7394,64 @@ hold: (* 2 (max window-min-height (if mode-line-format 2 1)))))))))) +(defcustom split-window-preferred-direction 'vertical + "The first direction tried when Emacs needs to split a window. +This variable controls in which order `split-window-sensibly' will try to +split the window. That order specially matters when both dimensions of +the frame are long enough to be split according to +`split-width-threshold' and `split-height-threshold'. If this is set to +`vertical' (the default), `split-window-sensibly' tries to split +vertically first and then horizontally. If set to `horizontal' it does +the opposite. If set to `longest', the first direction tried +depends on the frame shape: in landscape orientation it will be like +`horizontal', but in portrait it will be like `vertical'. Basically, +the longest of the two dimension is split first. + +If both `split-width-threshold' and `split-height-threshold' cannot be +satisfied, it will fallback to split vertically. + +See `split-window-preferred-function' for more control of the splitting +strategy." + :type '(radio + (const :tag "Try to split vertically first" + vertical) + (const :tag "Try to split horizontally first" + horizontal) + (const :tag "Try to split along the longest edge first" + longest)) + :version "31.1" + :group 'windows) + +(defun window--try-vertical-split (window) + "Helper function for `split-window-sensibly'" + (when (window-splittable-p window) + (with-selected-window window + (split-window-below)))) + +(defun window--try-horizontal-split (window) + "Helper function for `split-window-sensibly'" + (when (window-splittable-p window t) + (with-selected-window window + (split-window-right)))) + (defun split-window-sensibly (&optional window) "Split WINDOW in a way suitable for `display-buffer'. -WINDOW defaults to the currently selected window. -If `split-height-threshold' specifies an integer, WINDOW is at -least `split-height-threshold' lines tall and can be split -vertically, split WINDOW into two windows one above the other and -return the lower window. Otherwise, if `split-width-threshold' -specifies an integer, WINDOW is at least `split-width-threshold' -columns wide and can be split horizontally, split WINDOW into two -windows side by side and return the window on the right. If this -can't be done either and WINDOW is the only window on its frame, -try to split WINDOW vertically disregarding any value specified -by `split-height-threshold'. If that succeeds, return the lower -window. Return nil otherwise. +The variable `split-window-preferred-direction' prescribes an order of +directions in which Emacs should try to split WINDOW. If that order +mandates starting with a vertical split, and `split-height-threshold' +specifies an integer that is at least as large a WINDOW's height, split +WINDOW into two windows one below the other and return the lower one. +If that order mandates starting with a horizontal split, and +`split-width-threshold' specifies an integer that is at least as large +as WINDOW's width, split WINDOW into two windows side by side and return +the one on the right. + +In either case, if the first attempt to split WINDOW fails, try to split +the window in the other direction in the same manner as described above. +If that attempt fails too, and WINDOW is the only window on its frame, +try splitting WINDOW into two windows, one below the other, disregarding +the value of `split-height-threshold' and return the window on the +bottom. By default `display-buffer' routines call this function to split the largest or least recently used window. To change the default @@ -7427,14 +7471,14 @@ Have a look at the function `window-splittable-p' if you want to know how `split-window-sensibly' determines whether WINDOW can be split." (let ((window (or window (selected-window)))) - (or (and (window-splittable-p window) - ;; Split window vertically. - (with-selected-window window - (split-window-below))) - (and (window-splittable-p window t) - ;; Split window horizontally. - (with-selected-window window - (split-window-right))) + (or (if (or + (eql split-window-preferred-direction 'horizontal) + (and (eql split-window-preferred-direction 'longest) + (> (frame-width) (frame-height)))) + (or (window--try-horizontal-split window) + (window--try-vertical-split window)) + (or (window--try-vertical-split window) + (window--try-horizontal-split window))) (and ;; If WINDOW is the only usable window on its frame (it is ;; the only one or, not being the only one, all the other @@ -7452,10 +7496,8 @@ split." frame nil 'nomini) t))) (not (window-minibuffer-p window)) - (let ((split-height-threshold 0)) - (when (window-splittable-p window) - (with-selected-window window - (split-window-below)))))))) + (let ((split-height-threshold 0)) + (window--try-vertical-split window)))))) (defun window--try-to-split-window (window &optional alist) "Try to split WINDOW. From 628e3cb22d196c31fc2452c3eab4a62af4bf66b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Bidar?= Date: Wed, 22 Jan 2025 01:28:22 +0200 Subject: [PATCH 112/279] Add 'nnregistry-request-group' function for 'gnus-refer-article' nnregistry doesn't handle any servers or groups; however we have to define the dummy function so Gnus-registry works as refer article method, as the `gnus-check-group-server' function requires it. The latter function is called when referring to articles to check the source group first before actually requesting any articles. * lisp/gnus/nnregistry.el (nnregistry-request-group): New deffoo. (Bug#22414) --- lisp/gnus/nnregistry.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lisp/gnus/nnregistry.el b/lisp/gnus/nnregistry.el index edf773209d6..10363560ba6 100644 --- a/lisp/gnus/nnregistry.el +++ b/lisp/gnus/nnregistry.el @@ -47,6 +47,9 @@ (deffoo nnregistry-open-server (_server &optional _defs) gnus-registry-db) +(deffoo nnregistry-request-group (_group &optional _server _dont-check _info) + t) + (defvar nnregistry-within-nnregistry nil) (deffoo nnregistry-request-article (id &optional _group _server buffer) From 512187feb046aea6de6d26e45271481a324a928c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Feb 2025 12:41:36 +0200 Subject: [PATCH 113/279] * lisp/mouse.el (mouse-skip-word): Avoid errors at EOB. (Bug#75965) --- lisp/mouse.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lisp/mouse.el b/lisp/mouse.el index b05115b237d..3a8388870be 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -1892,8 +1892,14 @@ The region will be defined with mark and point." If `mouse-1-double-click-prefer-symbols' is non-nil, skip over symbol. If DIR is positive skip forward; if negative, skip backward." (let* ((char (following-char)) + (syntax-after-pt (syntax-class (syntax-after (point)))) (syntax (char-to-string - (syntax-class-to-char (syntax-class (syntax-after (point)))))) + (if syntax-after-pt + (syntax-class-to-char syntax-after-pt) + ;; Zero is what 'following-char' returns at EOB, so + ;; we feed that to 'char-syntax' when 'syntax-class' + ;; returns nil, which means we are at EOB. + (char-syntax ?\0)))) sym) (cond ((and mouse-1-double-click-prefer-symbols (setq sym (bounds-of-thing-at-point 'symbol))) From 535eec814484c437443051e0b6d2d654eef9b7e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jostein=20Kj=C3=B8nigsen?= Date: Sat, 1 Feb 2025 22:16:36 +0100 Subject: [PATCH 114/279] lisp/progmodes/csharp-mode.el: Improve string-interpolation Correctly fontify expressions inside string-interpolations. (Bug#75580) --- lisp/progmodes/csharp-mode.el | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 9d19456179b..b26ce4e34a5 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -736,6 +736,12 @@ compilation and evaluation time conflicts." (treesit-query-compile 'c-sharp "(interpolated_string_text)" t) t)) +(defun csharp-ts-mode--test-string-content () + "Return non-nil if (interpolated_string_text) is in the grammar." + (ignore-errors + (treesit-query-compile 'c-sharp "(string_content)" t) + t)) + (defun csharp-ts-mode--test-type-constraint () "Return non-nil if (type_constraint) is in the grammar." (ignore-errors @@ -830,10 +836,12 @@ compilation and evaluation time conflicts." (boolean_literal) @font-lock-constant-face) :language 'c-sharp - :override t :feature 'string `([(string_literal) (verbatim_string_literal) + ,@ (when (csharp-ts-mode--test-string-content) + '((string_content) + "\"")) ,@(if (csharp-ts-mode--test-interpolated-string-text) '((interpolated_string_text) (interpolated_verbatim_string_text) From 72bbbff7e8128fe14c0b69c7282667788758b8b4 Mon Sep 17 00:00:00 2001 From: Jared Finder Date: Sun, 2 Feb 2025 10:11:20 -0800 Subject: [PATCH 115/279] Update window-tool-bar Add support for the remaining tool bar item specs, new user option `window-tool-bar-style', and add support for older Emacs versions. * doc/emacs/windows.texi (Window Tool Bar): Add documentation for new user option `window-tool-bar-style'. * lisp/window-tool-bar.el (customize-package-emacs-version-alist): Add package-version to Emacs version mapping. (window-tool-bar-string): Do not show spacers after hidden buttons. (window-tool-bar--keymap-entry-to-string): Call new function `window-tool-bar--style'. Add handling for :visible, :filter, :button, :vert-only, and :help item specs. Show key bindings. (window-tool-bar--last-command-triggers-refresh-p): Use "cannot" in comment. (window-tool-bar--allow-images): Delete this, it is replaced by new user option `window-tool-bar-style'. (window-tool-bar--use-images): Delete this, it is replaced by new function `window-tool-bar--style'. (window-tool-bar--turn-on): Move earlier in file, no changes. (window-tool-bar-style): New user option supporting all values `tool-bar-style' supports as well as inheriting from tool-bar-style. (window-tool-bar--style): New function to calculate active tool bar style based on `window-tool-bar-style', `tool-bar-style', and frame capabilities. (global-window-tool-bar-mode, window-tool-bar-button) (window-tool-bar-button-hover, window-tool-bar-button-disabled): Retroactively add package-version. (window-tool-bar-button-checked) (window-tool-bar-button-checked-hover): New faces for :button item spec. (window-tool-bar--get-keymap): Call new function `window-tool-bar--style'. (Bug#75844) --- doc/emacs/windows.texi | 10 ++ lisp/window-tool-bar.el | 281 +++++++++++++++++++++++++++------------- 2 files changed, 204 insertions(+), 87 deletions(-) diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index a4941435073..4a35fd54f66 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -731,6 +731,16 @@ a custom tool bar, you could add the following code to your init file (add-hook 'special-mode-hook 'window-tool-bar-mode) @end example +@vindex window-tool-bar-style +@cindex window tool bar style +On graphical displays the window tool bar can be displayed in several +different styles. By default, the window tool bar displays items as +just images. To impose a specific style, customize the variable +@code{window-tool-bar-style}. + +On text-only displays the window tool bar only shows text for each +button even if another style is specified. + Emacs can also display a single tool bar at the top of frames (@pxref{Tool Bars}). diff --git a/lisp/window-tool-bar.el b/lisp/window-tool-bar.el index e2c886c41e5..96726960fea 100644 --- a/lisp/window-tool-bar.el +++ b/lisp/window-tool-bar.el @@ -4,8 +4,9 @@ ;; Author: Jared Finder ;; Created: Nov 21, 2023 -;; Version: 0.2.1 +;; Version: 0.3 ;; Keywords: mouse +;; URL: http://github.com/chaosemer/window-tool-bar ;; Package-Requires: ((emacs "27.1") (compat "29.1")) ;; This is a GNU ELPA :core package. Avoid adding functionality that @@ -54,44 +55,27 @@ ;;; Known issues: ;; -;; On GNU Emacs 29.1, terminals dragging to resize windows will error -;; with message " is undefined". This is a -;; bug in GNU Emacs, +;; On GNU Emacs 29.1 and earlier, terminals dragging to resize windows +;; will error with message " is undefined". +;; This is a bug in GNU Emacs, ;; . ;; -;; On GNU Emacs 29, performance in terminals is lower than on -;; graphical frames. This is due to a workaround, see "Workaround for -;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68334", below. +;; On GNU Emacs 29 and earlier, performance in terminals is lower than +;; on graphical frames. This is due to a workaround, see "Workaround +;; for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68334", below. ;;; Todo: ;; ;; Not all features planned are implemented yet. Eventually I would ;; like to also generally make tool bars better. ;; -;; Targeting 0.3: -;; * Properly support remaining less frequently used tool bar item specs. From -;; `parse_tool_bar_item': -;; * :visible -;; * :filter -;; * :button -;; * :wrap -;; * Add display customization similar to `tool-bar-style'. -;; -;; Targeting 1.0: +;; Post 1.0 work: ;; ;; * Clean up Emacs tool bars ;; * Default: Remove default tool-bar entirely ;; * grep, vc: Remove default tool-bar inherited ;; * info: Remove Next / Prev / Up, which is already in the header ;; * smerge: Add tool bar for next/prev -;; -;; Post 1.0 work: -;; -;; * Show keyboard shortcut on help text. -;; -;; * Add a bit more documentation. -;; * Add customization option: ignore-default-tool-bar-map -;; * Make tab-line dragging resize the window ;;; Code: @@ -99,6 +83,11 @@ (require 'mwheel) (require 'tab-line) (require 'tool-bar) + +(add-to-list 'customize-package-emacs-version-alist + '(window-tool-bar ("0.1" . "30.1") + ("0.2" . "30.1") + ("0.3" . "31.1"))) ;;; Benchmarking code ;; @@ -227,7 +216,7 @@ AVG-MEMORY-USE is a list of averages, with the same meaning as (defun window-tool-bar-string () "Return a (propertized) string for the tool bar. -This is for when you want more customizations than +This is for when you want more customizations than the command `window-tool-bar-mode' provides. Commonly added to the variable `tab-line-format', `header-line-format', or `mode-line-format'" (if (or (null window-tool-bar-string--cache) @@ -235,13 +224,14 @@ This is for when you want more customizations than (let* ((mem0 (memory-use-counts)) (toolbar-menu (window-tool-bar--get-keymap)) (mem1 (memory-use-counts)) - (result (mapconcat #'window-tool-bar--keymap-entry-to-string - (cdr toolbar-menu) ;Skip 'keymap + (strs (mapcar #'window-tool-bar--keymap-entry-to-string + (cdr toolbar-menu))) ;Skip 'keymap + (result (mapconcat #'identity + (delete nil strs) ;; Without spaces between the text, hovering ;; highlights all adjacent buttons. - (if (window-tool-bar--use-images) - (propertize " " 'invisible t) - " "))) + (if (eq 'text (window-tool-bar--style)) " " + (propertize " " 'invisible t)))) (mem2 (memory-use-counts))) (cl-mapl (lambda (l-init l0 l1) (cl-incf (car l-init) (- (car l1) (car l0)))) @@ -281,45 +271,101 @@ MENU-ITEM is a menu item to convert. See info node `(elisp)Tool Bar'." ((or `(,_ "--") `(,_ menu-item ,(and (pred stringp) (pred (string-prefix-p "--"))))) - (if (window-tool-bar--use-images) - window-tool-bar--graphical-separator - "|")) + (if (eq 'text (window-tool-bar--style)) "|" + window-tool-bar--graphical-separator)) ;; Menu item, turn into propertized string button (`(,key menu-item ,name-expr ,binding . ,plist) - (when binding ; If no binding exists, then button is hidden. - (let* ((name (eval name-expr)) - (str (upcase-initials (or (plist-get plist :label) - (string-trim-right name "\\.+")))) - (len (length str)) - (enable-form (plist-get plist :enable)) - (enabled (or (not enable-form) - (eval enable-form)))) - (if enabled + (let* ((visible-entry (plist-member plist :visible)) + (visible (or (null visible-entry) ;Default is visible + (eval (cadr visible-entry)))) + (wrap (plist-get plist :wrap)) + (filter (plist-get plist :filter))) + (when filter + (setf binding + ;; You would expect this to use `funcall', but existing + ;; code in `parse_tool_bar_item' uses `eval'. + (eval `(,filter ',binding)))) + (when (and binding + visible + (null wrap)) + (let* ((name (eval name-expr)) + (str (upcase-initials (or (plist-get plist :label) + (string-trim-right name "\\.+")))) + (len (length str)) + (enable-form (plist-get plist :enable)) + (enabled (or (not enable-form) + (eval enable-form))) + (button-spec (plist-get plist :button)) + (button-selected (eval (cdr-safe button-spec))) + (vert-only (plist-get plist :vert-only)) + image-start + image-end) + ;; Depending on style, Images can be displayed to the + ;; left, to the right, or in place of the text + (pcase-exhaustive (window-tool-bar--style) + ('image + (setf image-start 0 + image-end len)) + ('text + ;; Images shouldn't be available + ) + ((or 'both 'both-horiz) + (if vert-only + (setf image-start 0 image-end len) + (setf str (concat " " str) + image-start 0 + image-end 1 + len (1+ len)))) + ('text-image-horiz + (if vert-only + (setf image-start 0 image-end len) + (setf str (concat str " ") + image-start len + image-end (1+ len) + len (1+ len))))) + + (cond + ((and enabled button-selected) + (add-text-properties 0 len + '(mouse-face + window-tool-bar-button-checked-hover + keymap window-tool-bar--button-keymap + face window-tool-bar-button-checked) + str)) + (enabled (add-text-properties 0 len '(mouse-face window-tool-bar-button-hover keymap window-tool-bar--button-keymap face window-tool-bar-button) - str) - (put-text-property 0 len - 'face - 'window-tool-bar-button-disabled - str)) - (when-let* ((spec (and (window-tool-bar--use-images) - (plist-get menu-item :image)))) - (put-text-property 0 len - 'display - (append spec - (if enabled '(:margin 2 :ascent center) - '(:margin 2 :ascent center - :conversion disabled))) - str)) - (put-text-property 0 len - 'help-echo - (or (plist-get plist :help) name) - str) - (put-text-property 0 len 'tool-bar-key key str) - str))))) + str)) + (t + (put-text-property 0 len + 'face + 'window-tool-bar-button-disabled + str))) + (when-let* ((spec (and image-start image-end + (plist-get menu-item :image)))) + (put-text-property image-start image-end + 'display + (append spec + (if enabled '(:margin 2 :ascent center) + '(:margin 2 :ascent center + :conversion disabled))) + str)) + (let ((help-text (or (plist-get plist :help) name)) + (keys (where-is-internal binding nil t))) + (put-text-property 0 len + 'help-echo + (if keys + (concat help-text + " (" + (key-description keys) + ")") + help-text) + str)) + (put-text-property 0 len 'tool-bar-key key str) + str)))))) (defun window-tool-bar--call-button () "Call the button that was clicked on in the tab line." @@ -378,8 +424,8 @@ enclosed in a `progn' form. ELSE-FORMS may be empty." ;; interactions that can alter the tool bar. Specifically, this ;; excludes mouse movement, mouse wheel scroll, and pinch. (not (member type window-tool-bar--ignored-event-types)) - ;; Assume that any command that triggers shift select can't alter - ;; the tool bar. This excludes pure navigation commands. + ;; Assume that any command that triggers shift select cannot + ;; alter the tool bar. This excludes pure navigation commands. (not (window-tool-bar--command-triggers-shift-select-p last-command)) ;; Assume that self-insert-command won't alter the tool bar. ;; This is the most commonly executed command. @@ -415,20 +461,53 @@ enclosed in a `progn' form. ELSE-FORMS may be empty." (define-globalized-minor-mode global-window-tool-bar-mode window-tool-bar-mode window-tool-bar--turn-on :group 'window-tool-bar + :package-version '(window-tool-bar . "0.1") (add-hook 'isearch-mode-hook #'window-tool-bar--turn-on) (add-hook 'isearch-mode-end-hook #'window-tool-bar--turn-on)) -(defvar window-tool-bar--allow-images t - "Internal debug flag to force text mode.") - -(defun window-tool-bar--use-images () - "Internal function. -Respects `window-tool-bar--allow-images' as well as frame -capabilities." - (and window-tool-bar--allow-images - (display-images-p))) +(defun window-tool-bar--turn-on () + "Internal function called by the command `global-window-tool-bar-mode'." + (when global-window-tool-bar-mode + (window-tool-bar-mode 1))) ;;; Display styling: +(defcustom window-tool-bar-style 'image + "Tool bar style to use for window tool bars. +The meaning is the same as for `tool-bar-style', which see. If +set to the symbol `tool-bar-style', then use the value of +`tool-bar-style' instead. + +When images cannot be displayed (see `display-images-p'), the value set +here is ignored and the window tool bar displays text." + :type '(choice + (const :tag "Images" :value image) + (const :tag "Text" :value text) + ;; This option would require multiple tool bar lines. + ;;(const :tag "Both, text below image" :value both) + (const :tag "Both, text to right of image" :value both-horiz) + (const :tag "Both, text to left of image" :value text-image-horiz) + (const :tag "Inherit tool-bar-style" :value tool-bar-style) + (const :tag "System default" :value nil)) + :group 'window-tool-bar + :package-version '(window-tool-bar . "0.3")) + +(defun window-tool-bar--style () + "Return the effective style based on `window-tool-bar-style'. + +This also takes into account frame capabilities. If the current +frame cannot display images (see `display-images-p'), then this +will always return the symbol text." + (if (not (display-images-p)) + 'text + (let ((style window-tool-bar-style)) + (when (eq style 'tool-bar-style) + (setf style tool-bar-style)) + (unless (memq style '(image text both both-horiz text-image-horiz)) + (setf style (if (fboundp 'tool-bar-get-system-style) + (tool-bar-get-system-style) + 'image))) + style))) + (defface window-tool-bar-button '((default :inherit tab-line) @@ -441,7 +520,8 @@ capabilities." (t :inverse-video t)) "Face used for buttons when the mouse is not hovering over the button." - :group 'window-tool-bar) + :group 'window-tool-bar + :package-version '(window-tool-bar . "0.2")) (defface window-tool-bar-button-hover '((default @@ -452,7 +532,8 @@ capabilities." (t :inverse-video t)) "Face used for buttons when the mouse is hovering over the button." - :group 'window-tool-bar) + :group 'window-tool-bar + :package-version '(window-tool-bar . "0.2")) (defface window-tool-bar-button-disabled '((default @@ -465,7 +546,38 @@ capabilities." :inverse-video t :background "brightblack")) "Face used for buttons when the button is disabled." - :group 'window-tool-bar) + :group 'window-tool-bar + :package-version '(window-tool-bar . "0.2")) + +(defface window-tool-bar-button-checked + '((default + :inherit tab-line) + (((supports :box t)) + :box (:line-width -1 :style pressed-button) + :background "grey85") + (((class color)) + :background "blue" + :foreground "white") + (t + :inverse-video t)) + "Face used for buttons when they are toggled." + :group 'window-tool-bar + :package-version '(window-tool-bar . "0.3")) + +(defface window-tool-bar-button-checked-hover + '((default + :inherit tab-line) + (((class color) (min-colors 88) (supports :box t)) + :box (:line-width -1 :style pressed-button) + :background "grey95") + (((class color)) + :background "brightblue" + :foreground "white") + (t + :inverse-video t)) + "Face used for buttons when the mouse is hovering over the button." + :group 'window-tool-bar + :package-version '(window-tool-bar . "0.3")) ;;; Workaround for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68334. @@ -476,10 +588,10 @@ capabilities." "Return the tool bar keymap." (let ((tool-bar-always-show-default nil)) (if (and (version< emacs-version "30") - (not (window-tool-bar--use-images))) - ;; This code path is a less efficient workaround. - (window-tool-bar--make-keymap-1) - (keymap-global-lookup "")))) + (eq 'text (window-tool-bar--style))) + ;; This code path is a less efficient workaround. + (window-tool-bar--make-keymap-1) + (keymap-global-lookup "")))) (declare-function image-mask-p "image.c" (spec &optional frame)) @@ -506,12 +618,7 @@ capabilities." (plist-put plist :image image))) bind)) tool-bar-map)) - -(defun window-tool-bar--turn-on () - "Internal function called by `global-window-tool-bar-mode'." - (when global-window-tool-bar-mode - (window-tool-bar-mode 1))) - + (provide 'window-tool-bar) ;;; window-tool-bar.el ends here From b023d43ee7908d805a6776f18d1a94b213a021e3 Mon Sep 17 00:00:00 2001 From: Jared Finder Date: Thu, 6 Feb 2025 14:32:00 -0800 Subject: [PATCH 116/279] Cleanup tool-bar-mode documentation * doc/emacs/frames.texi (Tool Bars): Downcase concept index text. * lisp/cus-start.el (standard): Copy custom :tag strings from window-tool-bar-style's, which are more descriptive. (Bug#75844) --- doc/emacs/frames.texi | 6 +++--- lisp/cus-start.el | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index e0d8a607072..9992c39dcc9 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1296,7 +1296,7 @@ menus' visual appearance. @section Tool Bars @cindex tool bar mode @cindex tool bar, attached to frame -@cindex mode, Tool Bar +@cindex mode, tool bar @cindex icons, toolbar On graphical displays, Emacs puts a @dfn{tool bar} at the top of each @@ -1320,14 +1320,14 @@ control the use of tool bars at startup, customize the variable @code{tool-bar-mode}. @vindex tool-bar-style -@cindex Tool Bar style +@cindex tool bar style When Emacs is compiled with GTK+ support, each tool bar item can consist of an image, or a text label, or both. By default, Emacs follows the Gnome desktop's tool bar style setting; if none is defined, it displays tool bar items as just images. To impose a specific tool bar style, customize the variable @code{tool-bar-style}. -@cindex Tool Bar position +@cindex tool bar position You can also control the placement of the tool bar for the GTK+ tool bar with the frame parameter @code{tool-bar-position}. @xref{Frame Parameters,,, elisp, The Emacs Lisp Reference Manual}. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index 0f7d7c3c020..5d35edd212b 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -698,9 +698,9 @@ since it could result in memory overflow and make Emacs crash." frames (choice (const :tag "Images" :value image) (const :tag "Text" :value text) - (const :tag "Both" :value both) - (const :tag "Both-horiz" :value both-horiz) - (const :tag "Text-image-horiz" :value text-image-horiz) + (const :tag "Both, text below image" :value both) + (const :tag "Both, text to right of image" :value both-horiz) + (const :tag "Both, text to left of image" :value text-image-horiz) (const :tag "System default" :value nil)) "24.1") (tool-bar-max-label-size frames integer "24.1") (tab-bar-position From 223ee56aae7cf052419cf026bce4d7ea29671286 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Feb 2025 13:47:11 +0200 Subject: [PATCH 117/279] ; Avoid passive tense in Emacs manual * doc/lispref/variables.texi (Defining Variables): Avoid passive tense (bug#76135). --- doc/lispref/variables.texi | 44 +++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index b56dfb6077b..7bc9243649c 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -499,33 +499,37 @@ initializes it only if it is originally void. Definitions}. @defspec defvar symbol [value [doc-string]] -This special form defines @var{symbol} as a variable. Note that -@var{symbol} is not evaluated; the symbol to be defined should appear -explicitly in the @code{defvar} form. The variable is marked as -@dfn{special}, meaning that it should always be dynamically bound +This special form defines @var{symbol} as a variable and optionally +initializes and documents it. Note that it doesn't evaluate +@var{symbol}; the symbol to be defined should appear explicitly in the +@code{defvar} form. @code{defvar} also marks @var{symbol} as +@dfn{special}, meaning that its bindings should always be dynamic (@pxref{Variable Scoping}). If @var{value} is specified, and @var{symbol} is void (i.e., it has no -dynamically bound value; @pxref{Void Variables}), then @var{value} is -evaluated and @var{symbol} is set to the result. But if @var{symbol} -is not void, @var{value} is not evaluated, and @var{symbol}'s value is -left unchanged. If @var{value} is omitted, the value of @var{symbol} -is not changed in any case. +dynamically bound value; @pxref{Void Variables}), then @code{defvar} +evaluates @var{value}, and initializes @var{symbol} by setting it to the +result of the evaluation. But if @var{symbol} is not void, +@code{defvar} does not evaluate @var{value}, and leaves @var{symbol}'s +value unchanged. If @var{value} is omitted, @code{defvar} doesn't +change the value of @var{symbol} in any case. Note that specifying a value, even @code{nil}, marks the variable as -special permanently. Whereas if @var{value} is omitted then the -variable is only marked special locally (i.e.@: within the current -lexical scope, or file if at the top-level). This can be useful for -suppressing byte compilation warnings, see @ref{Compiler Errors}. +special permanently. Whereas if @var{value} is omitted, then +@code{defvar} marks the variable special only locally (i.e.@: within the +current lexical scope, or within the current file, if @code{defvar} is +at the top-level). This can be useful for suppressing byte compilation +warnings, see @ref{Compiler Errors}. -If @var{symbol} has a buffer-local binding in the current buffer, -@code{defvar} acts on the default value, which is buffer-independent, -rather than the buffer-local binding. It sets the default value if -the default value is void. @xref{Buffer-Local Variables}. +If @var{symbol} has a buffer-local binding in the current buffer, and +@var{value} is specified, @code{defvar} modifies the default value of +@var{symbol}, which is buffer-independent, rather than the buffer-local +binding. It sets the default value if the default value is void. +@xref{Buffer-Local Variables}. -If @var{symbol} is already let bound (e.g., if the @code{defvar} -form occurs in a @code{let} form), then @code{defvar} sets the toplevel -default value, like @code{set-default-toplevel-value}. +If @var{symbol} is already let bound (e.g., if the @code{defvar} form +occurs in a @code{let} form), then @code{defvar} sets the toplevel +default value of @var{symbol}, like @code{set-default-toplevel-value}. The let binding remains in effect until its binding construct exits. @xref{Variable Scoping}. From 3123562866130d4ab45c5af7b80aaf0815060ce5 Mon Sep 17 00:00:00 2001 From: shipmints Date: Fri, 7 Feb 2025 14:25:50 -0500 Subject: [PATCH 118/279] Eliminate savehist duplicated symbols * lisp/savehist.el (savehist-save): Do not save symbols duplicated between 'savehist-minibuffer-history-variables' and 'savehist-additional-variables'. (Bug#76123) * test/lisp/savehist-tests.el: New file. --- etc/NEWS | 9 ++++ lisp/savehist.el | 29 +++++----- test/lisp/savehist-tests.el | 104 ++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 test/lisp/savehist-tests.el diff --git a/etc/NEWS b/etc/NEWS index 191b5235bde..1632cdcfed2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -491,6 +491,15 @@ If 'save-place-autosave-interval' is nil, auto saving is disabled; this is the default. As before, saved places are scheduled to be saved at Emacs exit. +** Savehist + +--- +*** Savehist now saves variables only once. +If you configured 'savehist-additional-variables' with variables that +were also dynamically accumulated during minibuffer use, they were saved +twice in the file indicated by 'savehist-file'. These will no longer be +saved twice. + ** Message --- diff --git a/lisp/savehist.el b/lisp/savehist.el index 7cfb358dd6d..32985bac0e1 100644 --- a/lisp/savehist.el +++ b/lisp/savehist.el @@ -299,20 +299,21 @@ If AUTO-SAVE is non-nil, compare the saved contents to the one last saved, (insert "))\n")))))) ;; Save the additional variables. (dolist (elem savehist-additional-variables) - (let ((symbol (if (consp elem) - (car elem) - elem))) - (when (boundp symbol) - (let ((value (symbol-value symbol))) - (when (savehist-printable value) - ;; When we have a max-size, chop off the last elements. - (when (and (consp elem) - (listp value) - (length> value (cdr elem))) - (setq value (copy-sequence value)) - (setcdr (nthcdr (cdr elem) value) nil)) - (prin1 `(setq ,symbol ',value) (current-buffer)) - (insert ?\n))))))) + (when (not (memq elem savehist-minibuffer-history-variables)) + (let ((symbol (if (consp elem) + (car elem) + elem))) + (when (boundp symbol) + (let ((value (symbol-value symbol))) + (when (savehist-printable value) + ;; When we have a max-size, chop off the last elements. + (when (and (consp elem) + (listp value) + (length> value (cdr elem))) + (setq value (copy-sequence value)) + (setcdr (nthcdr (cdr elem) value) nil)) + (prin1 `(setq ,symbol ',value) (current-buffer)) + (insert ?\n)))))))) ;; If autosaving, avoid writing if nothing has changed since the ;; last write. (let ((checksum (md5 (current-buffer) nil nil savehist-coding-system))) diff --git a/test/lisp/savehist-tests.el b/test/lisp/savehist-tests.el new file mode 100644 index 00000000000..e37dceccc10 --- /dev/null +++ b/test/lisp/savehist-tests.el @@ -0,0 +1,104 @@ +;;; savehist-tests.el --- Tests for savehist.el -*- lexical-binding:t -*- + +;; Copyright (C) 2025 Free Software Foundation, Inc. + +;; Author: Stephane Marks + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; These tests emulate what `read-from-minibuffer' would do via +;; `savehist-minibuffer-hook' without calling `read-from-minibuffer'. + +;;; Code: + +(require 'ert) +(require 'ert-x) +(require 'savehist) + +(ert-deftest savehist-test-saved-variables () + ;; These accommodate symbol-value. + (defvar t1) + (defvar t2) + (ert-with-temp-file tmpfile + (let* ((savehist-file tmpfile) + (savehist-save-minibuffer-history t) + (savehist-save-hook) + (savehist-loaded) + (savehist-minibuffer-history-variables) + (savehist-additional-variables '(t2)) + (savehist-ignored-variables '(t3)) + (t1 '("t1-value")) + (t2 '("t2-value")) + (t3 '("t3-value")) + (t1-copy (copy-tree t1)) + (t2-copy (copy-tree t2)) + (t3-copy (copy-tree t3)) + (save-var (lambda (x) + (let ((minibuffer-history-variable x)) + (savehist-minibuffer-hook))))) + (savehist-mode) + (funcall save-var 't1) + (funcall save-var 't2) + (funcall save-var 't3) ; should be ignored + (savehist-save) + (setq t1 nil t2 nil t3 nil) + (progn + ;; Force reloading the file. + (savehist-mode -1) + (setq savehist-loaded nil) + (savehist-mode)) + (should (equal t1 t1-copy)) + (should (equal t2 t2-copy)) + (should (equal t3 nil))))) + +(ert-deftest savehist-test-duplicated-saved-symbols () + (defvar t1) + (defvar t2) + (ert-with-temp-file tmpfile + (let* ((savehist-file tmpfile) + (savehist-save-minibuffer-history t) + (savehist-save-hook) + (savehist-loaded) + (savehist-minibuffer-history-variables) ; will be '(t2 t1) + (savehist-additional-variables '(t2)) ; t2 should not be saved twice + (t1 '("t1-value")) + (t2 '("t2-value")) + (save-var (lambda (x) + (let ((minibuffer-history-variable x)) + (savehist-minibuffer-hook))))) + (savehist-mode) + (funcall save-var 't1) + (funcall save-var 't2) + (savehist-save) + (progn + ;; Force reloading the file. + (savehist-mode -1) + (setq savehist-loaded nil) + (savehist-mode)) + (let ((saved-variables)) + (with-temp-buffer + (insert-file-contents tmpfile) + (goto-char 1) + ;; alnum bypasses savehist-minibuffer-history-variables + (while (re-search-forward "(setq \\([[:alnum:]]+\\) " nil t 1) + (push (match-string 1) saved-variables))) + (should (= (length saved-variables) + (length (seq-uniq saved-variables #'equal)))))))) + +(provide 'savehist-tests) +;;; savehist-tests.el ends here From ad157a86ea9486fcd54522a198108258be28e151 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Feb 2025 14:01:17 +0200 Subject: [PATCH 119/279] ; * etc/NEWS: Fix last change (bug#76123). --- etc/NEWS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 1632cdcfed2..4ab24df14d2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -494,11 +494,11 @@ Emacs exit. ** Savehist --- -*** Savehist now saves variables only once. +*** Savehist no longer saves additional variables more than once. If you configured 'savehist-additional-variables' with variables that -were also dynamically accumulated during minibuffer use, they were saved -twice in the file indicated by 'savehist-file'. These will no longer be -saved twice. +were also dynamically accumulated in minibuffer history during +minibuffer use, they are now saved only once in the file specified by +'savehist-file'. Previously, they were saved twice. ** Message From ed9dd4705c7299c12c18d566bd8db4183b1c57f3 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Feb 2025 14:06:00 +0200 Subject: [PATCH 120/279] ; * admin/authors.el (authors-aliases): Add aliases. --- admin/authors.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/authors.el b/admin/authors.el index 838862241c0..f77ad144cfc 100644 --- a/admin/authors.el +++ b/admin/authors.el @@ -264,6 +264,7 @@ files.") ;; There are other Stefans. ;;; ("Stefan Monnier" "Stefan") (nil "ssnnoo") + ("Stephane Marks" "shipmints@gmail\\.com") ("Steven L. Baur" "SL Baur" "Steven L Baur") ("Stewart M. Clamen" "Stewart Clamen") (nil "StrawberryTea" "look@strawberrytea\\.xyz") @@ -278,7 +279,7 @@ files.") ("Thomas Dye" "Tom Dye") ("Thomas Horsley" "Tom Horsley") ; FIXME ? ("Thomas Wurgler" "Tom Wurgler") - (nil "thuna\\.cing@gmail\\.com") + ("Umut Thuna Akgul" "thuna\\.cing@gmail\\.com") ("Toby Cubitt" "Toby S\\. Cubitt") ("Tomohiko Morioka" "MORIOKA Tomohiko") ("Torbjörn Axelsson" "Torbjvrn Axelsson") From 36c91fdacc4995672e88e147c34b19d9244da033 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 8 Feb 2025 07:40:44 -0500 Subject: [PATCH 121/279] ; Update ldefs-boot.el --- lisp/ldefs-boot.el | 655 +++++++++++++++++++++++++++++---------------- 1 file changed, 418 insertions(+), 237 deletions(-) diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 648633004c9..c1deb84754d 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -417,7 +417,7 @@ indented." t) ;;; Generated autoloads from allout.el -(push (purecopy '(allout 2 3)) package--builtin-versions) +(push '(allout 2 3) package--builtin-versions) (autoload 'allout-auto-activation-helper "allout" "\ Institute `allout-auto-activation'. @@ -758,7 +758,7 @@ for details on preparing Emacs for automatic allout activation. ;;; Generated autoloads from allout-widgets.el -(push (purecopy '(allout-widgets 1 0)) package--builtin-versions) +(push '(allout-widgets 1 0) package--builtin-versions) (autoload 'allout-widgets-setup "allout-widgets" "\ Commission or decommission `allout-widgets-mode' along with `allout-mode'. @@ -874,7 +874,7 @@ the buffer *Birthday-Present-for-Name*. ;;; Generated autoloads from ansi-color.el -(push (purecopy '(ansi-color 3 4 2)) package--builtin-versions) +(push '(ansi-color 3 4 2) package--builtin-versions) (autoload 'ansi-color-for-comint-mode-on "ansi-color" "\ Set `ansi-color-for-comint-mode' to t." t) (autoload 'ansi-color-process-output "ansi-color" "\ @@ -909,7 +909,7 @@ and is meant to be used in `compilation-filter-hook'.") ;;; Generated autoloads from progmodes/antlr-mode.el -(push (purecopy '(antlr-mode 2 2 3)) package--builtin-versions) +(push '(antlr-mode 2 2 3) package--builtin-versions) (autoload 'antlr-show-makefile-rules "antlr-mode" "\ Show Makefile rules for all grammar files in the current directory. If the `major-mode' of the current buffer has the value `makefile-mode', @@ -1420,9 +1420,7 @@ Features a private abbrev table and the following bindings: The character used for making comments is set by the variable `asm-comment-char' (which defaults to `?\\;'). - -Alternatively, you may set this variable in `asm-mode-set-comment-hook', -which is called near the beginning of mode initialization. +Alternatively, you may set this variable in `asm-mode-hook'. Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization. @@ -1470,7 +1468,7 @@ by doing (clear-string STRING). ;;; Generated autoloads from auth-source-pass.el -(push (purecopy '(auth-source-pass 5 0 0)) package--builtin-versions) +(push '(auth-source-pass 5 0 0) package--builtin-versions) (autoload 'auth-source-pass-enable "auth-source-pass" "\ Enable auth-source-password-store.") (autoload 'auth-source-pass-get "auth-source-pass" "\ @@ -1684,6 +1682,11 @@ The mode's hook is called both when the mode is enabled and when it is disabled. (fn &optional ARG)" t) +(defvar inhibit-auto-revert-buffers nil "\ +A list of buffers with suppressed auto-revert.") +(defmacro inhibit-auto-revert (&rest body) "\ +Deactivate auto-reverting of current buffer temporarily. +Run BODY." (declare (indent 0) (debug (body))) (let ((buf (make-symbol "buf"))) `(progn (dolist (,buf inhibit-auto-revert-buffers) (unless (buffer-live-p ,buf) (setq inhibit-auto-revert-buffers (delq ,buf inhibit-auto-revert-buffers)))) (let ((,buf (and (not (memq (current-buffer) inhibit-auto-revert-buffers)) (current-buffer)))) (unwind-protect (progn (when ,buf (add-to-list 'inhibit-auto-revert-buffers ,buf)) ,@body) (when ,buf (setq inhibit-auto-revert-buffers (delq ,buf inhibit-auto-revert-buffers)))))))) (register-definition-prefixes "autorevert" '("auto-revert-" "global-auto-revert-")) @@ -1729,7 +1732,7 @@ definition of \"random distance\".) ;;; Generated autoloads from emacs-lisp/backtrace.el -(push (purecopy '(backtrace 1 0)) package--builtin-versions) +(push '(backtrace 1 0) package--builtin-versions) (autoload 'backtrace "backtrace" "\ Print a trace of Lisp function calls currently active. Output stream used is value of `standard-output'.") @@ -1958,7 +1961,7 @@ Major mode for editing BibTeX style files. ;;; Generated autoloads from bind-key.el -(push (purecopy '(bind-key 2 4 1)) package--builtin-versions) +(push '(bind-key 2 4 1) package--builtin-versions) (defvar personal-keybindings nil "\ List of bindings performed by `bind-key'. @@ -2384,7 +2387,7 @@ deletion, or > if it is flagged for displaying." t) (defalias 'edit-bookmarks 'bookmark-bmenu-list) (autoload 'bookmark-bmenu-search "bookmark" "\ Incremental search of bookmarks, hiding the non-matches as we go." '(bookmark-bmenu-mode)) -(defvar menu-bar-bookmark-map (let ((map (make-sparse-keymap "Bookmark functions"))) (bindings--define-key map [load] '(menu-item "Load a Bookmark File..." bookmark-load :help "Load bookmarks from a bookmark file)")) (bindings--define-key map [write] '(menu-item "Save Bookmarks As..." bookmark-write :help "Write bookmarks to a file (reading the file name with the minibuffer)")) (bindings--define-key map [save] '(menu-item "Save Bookmarks" bookmark-save :help "Save currently defined bookmarks")) (bindings--define-key map [edit] '(menu-item "Edit Bookmark List" bookmark-bmenu-list :help "Display a list of existing bookmarks")) (bindings--define-key map [delete] '(menu-item "Delete Bookmark..." bookmark-delete :help "Delete a bookmark from the bookmark list")) (bindings--define-key map [delete-all] '(menu-item "Delete all Bookmarks..." bookmark-delete-all :help "Delete all bookmarks from the bookmark list")) (bindings--define-key map [rename] '(menu-item "Rename Bookmark..." bookmark-rename :help "Change the name of a bookmark")) (bindings--define-key map [locate] '(menu-item "Insert Location..." bookmark-locate :help "Insert the name of the file associated with a bookmark")) (bindings--define-key map [insert] '(menu-item "Insert Contents..." bookmark-insert :help "Insert the text of the file pointed to by a bookmark")) (bindings--define-key map [set] '(menu-item "Set Bookmark..." bookmark-set :help "Set a bookmark named inside a file.")) (bindings--define-key map [jump] '(menu-item "Jump to Bookmark..." bookmark-jump :help "Jump to a bookmark (a point in some file)")) map)) +(defvar menu-bar-bookmark-map (let ((map (make-sparse-keymap "Bookmark functions"))) (define-key map [load] '(menu-item "Load a Bookmark File..." bookmark-load :help "Load bookmarks from a bookmark file)")) (define-key map [write] '(menu-item "Save Bookmarks As..." bookmark-write :help "Write bookmarks to a file (reading the file name with the minibuffer)")) (define-key map [save] '(menu-item "Save Bookmarks" bookmark-save :help "Save currently defined bookmarks")) (define-key map [edit] '(menu-item "Edit Bookmark List" bookmark-bmenu-list :help "Display a list of existing bookmarks")) (define-key map [delete] '(menu-item "Delete Bookmark..." bookmark-delete :help "Delete a bookmark from the bookmark list")) (define-key map [delete-all] '(menu-item "Delete all Bookmarks..." bookmark-delete-all :help "Delete all bookmarks from the bookmark list")) (define-key map [rename] '(menu-item "Rename Bookmark..." bookmark-rename :help "Change the name of a bookmark")) (define-key map [locate] '(menu-item "Insert Location..." bookmark-locate :help "Insert the name of the file associated with a bookmark")) (define-key map [insert] '(menu-item "Insert Contents..." bookmark-insert :help "Insert the text of the file pointed to by a bookmark")) (define-key map [set] '(menu-item "Set Bookmark..." bookmark-set :help "Set a bookmark named inside a file.")) (define-key map [jump] '(menu-item "Jump to Bookmark..." bookmark-jump :help "Jump to a bookmark (a point in some file)")) map)) (defalias 'menu-bar-bookmark-map menu-bar-bookmark-map) (register-definition-prefixes "bookmark" '("bookmark-" "with-buffer-modified-unmodified")) @@ -2487,7 +2490,13 @@ Optional prefix argument ARG non-nil inverts the value of the option (fn &optional ARG)" t) (autoload 'browse-url-with-browser-kind "browse-url" "\ Browse URL with a browser of the given browser KIND. -KIND is either `internal' or `external'. + +KIND is either `internal' or `external'. In order to find an +appropriate browser for the given KIND, first consult the `browse-url-handlers' +and `browse-url-default-handlers' lists. If no handler is found, try the +functions `browse-url-browser-function', +`browse-url-secondary-browser-function', `browse-url-default-browser' +and `eww', in that order. When called interactively, the default browser kind is the opposite of the browser kind of `browse-url-browser-function'. @@ -2568,6 +2577,12 @@ If `browse-url-android-share' is non-nil, try to share URL using an external program instead. Default to the URL around or before point. +(fn URL &optional NEW-WINDOW)" t) +(autoload 'browse-url-default-gtk-browser "browse-url" "\ +Browse URL with GTK's idea of the default browser. +If the selected frame isn't a GTK frame, fall back to +`browse-url-default-browser'. + (fn URL &optional NEW-WINDOW)" t) (autoload 'browse-url-emacs "browse-url" "\ Ask Emacs to load URL into a buffer and show it in another window. @@ -2575,41 +2590,6 @@ Optional argument SAME-WINDOW non-nil means show the URL in the currently selected window instead. (fn URL &optional SAME-WINDOW)" t) -(autoload 'browse-url-gnome-moz "browse-url" "\ -Ask Mozilla to load URL via the GNOME program `gnome-moz-remote'. -Default to the URL around or before point. The strings in variable -`browse-url-gnome-moz-arguments' are also passed. - -When called interactively, if variable `browse-url-new-window-flag' is -non-nil, load the document in a new browser window, otherwise use an -existing one. A non-nil interactive prefix argument reverses the -effect of `browse-url-new-window-flag'. - -When called non-interactively, optional second argument NEW-WINDOW is -used instead of `browse-url-new-window-flag'. - -(fn URL &optional NEW-WINDOW)" t) -(make-obsolete 'browse-url-gnome-moz 'nil "25.1") -(autoload 'browse-url-conkeror "browse-url" "\ -Ask the Conkeror WWW browser to load URL. -Default to the URL around or before point. Also pass the strings -in the variable `browse-url-conkeror-arguments' to Conkeror. - -When called interactively, if variable -`browse-url-new-window-flag' is non-nil, load the document in a -new Conkeror window, otherwise use a random existing one. A -non-nil interactive prefix argument reverses the effect of -`browse-url-new-window-flag'. - -If variable `browse-url-conkeror-new-window-is-buffer' is -non-nil, then whenever a document would otherwise be loaded in a -new window, load it in a new buffer in an existing window instead. - -When called non-interactively, use optional second argument -NEW-WINDOW instead of `browse-url-new-window-flag'. - -(fn URL &optional NEW-WINDOW)" t) -(make-obsolete 'browse-url-conkeror 'nil "28.1") (autoload 'browse-url-w3 "browse-url" "\ Ask the w3 WWW browser to load URL. Default to the URL around or before point. @@ -2623,13 +2603,6 @@ used instead of `browse-url-new-window-flag'. (fn URL &optional NEW-WINDOW)" t) (make-obsolete 'browse-url-w3 'nil "29.1") -(autoload 'browse-url-w3-gnudoit "browse-url" "\ -Ask another Emacs running emacsclient to load the URL using the W3 browser. -The `browse-url-gnudoit-program' program is used with options given by -`browse-url-gnudoit-args'. Default to the URL around or before point. - -(fn URL &optional NEW-WINDOW)" t) -(make-obsolete 'browse-url-w3-gnudoit 'nil "25.1") (autoload 'browse-url-text-xterm "browse-url" "\ Ask a text browser to load URL. URL defaults to the URL around or before point. @@ -3595,7 +3568,7 @@ the absolute file name of the file if STYLE-NAME is nil. ;;; Generated autoloads from progmodes/cc-mode.el -(push (purecopy '(cc-mode 5 33 1)) package--builtin-versions) +(push '(cc-mode 5 33 1) package--builtin-versions) (autoload 'c-initialize-cc-mode "cc-mode" "\ Initialize CC Mode for use in the current buffer. If the optional NEW-STYLE-INIT is nil or left out then all necessary @@ -4116,7 +4089,7 @@ See the documentation of `define-ccl-program' for the detail of CCL program. ;;; Generated autoloads from cedet/cedet.el -(push (purecopy '(cedet 2 0)) package--builtin-versions) +(push '(cedet 2 0) package--builtin-versions) (register-definition-prefixes "cedet" '("cedet-")) @@ -4142,7 +4115,7 @@ See the documentation of `define-ccl-program' for the detail of CCL program. ;;; Generated autoloads from progmodes/cfengine.el -(push (purecopy '(cfengine 1 4)) package--builtin-versions) +(push '(cfengine 1 4) package--builtin-versions) (autoload 'cfengine3-mode "cfengine" "\ Major mode for editing CFEngine3 input. There are no special keybindings by default. @@ -4508,7 +4481,7 @@ disabled. ;;; Generated autoloads from emacs-lisp/cl-generic.el -(push (purecopy '(cl-generic 1 0)) package--builtin-versions) +(push '(cl-generic 1 0) package--builtin-versions) ;;; Generated autoloads from emacs-lisp/cl-indent.el @@ -4595,7 +4568,7 @@ instead. ;;; Generated autoloads from emacs-lisp/cl-lib.el -(push (purecopy '(cl-lib 1 0)) package--builtin-versions) +(push '(cl-lib 1 0) package--builtin-versions) (defvar cl-custom-print-functions nil "\ This is a list of functions that format user objects for printing. Each function is called in turn with three arguments: the object, the @@ -4654,7 +4627,7 @@ disabled. ;;; Generated autoloads from emacs-lisp/cl-print.el -(push (purecopy '(cl-print 1 0)) package--builtin-versions) +(push '(cl-print 1 0) package--builtin-versions) (autoload 'cl-print-object "cl-print" "\ Dispatcher to print OBJECT on STREAM according to its type. You can add methods to it to customize the output. @@ -4849,7 +4822,7 @@ See `make-comint' and `comint-exec'. (fn PROGRAM &optional SWITCHES)" t) (function-put 'comint-run 'interactive-only 'make-comint) -(defvar comint-file-name-prefix (purecopy "") "\ +(defvar comint-file-name-prefix "" "\ Prefix prepended to absolute file names taken from process input. This is used by Comint's and shell's completion functions, and by shell's directory tracking functions.") @@ -4945,6 +4918,8 @@ Force the produced .eln to be outputted in the eln system directory (the last entry in `native-comp-eln-load-path') unless `native-compile-target-directory' is non-nil. If the environment variable \"NATIVE_DISABLED\" is set, only byte compile.") +(autoload 'native-compile-prune-cache "comp" "\ +Remove .eln files that aren't applicable to the current Emacs invocation." t) (register-definition-prefixes "comp" '("comp-" "native-comp" "no-native-compile")) @@ -5120,7 +5095,7 @@ List of directories to search for source files named in error messages. Elements should be directory names, not file names of directories. The value nil as an element means to try the default directory.") (custom-autoload 'compilation-search-path "compile" t) -(defvar compile-command (purecopy "make -k ") "\ +(defvar compile-command "make -k " "\ Last shell command used to do a compilation; default for next compilation. Sometimes it is useful for files to supply local values for this variable. @@ -5417,7 +5392,43 @@ list.") ;;; Generated autoloads from emacs-lisp/cond-star.el -(register-definition-prefixes "cond-star" '("cond*" "match*")) +(autoload 'cond* "cond-star" "\ +Extended form of traditional Lisp `cond' construct. +A `cond*' construct is a series of clauses, and a clause +normally has the form (CONDITION BODY...). + +CONDITION can be a Lisp expression, as in `cond'. +Or it can be one of `(pcase* PATTERN DATUM)', +`(bind* BINDINGS...)', or `(match* PATTERN DATUM)', + +`(pcase* PATTERN DATUM)' means to match DATUM against the +pattern PATTERN, using the same pattern syntax as `pcase'. +The condition counts as true if PATTERN matches DATUM. + +`(bind* BINDINGS...)' means to bind BINDINGS (as if they were in `let*') +for the body of the clause. As a condition, it counts as true +if the first binding's value is non-nil. All the bindings are made +unconditionally for whatever scope they cover. + +`(match* PATTERN DATUM)' is an alternative to `pcase*' that uses another +syntax for its patterns, see `match*'. + +When a clause's condition is true, and it exits the `cond*' +or is the last clause, the value of the last expression +in its body becomes the return value of the `cond*' construct. + +Non-exit clause: + +If a clause has only one element, or if its first element is +a `bind*' clause, this clause never exits the `cond*' construct. +Instead, control always falls through to the next clause (if any). +All bindings made in CONDITION for the BODY of the non-exit clause +are passed along to the rest of the clauses in this `cond*' construct. + +\\[match*\\] for documentation of the patterns for use in `match*'. + +(fn &rest CLAUSES)" nil t) +(register-definition-prefixes "cond-star" '("cond*-" "match*")) ;;; Generated autoloads from textmodes/conf-mode.el @@ -7545,7 +7556,7 @@ the word at mouse click. ;;; Generated autoloads from vc/diff.el -(defvar diff-switches (purecopy "-u") "\ +(defvar diff-switches "-u" "\ A string or list of strings specifying switches to be passed to diff. This variable is also used in the `vc-diff' command (and related @@ -7553,7 +7564,7 @@ commands) if the backend-specific diff switch variable isn't set (`vc-git-diff-switches' for git, for instance), and `vc-diff-switches' isn't set.") (custom-autoload 'diff-switches "diff" t) -(defvar diff-command (purecopy "diff") "\ +(defvar diff-command "diff" "\ The command to use to run diff.") (custom-autoload 'diff-command "diff" t) (autoload 'diff "diff" "\ @@ -7680,7 +7691,7 @@ If given a \\[universal-argument] \\[universal-argument] prefix, also prompt for ;;; Generated autoloads from dired.el -(defvar dired-listing-switches (purecopy "-al") "\ +(defvar dired-listing-switches "-al" "\ Switches passed to `ls' for Dired. MUST contain the `l' option. May contain all other options that don't contradict `-l'; may contain even `F', `b', `i' and `s'. See also the variable @@ -7893,16 +7904,24 @@ redefine OBJECT if it is a symbol. Return a new, empty display table.") (autoload 'display-table-slot "disp-table" "\ Return the value of the extra slot in DISPLAY-TABLE named SLOT. -SLOT may be a number from 0 to 5 inclusive, or a slot name (symbol). +SLOT may be a number from 0 to 17 inclusive, or a slot name (symbol). Valid symbols are `truncation', `wrap', `escape', `control', -`selective-display', and `vertical-border'. +`selective-display', `vertical-border', `box-vertical', +`box-horizontal', `box-down-right', `box-down-left', `box-up-right', +`box-up-left',`box-double-vertical', `box-double-horizontal', +`box-double-down-right', `box-double-down-left', +`box-double-up-right', `box-double-up-left', (fn DISPLAY-TABLE SLOT)") (autoload 'set-display-table-slot "disp-table" "\ Set the value of the extra slot in DISPLAY-TABLE named SLOT to VALUE. -SLOT may be a number from 0 to 5 inclusive, or a name (symbol). +SLOT may be a number from 0 to 17 inclusive, or a name (symbol). Valid symbols are `truncation', `wrap', `escape', `control', -`selective-display', and `vertical-border'. +`selective-display', `vertical-border', `box-vertical', +`box-horizontal', `box-down-right', `box-down-left', `box-up-right', +`box-up-left',`box-double-vertical', `box-double-horizontal', +`box-double-down-right', `box-double-down-left', +`box-double-up-right', `box-double-up-left', (fn DISPLAY-TABLE SLOT VALUE)") (autoload 'describe-display-table "disp-table" "\ @@ -7911,6 +7930,13 @@ Describe the display table DT in a help buffer. (fn DT)") (autoload 'describe-current-display-table "disp-table" "\ Describe the display table in use in the selected window and buffer." t) +(autoload 'standard-display-unicode-special-glyphs "disp-table" "\ +Display some glyps using Unicode characters. +The glyphs being changed by this function are `vertical-border', +`box-vertical',`box-horizontal', `box-down-right', `box-down-left', +`box-up-right', `box-up-left',`box-double-vertical', +`box-double-horizontal', `box-double-down-right', +`box-double-down-left', `box-double-up-right', `box-double-up-left'," t) (autoload 'standard-display-8bit "disp-table" "\ Display characters representing raw bytes in the range L to H literally. @@ -8227,7 +8253,7 @@ Default is 2. ;;; Generated autoloads from dnd.el -(defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) (,(purecopy "^file://[^/]") . dnd-open-file) (,(purecopy "^file:/[^/]") . dnd-open-local-file) (,(purecopy "^file:[^/]") . dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|nfs\\)://") . dnd-open-file)) "\ +(defvar dnd-protocol-alist '(("^file:///" . dnd-open-local-file) ("^file://[^/]" . dnd-open-file) ("^file:/[^/]" . dnd-open-local-file) ("^file:[^/]" . dnd-open-local-file) ("^\\(https?\\|ftp\\|nfs\\)://" . dnd-open-file)) "\ The functions to call for different protocols when a drop is made. This variable is used by `dnd-handle-multiple-urls'. The list contains of (REGEXP . FUNCTION) pairs. @@ -8981,7 +9007,7 @@ Read the .ecompleterc file.") ;;; Generated autoloads from cedet/ede.el -(push (purecopy '(ede 2 0)) package--builtin-versions) +(push '(ede 2 0) package--builtin-versions) (defvar global-ede-mode nil "\ Non-nil if Global Ede mode is enabled. See the `global-ede-mode' command @@ -9073,7 +9099,7 @@ Toggle edebugging of all forms." t) ;;; Generated autoloads from vc/ediff.el -(push (purecopy '(ediff 2 81 6)) package--builtin-versions) +(push '(ediff 2 81 6) package--builtin-versions) (autoload 'ediff-files "ediff" "\ Run Ediff on a pair of files, FILE-A and FILE-B. STARTUP-HOOKS is a list of functions that Emacs calls without @@ -9409,7 +9435,7 @@ To change the default, set the variable `ediff-use-toolbar-p', which see." t) ;;; Generated autoloads from editorconfig.el -(push (purecopy '(editorconfig 0 11 0)) package--builtin-versions) +(push '(editorconfig 0 11 0) package--builtin-versions) (defvar editorconfig-mode nil "\ Non-nil if Editorconfig mode is enabled. See the `editorconfig-mode' command @@ -9559,7 +9585,7 @@ Turn on EDT Emulation." t) ;;; Generated autoloads from progmodes/eglot.el -(push (purecopy '(eglot 1 17)) package--builtin-versions) +(push '(eglot 1 18) package--builtin-versions) (define-obsolete-function-alias 'eglot-update #'eglot-upgrade-eglot "29.1") (autoload 'eglot "eglot" "\ Start LSP server for PROJECT's buffers under MANAGED-MAJOR-MODES. @@ -9661,7 +9687,7 @@ BUFFER is put back into its original major mode. ;;; Generated autoloads from emacs-lisp/eieio.el -(push (purecopy '(eieio 1 4)) package--builtin-versions) +(push '(eieio 1 4) package--builtin-versions) (autoload 'make-instance "eieio" "\ Make a new instance of CLASS based on INITARGS. For example: @@ -9684,7 +9710,7 @@ for each slot. For example: ;;; Generated autoloads from emacs-lisp/eieio-core.el -(push (purecopy '(eieio-core 1 4)) package--builtin-versions) +(push '(eieio-core 1 4) package--builtin-versions) (autoload 'eieio-defclass-autoload "eieio-core" "\ Create autoload symbols for the EIEIO class CNAME. SUPERCLASSES are the superclasses that CNAME inherits from. @@ -9746,7 +9772,7 @@ Describe CTR if it is a class constructor. ;;; Generated autoloads from emacs-lisp/eldoc.el -(push (purecopy '(eldoc 1 15 0)) package--builtin-versions) +(push '(eldoc 1 15 0) package--builtin-versions) ;;; Generated autoloads from elec-pair.el @@ -10462,7 +10488,9 @@ The buffer is expected to contain a mail message." t) (function-put 'epa-mail-decrypt 'interactive-only 't) (autoload 'epa-mail-verify "epa-mail" "\ Verify OpenPGP cleartext signed messages in the current buffer. -The buffer is expected to contain a mail message." t) +The buffer is expected to contain a mail message. + +If the verification fails, signal an error." t) (function-put 'epa-mail-verify 'interactive-only 't) (autoload 'epa-mail-sign "epa-mail" "\ Sign the current buffer. @@ -10522,7 +10550,7 @@ disabled. ;;; Generated autoloads from epg.el -(push (purecopy '(epg 1 0 0)) package--builtin-versions) +(push '(epg 1 0 0) package--builtin-versions) (autoload 'epg-make-context "epg" "\ Return a context object. @@ -10565,7 +10593,7 @@ Look at CONFIG and try to expand GROUP. ;;; Generated autoloads from erc/erc.el -(push (purecopy '(erc 5 6 1 -4)) package--builtin-versions) +(push '(erc 5 6 1 -4) package--builtin-versions) (dolist (symbol '( erc-sasl erc-spelling ; 29 erc-imenu erc-nicks)) ; 30 (custom-add-load symbol symbol)) @@ -11025,7 +11053,7 @@ Default bookmark handler for Eshell buffers. ;;; Generated autoloads from eshell/eshell.el -(push (purecopy '(eshell 2 4 2)) package--builtin-versions) +(push '(eshell 2 4 2) package--builtin-versions) (autoload 'eshell "eshell" "\ Create an interactive Eshell buffer. Start a new Eshell session, or switch to an already active @@ -11081,7 +11109,7 @@ To switch to a new tags table, do not set this variable; instead, invoke `visit-tags-table', which is the only reliable way of setting the value of this variable, whether buffer-local or global. Use the `etags' program to make a tags table file.") - (put 'tags-file-name 'variable-interactive (purecopy "fVisit tags table: ")) + (put 'tags-file-name 'variable-interactive "fVisit tags table: ") (put 'tags-file-name 'safe-local-variable 'stringp) (defvar tags-case-fold-search 'default "\ Whether tags operations should be case-sensitive. @@ -11096,7 +11124,7 @@ To switch to a new list of tags tables, setting this variable is sufficient. If you set this variable, do not also set `tags-file-name'. Use the `etags' program to make a tags table file.") (custom-autoload 'tags-table-list "etags" t) -(defvar tags-compression-info-list (purecopy '("" ".Z" ".bz2" ".gz" ".xz" ".tgz")) "\ +(defvar tags-compression-info-list '("" ".Z" ".bz2" ".gz" ".xz" ".tgz") "\ List of extensions tried by etags when `auto-compression-mode' is on. An empty string means search the non-compressed file.") (custom-autoload 'tags-compression-info-list "etags" t) @@ -11627,7 +11655,7 @@ queries the server for the existing fields and displays a corresponding form. (autoload 'eudc-load-eudc "eudc" "\ Load the Emacs Unified Directory Client. This does nothing except loading eudc by autoload side-effect." t) -(defvar eudc-tools-menu (let ((map (make-sparse-keymap "Directory Servers"))) (define-key map [phone] `(menu-item ,(purecopy "Get Phone") eudc-get-phone :help ,(purecopy "Get the phone field of name from the directory server"))) (define-key map [email] `(menu-item ,(purecopy "Get Email") eudc-get-email :help ,(purecopy "Get the email field of NAME from the directory server"))) (define-key map [separator-eudc-email] menu-bar-separator) (define-key map [expand-inline] `(menu-item ,(purecopy "Expand Inline Query") eudc-expand-inline :help ,(purecopy "Query the directory server, and expand the query string before point"))) (define-key map [query] `(menu-item ,(purecopy "Query with Form") eudc-query-form :help ,(purecopy "Display a form to query the directory server"))) (define-key map [separator-eudc-query] menu-bar-separator) (define-key map [new] `(menu-item ,(purecopy "New Server") eudc-set-server :help ,(purecopy "Set the directory server to SERVER using PROTOCOL"))) (define-key map [load] `(menu-item ,(purecopy "Load Hotlist of Servers") eudc-load-eudc :help ,(purecopy "Load the Emacs Unified Directory Client"))) map)) +(defvar eudc-tools-menu (let ((map (make-sparse-keymap "Directory Servers"))) (define-key map [phone] '(menu-item "Get Phone" eudc-get-phone :help "Get the phone field of name from the directory server")) (define-key map [email] '(menu-item "Get Email" eudc-get-email :help "Get the email field of NAME from the directory server")) (define-key map [separator-eudc-email] menu-bar-separator) (define-key map [expand-inline] '(menu-item "Expand Inline Query" eudc-expand-inline :help "Query the directory server, and expand the query string before point")) (define-key map [query] '(menu-item "Query with Form" eudc-query-form :help "Display a form to query the directory server")) (define-key map [separator-eudc-query] menu-bar-separator) (define-key map [new] '(menu-item "New Server" eudc-set-server :help "Set the directory server to SERVER using PROTOCOL")) (define-key map [load] '(menu-item "Load Hotlist of Servers" eudc-load-eudc :help "Load the Emacs Unified Directory Client")) map)) (fset 'eudc-tools-menu (symbol-value 'eudc-tools-menu)) (register-definition-prefixes "eudc" '("eudc-")) @@ -11837,8 +11865,9 @@ new buffer instead of reusing the default EWW buffer. (fn FILE &optional NEW-BUFFER)" t) (autoload 'eww-search-words "eww" "\ Search the web for the text in the region. -If region is active (and not whitespace), search the web for -the text between region beginning and end. Else, prompt the +If region is active (and not whitespace), search the web for the +text between region beginning and end, subject to user's confirmation +controlled by `eww-search-confirm-send-region'. Else, prompt the user for a search string. See the variable `eww-search-prefix' for the search engine used." t) (autoload 'eww-mode "eww" "\ @@ -11952,7 +11981,7 @@ This is used only in conjunction with `expand-add-abbrevs'." t) ;;; Generated autoloads from external-completion.el -(push (purecopy '(external-completion 0 1)) package--builtin-versions) +(push '(external-completion 0 1) package--builtin-versions) (register-definition-prefixes "external-completion" '("external-completion-")) @@ -12270,7 +12299,7 @@ color. The function should accept a single argument, the color name. ;;; Generated autoloads from emacs-lisp/faceup.el -(push (purecopy '(faceup 0 0 6)) package--builtin-versions) +(push '(faceup 0 0 6) package--builtin-versions) (autoload 'faceup-view-buffer "faceup" "\ Display the faceup representation of the current buffer." t) (autoload 'faceup-write-file "faceup" "\ @@ -12307,7 +12336,7 @@ FUNCTION must return an explanation when the test fails and ;;; Generated autoloads from mail/feedmail.el -(push (purecopy '(feedmail 11)) package--builtin-versions) +(push '(feedmail 11) package--builtin-versions) (autoload 'feedmail-send-it "feedmail" "\ Send the current mail buffer using the Feedmail package. This is a suitable value for `send-mail-function'. It can be used @@ -12737,7 +12766,7 @@ Set up hooks, load the cache file -- if existing -- and build the menu.") ;;; Generated autoloads from find-cmd.el -(push (purecopy '(find-cmd 0 6)) package--builtin-versions) +(push '(find-cmd 0 6) package--builtin-versions) (autoload 'find-cmd "find-cmd" "\ Initiate the building of a find command. For example: @@ -12819,7 +12848,7 @@ specifies what to use in place of \"-ls\" as the final argument. ;;; Generated autoloads from find-file.el -(defvar ff-special-constructs `((,(purecopy "^#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]") \, (lambda nil (match-string 2)))) "\ +(defvar ff-special-constructs `(("^#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]" \, (lambda nil (match-string 2)))) "\ List of special constructs recognized by `ff-treat-as-special'. Each element, tried in order, has the form (REGEXP . EXTRACT). If REGEXP matches the current line (from the beginning of the line), @@ -12939,12 +12968,21 @@ Search for SYMBOL's definition of type TYPE in LIBRARY. Visit the library in a buffer, and return a cons cell (BUFFER . POSITION), or just (BUFFER . nil) if the definition can't be found in the file. -If TYPE is nil, look for a function definition. -Otherwise, TYPE specifies the kind of definition, -and it is interpreted via `find-function-regexp-alist'. +If TYPE is nil, look for a function definition, +otherwise, TYPE specifies the kind of definition. +TYPE is looked up in SYMBOL's property `find-function-type-alist' +(which can be maintained with `find-function-update-type-alist') +or the variable `find-function-regexp-alist'. + The search is done in the source for library LIBRARY. (fn SYMBOL TYPE LIBRARY)") +(autoload 'find-function-update-type-alist "find-func" "\ +Update SYMBOL property `find-function-type-alist' with (TYPE . VARIABLE). +Property `find-function-type-alist' is a symbol-specific version +of variable `find-function-regexp-alist' and has the same format. + +(fn SYMBOL TYPE VARIABLE)") (autoload 'find-function-noselect "find-func" "\ Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. @@ -13157,7 +13195,7 @@ lines. ;;; Generated autoloads from progmodes/flymake.el -(push (purecopy '(flymake 1 3 7)) package--builtin-versions) +(push '(flymake 1 3 7) package--builtin-versions) (autoload 'flymake-log "flymake" "\ Log, at level LEVEL, the message MSG formatted with ARGS. LEVEL is passed to `display-warning', which is used to display @@ -13278,7 +13316,7 @@ REPORT-FN is Flymake's callback. ;;; Generated autoloads from progmodes/flymake-proc.el -(push (purecopy '(flymake-proc 1 0)) package--builtin-versions) +(push '(flymake-proc 1 0) package--builtin-versions) (register-definition-prefixes "flymake-proc" '("flymake-proc-")) @@ -13354,7 +13392,7 @@ Flyspell whole buffer." t) ;;; Generated autoloads from foldout.el -(push (purecopy '(foldout 1 10)) package--builtin-versions) +(push '(foldout 1 10) package--builtin-versions) (register-definition-prefixes "foldout" '("foldout-")) @@ -14235,7 +14273,7 @@ DEFAULT-MAP specifies the default key map for ICON-LIST. ;;; Generated autoloads from gnus/gnus.el -(push (purecopy '(gnus 5 13)) package--builtin-versions) +(push '(gnus 5 13) package--builtin-versions) (custom-autoload 'gnus-select-method "gnus") (autoload 'gnus-child-no-server "gnus" "\ Read network news as a child, without connecting to the local server. @@ -15221,14 +15259,14 @@ Face name to use for grep matches.") (defconst grep-regexp-alist `((,(concat "^\\(?:" "\\(?1:[^\0\n]+\\)\\(?3:\0\\)\\(?2:[0-9]+\\):" "\\|" "\\(?1:" "\\(?:[a-zA-Z]:\\)?" "[^\n:]+?[^\n/:]\\):[\11 ]*\\(?2:[1-9][0-9]*\\)[\11 ]*:" "\\)") 1 2 (,(lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face))) (when mbeg (- mbeg beg))))) \, (lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face)) (mend (and mbeg (next-single-property-change mbeg 'font-lock-face nil end)))) (when mend (- mend beg 1)))))) nil nil (3 '(face nil display ":"))) ("^Binary file \\(.+\\) matches" 1 nil nil 0 1)) "\ Regexp used to match grep hits. See `compilation-error-regexp-alist' for format details.") -(defvar grep-program (purecopy "grep") "\ +(defvar grep-program "grep" "\ The default grep program for `grep-command' and `grep-find-command'. This variable's value takes effect when `grep-compute-defaults' is called.") -(defvar find-program (purecopy "find") "\ +(defvar find-program "find" "\ The default find program. This is used by commands like `grep-find-command', `find-dired' and others.") -(defvar xargs-program (purecopy "xargs") "\ +(defvar xargs-program "xargs" "\ The default xargs program for `grep-find-command'. See `grep-find-use-xargs'. This variable's value takes effect when `grep-compute-defaults' is called.") @@ -15707,20 +15745,20 @@ If the `kbd-help' text or overlay property at point produces a string, return it. Otherwise, use the `help-echo' property. If this produces no string either, return nil.") (autoload 'display-local-help "help-at-pt" "\ -Display local help in the echo area. -This command, by default, displays a short help message, namely -the string produced by the `kbd-help' property at point. If -`kbd-help' does not produce a string, but the `help-echo' -property does, then that string is printed instead. +Display in the echo area `kbd-help' or `help-echo' text at point. +This command displays the help message which is the string produced +by the `kbd-help' property at point. If `kbd-help' at point does not +produce a string, but the `help-echo' property does, then that string +is displayed instead. The string is passed through `substitute-command-keys' before it is displayed. -If INHIBIT-WARNING is non-nil, this prevents display of a message -in case there is no help. +If INHIBIT-WARNING is non-nil, do not display a warning message when +there is no help property at point. If DESCRIBE-BUTTON in non-nil (interactively, the prefix arg), and -there's a button/widget at point, pop a buffer describing that +there's a button/widget at point, pop up a buffer describing that button/widget instead. (fn &optional INHIBIT-WARNING DESCRIBE-BUTTON)" t) @@ -16461,7 +16499,7 @@ disabled. ;;; Generated autoloads from progmodes/hideshow.el -(defvar hs-special-modes-alist (mapcar #'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c-ts-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (c++-ts-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (java-ts-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (js-ts-mode "{" "}" "/[*/]" nil) (lua-ts-mode "{\\|\\[\\[" "}\\|\\]\\]" "--" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|]*[^/]>" " func.method is one node. + ;; .method({ + ;; return 1; ({ return 1; }) is another node + ;; }) + ;; + ;; So when we go up the parse tree, we go through the block + ;; ({...}), then the next parent is already the whole call + ;; expression, and we never stops at the beginning of "method". + ;; Therefore we need this heuristic. + (and (progn (back-to-indentation) + (eq (char-after) ?.)) + (point)))) + (defun c-ts-common--standalone-parent (parent) "Find the first parent that starts on a new line. Start searching from PARENT, so if PARENT satisfies the condition, it'll @@ -574,12 +600,11 @@ for determining standlone line." (catch 'term (while parent (goto-char (treesit-node-start parent)) - (when (if treesit-simple-indent-standalone-predicate - (setq anchor + (when (setq anchor + (if treesit-simple-indent-standalone-predicate (funcall treesit-simple-indent-standalone-predicate - parent)) - (looking-back (rx bol (* whitespace) (? ".")) - (line-beginning-position))) + parent) + (c-ts-common--standalone-predicate parent))) (throw 'term (if (numberp anchor) anchor (point)))) (setq parent (treesit-node-parent parent))))))) @@ -602,13 +627,12 @@ for determining standlone line." (let (anchor) (while (and node (goto-char (treesit-node-start node)) - (not (if treesit-simple-indent-standalone-predicate - (setq anchor + (not (setq anchor + (if treesit-simple-indent-standalone-predicate (funcall treesit-simple-indent-standalone-predicate - node)) - (looking-back (rx bol (* whitespace) (? ".")) - (pos-bol))))) + parent) + (c-ts-common--standalone-predicate parent))))) (setq node (treesit-node-prev-sibling node 'named)))) (if (numberp anchor) anchor (treesit-node-start node)))) From 4d6f40dfc9075d64275da97dc35a2becc9eca4a2 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 14 Feb 2025 17:56:22 +0800 Subject: [PATCH 251/279] * lisp/x-dnd.el (x-dnd-do-direct-save): Remove redundant stmts. --- lisp/x-dnd.el | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 760dd0a42bf..13fe3842f18 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -1544,41 +1544,39 @@ was taken, or the direct save failed." (x-dnd-use-offix-drop nil) (x-dnd-use-unsupported-drop nil) (prop-deleted nil) - (action nil) encoded-name) (unwind-protect - (setq action - (progn - (when (file-remote-p file) - (setq file-name (file-local-copy file)) - (setq dnd-last-dragged-remote-file file-name) - (add-hook 'kill-emacs-hook - #'dnd-remove-last-dragged-remote-file)) - (setq encoded-name - (encode-coding-string name - (or file-name-coding-system - default-file-name-coding-system))) - (setq x-dnd-xds-current-file file-name) - (x-change-window-property "XdndDirectSave0" encoded-name - frame "text/plain" 8 nil) - (gui-set-selection 'XdndSelection (concat "file://" file-name)) - ;; FIXME: this does not work with GTK file managers, - ;; since they always reach for `text/uri-list' first, - ;; contrary to the spec. - (let ((action (x-begin-drag '("XdndDirectSave0" "text/uri-list" - "application/octet-stream") - 'XdndActionDirectSave - frame nil allow-same-frame))) - (if (not x-dnd-xds-performed) - action - (let ((property (x-window-property "XdndDirectSave0" frame - "AnyPropertyType" nil t))) - (setq prop-deleted t) - ;; "System-G" deletes the property upon success. - (and (or (null property) - (and (stringp property) - (not (equal property "")))) - action)))))) + (progn + (when (file-remote-p file) + (setq file-name (file-local-copy file)) + (setq dnd-last-dragged-remote-file file-name) + (add-hook 'kill-emacs-hook + #'dnd-remove-last-dragged-remote-file)) + (setq encoded-name + (encode-coding-string name + (or file-name-coding-system + default-file-name-coding-system))) + (setq x-dnd-xds-current-file file-name) + (x-change-window-property "XdndDirectSave0" encoded-name + frame "text/plain" 8 nil) + (gui-set-selection 'XdndSelection (concat "file://" file-name)) + ;; FIXME: this does not work with GTK file managers, + ;; since they always reach for `text/uri-list' first, + ;; contrary to the spec. + (let ((action (x-begin-drag '("XdndDirectSave0" "text/uri-list" + "application/octet-stream") + 'XdndActionDirectSave + frame nil allow-same-frame))) + (if (not x-dnd-xds-performed) + action + (let ((property (x-window-property "XdndDirectSave0" frame + "AnyPropertyType" nil t))) + (setq prop-deleted t) + ;; "System-G" deletes the property upon success. + (and (or (null property) + (and (stringp property) + (not (equal property "")))) + action))))) (unless prop-deleted (x-delete-window-property "XdndDirectSave0" frame)) ;; Delete any remote copy that was made. From 608113628c2750b09b925b17c96a29b2dc9abc37 Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Fri, 14 Feb 2025 13:49:49 +0000 Subject: [PATCH 252/279] Avoid crashes in lread.c when invalid characters are read * src/lread.c (readchar): Don't crash for non-fixnum return values. (read_filtered_event): Don't crash for invalid symbol properties. (Fread_char): (Fread_char_exclusive): (character_name_to_code): Check 'FIXNUMP' before using 'XFIXNUM'. (read_char_escape): Crash on invalid Lisp-supplied data when ENABLE_CHECKING; otherwise, signal an error. --- src/lread.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lread.c b/src/lread.c index 6af95873bb8..46c705e5c76 100644 --- a/src/lread.c +++ b/src/lread.c @@ -398,7 +398,7 @@ readchar (Lisp_Object readcharfun, bool *multibyte) tem = call0 (readcharfun); - if (NILP (tem)) + if (!FIXNUMP (tem)) return -1; return XFIXNUM (tem); @@ -816,7 +816,7 @@ read_filtered_event (bool no_switch_frame, bool ascii_required, tem1 = Fget (Fcar (tem), Qascii_character); /* Merge this symbol's modifier bits with the ASCII equivalent of its basic code. */ - if (!NILP (tem1)) + if (FIXNUMP (tem1) && FIXNUMP (Fcar (Fcdr (tem)))) XSETFASTINT (val, XFIXNUM (tem1) | XFIXNUM (Fcar (Fcdr (tem)))); } } @@ -898,7 +898,7 @@ If `inhibit-interaction' is non-nil, this function will signal an } val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds); - return (NILP (val) ? Qnil + return (!FIXNUMP (val) ? Qnil : make_fixnum (char_resolve_modifier_mask (XFIXNUM (val)))); } @@ -976,7 +976,7 @@ If `inhibit-interaction' is non-nil, this function will signal an val = read_filtered_event (1, 1, 0, ! NILP (inherit_input_method), seconds); - return (NILP (val) ? Qnil + return (!FIXNUMP (val) ? Qnil : make_fixnum (char_resolve_modifier_mask (XFIXNUM (val)))); } @@ -2820,7 +2820,7 @@ character_name_to_code (char const *name, ptrdiff_t name_len, invalid_syntax_lisp (CALLN (Fformat, format, namestr), readcharfun); } - return XFIXNUM (code); + return FIXNUMP (code) ? XFIXNUM (code) : -1; } /* Bound on the length of a Unicode character name. As of @@ -3059,6 +3059,8 @@ read_char_escape (Lisp_Object readcharfun, int next_char) break; } eassert (chr >= 0 && chr < (1 << CHARACTERBITS)); + if (chr < 0 || chr >= (1 << CHARACTERBITS)) + invalid_syntax ("Invalid character", readcharfun); /* Apply Control modifiers, using the rules: \C-X = ascii_ctrl(nomod(X)) | mods(X) if nomod(X) is one of: From 9ded6fd73e929977a38d4c644aa4e9fe66e76e90 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Fri, 14 Feb 2025 15:21:30 +0100 Subject: [PATCH 253/279] Adapt PuTTY integration into Tramp * doc/misc/tramp.texi (Inline methods, External methods): PuTTY must be at least version 0.82. * lisp/net/tramp-cache.el (with-tramp-saved-connection-property) (with-tramp-saved-connection-properties): Add traces. * lisp/net/tramp-sh.el (tramp-methods) : Adapt `tramp-login-args' and `tramp-copy-args' arguments. (Bug#75746) --- doc/misc/tramp.texi | 10 ++++++---- lisp/net/tramp-cache.el | 4 ++++ lisp/net/tramp-sh.el | 12 ++++++++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 86ffba29744..ac0bb63335c 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -955,9 +955,10 @@ This is another method from the Kerberos suite. It behaves like @cindex @option{plink} method @item @option{plink} -@option{plink} method is for MS Windows users with the PuTTY -implementation of SSH@. It uses @samp{plink -ssh} to log in to the -remote host. It supports changing the remote login shell @command{/bin/sh}. +@option{plink} method is for MS Windows users with the +PuTTY@footnote{It requires at least PuTTY 0.82.} implementation of +SSH@. It uses @samp{plink -ssh} to log in to the remote host. It +supports changing the remote login shell @command{/bin/sh}. Check the @samp{Share SSH connections if possible} control for that session. @@ -1190,7 +1191,8 @@ This method supports the @samp{-p} argument. These methods are similar to @option{scp} or @option{sftp}, but they use the @command{plink} command to connect to the remote host, and they use @command{pscp} or @command{psftp} for transferring the files. -These programs are part of PuTTY, an SSH implementation for MS Windows. +These programs are part of PuTTY@footnote{It requires at least PuTTY +0.82.}, an SSH implementation for MS Windows. They support changing the remote login shell @command{/bin/sh}. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index a5245deaf2b..e7ad565dc30 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -482,8 +482,10 @@ used to cache connection properties of the local machine." (hash (tramp-get-hash-table key)) (cached (and (hash-table-p hash) (gethash ,property hash tramp-cache-undefined)))) + (tramp-message key 7 "Saved %s %s" property cached) (unwind-protect (progn ,@body) ;; Reset PROPERTY. Recompute hash, it could have been flushed. + (tramp-message key 7 "Restored %s %s" property cached) (setq hash (tramp-get-hash-table key)) (if (not (eq cached tramp-cache-undefined)) (puthash ,property cached hash) @@ -501,8 +503,10 @@ PROPERTIES is a list of file properties (strings)." (lambda (property) (cons property (gethash property hash tramp-cache-undefined))) ,properties))) + (tramp-message key 7 "Saved %s" values) (unwind-protect (progn ,@body) ;; Reset PROPERTIES. Recompute hash, it could have been flushed. + (tramp-message key 7 "Restored %s" values) (setq hash (tramp-get-hash-table key)) (dolist (value values) (if (not (eq (cdr value) tramp-cache-undefined)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index a21af990e0e..f85a371cded 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -322,6 +322,8 @@ The string is used in `tramp-methods'.") `("plink" (tramp-login-program "plink") (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%c") + ;; Since PuTTY 0.82. + ("-legacy-stdio-prompts") ("-t") ("%h") ("\"") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" @@ -335,6 +337,8 @@ The string is used in `tramp-methods'.") `("plinkx" (tramp-login-program "plink") (tramp-login-args (("-load") ("%h") ("%c") ("-t") ("\"") + ;; Since PuTTY 0.82. + ("-legacy-stdio-prompts") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" tramp-terminal-type @@ -347,6 +351,8 @@ The string is used in `tramp-methods'.") `("pscp" (tramp-login-program "plink") (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%c") + ;; Since PuTTY 0.82. + ("-legacy-stdio-prompts") ("-t") ("%h") ("\"") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" @@ -358,6 +364,8 @@ The string is used in `tramp-methods'.") (tramp-remote-shell-args ("-c")) (tramp-copy-program "pscp") (tramp-copy-args (("-l" "%u") ("-P" "%p") ("-scp") + ;; Since PuTTY 0.82. + ("-legacy-stdio-prompts") ("-p" "%k") ("-q") ("-r"))) (tramp-copy-keep-date t) (tramp-copy-recursive t))) @@ -365,6 +373,8 @@ The string is used in `tramp-methods'.") `("psftp" (tramp-login-program "plink") (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%c") + ;; Since PuTTY 0.82. + ("-legacy-stdio-prompts") ("-t") ("%h") ("\"") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" @@ -376,6 +386,8 @@ The string is used in `tramp-methods'.") (tramp-remote-shell-args ("-c")) (tramp-copy-program "pscp") (tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp") + ;; Since PuTTY 0.82. + ("-legacy-stdio-prompts") ("-p" "%k"))) (tramp-copy-keep-date t))) From 0edf094e54c721f6039b878cafb8ed02fac74a0f Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Sun, 2 Feb 2025 17:18:52 +0100 Subject: [PATCH 254/279] Consolidate some cl-lib tests For discussion, see bug#75633#16 and the following thread: https://lists.gnu.org/r/emacs-devel/2025-02/msg00053.html * test/lisp/emacs-lisp/cl-extra-tests.el (cl-lib-test-remprop) (cl-lib-test-coerce-to-vector, cl-parse-integer): Move here from cl-lib-tests.el. (cl-extra-test-remprop): Remove duplicate test, folding body... (cl-get): ...into this test. (cl-extra-test-concatenate): Remove duplicate test, folding body... (cl-concatenate): ...into this test. * test/lisp/emacs-lisp/cl-lib-tests.el: Update historic commentary. (cl-lib-test-remprop, cl-lib-test-coerce-to-vector) (cl-parse-integer): Move to cl-extra-tests.el. (cl-lib-test-remove-if-not, cl-lib-test-remove) (cl-lib-test-set-functions, cl-lib-test-string-position) (cl-lib-test-mismatch, cl-nset-difference): Move to cl-seq-tests.el. (cl-lib-test-gensym, cl-lib-keyword-names-versus-values) (cl-lib-empty-keyargs, mystruct, cl-lib-struct-accessors) (cl-lib-struct-constructors, cl-lib-arglist-performance, cl-the) (cl-flet-test, cl-lib-test-typep, cl-lib-symbol-macrolet) (cl-lib-symbol-macrolet-4+5, cl-lib-symbol-macrolet-2) (cl-lib-symbol-macrolet-hide, cl-lib-defstruct-record): Move to cl-macs-tests.el. (cl-lib-test-endp): Remove duplicate test, folding body into cl-seq-endp-test. (cl-lib-set-difference): Remove duplicate test, folding body into cl-set-difference-test. * test/lisp/emacs-lisp/cl-macs-tests.el: Do not require cl-macs and pcase. (mystruct, cl-lib-struct-accessors, cl-lib-struct-constructors) (cl-lib-arglist-performance, cl-lib-defstruct-record) (cl-lib-symbol-macrolet, cl-lib-symbol-macrolet-4+5) (cl-lib-symbol-macrolet-2, cl-lib-symbol-macrolet-hide, cl-flet-test) (cl-lib-keyword-names-versus-values, cl-lib-empty-keyargs) (cl-lib-test-gensym, cl-the, cl-lib-test-typep): Move here from cl-lib-tests.el. (cl-case-error, cl-case-warning): Fix indentation. * test/lisp/emacs-lisp/cl-seq-tests.el: Require cl-lib rather than cl-seq. (cl-seq-endp-test): Absorb body of cl-lib-test-endp. (cl-lib-test-remove, cl-lib-test-remove-if-not) (cl-lib-test-string-position, cl-lib-test-mismatch) (cl-lib-test-set-functions, cl-nset-difference): Move here from cl-lib-tests.el. (cl-set-difference-test): Absorb body of cl-lib-set-difference. --- test/lisp/emacs-lisp/cl-extra-tests.el | 70 +++++- test/lisp/emacs-lisp/cl-lib-tests.el | 322 +------------------------ test/lisp/emacs-lisp/cl-macs-tests.el | 134 +++++++++- test/lisp/emacs-lisp/cl-seq-tests.el | 153 +++++++++++- 4 files changed, 332 insertions(+), 347 deletions(-) diff --git a/test/lisp/emacs-lisp/cl-extra-tests.el b/test/lisp/emacs-lisp/cl-extra-tests.el index bec4e373201..75533b36f29 100644 --- a/test/lisp/emacs-lisp/cl-extra-tests.el +++ b/test/lisp/emacs-lisp/cl-extra-tests.el @@ -22,12 +22,55 @@ (require 'cl-lib) (require 'ert) +(ert-deftest cl-lib-test-remprop () + (let ((x (cl-gensym))) + (should (equal (symbol-plist x) '())) + ;; Remove nonexistent property on empty plist. + (cl-remprop x 'b) + (should (equal (symbol-plist x) '())) + (put x 'a 1) + (should (equal (symbol-plist x) '(a 1))) + ;; Remove nonexistent property on nonempty plist. + (cl-remprop x 'b) + (should (equal (symbol-plist x) '(a 1))) + (put x 'b 2) + (put x 'c 3) + (put x 'd 4) + (should (equal (symbol-plist x) '(a 1 b 2 c 3 d 4))) + ;; Remove property that is neither first nor last. + (cl-remprop x 'c) + (should (equal (symbol-plist x) '(a 1 b 2 d 4))) + ;; Remove last property from a plist of length >1. + (cl-remprop x 'd) + (should (equal (symbol-plist x) '(a 1 b 2))) + ;; Remove first property from a plist of length >1. + (cl-remprop x 'a) + (should (equal (symbol-plist x) '(b 2))) + ;; Remove property when there is only one. + (cl-remprop x 'b) + (should (equal (symbol-plist x) '())))) + (ert-deftest cl-get () (put 'cl-get-test 'x 1) (put 'cl-get-test 'y nil) (should (eq (cl-get 'cl-get-test 'x) 1)) (should (eq (cl-get 'cl-get-test 'y :none) nil)) - (should (eq (cl-get 'cl-get-test 'z :none) :none))) + (should (eq (cl-get 'cl-get-test 'z :none) :none)) + (let ((sym (make-symbol "test"))) + (put sym 'foo 'bar) + (should (equal (cl-get sym 'foo) 'bar)) + (cl-remprop sym 'foo) + (should (equal (cl-get sym 'foo 'default) 'default)))) + +(ert-deftest cl-lib-test-coerce-to-vector () + (let* ((a (vector)) + (b (vector 1 a 3)) + (c (list)) + (d (list b a))) + (should (eql (cl-coerce a 'vector) a)) + (should (eql (cl-coerce b 'vector) b)) + (should (equal (cl-coerce c 'vector) (vector))) + (should (equal (cl-coerce d 'vector) (vector b a))))) (ert-deftest cl-extra-test-coerce () (should (equal (cl-coerce "abc" 'list) '(?a ?b ?c))) @@ -152,7 +195,8 @@ (should (equal (cl-concatenate 'vector [1 2 3] [4 5 6]) [1 2 3 4 5 6])) (should (equal (cl-concatenate 'string "123" "456") - "123456"))) + "123456")) + (should (equal (cl-concatenate 'list '(1 2) '(3 4) '(5 6)) '(1 2 3 4 5 6)))) (ert-deftest cl-extra-test-mapcan () (should (equal (cl-mapcan #'list '(1 2 3)) '(1 2 3))) @@ -258,6 +302,17 @@ (should (equal (cl-signum -10) -1)) (should (equal (cl-signum 0) 0))) +(ert-deftest cl-parse-integer () + (should-error (cl-parse-integer "abc")) + (should (null (cl-parse-integer "abc" :junk-allowed t))) + (should (null (cl-parse-integer "" :junk-allowed t))) + (should (= 342391 (cl-parse-integer "0123456789" :radix 8 :junk-allowed t))) + (should-error (cl-parse-integer "0123456789" :radix 8)) + (should (= -239 (cl-parse-integer "-efz" :radix 16 :junk-allowed t))) + (should-error (cl-parse-integer "efz" :radix 16)) + (should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2))) + (should (= -123 (cl-parse-integer " -123 ")))) + (ert-deftest cl-extra-test-parse-integer () (should (equal (cl-parse-integer "10") 10)) (should (equal (cl-parse-integer "-10") -10)) @@ -274,10 +329,6 @@ (should (equal (cl-subseq '(1 2 3 4 5) 2) '(3 4 5))) (should (equal (cl-subseq '(1 2 3 4 5) 1 3) '(2 3)))) -(ert-deftest cl-extra-test-concatenate () - (should (equal (cl-concatenate 'string "hello " "world") "hello world")) - (should (equal (cl-concatenate 'list '(1 2) '(3 4) '(5 6)) '(1 2 3 4 5 6)))) - (ert-deftest cl-extra-test-revappend () (should (equal (cl-revappend '(1 2 3) '(4 5 6)) '(3 2 1 4 5 6)))) @@ -297,11 +348,4 @@ (should (cl-tailp l l)) (should (not (cl-tailp '(4 5) l))))) -(ert-deftest cl-extra-test-remprop () - (let ((sym (make-symbol "test"))) - (put sym 'foo 'bar) - (should (equal (cl-get sym 'foo) 'bar)) - (cl-remprop sym 'foo) - (should (equal (cl-get sym 'foo 'default) 'default)))) - ;;; cl-extra-tests.el ends here diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el index ff860d94468..12de268bced 100644 --- a/test/lisp/emacs-lisp/cl-lib-tests.el +++ b/test/lisp/emacs-lisp/cl-lib-tests.el @@ -19,229 +19,14 @@ ;;; Commentary: -;; Extracted from ert-tests.el, back when ert used to reimplement some -;; cl functions. +;; Some of these tests were extracted from ert-tests.el, back when ert +;; used to reimplement some cl functions. ;;; Code: (require 'cl-lib) (require 'ert) -(ert-deftest cl-lib-test-remprop () - (let ((x (cl-gensym))) - (should (equal (symbol-plist x) '())) - ;; Remove nonexistent property on empty plist. - (cl-remprop x 'b) - (should (equal (symbol-plist x) '())) - (put x 'a 1) - (should (equal (symbol-plist x) '(a 1))) - ;; Remove nonexistent property on nonempty plist. - (cl-remprop x 'b) - (should (equal (symbol-plist x) '(a 1))) - (put x 'b 2) - (put x 'c 3) - (put x 'd 4) - (should (equal (symbol-plist x) '(a 1 b 2 c 3 d 4))) - ;; Remove property that is neither first nor last. - (cl-remprop x 'c) - (should (equal (symbol-plist x) '(a 1 b 2 d 4))) - ;; Remove last property from a plist of length >1. - (cl-remprop x 'd) - (should (equal (symbol-plist x) '(a 1 b 2))) - ;; Remove first property from a plist of length >1. - (cl-remprop x 'a) - (should (equal (symbol-plist x) '(b 2))) - ;; Remove property when there is only one. - (cl-remprop x 'b) - (should (equal (symbol-plist x) '())))) - -(ert-deftest cl-lib-test-remove-if-not () - (let ((list (list 'a 'b 'c 'd)) - (i 0)) - (let ((result (cl-remove-if-not (lambda (x) - (should (eql x (nth i list))) - (cl-incf i) - (member i '(2 3))) - list))) - (should (equal i 4)) - (should (equal result '(b c))) - (should (equal list '(a b c d))))) - (should (equal '() - (cl-remove-if-not (lambda (_x) (should nil)) '())))) - -(ert-deftest cl-lib-test-remove () - (let ((list (list 'a 'b 'c 'd)) - (key-index 0) - (test-index 0)) - (let ((result - (cl-remove 'foo list - :key (lambda (x) - (should (eql x (nth key-index list))) - (prog1 - (list key-index x) - (cl-incf key-index))) - :test - (lambda (a b) - (should (eql a 'foo)) - (should (equal b (list test-index - (nth test-index list)))) - (cl-incf test-index) - (member test-index '(2 3)))))) - (should (equal key-index 4)) - (should (equal test-index 4)) - (should (equal result '(a d))) - (should (equal list '(a b c d))))) - (let ((x (cons nil nil)) - (y (cons nil nil))) - (should (equal (cl-remove x (list x y)) - ;; or (list x), since we use `equal' -- the - ;; important thing is that only one element got - ;; removed, this proves that the default test is - ;; `eql', not `equal' - (list y))))) - - -(ert-deftest cl-lib-test-set-functions () - (let ((c1 (cons nil nil)) - (c2 (cons nil nil)) - (sym (make-symbol "a"))) - (let ((e '()) - (a (list 'a 'b sym nil "" "x" c1 c2)) - (b (list c1 'y 'b sym 'x))) - (should (equal (cl-set-difference e e) e)) - (should (equal (cl-set-difference a e) a)) - (should (equal (cl-set-difference e a) e)) - (should (equal (cl-set-difference a a) e)) - (should (equal (cl-set-difference b e) b)) - (should (equal (cl-set-difference e b) e)) - (should (equal (cl-set-difference b b) e)) - ;; Note: this test (and others) is sensitive to the order of the - ;; result, which is not documented. - (should (equal (cl-set-difference a b) (list 'a nil "" "x" c2))) - (should (equal (cl-set-difference b a) (list 'y 'x))) - - ;; We aren't testing whether this is really using `eq' rather than `eql'. - (should (equal (cl-set-difference e e :test 'eq) e)) - (should (equal (cl-set-difference a e :test 'eq) a)) - (should (equal (cl-set-difference e a :test 'eq) e)) - (should (equal (cl-set-difference a a :test 'eq) e)) - (should (equal (cl-set-difference b e :test 'eq) b)) - (should (equal (cl-set-difference e b :test 'eq) e)) - (should (equal (cl-set-difference b b :test 'eq) e)) - (should (equal (cl-set-difference a b :test 'eq) (list 'a nil "" "x" c2))) - (should (equal (cl-set-difference b a :test 'eq) (list 'y 'x))) - - (should (equal (cl-union e e) e)) - (should (equal (cl-union a e) a)) - (should (equal (cl-union e a) a)) - (should (equal (cl-union a a) a)) - (should (equal (cl-union b e) b)) - (should (equal (cl-union e b) b)) - (should (equal (cl-union b b) b)) - (should (equal (cl-union a b) (list 'x 'y 'a 'b sym nil "" "x" c1 c2))) - - (should (equal (cl-union b a) (list 'x 'y 'a 'b sym nil "" "x" c1 c2))) - - (should (equal (cl-intersection e e) e)) - (should (equal (cl-intersection a e) e)) - (should (equal (cl-intersection e a) e)) - (should (equal (cl-intersection a a) a)) - (should (equal (cl-intersection b e) e)) - (should (equal (cl-intersection e b) e)) - (should (equal (cl-intersection b b) b)) - (should (equal (cl-intersection a b) (list sym 'b c1))) - (should (equal (cl-intersection b a) (list sym 'b c1)))))) - -(ert-deftest cl-lib-test-gensym () - ;; Since the expansion of `should' calls `cl-gensym' and thus has a - ;; side-effect on `cl--gensym-counter', we have to make sure all - ;; macros in our test body are expanded before we rebind - ;; `cl--gensym-counter' and run the body. Otherwise, the test would - ;; fail if run interpreted. - (let ((body (byte-compile - '(lambda () - (should (equal (symbol-name (cl-gensym)) "G0")) - (should (equal (symbol-name (cl-gensym)) "G1")) - (should (equal (symbol-name (cl-gensym)) "G2")) - (should (equal (symbol-name (cl-gensym "foo")) "foo3")) - (should (equal (symbol-name (cl-gensym "bar")) "bar4")) - (should (equal cl--gensym-counter 5)))))) - (let ((cl--gensym-counter 0)) - (funcall body)))) - -(ert-deftest cl-lib-test-coerce-to-vector () - (let* ((a (vector)) - (b (vector 1 a 3)) - (c (list)) - (d (list b a))) - (should (eql (cl-coerce a 'vector) a)) - (should (eql (cl-coerce b 'vector) b)) - (should (equal (cl-coerce c 'vector) (vector))) - (should (equal (cl-coerce d 'vector) (vector b a))))) - -(ert-deftest cl-lib-test-string-position () - (should (eql (cl-position ?x "") nil)) - (should (eql (cl-position ?a "abc") 0)) - (should (eql (cl-position ?b "abc") 1)) - (should (eql (cl-position ?c "abc") 2)) - (should (eql (cl-position ?d "abc") nil)) - (should (eql (cl-position ?A "abc") nil))) - -(ert-deftest cl-lib-test-mismatch () - (should (eql (cl-mismatch "" "") nil)) - (should (eql (cl-mismatch "" "a") 0)) - (should (eql (cl-mismatch "a" "a") nil)) - (should (eql (cl-mismatch "ab" "a") 1)) - (should (eql (cl-mismatch "Aa" "aA") 0)) - (should (eql (cl-mismatch '(a b c) '(a b d)) 2))) - -(ert-deftest cl-lib-keyword-names-versus-values () - (should (equal - (funcall (cl-function (lambda (&key a b) (list a b))) - :b :a :a 42) - '(42 :a)))) - -(ert-deftest cl-lib-empty-keyargs () - (should-error (funcall (cl-function (lambda (&key) 1)) - :b 1))) - -(cl-defstruct (mystruct - (:constructor cl-lib--con-1 (&aux (abc 1))) - (:constructor cl-lib--con-2 (&optional def) "Constructor docstring.")) - "General docstring." - (abc 5 :readonly t) (def nil)) -(ert-deftest cl-lib-struct-accessors () - (let ((x (make-mystruct :abc 1 :def 2))) - (should (eql (cl-struct-slot-value 'mystruct 'abc x) 1)) - (should (eql (cl-struct-slot-value 'mystruct 'def x) 2)) - (setf (cl-struct-slot-value 'mystruct 'def x) -1) - (should (eql (cl-struct-slot-value 'mystruct 'def x) -1)) - (should (eql (cl-struct-slot-offset 'mystruct 'abc) 1)) - (should-error (cl-struct-slot-offset 'mystruct 'marypoppins)) - (should (pcase (cl-struct-slot-info 'mystruct) - (`((cl-tag-slot) (abc 5 :readonly t) - (def . ,(or 'nil '(nil)))) - t))))) -(ert-deftest cl-lib-struct-constructors () - (should (string-match "\\`Constructor docstring." - (documentation 'cl-lib--con-2 t))) - (should (mystruct-p (cl-lib--con-1))) - (should (mystruct-p (cl-lib--con-2)))) - -(ert-deftest cl-lib-arglist-performance () - ;; An `&aux' should not cause lambda's arglist to be turned into an &rest - ;; that's parsed by hand. - (should (equal () (help-function-arglist 'cl-lib--con-1))) - (should (pcase (help-function-arglist 'cl-lib--con-2) - (`(&optional ,_) t)))) - -(ert-deftest cl-the () - (should (eql (cl-the integer 42) 42)) - (should-error (cl-the integer "abc")) - (let ((side-effect 0)) - (should (= (cl-the integer (cl-incf side-effect)) 1)) - (should (= side-effect 1)))) - (ert-deftest cl-lib-test-pushnew () (let ((list '(1 2 3))) (cl-pushnew 0 list) @@ -468,12 +253,6 @@ (should (equal (cl-pairlis '(a nil c) '(1 2 3)) '((a . 1) (nil . 2) (c . 3)))) (should (equal (cl-pairlis '(a b c) '(1 nil 3)) '((a . 1) (b) (c . 3))))) -(ert-deftest cl-lib-test-endp () - (should (cl-endp '())) - (should-not (cl-endp '(1))) - (should-error (cl-endp 1) :type 'wrong-type-argument) - (should-error (cl-endp [1]) :type 'wrong-type-argument)) - (ert-deftest cl-lib-test-nth-value () (let ((vals (cl-values 2 3))) (should (= (cl-nth-value 0 vals) 2)) @@ -544,70 +323,6 @@ (should-error (cl-adjoin 1 nums :key 'int-to-string :test-not myfn-p) :type 'wrong-type-argument))) -(ert-deftest cl-parse-integer () - (should-error (cl-parse-integer "abc")) - (should (null (cl-parse-integer "abc" :junk-allowed t))) - (should (null (cl-parse-integer "" :junk-allowed t))) - (should (= 342391 (cl-parse-integer "0123456789" :radix 8 :junk-allowed t))) - (should-error (cl-parse-integer "0123456789" :radix 8)) - (should (= -239 (cl-parse-integer "-efz" :radix 16 :junk-allowed t))) - (should-error (cl-parse-integer "efz" :radix 16)) - (should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2))) - (should (= -123 (cl-parse-integer " -123 ")))) - -(ert-deftest cl-flet-test () - (should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5))) - -(ert-deftest cl-lib-test-typep () - (cl-deftype cl-lib-test-type (&optional x) `(member ,x)) - ;; Make sure we correctly implement the rule that deftype's optional args - ;; default to `*' rather than to nil. - (should (cl-typep '* 'cl-lib-test-type)) - (should-not (cl-typep 1 'cl-lib-test-type))) - -(ert-deftest cl-lib-symbol-macrolet () - ;; bug#26325 - (should (equal (cl-flet ((f (x) (+ x 5))) - (let ((x 5)) - (f (+ x 6)))) - ;; Go through `eval', otherwise the macro-expansion - ;; error prevents running the whole test suite :-( - (eval '(cl-symbol-macrolet ((f (+ x 6))) - (cl-flet ((f (x) (+ x 5))) - (let ((x 5)) - (f f)))) - t)))) - -(defmacro cl-lib-symbol-macrolet-4+5 () - ;; bug#26068 - (let* ((sname "x") - (s1 (make-symbol sname)) - (s2 (make-symbol sname))) - `(cl-symbol-macrolet ((,s1 4) - (,s2 5)) - (+ ,s1 ,s2)))) - -(ert-deftest cl-lib-symbol-macrolet-2 () - (should (equal (cl-lib-symbol-macrolet-4+5) (+ 4 5)))) - - -(ert-deftest cl-lib-symbol-macrolet-hide () - ;; bug#26325, bug#26073 - (should (equal (let ((y 5)) - (cl-symbol-macrolet ((x y)) - (list x - (let ((x 6)) (list x y)) - (cl-letf ((x 6)) (list x y)) - (apply (lambda (x) (+ x 1)) (list 8))))) - '(5 (6 5) (6 6) 9)))) - -(ert-deftest cl-lib-defstruct-record () - (cl-defstruct foo x) - (let ((x (make-foo :x 42))) - (should (recordp x)) - (should (eq (type-of x) 'foo)) - (should (eql (foo-x x) 42)))) - (ert-deftest old-struct () (cl-defstruct foo x) (with-suppressed-warnings ((obsolete cl-old-struct-compat-mode)) @@ -638,37 +353,4 @@ (should (equal (mapcar (cl-constantly 3) '(a b c d)) '(3 3 3 3)))) -(ert-deftest cl-lib-set-difference () - ;; our set-difference preserves order, though it is not required to - ;; by cl standards. Nevertheless better keep that invariant - (should (equal (cl-set-difference '(1 2 3 4) '(3 4 5 6)) - '(1 2)))) - -(ert-deftest cl-nset-difference () - ;; our nset-difference doesn't - (let* ((l1 (list 1 2 3 4)) (l2 '(3 4 5 6)) - (diff (cl-nset-difference l1 l2))) - (should (memq 1 diff)) - (should (memq 2 diff)) - (should (= (length diff) 2)) - (should (equal l2 '(3 4 5 6)))) - (let* ((l1 (list "1" "2" "3" "4")) (l2 '("3" "4" "5" "6")) - (diff (cl-nset-difference l1 l2 :test #'equal))) - (should (member "1" diff)) - (should (member "2" diff)) - (should (= (length diff) 2)) - (should (equal l2 '("3" "4" "5" "6")))) - (let* ((l1 (list '(a . 1) '(b . 2) '(c . 3) '(d . 4))) - (l2 (list '(c . 3) '(d . 4) '(e . 5) '(f . 6))) - (diff (cl-nset-difference l1 l2 :key #'car))) - (should (member '(a . 1) diff)) - (should (member '(b . 2) diff)) - (should (= (length diff) 2))) - (let* ((l1 (list '("a" . 1) '("b" . 2) '("c" . 3) '("d" . 4))) - (l2 (list '("c" . 3) '("d" . 4) '("e" . 5) '("f" . 6))) - (diff (cl-nset-difference l1 l2 :key #'car :test #'string=))) - (should (member '("a" . 1) diff)) - (should (member '("b" . 2) diff)) - (should (= (length diff) 2)))) - ;;; cl-lib-tests.el ends here diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el index 628bae36e48..4fa5c4edba1 100644 --- a/test/lisp/emacs-lisp/cl-macs-tests.el +++ b/test/lisp/emacs-lisp/cl-macs-tests.el @@ -22,11 +22,9 @@ ;;; Code: (require 'cl-lib) -(require 'cl-macs) (require 'edebug) (require 'ert) (require 'ert-x) -(require 'pcase) ;;;; cl-loop tests -- many adapted from Steele's CLtL2 @@ -518,6 +516,45 @@ collection clause." collect (list k x)))))) +(cl-defstruct (mystruct + (:constructor cl-lib--con-1 (&aux (abc 1))) + (:constructor cl-lib--con-2 (&optional def) "Constructor docstring.")) + "General docstring." + (abc 5 :readonly t) (def nil)) + +(ert-deftest cl-lib-struct-accessors () + (let ((x (make-mystruct :abc 1 :def 2))) + (should (eql (cl-struct-slot-value 'mystruct 'abc x) 1)) + (should (eql (cl-struct-slot-value 'mystruct 'def x) 2)) + (setf (cl-struct-slot-value 'mystruct 'def x) -1) + (should (eql (cl-struct-slot-value 'mystruct 'def x) -1)) + (should (eql (cl-struct-slot-offset 'mystruct 'abc) 1)) + (should-error (cl-struct-slot-offset 'mystruct 'marypoppins)) + (should (pcase (cl-struct-slot-info 'mystruct) + (`((cl-tag-slot) (abc 5 :readonly t) + (def . ,(or 'nil '(nil)))) + t))))) + +(ert-deftest cl-lib-struct-constructors () + (should (string-match "\\`Constructor docstring." + (documentation 'cl-lib--con-2 t))) + (should (mystruct-p (cl-lib--con-1))) + (should (mystruct-p (cl-lib--con-2)))) + +(ert-deftest cl-lib-arglist-performance () + ;; An `&aux' should not cause lambda's arglist to be turned into an &rest + ;; that's parsed by hand. + (should (equal () (help-function-arglist 'cl-lib--con-1))) + (should (pcase (help-function-arglist 'cl-lib--con-2) + (`(&optional ,_) t)))) + +(ert-deftest cl-lib-defstruct-record () + (cl-defstruct foo x) + (let ((x (make-foo :x 42))) + (should (recordp x)) + (should (eq (type-of x) 'foo)) + (should (eql (foo-x x) 42)))) + (ert-deftest cl-defstruct/builtin-type () (should-error (macroexpand '(cl-defstruct hash-table)) @@ -563,6 +600,41 @@ collection clause." m))) '(42 5 42)))) +(ert-deftest cl-lib-symbol-macrolet () + ;; bug#26325 + (should (equal (cl-flet ((f (x) (+ x 5))) + (let ((x 5)) + (f (+ x 6)))) + ;; Go through `eval', otherwise the macro-expansion + ;; error prevents running the whole test suite :-( + (eval '(cl-symbol-macrolet ((f (+ x 6))) + (cl-flet ((f (x) (+ x 5))) + (let ((x 5)) + (f f)))) + t)))) + +(defmacro cl-lib-symbol-macrolet-4+5 () + ;; bug#26068 + (let* ((sname "x") + (s1 (make-symbol sname)) + (s2 (make-symbol sname))) + `(cl-symbol-macrolet ((,s1 4) + (,s2 5)) + (+ ,s1 ,s2)))) + +(ert-deftest cl-lib-symbol-macrolet-2 () + (should (equal (cl-lib-symbol-macrolet-4+5) (+ 4 5)))) + +(ert-deftest cl-lib-symbol-macrolet-hide () + ;; bug#26325, bug#26073 + (should (equal (let ((y 5)) + (cl-symbol-macrolet ((x y)) + (list x + (let ((x 6)) (list x y)) + (cl-letf ((x 6)) (list x y)) + (apply (lambda (x) (+ x 1)) (list 8))))) + '(5 (6 5) (6 6) 9)))) + (ert-deftest cl-macs-loop-conditional-step-clauses () "These tests failed under the initial fixes in #bug#29799." (should (cl-loop for i from 1 upto 100 and j = 1 then (1+ j) @@ -718,6 +790,9 @@ collection clause." (f lex-var))))) (should (equal (f nil) 'a))))) +(ert-deftest cl-flet-test () + (should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5))) + (ert-deftest cl-macs--test-flet-block () (should (equal (cl-block f1 (cl-flet ((f1 (a) (cons (cl-return-from f1 a) 6))) @@ -803,9 +878,9 @@ collection clause." (cl-ecase val (t 1) (123 2)) (cl-ecase val (123 2) (t 1)))) (ert-info ((prin1-to-string form) :prefix "Form: ") - (let ((error (should-error (macroexpand form)))) - (should (equal (cdr error) - '("Misplaced t or `otherwise' clause")))))))) + (let ((error (should-error (macroexpand form)))) + (should (equal (cdr error) + '("Misplaced t or `otherwise' clause")))))))) (ert-deftest cl-case-warning () "Test that `cl-case' and `cl-ecase' warn about suspicious @@ -833,10 +908,10 @@ constructs." (dolist (macro '(cl-case cl-ecase)) (let ((form `(,macro val (,case 1)))) (ert-info ((prin1-to-string form) :prefix "Form: ") - (ert-with-message-capture messages - (macroexpand form) - (should (equal messages - (concat "Warning: " message "\n")))))))))) + (ert-with-message-capture messages + (macroexpand form) + (should (equal messages + (concat "Warning: " message "\n")))))))))) (ert-deftest cl-case-no-warning () "Test that `cl-case' and `cl-ecase' don't warn in some valid cases. @@ -875,4 +950,45 @@ See Bug#57915." (should (equal (cl--test-s-cl--test-a x) 4)) (should (equal (cl--test-s-b x) 'dyn))))) +(ert-deftest cl-lib-keyword-names-versus-values () + (should (equal + (funcall (cl-function (lambda (&key a b) (list a b))) + :b :a :a 42) + '(42 :a)))) + +(ert-deftest cl-lib-empty-keyargs () + (should-error (funcall (cl-function (lambda (&key) 1)) + :b 1))) + +(ert-deftest cl-lib-test-gensym () + ;; Since the expansion of `should' calls `cl-gensym' and thus has a + ;; side-effect on `cl--gensym-counter', we have to make sure all + ;; macros in our test body are expanded before we rebind + ;; `cl--gensym-counter' and run the body. Otherwise, the test would + ;; fail if run interpreted. + (let ((body (byte-compile + '(lambda () + (should (equal (symbol-name (cl-gensym)) "G0")) + (should (equal (symbol-name (cl-gensym)) "G1")) + (should (equal (symbol-name (cl-gensym)) "G2")) + (should (equal (symbol-name (cl-gensym "foo")) "foo3")) + (should (equal (symbol-name (cl-gensym "bar")) "bar4")) + (should (equal cl--gensym-counter 5)))))) + (let ((cl--gensym-counter 0)) + (funcall body)))) + +(ert-deftest cl-the () + (should (eql (cl-the integer 42) 42)) + (should-error (cl-the integer "abc")) + (let ((side-effect 0)) + (should (= (cl-the integer (cl-incf side-effect)) 1)) + (should (= side-effect 1)))) + +(ert-deftest cl-lib-test-typep () + (cl-deftype cl-lib-test-type (&optional x) `(member ,x)) + ;; Make sure we correctly implement the rule that deftype's optional args + ;; default to `*' rather than to nil. + (should (cl-typep '* 'cl-lib-test-type)) + (should-not (cl-typep 1 'cl-lib-test-type))) + ;;; cl-macs-tests.el ends here diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el b/test/lisp/emacs-lisp/cl-seq-tests.el index 97276be3870..2348a7fc812 100644 --- a/test/lisp/emacs-lisp/cl-seq-tests.el +++ b/test/lisp/emacs-lisp/cl-seq-tests.el @@ -22,7 +22,7 @@ ;;; Code: (require 'ert) -(require 'cl-seq) +(require 'cl-lib) (ert-deftest cl-union-test-00 () "Test for bug#22729." @@ -54,8 +54,10 @@ Additionally register an `ert-info' to help identify test failures." (ert-deftest cl-seq-endp-test () (should (cl-endp '())) - (should (not (cl-endp '(1 2 3)))) - (should-error (cl-endp 42) :type 'wrong-type-argument)) + (should-not (cl-endp '(1))) + (should-not (cl-endp '(1 2 3))) + (should-error (cl-endp 1) :type 'wrong-type-argument) + (should-error (cl-endp [1]) :type 'wrong-type-argument)) (ert-deftest cl-seq-reduce-test () (should (equal 6 (cl-reduce #'+ '(1 2 3)))) @@ -97,6 +99,37 @@ Additionally register an `ert-info' to help identify test failures." (should (equal '(1 2 a a 5 2 6) (cl-replace l1 l2 :start1 2 :end1 4))) (should (equal '(a a 3 4 5 2 6) (cl-replace l1 l2 :start2 2 :end2 4))))) +(ert-deftest cl-lib-test-remove () + (let ((list (list 'a 'b 'c 'd)) + (key-index 0) + (test-index 0)) + (let ((result + (cl-remove 'foo list + :key (lambda (x) + (should (eql x (nth key-index list))) + (prog1 + (list key-index x) + (cl-incf key-index))) + :test + (lambda (a b) + (should (eql a 'foo)) + (should (equal b (list test-index + (nth test-index list)))) + (cl-incf test-index) + (member test-index '(2 3)))))) + (should (equal key-index 4)) + (should (equal test-index 4)) + (should (equal result '(a d))) + (should (equal list '(a b c d))))) + (let ((x (cons nil nil)) + (y (cons nil nil))) + (should (equal (cl-remove x (list x y)) + ;; or (list x), since we use `equal' -- the + ;; important thing is that only one element got + ;; removed, this proves that the default test is + ;; `eql', not `equal' + (list y))))) + ;; keywords supported: :test :test-not :key :count :start :end :from-end (ert-deftest cl-seq-remove-test () (let ((list '(1 2 3 4 5 2 6))) @@ -122,6 +155,20 @@ Additionally register an `ert-info' to help identify test failures." (should (equal '() (cl-remove-if #'cl-evenp '()))) (should (equal '() (cl-remove-if #'cl-evenp '(2))))) +(ert-deftest cl-lib-test-remove-if-not () + (let ((list (list 'a 'b 'c 'd)) + (i 0)) + (let ((result (cl-remove-if-not (lambda (x) + (should (eql x (nth i list))) + (cl-incf i) + (member i '(2 3))) + list))) + (should (equal i 4)) + (should (equal result '(b c))) + (should (equal list '(a b c d))))) + (should (equal '() + (cl-remove-if-not (lambda (_x) (should nil)) '())))) + (ert-deftest cl-remove-if-not-test () (should (equal '(2 4) (cl-remove-if-not #'cl-evenp '(1 2 3 4)))) (should (equal '(2 4) (cl-remove-if-not #'cl-evenp '(1 2 3 4) :count 2))) @@ -309,6 +356,14 @@ Additionally register an `ert-info' to help identify test failures." (let ((pred (lambda (x) (> (cl-position x orig :from-end t) 1)))) (should (equal '(b 2 3 4 5 2 6) (cl-nsubstitute 'b nil l :if-not pred)))))) +(ert-deftest cl-lib-test-string-position () + (should (eql (cl-position ?x "") nil)) + (should (eql (cl-position ?a "abc") 0)) + (should (eql (cl-position ?b "abc") 1)) + (should (eql (cl-position ?c "abc") 2)) + (should (eql (cl-position ?d "abc") nil)) + (should (eql (cl-position ?A "abc") nil))) + ;; keywords supported: :test :test-not :key :start :end :from-end (ert-deftest cl-seq-position-test () (let ((list '(1 2 3 4 5 2 6))) @@ -401,6 +456,14 @@ Additionally register an `ert-info' to help identify test failures." '(1 2 3 4 5 6)))) (should (equal result 2)))) +(ert-deftest cl-lib-test-mismatch () + (should (eql (cl-mismatch "" "") nil)) + (should (eql (cl-mismatch "" "a") 0)) + (should (eql (cl-mismatch "a" "a") nil)) + (should (eql (cl-mismatch "ab" "a") 1)) + (should (eql (cl-mismatch "Aa" "aA") 0)) + (should (eql (cl-mismatch '(a b c) '(a b d)) 2))) + ;; keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end (ert-deftest cl-seq-mismatch-test () (let ((list '(1 2 3 4 5 2 6)) @@ -776,6 +839,57 @@ Additionally register an `ert-info' to help identify test failures." '(((1 2) . 1) ((3 4) . 2) ((5) . 2))))) (should (equal result '((1 2) . 1))))) +(ert-deftest cl-lib-test-set-functions () + (let ((c1 (cons nil nil)) + (c2 (cons nil nil)) + (sym (make-symbol "a"))) + (let ((e '()) + (a (list 'a 'b sym nil "" "x" c1 c2)) + (b (list c1 'y 'b sym 'x))) + (should (equal (cl-set-difference e e) e)) + (should (equal (cl-set-difference a e) a)) + (should (equal (cl-set-difference e a) e)) + (should (equal (cl-set-difference a a) e)) + (should (equal (cl-set-difference b e) b)) + (should (equal (cl-set-difference e b) e)) + (should (equal (cl-set-difference b b) e)) + ;; Note: this test (and others) is sensitive to the order of the + ;; result, which is not documented. + (should (equal (cl-set-difference a b) (list 'a nil "" "x" c2))) + (should (equal (cl-set-difference b a) (list 'y 'x))) + + ;; We aren't testing whether this is really using `eq' rather than `eql'. + (should (equal (cl-set-difference e e :test 'eq) e)) + (should (equal (cl-set-difference a e :test 'eq) a)) + (should (equal (cl-set-difference e a :test 'eq) e)) + (should (equal (cl-set-difference a a :test 'eq) e)) + (should (equal (cl-set-difference b e :test 'eq) b)) + (should (equal (cl-set-difference e b :test 'eq) e)) + (should (equal (cl-set-difference b b :test 'eq) e)) + (should (equal (cl-set-difference a b :test 'eq) (list 'a nil "" "x" c2))) + (should (equal (cl-set-difference b a :test 'eq) (list 'y 'x))) + + (should (equal (cl-union e e) e)) + (should (equal (cl-union a e) a)) + (should (equal (cl-union e a) a)) + (should (equal (cl-union a a) a)) + (should (equal (cl-union b e) b)) + (should (equal (cl-union e b) b)) + (should (equal (cl-union b b) b)) + (should (equal (cl-union a b) (list 'x 'y 'a 'b sym nil "" "x" c1 c2))) + + (should (equal (cl-union b a) (list 'x 'y 'a 'b sym nil "" "x" c1 c2))) + + (should (equal (cl-intersection e e) e)) + (should (equal (cl-intersection a e) e)) + (should (equal (cl-intersection e a) e)) + (should (equal (cl-intersection a a) a)) + (should (equal (cl-intersection b e) e)) + (should (equal (cl-intersection e b) e)) + (should (equal (cl-intersection b b) b)) + (should (equal (cl-intersection a b) (list sym 'b c1))) + (should (equal (cl-intersection b a) (list sym 'b c1)))))) + (ert-deftest cl-intersection-test () (let ((result (cl-intersection '(1 2 3 4) '(3 4 5 6)))) (should (equal result '(4 3)))) @@ -815,8 +929,10 @@ Additionally register an `ert-info' to help identify test failures." '(1 2 3)))) (ert-deftest cl-set-difference-test () - (let ((result (cl-set-difference '(1 2 3 4) '(3 4 5 6)))) - (should (equal result '(1 2)))) + ;; Our set-difference preserves order, though it is not required to + ;; by CL standards. Nevertheless better keep that invariant. + (should (equal (cl-set-difference '(1 2 3 4) '(3 4 5 6)) + '(1 2))) (let ((result (cl-set-difference '(1 2 3) '()))) (should (equal result '(1 2 3)))) (let ((result (cl-set-difference '(1 2 3) '(1 2 3)))) @@ -843,6 +959,33 @@ Additionally register an `ert-info' to help identify test failures." (should (equal list1 '(1 2 3))) (should (equal list2 '(2 3 4))))) +(ert-deftest cl-nset-difference () + ;; Our nset-difference doesn't preserve order. + (let* ((l1 (list 1 2 3 4)) (l2 '(3 4 5 6)) + (diff (cl-nset-difference l1 l2))) + (should (memq 1 diff)) + (should (memq 2 diff)) + (should (= (length diff) 2)) + (should (equal l2 '(3 4 5 6)))) + (let* ((l1 (list "1" "2" "3" "4")) (l2 '("3" "4" "5" "6")) + (diff (cl-nset-difference l1 l2 :test #'equal))) + (should (member "1" diff)) + (should (member "2" diff)) + (should (= (length diff) 2)) + (should (equal l2 '("3" "4" "5" "6")))) + (let* ((l1 (list '(a . 1) '(b . 2) '(c . 3) '(d . 4))) + (l2 (list '(c . 3) '(d . 4) '(e . 5) '(f . 6))) + (diff (cl-nset-difference l1 l2 :key #'car))) + (should (member '(a . 1) diff)) + (should (member '(b . 2) diff)) + (should (= (length diff) 2))) + (let* ((l1 (list '("a" . 1) '("b" . 2) '("c" . 3) '("d" . 4))) + (l2 (list '("c" . 3) '("d" . 4) '("e" . 5) '("f" . 6))) + (diff (cl-nset-difference l1 l2 :key #'car :test #'string=))) + (should (member '("a" . 1) diff)) + (should (member '("b" . 2) diff)) + (should (= (length diff) 2)))) + (ert-deftest cl-nset-difference-test () (should-not (cl-nset-difference () ())) (should-not (cl-nset-difference () (list 1 2 3))) From ac143186c04ffd729cfe11abd99f02abdf742f64 Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Sun, 2 Feb 2025 18:05:57 +0100 Subject: [PATCH 255/279] Document cl-n... set operations consistently The docstrings of cl-nintersection and cl-nset-difference have been inconsistent with their manual entries since the beginning of emacs.git history (bug#76017). This patch settles on the weaker and thus backward-compatible requirement that only their first argument be safe to mutate. * lisp/emacs-lisp/bytecomp.el: Include only first argument in mutates-arguments property. * lisp/emacs-lisp/cl-seq.el (cl-nintersection, cl-nset-difference): Make docstring consistent with manual in that the second argument is not modified. * test/lisp/emacs-lisp/cl-seq-tests.el (cl-nintersection-test) (cl-nset-difference-test): Simplify. (cl-nset-difference): Pass fresh list as second argument, otherwise destructive modifications to it could go undetected. --- lisp/emacs-lisp/bytecomp.el | 2 +- lisp/emacs-lisp/cl-seq.el | 8 +++--- test/lisp/emacs-lisp/cl-seq-tests.el | 42 +++++++++++++++------------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 931b155313e..2ddbb2ec1da 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3583,7 +3583,7 @@ This assumes the function has the `important-return-value' property." (cl-nsubst 3) (cl-nsubst-if 3) (cl-nsubst-if-not 3) (cl-nsubstitute 3) (cl-nsubstitute-if 3) (cl-nsubstitute-if-not 3) (cl-nsublis 2) - (cl-nunion 1 2) (cl-nintersection 1 2) (cl-nset-difference 1 2) + (cl-nunion 1 2) (cl-nintersection 1) (cl-nset-difference 1) (cl-nset-exclusive-or 1 2) (cl-nreconc 1) (cl-sort 1) (cl-stable-sort 1) (cl-merge 2 3) diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el index 1878153f811..5b4337ad9cb 100644 --- a/lisp/emacs-lisp/cl-seq.el +++ b/lisp/emacs-lisp/cl-seq.el @@ -864,8 +864,8 @@ to avoid corrupting the original LIST1 and LIST2. (defun cl-nintersection (cl-list1 cl-list2 &rest cl-keys) "Combine LIST1 and LIST2 using a set-intersection operation. The resulting list contains all items that appear in both LIST1 and LIST2. -This is a destructive function; it reuses the storage of LIST1 and LIST2 -whenever possible. +This is a destructive function; it reuses the storage of LIST1 (but not +LIST2) whenever possible. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" (and cl-list1 cl-list2 (apply 'cl-intersection cl-list1 cl-list2 cl-keys))) @@ -894,8 +894,8 @@ to avoid corrupting the original LIST1 and LIST2. (defun cl-nset-difference (cl-list1 cl-list2 &rest cl-keys) "Combine LIST1 and LIST2 using a set-difference operation. The resulting list contains all items that appear in LIST1 but not LIST2. -This is a destructive function; it reuses the storage of LIST1 and LIST2 -whenever possible. +This is a destructive function; it reuses the storage of LIST1 (but not +LIST2) whenever possible. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" (if (or (null cl-list1) (null cl-list2)) cl-list1 diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el b/test/lisp/emacs-lisp/cl-seq-tests.el index 2348a7fc812..f72596e4a4b 100644 --- a/test/lisp/emacs-lisp/cl-seq-tests.el +++ b/test/lisp/emacs-lisp/cl-seq-tests.el @@ -914,18 +914,18 @@ Additionally register an `ert-info' to help identify test failures." (ert-deftest cl-nintersection-test () (should-not (cl-nintersection () ())) - (should-not (cl-nintersection () (list 1 2 3))) - (should-not (cl-nintersection (list 1 2) (list 3 4))) - (should (equal (cl-nintersection (list 1 2 3 4) (list 3 4 5 6)) + (should-not (cl-nintersection () '(1 2 3))) + (should-not (cl-nintersection (list 1 2) '(3 4))) + (should (equal (cl-nintersection (list 1 2 3 4) '(3 4 5 6)) '(4 3))) - (should (equal (cl-nintersection (list 1 2 3) (list 1 2 3)) + (should (equal (cl-nintersection (list 1 2 3) '(1 2 3)) '(1 2 3))) - (should (equal (cl-nintersection (list 1 1 2 2 3) (list 2 2 3 4)) + (should (equal (cl-nintersection (list 1 1 2 2 3) '(2 2 3 4)) '(3 2 2))) (should (equal (cl-nintersection (list 1 (copy-sequence "two") 3) - (list 3 "two" 4)) + '(3 "two" 4)) '(3))) - (should (equal (cl-nintersection (list 1 2 3) (list 3 2 1) :test #'equal) + (should (equal (cl-nintersection (list 1 2 3) '(3 2 1) :test #'equal) '(1 2 3)))) (ert-deftest cl-set-difference-test () @@ -961,47 +961,49 @@ Additionally register an `ert-info' to help identify test failures." (ert-deftest cl-nset-difference () ;; Our nset-difference doesn't preserve order. - (let* ((l1 (list 1 2 3 4)) (l2 '(3 4 5 6)) + (let* ((l1 (list 1 2 3 4)) (l2 (list 3 4 5 6)) (diff (cl-nset-difference l1 l2))) (should (memq 1 diff)) (should (memq 2 diff)) - (should (= (length diff) 2)) + (should (length= diff 2)) (should (equal l2 '(3 4 5 6)))) - (let* ((l1 (list "1" "2" "3" "4")) (l2 '("3" "4" "5" "6")) + (let* ((l1 (list "1" "2" "3" "4")) (l2 (list "3" "4" "5" "6")) (diff (cl-nset-difference l1 l2 :test #'equal))) (should (member "1" diff)) (should (member "2" diff)) - (should (= (length diff) 2)) + (should (length= diff 2)) (should (equal l2 '("3" "4" "5" "6")))) (let* ((l1 (list '(a . 1) '(b . 2) '(c . 3) '(d . 4))) (l2 (list '(c . 3) '(d . 4) '(e . 5) '(f . 6))) (diff (cl-nset-difference l1 l2 :key #'car))) (should (member '(a . 1) diff)) (should (member '(b . 2) diff)) - (should (= (length diff) 2))) + (should (length= diff 2)) + (should (equal l2 '((c . 3) (d . 4) (e . 5) (f . 6))))) (let* ((l1 (list '("a" . 1) '("b" . 2) '("c" . 3) '("d" . 4))) (l2 (list '("c" . 3) '("d" . 4) '("e" . 5) '("f" . 6))) (diff (cl-nset-difference l1 l2 :key #'car :test #'string=))) (should (member '("a" . 1) diff)) (should (member '("b" . 2) diff)) - (should (= (length diff) 2)))) + (should (length= diff 2)) + (should (equal l2 '(("c" . 3) ("d" . 4) ("e" . 5) ("f" . 6)))))) (ert-deftest cl-nset-difference-test () (should-not (cl-nset-difference () ())) (should-not (cl-nset-difference () (list 1 2 3))) - (should-not (cl-nset-difference (list 1 2 3) (list 1 2 3))) - (should-not (cl-nset-difference (list 1 2 3) (list 3 2 1) :test #'equal)) + (should-not (cl-nset-difference (list 1 2 3) '(1 2 3))) + (should-not (cl-nset-difference (list 1 2 3) '(3 2 1) :test #'equal)) (should (equal (cl-nset-difference (list 1 2 3) ()) '(1 2 3))) - (should (equal (cl-nset-difference (list 1 2 3 4) (list 3 4 5 6)) + (should (equal (cl-nset-difference (list 1 2 3 4) '(3 4 5 6)) '(1 2))) - (should (equal (cl-nset-difference (list 1 1 2 2 3) (list 3 4 5)) + (should (equal (cl-nset-difference (list 1 1 2 2 3) '(3 4 5)) '(1 1 2 2))) - (should (equal (cl-nset-difference (list 1 2 3) (list 3 2 4)) + (should (equal (cl-nset-difference (list 1 2 3) '(3 2 4)) '(1))) - (should (equal (cl-nset-difference (list 1 2 3 4 5) (list 3 4 5 6 7)) + (should (equal (cl-nset-difference (list 1 2 3 4 5) '(3 4 5 6 7)) '(1 2))) - (should (equal (cl-nset-difference (list 1 (copy-sequence "a")) (list 1 "a")) + (should (equal (cl-nset-difference (list 1 (copy-sequence "a")) '(1 "a")) '("a")))) (ert-deftest cl-set-exclusive-or-test () From 2b68e3f48b81dd0303f3f7e83f8c62ebc26e87df Mon Sep 17 00:00:00 2001 From: "Basil L. Contovounesios" Date: Fri, 14 Feb 2025 15:36:19 +0100 Subject: [PATCH 256/279] ; Suppress obsoletion warning in package-x tests. --- test/lisp/emacs-lisp/package-tests.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el index f13ac3fa8d8..b779dcee393 100644 --- a/test/lisp/emacs-lisp/package-tests.el +++ b/test/lisp/emacs-lisp/package-tests.el @@ -826,7 +826,8 @@ but with a different end of line convention (bug#48137)." ;;; Tests for package-x features. -(require 'package-x) +(with-suppressed-warnings ((obsolete package-x)) + (require 'package-x)) (defvar package-x-test--single-archive-entry-1-3 (cons 'simple-single From 7c22f13ba394d47992a0df3678d23b5bd3da3820 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 14 Feb 2025 16:09:32 +0100 Subject: [PATCH 257/279] ; * doc/misc/message.texi (Message Headers): Improve wording. (Bug#72442) --- doc/misc/message.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/misc/message.texi b/doc/misc/message.texi index 418eb14e042..5cad78b4c48 100644 --- a/doc/misc/message.texi +++ b/doc/misc/message.texi @@ -1695,7 +1695,7 @@ result is inserted. Responses to messages have subjects that start with @samp{Re: }. This is @emph{not} an abbreviation of the English word ``response'', but it comes from the Latin ``res'', and means ``in the matter of''. Some -standards-challenged companies have failed to grasp this fact, and have +companies, seemingly allergic to standards, have failed to grasp this fact, and have ``internationalized'' their software to use abominations like @samp{Aw: } (``antwort'') or @samp{Sv: } (``svar'') instead, which is meaningless and evil. However, you may have to deal with users that From b967891088db359fe16ce8317441e930651fb2ea Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Fri, 14 Feb 2025 11:56:19 +0100 Subject: [PATCH 258/279] Correct docstrings describing "Re" alternatives. * lisp/mail/mail-utils.el (mail-re-regexps): Use "Re", not "Re:". * lisp/mail/rmail.el (rmail-re-abbrevs): Here also. --- lisp/mail/mail-utils.el | 2 +- lisp/mail/rmail.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el index 5ddcb4b7686..d7748ffe6aa 100644 --- a/lisp/mail/mail-utils.el +++ b/lisp/mail/mail-utils.el @@ -63,7 +63,7 @@ also the To field, unless this would leave an empty To field." '("RE" "R\u00c9\\.?" "FWD?" "رد" "回复" "回覆" "SV" "Antw\\.?" "VS" "REF" "AW" "ΑΠ" "ΣΧΕΤ" "השב" "Vá" "R" "RIF" "BLS" "RES" "Odp" "YNT" "ATB") - "List of localized \"Re:\" abbreviations in various languages. + "List of localized \"Re\" abbreviations in various languages. Each component can be a regular expression or a simple string. Matching is done case-insensitively. Used to initialize the legacy `rmail-re-abbrevs' and `message-subject-re-regexp' user options." diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index 4b93f379c72..0d657aea8a1 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -537,7 +537,7 @@ Examples: (concat "\\(" (string-join mail-re-regexps "\\|") "\\)") - "Regexp with localized \"Re:\" abbreviations in various languages. + "Regexp with localized \"Re\" abbreviations in various languages. Matching is done case-insensitively. Initialized from `mail-re-regexps', which is easier to customize." :set-after '(mail-re-regexps) From 300bae4f7c75291c1d1af0eced102ce9b1c44000 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 14 Feb 2025 11:25:52 -0500 Subject: [PATCH 259/279] Fix some uses of `%s` for non-strings/names * lisp/files.el (normal-mode, set-auto-mode--apply-alist): * lisp/gnus/nnimap.el (nnimap-command): * lisp/emacs-lisp/bytecomp.el (bytecomp--check-cus-type): Prefer %S over %s for arbitrary sexps and lists. --- lisp/emacs-lisp/bytecomp.el | 26 +++++++++++++------------- lisp/files.el | 6 +++--- lisp/gnus/nnimap.el | 2 +- lisp/vc/diff-mode.el | 3 +++ 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 2ddbb2ec1da..e48cac6c9b1 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -5275,11 +5275,11 @@ FORM is used to provide location, `bytecomp--cus-function' and (and tl (progn (bytecomp--cus-warn - tl "misplaced %s keyword in `%s' type" (car tl) head) + tl "misplaced %S keyword in `%S' type" (car tl) head) t)))))) ((memq head '(choice radio)) (unless tail - (bytecomp--cus-warn type "`%s' without any types inside" head)) + (bytecomp--cus-warn type "`%S' without any types inside" head)) (let ((clauses tail) (constants nil) (tags nil)) @@ -5287,7 +5287,7 @@ FORM is used to provide location, `bytecomp--cus-function' and (let* ((ty (car clauses)) (ty-head (car-safe ty))) (when (and (eq ty-head 'other) (cdr clauses)) - (bytecomp--cus-warn ty "`other' not last in `%s'" head)) + (bytecomp--cus-warn ty "`other' not last in `%S'" head)) (when (memq ty-head '(const other)) (let ((ty-tail (cdr ty)) (val nil)) @@ -5299,13 +5299,13 @@ FORM is used to provide location, `bytecomp--cus-function' and (setq val (car ty-tail))) (when (member val constants) (bytecomp--cus-warn - ty "duplicated value in `%s': `%S'" head val)) + ty "duplicated value in `%S': `%S'" head val)) (push val constants))) (let ((tag (and (consp ty) (plist-get (cdr ty) :tag)))) (when (stringp tag) (when (member tag tags) (bytecomp--cus-warn - ty "duplicated :tag string in `%s': %S" head tag)) + ty "duplicated :tag string in `%S': %S" head tag)) (push tag tags))) (bytecomp--check-cus-type ty)) (setq clauses (cdr clauses))))) @@ -5317,7 +5317,7 @@ FORM is used to provide location, `bytecomp--cus-function' and (bytecomp--check-cus-type ty))) ((memq head '(list group vector set repeat)) (unless tail - (bytecomp--cus-warn type "`%s' without type specs" head)) + (bytecomp--cus-warn type "`%S' without type specs" head)) (dolist (ty tail) (bytecomp--check-cus-type ty))) ((memq head '(alist plist)) @@ -5333,21 +5333,21 @@ FORM is used to provide location, `bytecomp--cus-function' and (val (car tail))) (cond ((or (> n 1) (and value-tag tail)) - (bytecomp--cus-warn type "`%s' with too many values" head)) + (bytecomp--cus-warn type "`%S' with too many values" head)) (value-tag (setq val (cadr value-tag))) ;; ;; This is a useful check but it results in perhaps ;; ;; a bit too many complaints. ;; ((null tail) ;; (bytecomp--cus-warn - ;; type "`%s' without value is implicitly nil" head)) + ;; type "`%S' without value is implicitly nil" head)) ) (when (memq (car-safe val) '(quote function)) - (bytecomp--cus-warn type "`%s' with quoted value: %S" head val)))) + (bytecomp--cus-warn type "`%S' with quoted value: %S" head val)))) ((eq head 'quote) - (bytecomp--cus-warn type "type should not be quoted: %s" (cadr type))) + (bytecomp--cus-warn type "type should not be quoted: %S" (cadr type))) ((memq head invalid-types) - (bytecomp--cus-warn type "`%s' is not a valid type" head)) + (bytecomp--cus-warn type "`%S' is not a valid type" head)) ((or (not (symbolp head)) (keywordp head)) (bytecomp--cus-warn type "irregular type `%S'" head)) ))) @@ -5355,9 +5355,9 @@ FORM is used to provide location, `bytecomp--cus-function' and (bytecomp--cus-warn type "irregular type `%S'" type)) ((memq type '( list cons group vector choice radio const other function-item variable-item set repeat restricted-sexp)) - (bytecomp--cus-warn type "`%s' without arguments" type)) + (bytecomp--cus-warn type "`%S' without arguments" type)) ((memq type invalid-types) - (bytecomp--cus-warn type "`%s' is not a valid type" type)) + (bytecomp--cus-warn type "`%S' is not a valid type" type)) ))) (defun bytecomp--check-cus-face-spec (spec) diff --git a/lisp/files.el b/lisp/files.el index 499f062932f..a71d0c5c9d0 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2970,13 +2970,13 @@ the local variables spec." (let ((enable-local-variables (or (not find-file) enable-local-variables))) ;; FIXME this is less efficient than it could be, since both ;; s-a-m and h-l-v may parse the same regions, looking for "mode:". - (with-demoted-errors "File mode specification error: %s" + (with-demoted-errors "File mode specification error: %S" (set-auto-mode)) ;; `delay-mode-hooks' being non-nil will have prevented the major ;; mode's call to `run-mode-hooks' from calling ;; `hack-local-variables'. In that case, call it now. (when delay-mode-hooks - (with-demoted-errors "File local-variables error: %s" + (with-demoted-errors "File local-variables error: %S" (hack-local-variables 'no-mode)))) ;; Turn font lock off and on, to make sure it takes account of ;; whatever file local variables are relevant to it. @@ -3517,7 +3517,7 @@ extra checks should be done." alist name case-insensitive-p)) (when (and dir-local mode (not (set-auto-mode--dir-local-valid-p mode))) - (message "Ignoring invalid mode `%s'" mode) + (message "Ignoring invalid mode `%S'" mode) (setq mode nil)) (when mode (set-auto-mode-0 mode keep-mode-if-same) diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index f63138300b1..4965e66503a 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -2004,7 +2004,7 @@ Return the server's response to the SELECT or EXAMINE command." (cons t response) (nnheader-report 'nnimap "%s" (mapconcat (lambda (a) - (format "%s" a)) + (format "%S" a)) (car response) " ")) nil))) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 517b3d9f4f3..5906f8a0571 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -1550,6 +1550,9 @@ else cover the whole buffer." (defvar whitespace-style) (defvar whitespace-trailing-regexp) +;; Prevent applying `view-read-only' to diff-mode buffers (bug#75993). +;; We don't derive from `special-mode' because that would inhibit the +;; `self-insert-command' binding of normal keys. (put 'diff-mode 'mode-class 'special) ;;;###autoload (define-derived-mode diff-mode fundamental-mode "Diff" From ac9cf20919c46169a2e3aaa2b75ccb37dd5b5ff1 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Fri, 14 Feb 2025 08:36:24 -0800 Subject: [PATCH 260/279] ; Fix c-ts-common--prev-standalone-sibling * lisp/progmodes/c-ts-common.el: (c-ts-common--prev-standalone-sibling): Fix. --- lisp/progmodes/c-ts-common.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index c3a965b8e94..33365a3921b 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -631,10 +631,10 @@ for determining standlone line." (if treesit-simple-indent-standalone-predicate (funcall treesit-simple-indent-standalone-predicate - parent) + node) (c-ts-common--standalone-predicate parent))))) - (setq node (treesit-node-prev-sibling node 'named)))) - (if (numberp anchor) anchor (treesit-node-start node)))) + (setq node (treesit-node-prev-sibling node 'named))) + (if (numberp anchor) anchor (treesit-node-start node))))) (defun c-ts-common-parent-ignore-preproc (node) "Return the parent of NODE, skipping preproc nodes." From f05ce9e6bbe7202060580c122e033f5e4ac98e90 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 14 Feb 2025 22:46:07 +0100 Subject: [PATCH 261/279] Inline important-return-value declarations in cl-lib.el These declarations are now properly added to 'cl-lib.el' itself, or to 'cl-loaddefs.el'. This means that they will now correctly show up immediately when loading 'cl-lib.el', instead of only after 'cl-macs.el' is pulled in by an autoload. C.f. Bug#76247. I did not considered worth reproducing everywhere the list saying which functions among the below belong to these two categories: 1. Functions that are side-effect-free except for the behavior of functions passed as argument. 2. Functions that mutate and return a list. AFAIU, this is not actionable with our current byte-compiler, i.e. we can't add any extra declarations based on it. However, if the list should be needed at some point, for example due to improvements in the compiler, this commit will be where to find it. In the worst case, and with more work, it's also deducible from the source code itself. * lisp/emacs-lisp/cl-macs.el: Move important-return-value declarations from here... * lisp/emacs-lisp/cl-extra.el (cl-map, cl-maplist, cl-mapcan) (cl-mapcon, cl-some, cl-every, cl-notany, cl-notevery, cl-nreconc): * lisp/emacs-lisp/cl-lib.el (cl-mapcar, cl-adjoin, cl-subst): * lisp/emacs-lisp/cl-seq.el (cl-reduce, cl-remove, cl-remove-if) (cl-remove-if-not, cl-delete, cl-delete-if, cl-delete-if-not) (cl-remove-duplicates, cl-delete-duplicates, cl-substitute) (cl-substitute-if, cl-substitute-if-not, cl-nsubstitute) (cl-nsubstitute-if, cl-nsubstitute-if-not, cl-find, cl-find-if) (cl-find-if-not, cl-position, cl-position-if, cl-position-if-not) (cl-count, cl-count-if, cl-count-if-not, cl-mismatch, cl-search) (cl-sort, cl-stable-sort, cl-merge, cl-member, cl-member-if) (cl-member-if-not, cl-assoc, cl-assoc-if, cl-assoc-if-not, cl-rassoc) (cl-rassoc-if, cl-rassoc-if-not, cl-union, cl-nunion, cl-intersection) (cl-nintersection, cl-set-difference, cl-nset-difference) (cl-set-exclusive-or, cl-nset-exclusive-or, cl-subsetp, cl-subst-if) (cl-subst-if-not, cl-nsubst, cl-nsubst-if, cl-nsubst-if-not, cl-sublis) (cl-nsublis, cl-tree-equal): ...to have them inline here. --- lisp/emacs-lisp/cl-extra.el | 9 ++++++ lisp/emacs-lisp/cl-lib.el | 5 ++- lisp/emacs-lisp/cl-macs.el | 40 ----------------------- lisp/emacs-lisp/cl-seq.el | 63 +++++++++++++++++++++++++++++++++++-- 4 files changed, 74 insertions(+), 43 deletions(-) diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el index 7732a848d3b..62e12217e0d 100644 --- a/lisp/emacs-lisp/cl-extra.el +++ b/lisp/emacs-lisp/cl-extra.el @@ -131,6 +131,7 @@ strings case-insensitively." "Map a FUNCTION across one or more SEQUENCEs, returning a sequence. TYPE is the sequence type to return. \n(fn TYPE FUNCTION SEQUENCE...)" + (declare (important-return-value t)) (let ((cl-res (apply #'cl-mapcar cl-func cl-seq cl-rest))) (and cl-type (cl-coerce cl-res cl-type)))) @@ -140,6 +141,7 @@ TYPE is the sequence type to return. Like `cl-mapcar', except applies to lists and their cdr's rather than to the elements themselves. \n(fn FUNCTION LIST...)" + (declare (important-return-value t)) (if cl-rest (let ((cl-res nil) (cl-args (cons cl-list (copy-sequence cl-rest))) @@ -189,6 +191,7 @@ the elements themselves. (defun cl-mapcan (cl-func cl-seq &rest cl-rest) "Like `cl-mapcar', but nconc's together the values returned by the function. \n(fn FUNCTION SEQUENCE...)" + (declare (important-return-value t)) (if cl-rest (apply #'nconc (apply #'cl-mapcar cl-func cl-seq cl-rest)) (mapcan cl-func cl-seq))) @@ -197,6 +200,7 @@ the elements themselves. (defun cl-mapcon (cl-func cl-list &rest cl-rest) "Like `cl-maplist', but nconc's together the values returned by the function. \n(fn FUNCTION LIST...)" + (declare (important-return-value t)) (apply #'nconc (apply #'cl-maplist cl-func cl-list cl-rest))) ;;;###autoload @@ -207,6 +211,7 @@ same as the first return value of PREDICATE where PREDICATE has a non-nil value. \n(fn PREDICATE SEQ...)" + (declare (important-return-value t)) (if (or cl-rest (nlistp cl-seq)) (catch 'cl-some (apply #'cl-map nil @@ -222,6 +227,7 @@ non-nil value. (defun cl-every (cl-pred cl-seq &rest cl-rest) "Return true if PREDICATE is true of every element of SEQ or SEQs. \n(fn PREDICATE SEQ...)" + (declare (important-return-value t)) (if (or cl-rest (nlistp cl-seq)) (catch 'cl-every (apply #'cl-map nil @@ -236,12 +242,14 @@ non-nil value. (defun cl-notany (cl-pred cl-seq &rest cl-rest) "Return true if PREDICATE is false of every element of SEQ or SEQs. \n(fn PREDICATE SEQ...)" + (declare (important-return-value t)) (not (apply #'cl-some cl-pred cl-seq cl-rest))) ;;;###autoload (defun cl-notevery (cl-pred cl-seq &rest cl-rest) "Return true if PREDICATE is false of some element of SEQ or SEQs. \n(fn PREDICATE SEQ...)" + (declare (important-return-value t)) (not (apply #'cl-every cl-pred cl-seq cl-rest))) ;;;###autoload @@ -589,6 +597,7 @@ too large if positive or too small if negative)." ;;;###autoload (defun cl-nreconc (x y) "Equivalent to (nconc (nreverse X) Y)." + (declare (important-return-value t)) (nconc (nreverse x) y)) ;;;###autoload diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 1ec850cf0e8..883a13e3244 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el @@ -369,6 +369,7 @@ and mapping stops as soon as the shortest list runs out. With just one SEQ, this is like `mapcar'. With several, it is like the Common Lisp `mapcar' function extended to arbitrary sequence types. \n(fn FUNCTION SEQ...)" + (declare (important-return-value t)) (if cl-rest (if (or (cdr cl-rest) (nlistp cl-x) (nlistp (car cl-rest))) (cl--mapcar-many cl-func (cons cl-x cl-rest) 'accumulate) @@ -506,7 +507,8 @@ The elements of LIST are not copied, just the list structure itself." Otherwise, return LIST unmodified. \nKeywords supported: :test :test-not :key \n(fn ITEM LIST [KEYWORD VALUE]...)" - (declare (compiler-macro cl--compiler-macro-adjoin)) + (declare (important-return-value t) + (compiler-macro cl--compiler-macro-adjoin)) (cond ((or (equal cl-keys '(:test eq)) (and (null cl-keys) (not (numberp cl-item)))) (if (memq cl-item cl-list) cl-list (cons cl-item cl-list))) @@ -519,6 +521,7 @@ Otherwise, return LIST unmodified. Return a copy of TREE with all elements `eql' to OLD replaced by NEW. \nKeywords supported: :test :test-not :key \n(fn NEW OLD TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (if (or cl-keys (and (numberp cl-old) (not (integerp cl-old)))) (apply 'cl-sublis (list (cons cl-old cl-new)) cl-tree cl-keys) (cl--do-subst cl-new cl-old cl-tree))) diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 1da218934ab..44fe67b6c85 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3729,46 +3729,6 @@ macro that returns its `&whole' argument." (cl-proclaim '(inline cl-acons cl-map cl-notany cl-notevery cl-revappend cl-nreconc)) - -;;; Things whose return value should probably be used. -(mapc (lambda (x) (function-put x 'important-return-value t)) - '( - ;; Functions that are side-effect-free except for the - ;; behavior of functions passed as argument. - cl-mapcar cl-mapcan cl-maplist cl-map cl-mapcon - cl-reduce - cl-assoc cl-assoc-if cl-assoc-if-not - cl-rassoc cl-rassoc-if cl-rassoc-if-not - cl-member cl-member-if cl-member-if-not - cl-adjoin - cl-mismatch cl-search - cl-find cl-find-if cl-find-if-not - cl-position cl-position-if cl-position-if-not - cl-count cl-count-if cl-count-if-not - cl-remove cl-remove-if cl-remove-if-not - cl-remove-duplicates - cl-subst cl-subst-if cl-subst-if-not - cl-substitute cl-substitute-if cl-substitute-if-not - cl-sublis - cl-union cl-intersection cl-set-difference cl-set-exclusive-or - cl-subsetp - cl-every cl-some cl-notevery cl-notany - cl-tree-equal - - ;; Functions that mutate and return a list. - cl-delete cl-delete-if cl-delete-if-not - cl-delete-duplicates - cl-nsubst cl-nsubst-if cl-nsubst-if-not - cl-nsubstitute cl-nsubstitute-if cl-nsubstitute-if-not - cl-nunion cl-nintersection cl-nset-difference cl-nset-exclusive-or - cl-nreconc cl-nsublis - cl-merge - ;; It's safe to ignore the value of `cl-sort' and `cl-stable-sort' - ;; when used on arrays, but most calls pass lists. - cl-sort cl-stable-sort - )) - - ;;; Types and assertions. ;;;###autoload diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el index 5b4337ad9cb..651de6c4d47 100644 --- a/lisp/emacs-lisp/cl-seq.el +++ b/lisp/emacs-lisp/cl-seq.el @@ -145,6 +145,7 @@ the SEQ moving forward, and the order of arguments to the FUNCTION is also reversed. \n(fn FUNCTION SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:from-end (:start 0) :end :initial-value :key) () (or (listp cl-seq) (setq cl-seq (append cl-seq nil))) (setq cl-seq (cl-subseq cl-seq cl-start cl-end)) @@ -235,6 +236,7 @@ This is a non-destructive function; it makes a copy of SEQ if necessary to avoid corrupting the original SEQ. \nKeywords supported: :test :test-not :key :count :start :end :from-end \n(fn ITEM SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not :count :from-end (:start 0) :end) () (let ((len (length cl-seq))) @@ -282,6 +284,7 @@ This is a non-destructive function; it makes a copy of SEQ if necessary to avoid corrupting the original SEQ. \nKeywords supported: :key :count :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-remove nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -291,6 +294,7 @@ This is a non-destructive function; it makes a copy of SEQ if necessary to avoid corrupting the original SEQ. \nKeywords supported: :key :count :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-remove nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -299,6 +303,7 @@ to avoid corrupting the original SEQ. This is a destructive function; it reuses the storage of SEQ whenever possible. \nKeywords supported: :test :test-not :key :count :start :end :from-end \n(fn ITEM SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not :count :from-end (:start 0) :end) () (let ((len (length cl-seq))) @@ -344,6 +349,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. This is a destructive function; it reuses the storage of SEQ whenever possible. \nKeywords supported: :key :count :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-delete nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -352,6 +358,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. This is a destructive function; it reuses the storage of SEQ whenever possible. \nKeywords supported: :key :count :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-delete nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -359,6 +366,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. "Return a copy of SEQ with all duplicate elements removed. \nKeywords supported: :test :test-not :key :start :end :from-end \n(fn SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--delete-duplicates cl-seq cl-keys t)) ;;;###autoload @@ -366,6 +374,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. "Remove all duplicate elements from SEQ (destructively). \nKeywords supported: :test :test-not :key :start :end :from-end \n(fn SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--delete-duplicates cl-seq cl-keys nil)) (defun cl--delete-duplicates (cl-seq cl-keys cl-copy) @@ -417,6 +426,7 @@ This is a non-destructive function; it makes a copy of SEQ if necessary to avoid corrupting the original SEQ. \nKeywords supported: :test :test-not :key :count :start :end :from-end \n(fn NEW OLD SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not :count (:start 0) :end :from-end) () (if (or (eq cl-old cl-new) @@ -441,6 +451,7 @@ This is a non-destructive function; it makes a copy of SEQ if necessary to avoid corrupting the original SEQ. \nKeywords supported: :key :count :start :end :from-end \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-substitute cl-new nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -450,6 +461,7 @@ This is a non-destructive function; it makes a copy of SEQ if necessary to avoid corrupting the original SEQ. \nKeywords supported: :key :count :start :end :from-end \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-substitute cl-new nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -458,6 +470,7 @@ to avoid corrupting the original SEQ. This is a destructive function; it reuses the storage of SEQ whenever possible. \nKeywords supported: :test :test-not :key :count :start :end :from-end \n(fn NEW OLD SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not :count (:start 0) :end :from-end) () (let* ((cl-seq (if (stringp seq) (string-to-vector seq) seq)) @@ -494,6 +507,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. This is a destructive function; it reuses the storage of SEQ whenever possible. \nKeywords supported: :key :count :start :end :from-end \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-nsubstitute cl-new nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -502,6 +516,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. This is a destructive function; it reuses the storage of SEQ whenever possible. \nKeywords supported: :key :count :start :end :from-end \n(fn NEW PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-nsubstitute cl-new nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -510,6 +525,7 @@ This is a destructive function; it reuses the storage of SEQ whenever possible. Return the matching ITEM, or nil if not found. \nKeywords supported: :test :test-not :key :start :end :from-end \n(fn ITEM SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (let ((cl-pos (apply 'cl-position cl-item cl-seq cl-keys))) (and cl-pos (elt cl-seq cl-pos)))) @@ -519,6 +535,7 @@ Return the matching ITEM, or nil if not found. Return the matching item, or nil if not found. \nKeywords supported: :key :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-find nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -527,6 +544,7 @@ Return the matching item, or nil if not found. Return the matching item, or nil if not found. \nKeywords supported: :key :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-find nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -535,6 +553,7 @@ Return the matching item, or nil if not found. Return the index of the matching item, or nil if not found. \nKeywords supported: :test :test-not :key :start :end :from-end \n(fn ITEM SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end :from-end) () (cl--position cl-item cl-seq cl-start cl-end cl-from-end))) @@ -565,6 +584,7 @@ Return the index of the matching item, or nil if not found. Return the index of the matching item, or nil if not found. \nKeywords supported: :key :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-position nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -573,6 +593,7 @@ Return the index of the matching item, or nil if not found. Return the index of the matching item, or nil if not found. \nKeywords supported: :key :start :end :from-end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-position nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -580,6 +601,7 @@ Return the index of the matching item, or nil if not found. "Count the number of occurrences of ITEM in SEQ. \nKeywords supported: :test :test-not :key :start :end \n(fn ITEM SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end) () (let ((cl-count 0) cl-x) (or cl-end (setq cl-end (length cl-seq))) @@ -595,6 +617,7 @@ Return the index of the matching item, or nil if not found. "Count the number of items satisfying PREDICATE in SEQ. \nKeywords supported: :key :start :end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-count nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -602,6 +625,7 @@ Return the index of the matching item, or nil if not found. "Count the number of items not satisfying PREDICATE in SEQ. \nKeywords supported: :key :start :end \n(fn PREDICATE SEQ [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-count nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -611,6 +635,7 @@ Return nil if the sequences match. If one sequence is a prefix of the other, the return value indicates the end of the shorter sequence. \nKeywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end \n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :from-end (:start1 0) :end1 (:start2 0) :end2) () (or cl-end1 (setq cl-end1 (length cl-seq1))) @@ -642,6 +667,7 @@ Return the index of the leftmost element of the first match found; return nil if there are no matches. \nKeywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end \n(fn SEQ1 SEQ2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :from-end (:start1 0) :end1 (:start2 0) :end2) () (or cl-end1 (setq cl-end1 (length cl-seq1))) @@ -668,6 +694,9 @@ return nil if there are no matches. This is a destructive function; it reuses the storage of SEQ if possible. \nKeywords supported: :key \n(fn SEQ PREDICATE [KEYWORD VALUE]...)" + ;; It's safe to ignore the return value when used on arrays, + ;; but most calls pass lists. + (declare (important-return-value t)) (if (nlistp cl-seq) (if (stringp cl-seq) (concat (apply #'cl-sort (vconcat cl-seq) cl-pred cl-keys)) @@ -686,6 +715,9 @@ This is a destructive function; it reuses the storage of SEQ if possible. This is a destructive function; it reuses the storage of SEQ if possible. \nKeywords supported: :key \n(fn SEQ PREDICATE [KEYWORD VALUE]...)" + ;; It's safe to ignore the return value when used on arrays, + ;; but most calls pass lists. + (declare (important-return-value t)) (apply 'cl-sort cl-seq cl-pred cl-keys)) ;;;###autoload @@ -695,6 +727,7 @@ TYPE is the sequence type to return, SEQ1 and SEQ2 are the two argument sequences, and PREDICATE is a `less-than' predicate on the elements. \nKeywords supported: :key \n(fn TYPE SEQ1 SEQ2 PREDICATE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (or (listp cl-seq1) (setq cl-seq1 (append cl-seq1 nil))) (or (listp cl-seq2) (setq cl-seq2 (append cl-seq2 nil))) (cl--parsing-keywords (:key) () @@ -712,7 +745,8 @@ sequences, and PREDICATE is a `less-than' predicate on the elements. Return the sublist of LIST whose car is ITEM. \nKeywords supported: :test :test-not :key \n(fn ITEM LIST [KEYWORD VALUE]...)" - (declare (compiler-macro cl--compiler-macro-member)) + (declare (important-return-value t) + (compiler-macro cl--compiler-macro-member)) (if cl-keys (cl--parsing-keywords (:test :test-not :key :if :if-not) () (while (and cl-list (not (cl--check-test cl-item (car cl-list)))) @@ -727,6 +761,7 @@ Return the sublist of LIST whose car is ITEM. Return the sublist of LIST whose car matches. \nKeywords supported: :key \n(fn PREDICATE LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-member nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -735,6 +770,7 @@ Return the sublist of LIST whose car matches. Return the sublist of LIST whose car matches. \nKeywords supported: :key \n(fn PREDICATE LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-member nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -749,7 +785,8 @@ Return the sublist of LIST whose car matches. "Find the first item whose car matches ITEM in LIST. \nKeywords supported: :test :test-not :key \n(fn ITEM LIST [KEYWORD VALUE]...)" - (declare (compiler-macro cl--compiler-macro-assoc)) + (declare (important-return-value t) + (compiler-macro cl--compiler-macro-assoc)) (if cl-keys (cl--parsing-keywords (:test :test-not :key :if :if-not) () (while (and cl-alist @@ -767,6 +804,7 @@ Return the sublist of LIST whose car matches. "Find the first item whose car satisfies PREDICATE in LIST. \nKeywords supported: :key \n(fn PREDICATE LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-assoc nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -774,6 +812,7 @@ Return the sublist of LIST whose car matches. "Find the first item whose car does not satisfy PREDICATE in LIST. \nKeywords supported: :key \n(fn PREDICATE LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-assoc nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -781,6 +820,7 @@ Return the sublist of LIST whose car matches. "Find the first item whose cdr matches ITEM in LIST. \nKeywords supported: :test :test-not :key \n(fn ITEM LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (if (or cl-keys (numberp cl-item)) (cl--parsing-keywords (:test :test-not :key :if :if-not) () (while (and cl-alist @@ -795,6 +835,7 @@ Return the sublist of LIST whose car matches. "Find the first item whose cdr satisfies PREDICATE in LIST. \nKeywords supported: :key \n(fn PREDICATE LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-rassoc nil cl-list :if cl-pred cl-keys)) ;;;###autoload @@ -802,6 +843,7 @@ Return the sublist of LIST whose car matches. "Find the first item whose cdr does not satisfy PREDICATE in LIST. \nKeywords supported: :key \n(fn PREDICATE LIST [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-rassoc nil cl-list :if-not cl-pred cl-keys)) ;;;###autoload @@ -812,6 +854,7 @@ This is a non-destructive function; it makes a copy of the data if necessary to avoid corrupting the original LIST1 and LIST2. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) ((and (not cl-keys) (equal cl-list1 cl-list2)) cl-list1) (t @@ -834,6 +877,7 @@ This is a destructive function; it reuses the storage of LIST1 and LIST2 whenever possible. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) (t (apply 'cl-union cl-list1 cl-list2 cl-keys)))) @@ -845,6 +889,7 @@ This is a non-destructive function; it makes a copy of the data if necessary to avoid corrupting the original LIST1 and LIST2. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (and cl-list1 cl-list2 (if (equal cl-list1 cl-list2) cl-list1 (cl--parsing-keywords (:key) (:test :test-not) @@ -868,6 +913,7 @@ This is a destructive function; it reuses the storage of LIST1 (but not LIST2) whenever possible. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (and cl-list1 cl-list2 (apply 'cl-intersection cl-list1 cl-list2 cl-keys))) ;;;###autoload @@ -878,6 +924,7 @@ This is a non-destructive function; it makes a copy of the data if necessary to avoid corrupting the original LIST1 and LIST2. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (if (or (null cl-list1) (null cl-list2)) cl-list1 (cl--parsing-keywords (:key) (:test :test-not) (let ((cl-res nil)) @@ -898,6 +945,7 @@ This is a destructive function; it reuses the storage of LIST1 (but not LIST2) whenever possible. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (if (or (null cl-list1) (null cl-list2)) cl-list1 (apply 'cl-set-difference cl-list1 cl-list2 cl-keys))) @@ -909,6 +957,7 @@ This is a non-destructive function; it makes a copy of the data if necessary to avoid corrupting the original LIST1 and LIST2. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) ((equal cl-list1 cl-list2) nil) (t (append (apply 'cl-set-difference cl-list1 cl-list2 cl-keys) @@ -922,6 +971,7 @@ This is a destructive function; it reuses the storage of LIST1 and LIST2 whenever possible. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) ((equal cl-list1 cl-list2) nil) (t (nconc (apply 'cl-nset-difference cl-list1 cl-list2 cl-keys) @@ -933,6 +983,7 @@ whenever possible. I.e., if every element of LIST1 also appears in LIST2. \nKeywords supported: :test :test-not :key \n(fn LIST1 LIST2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cond ((null cl-list1) t) ((null cl-list2) nil) ((equal cl-list1 cl-list2) t) (t (cl--parsing-keywords (:key) (:test :test-not) @@ -948,6 +999,7 @@ I.e., if every element of LIST1 also appears in LIST2. Return a copy of TREE with all matching elements replaced by NEW. \nKeywords supported: :key \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-sublis (list (cons nil cl-new)) cl-tree :if cl-pred cl-keys)) ;;;###autoload @@ -956,6 +1008,7 @@ Return a copy of TREE with all matching elements replaced by NEW. Return a copy of TREE with all non-matching elements replaced by NEW. \nKeywords supported: :key \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-sublis (list (cons nil cl-new)) cl-tree :if-not cl-pred cl-keys)) ;;;###autoload @@ -965,6 +1018,7 @@ Any element of TREE which is `eql' to OLD is changed to NEW (via a call to `setcar'). \nKeywords supported: :test :test-not :key \n(fn NEW OLD TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-nsublis (list (cons cl-old cl-new)) cl-tree cl-keys)) ;;;###autoload @@ -973,6 +1027,7 @@ to `setcar'). Any element of TREE which matches is changed to NEW (via a call to `setcar'). \nKeywords supported: :key \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-nsublis (list (cons nil cl-new)) cl-tree :if cl-pred cl-keys)) ;;;###autoload @@ -981,6 +1036,7 @@ Any element of TREE which matches is changed to NEW (via a call to `setcar'). Any element of TREE which matches is changed to NEW (via a call to `setcar'). \nKeywords supported: :key \n(fn NEW PREDICATE TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (apply 'cl-nsublis (list (cons nil cl-new)) cl-tree :if-not cl-pred cl-keys)) (defvar cl--alist) @@ -991,6 +1047,7 @@ Any element of TREE which matches is changed to NEW (via a call to `setcar'). Return a copy of TREE with all matching elements replaced. \nKeywords supported: :test :test-not :key \n(fn ALIST TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not) () (let ((cl--alist cl-alist)) (cl--sublis-rec cl-tree)))) @@ -1014,6 +1071,7 @@ Return a copy of TREE with all matching elements replaced. Any matching element of TREE is changed via a call to `setcar'. \nKeywords supported: :test :test-not :key \n(fn ALIST TREE [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key :if :if-not) () (let ((cl-hold (list cl-tree)) (cl--alist cl-alist)) @@ -1040,6 +1098,7 @@ Any matching element of TREE is changed via a call to `setcar'. Atoms are compared by `eql'; cons cells are compared recursively. \nKeywords supported: :test :test-not :key \n(fn TREE1 TREE2 [KEYWORD VALUE]...)" + (declare (important-return-value t)) (cl--parsing-keywords (:test :test-not :key) () (cl--tree-equal-rec cl-x cl-y))) From dc86f59e926f618d4e3568a332b42ea0647a08ba Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Sat, 15 Feb 2025 00:40:52 +0100 Subject: [PATCH 262/279] Prefer `(defsubst A ...)` to `(cl-proclaim (inline A))` * lisp/emacs-lisp/cl-macs.el: Remove cl-proclaim... * lisp/emacs-lisp/cl-extra.el (cl-map, cl-notany, cl-notevery) (cl-revappend, cl-nreconc): * lisp/emacs-lisp/cl-lib.el (cl-acons): ...and use defsubst instead. (Bug#76294) --- lisp/emacs-lisp/cl-extra.el | 10 +++++----- lisp/emacs-lisp/cl-lib.el | 2 +- lisp/emacs-lisp/cl-macs.el | 4 ---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el index 62e12217e0d..09470457d93 100644 --- a/lisp/emacs-lisp/cl-extra.el +++ b/lisp/emacs-lisp/cl-extra.el @@ -127,7 +127,7 @@ strings case-insensitively." (and acc (nreverse cl-res))))) ;;;###autoload -(defun cl-map (cl-type cl-func cl-seq &rest cl-rest) +(defsubst cl-map (cl-type cl-func cl-seq &rest cl-rest) "Map a FUNCTION across one or more SEQUENCEs, returning a sequence. TYPE is the sequence type to return. \n(fn TYPE FUNCTION SEQUENCE...)" @@ -239,14 +239,14 @@ non-nil value. (null cl-seq))) ;;;###autoload -(defun cl-notany (cl-pred cl-seq &rest cl-rest) +(defsubst cl-notany (cl-pred cl-seq &rest cl-rest) "Return true if PREDICATE is false of every element of SEQ or SEQs. \n(fn PREDICATE SEQ...)" (declare (important-return-value t)) (not (apply #'cl-some cl-pred cl-seq cl-rest))) ;;;###autoload -(defun cl-notevery (cl-pred cl-seq &rest cl-rest) +(defsubst cl-notevery (cl-pred cl-seq &rest cl-rest) "Return true if PREDICATE is false of some element of SEQ or SEQs. \n(fn PREDICATE SEQ...)" (declare (important-return-value t)) @@ -589,13 +589,13 @@ too large if positive or too small if negative)." ;;; List functions. ;;;###autoload -(defun cl-revappend (x y) +(defsubst cl-revappend (x y) "Equivalent to (append (reverse X) Y)." (declare (side-effect-free t)) (nconc (reverse x) y)) ;;;###autoload -(defun cl-nreconc (x y) +(defsubst cl-nreconc (x y) "Equivalent to (nconc (nreverse X) Y)." (declare (important-return-value t)) (nconc (nreverse x) y)) diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 883a13e3244..dba01b28325 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el @@ -535,7 +535,7 @@ Return a copy of TREE with all elements `eql' to OLD replaced by NEW. cl-tree (cons a d)))) (t cl-tree))) -(defun cl-acons (key value alist) +(defsubst cl-acons (key value alist) "Add KEY and VALUE to ALIST. Return a new list with (cons KEY VALUE) as car and ALIST as cdr." (declare (side-effect-free error-free)) diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index 44fe67b6c85..caaffcf19be 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3725,10 +3725,6 @@ macro that returns its `&whole' argument." `(cl-getf (symbol-plist ,sym) ,prop ,def) `(get ,sym ,prop))) -;;; Things that are inline. -(cl-proclaim '(inline cl-acons cl-map cl-notany cl-notevery cl-revappend - cl-nreconc)) - ;;; Types and assertions. ;;;###autoload From b58552ca983ad37e51fb375bd45bd12a2beda3b2 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Fri, 14 Feb 2025 17:44:02 -0800 Subject: [PATCH 263/279] ; Another attempt at fixing c-ts-common--prev-standalone-sibling * lisp/progmodes/c-ts-common.el: (c-ts-common--prev-standalone-sibling): Fix. --- lisp/progmodes/c-ts-common.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 33365a3921b..7ebd0770a5d 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -632,7 +632,7 @@ for determining standlone line." (funcall treesit-simple-indent-standalone-predicate node) - (c-ts-common--standalone-predicate parent))))) + (c-ts-common--standalone-predicate node))))) (setq node (treesit-node-prev-sibling node 'named))) (if (numberp anchor) anchor (treesit-node-start node))))) From 8d968c0f22347c9a4b65fdd142c0f050db918745 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 14 Feb 2025 23:05:29 -0500 Subject: [PATCH 264/279] lisp/term/xterm.el (xterm--query-name-and-version): Don't quote lambda --- lisp/term/xterm.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index 15101ebd59d..4f23a909b69 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el @@ -912,10 +912,10 @@ We run the first FUNCTION whose STRING matches the input events." (catch 'result (xterm--query "\e[>0q" - '(("\eP>|" . (lambda () - ;; The reply should be: \e P > | STRING \e \\ - (let ((str (xterm--read-string ?\e ?\\))) - (throw 'result str)))))) + `(("\eP>|" . ,(lambda () + ;; The reply should be: \e P > | STRING \e \\ + (let ((str (xterm--read-string ?\e ?\\))) + (throw 'result str)))))) nil))) (defun xterm--push-map (map basemap) From 18ebbba6c422617a16cc36082a8ba871b5bfce2c Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 14 Feb 2025 23:28:52 -0500 Subject: [PATCH 265/279] (smerge-refine-exchange-point): New command * lisp/vc/smerge-mode.el (smerge--refine-highlight-change): Allow empty region and always create an overlay. Also, remember any adjustment we applied the overlay's boundaries. (smerge-refine-regions): Always create two overlays per hunk and "connect" them via `smerge--refine-other`. (smerge-refine-exchange-point): New command. --- etc/NEWS | 5 ++ lisp/vc/smerge-mode.el | 170 +++++++++++++++++++++++++++++++---------- 2 files changed, 133 insertions(+), 42 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 31109f0857c..51f481c763c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -434,6 +434,11 @@ default is nil, which retains the old format. *** New command 'smerge-extend' extends a conflict over surrounding lines. +*** New command 'smerge-refine-exchange-point' to jump to the other side. +When used inside a refined chunk, it jumps to the matching position in +the "other" side of the refinement: if you're in the new text, it jumps +to the corresponding position in the old text and vice versa. + ** Image Dired *** 'image-dired-show-all-from-dir' takes the same first argument as 'dired'. diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el index 5d172238a60..bce5822a042 100644 --- a/lisp/vc/smerge-mode.el +++ b/lisp/vc/smerge-mode.el @@ -505,6 +505,8 @@ This relies on mode-specific knowledge and thus only works in some major modes. Uses `smerge-resolve-function' to do the actual work." (interactive) (smerge-match-conflict) + ;; FIXME: This ends up removing the refinement-highlighting when no + ;; resolution is performed. (smerge-remove-props (match-beginning 0) (match-end 0)) (let ((md (match-data)) (m0b (match-beginning 0)) @@ -526,13 +528,12 @@ major modes. Uses `smerge-resolve-function' to do the actual work." (eq (match-beginning 1) (match-beginning 3))) (smerge-keep-n 3)) ;; Mode-specific conflict resolution. - ((condition-case nil - (atomic-change-group - (if safe - (funcall smerge-resolve-function safe) - (funcall smerge-resolve-function)) - t) - (error nil)) + ((ignore-errors + (atomic-change-group + (if safe + (funcall smerge-resolve-function safe) + (funcall smerge-resolve-function)) + t)) ;; Nothing to do: the resolution function has done it already. nil) ;; Non-conflict. @@ -653,11 +654,9 @@ major modes. Uses `smerge-resolve-function' to do the actual work." (save-excursion (goto-char (point-min)) (while (re-search-forward smerge-begin-re nil t) - (condition-case nil - (progn - (smerge-match-conflict) - (smerge-resolve 'safe)) - (error nil))))) + (with-demoted-errors "%S" + (smerge-match-conflict) + (smerge-resolve 'safe))))) (defun smerge-batch-resolve () ;; command-line-args-left is what is left of the command line. @@ -1038,25 +1037,62 @@ chars to try and eliminate some spurious differences." smerge-refine-forward-function) startline) (point))) - (end (progn (funcall (if smerge-refine-weight-hack - #'forward-char - smerge-refine-forward-function) - (if match-num2 - (- (string-to-number match-num2) - startline) - 1)) - (point)))) - (when smerge-refine-ignore-whitespace - (skip-chars-backward " \t\n" beg) (setq end (point)) - (goto-char beg) - (skip-chars-forward " \t\n" end) (setq beg (point))) - (when (> end beg) + (end (if (eq t match-num2) beg + (funcall (if smerge-refine-weight-hack + #'forward-char + smerge-refine-forward-function) + (if match-num2 + (- (string-to-number match-num2) + startline) + 1)) + (point)))) + (cl-assert (<= beg end)) + (when (and (eq t match-num2) (not (eolp))) + ;; FIXME: No idea where this off-by-one comes from, nor why it's only + ;; within lines. + (setq beg (1+ beg)) + (setq end (1+ end)) + (goto-char end)) + (let ((olbeg beg) + (olend end)) + (cond + ((> end beg) + (when smerge-refine-ignore-whitespace + (let* ((newend (progn (skip-chars-backward " \t\n" beg) (point))) + (newbeg (progn (goto-char beg) + (skip-chars-forward " \t\n" newend) (point)))) + (unless (= newend newbeg) + (push `(smerge--refine-adjust ,(- newbeg beg) . ,(- end newend)) + props) + (setq olend newend) + (setq olbeg newbeg))))) + (t + (cl-assert (= end beg)) + ;; If BEG=END, we have nothing to highlight, but we still want + ;; to create an overlay that we can find with char properties, + ;; so as to keep track of the position where a text was + ;; inserted/deleted, so make it span at a char. + (push (cond + ((< beg (point-max)) + (setq olend (1+ beg)) + '(smerge--refine-adjust 0 . -1)) + (t (cl-assert (< (point-min) end)) + (setq olbeg (1- end)) + '(smerge--refine-adjust -1 . 0))) + props))) + (let ((ol (make-overlay - beg end nil + olbeg olend nil ;; Make them tend to shrink rather than spread when editing. 'front-advance nil))) + ;; (overlay-put ol 'smerge--debug + ;; (list match-num1 match-num2 startline)) (overlay-put ol 'evaporate t) - (dolist (x props) (overlay-put ol (car x) (cdr x))) + (dolist (x props) + (when (or (> end beg) + ;; Don't highlight the char we cover artificially. + (not (memq (car-safe x) '(face font-lock-face)))) + (overlay-put ol (car x) (cdr x)))) ol))))) ;;;###autoload @@ -1118,20 +1154,20 @@ used to replace chars to try and eliminate some spurious differences." (m2 (match-string 2)) (m4 (match-string 4)) (m5 (match-string 5))) - (when (memq op '(?d ?c)) - (setq last1 - (smerge--refine-highlight-change - beg1 m1 m2 - ;; Try to use props-c only for changed chars, - ;; fallback to props-r for changed/removed chars, - ;; but if props-r is nil then fallback to props-c. - (or (and (eq op '?c) props-c) props-r props-c)))) - (when (memq op '(?a ?c)) - (setq last2 - (smerge--refine-highlight-change - beg2 m4 m5 - ;; Same logic as for removed chars above. - (or (and (eq op '?c) props-c) props-a props-c))))) + (setq last1 + (smerge--refine-highlight-change + beg1 m1 (if (eq op ?a) t m2) + ;; Try to use props-c only for changed chars, + ;; fallback to props-r for changed/removed chars, + ;; but if props-r is nil then fallback to props-c. + (or (and (eq op '?c) props-c) props-r props-c))) + (setq last2 + (smerge--refine-highlight-change + beg2 m4 (if (eq op ?d) t m5) + ;; Same logic as for removed chars above. + (or (and (eq op '?c) props-c) props-a props-c)))) + (overlay-put last1 'smerge--refine-other last2) + (overlay-put last2 'smerge--refine-other last1) (forward-line 1) ;Skip hunk header. (and (re-search-forward "^[0-9]" nil 'move) ;Skip hunk body. (goto-char (match-beginning 0)))) @@ -1206,6 +1242,54 @@ repeating the command will highlight other two parts." (unless smerge-use-changed-face '((smerge . refine) (font-lock-face . smerge-refined-added)))))) +(defun smerge-refine-exchange-point () + "Go to the matching position in the other chunk." + (interactive) + ;; FIXME: Chunks aren't marked in the same way for all users of + ;; `smerge-refine-regions' :-( + ;; (unless (get-char-property (point) 'smerge) + ;; (error "Not inside a refined chunk")) + (let* ((ref-pos + (if (or (get-char-property (point) 'smerge--refine-other) + (get-char-property (1- (point)) 'smerge--refine-other)) + (point) + ;; FIXME: Bound the search to the current chunk! + (let ((next (next-single-char-property-change + (point) 'smerge--refine-other)) + (prev (previous-single-char-property-change + (point) 'smerge--refine-other))) + (cond + ((and prev + (or (null next) + (> (- next (point)) (- (point) prev)))) + prev) + (t (or next + ;; FIXME: default to the bounds! + (user-error "No \"other\" position info found"))))))) + (boundary + (cond + ((< ref-pos (point)) + (let ((adjust (get-char-property (1- ref-pos) + 'smerge--refine-adjust))) + (min (point) (+ ref-pos (or (cdr adjust) 0))))) + ((> ref-pos (point)) + (let ((adjust (get-char-property ref-pos 'smerge--refine-adjust))) + (max (point) (- ref-pos (or (car adjust) 0))))) + (t ref-pos))) + (other-forw (get-char-property ref-pos 'smerge--refine-other)) + (other-back (get-char-property (1- ref-pos) 'smerge--refine-other)) + (other (or other-forw other-back)) + (dist (- boundary (point)))) + (if (not (overlay-start other)) + (user-error "The \"other\" position has vanished") + (goto-char + (- (if other-forw + (- (overlay-start other) + (or (car (overlay-get other 'smerge--refine-adjust)) 0)) + (+ (overlay-end other) + (or (cdr (overlay-get other 'smerge--refine-adjust)) 0))) + dist))))) + (defun smerge-swap () ;; FIXME: Extend for diff3 to allow swapping the middle end as well. "Swap the \"Upper\" and the \"Lower\" chunks. @@ -1470,7 +1554,9 @@ with a \\[universal-argument] prefix, makes up a 3-way conflict." (goto-char (point-min)) (while (smerge-find-conflict) (save-excursion - (font-lock-fontify-region (match-beginning 0) (match-end 0) nil))))) + (with-demoted-errors "%S" ;Those things do happen, occasionally. + (font-lock-fontify-region + (match-beginning 0) (match-end 0) nil)))))) (if (string-match (regexp-quote smerge-parsep-re) paragraph-separate) (unless smerge-mode (setq-local paragraph-separate From fe04b4fc27d50b7087ee622281672866dbf87818 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 15 Feb 2025 00:39:54 -0500 Subject: [PATCH 266/279] (smerge-refine-exchange-point): Error cleanly outside refinement * lisp/vc/smerge-mode.el (smerge-refine-regions): Cover each region with an overlay. (smerge-refine-exchange-point): Use it to detect more reliably that we're not inside a refined region. --- lisp/vc/smerge-mode.el | 52 +++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el index bce5822a042..f77b73c6170 100644 --- a/lisp/vc/smerge-mode.el +++ b/lisp/vc/smerge-mode.el @@ -1116,6 +1116,29 @@ used to replace chars to try and eliminate some spurious differences." (file2 (make-temp-file "diff2")) (smerge--refine-long-words (if smerge-refine-weight-hack (make-hash-table :test #'equal)))) + + ;; Cover the two regions with one `smerge--refine-region' overlay each. + (let ((ol1 (make-overlay beg1 end1 nil + ;; Make it shrink rather than spread when editing. + 'front-advance nil)) + (ol2 (make-overlay beg2 end2 nil + ;; Make it shrink rather than spread when editing. + 'front-advance nil)) + (common-props '((evaporate . t) (smerge--refine-region . t)))) + (dolist (prop (or props-a props-c)) + (when (and (not (memq (car prop) '(face font-lock-face))) + (member prop (or props-r props-c)) + (or (not (and props-c props-a props-r)) + (member prop props-c))) + ;; This PROP is shared among all those overlays. + ;; Better keep it also for the `smerge--refine-region' overlays, + ;; so the client package recognizes them as being part of the + ;; refinement (e.g. it will hopefully delete them like the others). + (push prop common-props))) + (dolist (prop common-props) + (overlay-put ol1 (car prop) (cdr prop)) + (overlay-put ol2 (car prop) (cdr prop)))) + (unless (markerp beg1) (setq beg1 (copy-marker beg1))) (unless (markerp beg2) (setq beg2 (copy-marker beg2))) (let ((write-region-inhibit-fsync t)) ; Don't fsync temp files (Bug#12747). @@ -1245,27 +1268,30 @@ repeating the command will highlight other two parts." (defun smerge-refine-exchange-point () "Go to the matching position in the other chunk." (interactive) - ;; FIXME: Chunks aren't marked in the same way for all users of - ;; `smerge-refine-regions' :-( - ;; (unless (get-char-property (point) 'smerge) - ;; (error "Not inside a refined chunk")) - (let* ((ref-pos + (let* ((covering-ol + (let ((ols (overlays-at (point)))) + (while (and ols (not (overlay-get (car ols) + 'smerge--refine-region))) + (pop ols)) + (or (car ols) + (user-error "Not inside a refined region")))) + (ref-pos (if (or (get-char-property (point) 'smerge--refine-other) (get-char-property (1- (point)) 'smerge--refine-other)) (point) - ;; FIXME: Bound the search to the current chunk! (let ((next (next-single-char-property-change - (point) 'smerge--refine-other)) + (point) 'smerge--refine-other nil + (overlay-end covering-ol))) (prev (previous-single-char-property-change - (point) 'smerge--refine-other))) + (point) 'smerge--refine-other nil + (overlay-start covering-ol)))) (cond - ((and prev - (or (null next) + ((and (> prev (overlay-start covering-ol)) + (or (>= next (overlay-end covering-ol)) (> (- next (point)) (- (point) prev)))) prev) - (t (or next - ;; FIXME: default to the bounds! - (user-error "No \"other\" position info found"))))))) + ((< next (overlay-end covering-ol)) next) + (t (user-error "No \"other\" position info found")))))) (boundary (cond ((< ref-pos (point)) From 81ca9c75f1170f2b4cc85c69e859f68da4c508e4 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Feb 2025 14:46:37 +0800 Subject: [PATCH 267/279] ; * etc/PROBLEMS: Document how to grant storage permissions on Wear OS. --- etc/PROBLEMS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 1f44c38ee3a..54e0c3ffd1e 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -3823,6 +3823,16 @@ devices manufactured by OnePlus and possibly others. Sadly, to the best of our knowledge such events cannot be distinguished from legitimate keypresses. +** Emacs crashes or is not acknowledged by the OS when requesting storage permissions. + +This is only possible on Wear OS (an Android distribution), where the +system component that provides confirmation dialogs for this type of +permission is unavailable. You may circumvent this component by +connecting to your device over ADB as in the preceding entries and +executing: + + $ adb shell appops set --uid org.gnu.emacs MANAGE_EXTERNAL_STORAGE allow + * Build-time problems ** Configuration From 58e4bfe3408f5f4562bf02ac200b680329f487c2 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 15 Feb 2025 16:58:18 +0800 Subject: [PATCH 268/279] Add two missing NULL checks of malloc'd values on Android * src/android.c (sendDndUri, sendDndText): Verify that allocated string memory is non-nil before writing to it. --- src/android.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/android.c b/src/android.c index 0234fd50f69..c20730460be 100644 --- a/src/android.c +++ b/src/android.c @@ -2530,6 +2530,11 @@ NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object, length = (*env)->GetStringLength (env, string); buffer = malloc (length * sizeof *buffer); + + /* Out of memory. */ + if (!buffer) + return 0; + characters = (*env)->GetStringChars (env, string, NULL); if (!characters) @@ -2567,6 +2572,11 @@ NATIVE_NAME (sendDndText) (JNIEnv *env, jobject object, length = (*env)->GetStringLength (env, string); buffer = malloc (length * sizeof *buffer); + + /* Out of memory. */ + if (!buffer) + return 0; + characters = (*env)->GetStringChars (env, string, NULL); if (!characters) From 0f768b8843bcdbbfa1c64aeee64d2de7d62c0d13 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 15 Feb 2025 13:15:36 +0200 Subject: [PATCH 269/279] Prevent buffer overflow in line-numbering code * src/xdisp.c (maybe_produce_line_number): Limit the value of 'display-line-numbers-width' to what can be shown in the window, and set dimension of the lnum_buf[] accordingly. (Bug#75969) --- src/xdisp.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/xdisp.c b/src/xdisp.c index c9bcafe57fd..0de5aee86dd 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -25008,7 +25008,6 @@ maybe_produce_line_number (struct it *it) /* Produce the glyphs for the line number. */ struct it tem_it; - char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1]; bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE; ptrdiff_t lnum_offset = -1; /* to produce 1-based line numbers */ int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID); @@ -25037,7 +25036,17 @@ maybe_produce_line_number (struct it *it) if (!it->lnum_width) { if (FIXNATP (Vdisplay_line_numbers_width)) - it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width); + { + EMACS_INT lnum_width = XFIXNAT (Vdisplay_line_numbers_width); + /* Limit the width to show at least 1 text character. */ + int lnum_width_limit + = (it->last_visible_x - it->first_visible_x) + / FRAME_COLUMN_WIDTH (it->f) + - 5 /* leave space for a few characters */ + - 2; /* two spaces around the number */ + it->lnum_width + = clip_to_bounds (1, lnum_width, lnum_width_limit); + } /* Max line number to be displayed cannot be more than the one corresponding to the last row of the desired matrix. */ @@ -25057,6 +25066,8 @@ maybe_produce_line_number (struct it *it) it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1); eassert (it->lnum_width > 0); } + /* Extra +2 for the two blanks we add before and after the number. */ + char *lnum_buf = alloca (it->lnum_width + 2 + 1); if (EQ (Vdisplay_line_numbers, Qrelative)) lnum_offset = it->pt_lnum; else if (EQ (Vdisplay_line_numbers, Qvisual)) From 6491fee366f58a831689c57aa31493dd70bc2245 Mon Sep 17 00:00:00 2001 From: kobarity Date: Mon, 13 Jan 2025 22:38:42 +0900 Subject: [PATCH 270/279] Fix string end search in python-nav-end-of-statement * lisp/progmodes/python.el (python-nav-end-of-statement): Change to look for string delimiter characters and check syntax, instead of looking for string-delimiter syntax. * test/lisp/progmodes/python-tests.el (python-nav-end-of-statement-5): New test. (Bug#75387) --- lisp/progmodes/python.el | 7 +++++-- test/lisp/progmodes/python-tests.el | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 8a99ff0434d..a42e2b2a28a 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -2328,8 +2328,11 @@ of the statement." (setq last-string-end (or (if (eq t (nth 3 (syntax-ppss))) - (re-search-forward - (rx (syntax string-delimiter)) nil t) + (cl-loop + while (re-search-forward + (rx (or "\"\"\"" "'''")) nil t) + unless (python-syntax-context 'string) + return (point)) (ignore-error scan-error (goto-char string-start) (python-nav--lisp-forward-sexp) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index ec0a836cb8f..898e2b036e0 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -3204,6 +3204,30 @@ d = '''d''' (python-tests-look-at "c'") (pos-eol)))))) +(ert-deftest python-nav-end-of-statement-5 () + "Test long multi-line string (Bug#75387)." + (let* ((line (format "%s\n" (make-string 80 ?a))) + (lines (apply #'concat (make-list 50 line)))) + (python-tests-with-temp-buffer + (concat + " +s = ''' +" + lines + "\\'''" + lines + "''' +a = 1 +") + (python-tests-look-at "s = '''") + (should (= (save-excursion + (python-nav-end-of-statement) + (point)) + (save-excursion + (python-tests-look-at "a = 1") + (forward-line -1) + (pos-eol))))))) + (ert-deftest python-nav-forward-statement-1 () (python-tests-with-temp-buffer " From a8a4c3a091bc6ebab40db3b33f4d15bb1040dbcb Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Mon, 3 Feb 2025 16:39:49 +0100 Subject: [PATCH 271/279] completing-read-multiple: CRM indication and prompt customization The `completing-read-multiple' prompt indicates multi completion. The customization option `crm-prompt' configures the formatting of the prompt. The variable can be set to "%p" in order to only display the original prompt, to "[%d] %p" to display the separator description and the prompt, or to "[CRM%s] %p" to display a shorter indicator of only the separator string and the prompt. * lisp/emacs-lisp/crm.el (crm-prompt): New user option. (crm-separator): Update value and docstring. (completing-read-multiple): Use `crm-prompt' to format the prompt. * etc/NEWS: Announce the change. (Bug#76028) --- etc/NEWS | 8 ++++++++ lisp/emacs-lisp/crm.el | 30 ++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 51f481c763c..6d934b2029c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -176,6 +176,14 @@ will still be on that candidate after "*Completions*" is updated with a new list of completions. The candidate is automatically deselected when the "*Completions*" buffer is hidden. +--- +*** New user option 'crm-prompt' for 'completing-read-multiple'. +This option configures the prompt format of 'completing-read-multiple'. +By default the prompt indicates to the user that the completion command +accepts a comma-separated list. The prompt format can include the +separator description and the separator string, which are both stored as +text properties of the 'crm-separator' regular expression. + ** Windows +++ diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el index a371a8e14de..676252ae126 100644 --- a/lisp/emacs-lisp/crm.el +++ b/lisp/emacs-lisp/crm.el @@ -79,9 +79,25 @@ (define-obsolete-variable-alias 'crm-default-separator 'crm-separator "29.1") -(defvar crm-separator "[ \t]*,[ \t]*" +(defvar crm-separator + (propertize "[ \t]*,[ \t]*" 'separator "," 'description "comma-separated list") "Separator regexp used for separating strings in `completing-read-multiple'. -It should be a regexp that does not match the list of completion candidates.") +It should be a regexp that does not match the list of completion +candidates. The regexp string can carry the text properties `separator' +and `description', which if present `completing-read-multiple' will show +as part of the prompt. See the user option `crm-prompt'.") + +(defcustom crm-prompt "[%d] %p" + "Prompt format for `completing-read-multiple'. +The prompt is formatted by `format-spec' with the keys %d, %s and %p +standing for the separator description, the separator itself and the +original prompt respectively." + :type '(choice (const :tag "Original prompt" "%p") + (const :tag "Description and prompt" "[%d] %p") + (const :tag "Short CRM indication" "[CRM%s] %p") + (string :tag "Custom string")) + :group 'minibuffer + :version "31.1") (defvar-keymap crm-local-completion-map :doc "Local keymap for minibuffer multiple input with completion. @@ -266,8 +282,14 @@ with empty strings removed." (unless (eq require-match t) require-match)) (setq-local crm-completion-table table)) (setq input (read-from-minibuffer - prompt initial-input map - nil hist def inherit-input-method))) + (format-spec + crm-prompt + (let* ((sep (or (get-text-property 0 'separator crm-separator) + (string-replace "[ \t]*" "" crm-separator))) + (desc (or (get-text-property 0 'description crm-separator) + (concat "list separated by " sep)))) + `((?s . ,sep) (?d . ,desc) (?p . ,prompt)))) + initial-input map nil hist def inherit-input-method))) ;; If the user enters empty input, `read-from-minibuffer' ;; returns the empty string, not DEF. (when (and def (string-equal input "")) From 7ad139d72108df78763b570b376fbe4aad952f72 Mon Sep 17 00:00:00 2001 From: David Ponce Date: Sat, 8 Feb 2025 13:55:16 +0100 Subject: [PATCH 272/279] Fix DOM printing Fix DOM printing when an attribute value is not a string, which is often the case in SVG DOM. Don't print attributes without a value. Refresh the list of HTML boolean attributes. * lisp/dom.el (dom--html-boolean-attribute-p): New function. (dom-print): Use it. Convert attribute value to string before to call `url-insert-entities-in-string'. Don't print attribute without a value. Compute indentation column outside of loop and call `indent-line-to' to indent line. (Bug#5928) * test/lisp/dom-tests.el (dom-tests-print-svg) (dom-tests-print-html-boolean): New tests. --- lisp/dom.el | 60 ++++++++++++++++++++++++------------------ test/lisp/dom-tests.el | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/lisp/dom.el b/lisp/dom.el index fc032058e9f..4d904c92de9 100644 --- a/lisp/dom.el +++ b/lisp/dom.el @@ -258,31 +258,41 @@ white-space." (insert ")") (insert "\n" (make-string (1+ column) ?\s)))))))) +(define-inline dom--html-boolean-attribute-p (attr) + "Return non-nil if ATTR is an HTML boolean attribute." + (inline-quote + (memq ,attr + ;; Extracted from the HTML Living Standard list of attributes + ;; at . + '( allowfullscreen alpha async autofocus autoplay checked + controls default defer disabled formnovalidate inert ismap + itemscope loop multiple muted nomodule novalidate open + playsinline readonly required reversed selected + shadowrootclonable shadowrootdelegatesfocus + shadowrootserializable)))) + (defun dom-print (dom &optional pretty xml) "Print DOM at point as HTML/XML. If PRETTY, indent the HTML/XML logically. If XML, generate XML instead of HTML." - (let ((column (current-column))) + (let ((column (current-column)) + (indent-tabs-mode nil)) ;; Indent with spaces (insert (format "<%s" (dom-tag dom))) - (let ((attr (dom-attributes dom))) - (dolist (elem attr) - ;; In HTML, these are boolean attributes that should not have - ;; an = value. - (insert (if (and (memq (car elem) - '(async autofocus autoplay checked - contenteditable controls default - defer disabled formNoValidate frameborder - hidden ismap itemscope loop - multiple muted nomodule novalidate open - readonly required reversed - scoped selected typemustmatch)) - (cdr elem) - (not xml)) - (format " %s" (car elem)) - (format " %s=\"%s\"" (car elem) - (url-insert-entities-in-string (cdr elem))))))) + (pcase-dolist (`(,attr . ,value) (dom-attributes dom)) + ;; Don't print attributes without a value. + (when value + (insert + ;; HTML boolean attributes should not have an = value. The + ;; presence of a boolean attribute on an element represents + ;; the true value, and the absence of the attribute + ;; represents the false value. + (if (and (not xml) (dom--html-boolean-attribute-p attr)) + (format " %s" attr) + (format " %s=%S" attr (url-insert-entities-in-string + (format "%s" value))))))) (let* ((children (dom-children dom)) - (non-text nil)) + (non-text nil) + (indent (+ column 2))) (if (null children) (insert " />") (insert ">") @@ -291,16 +301,14 @@ If XML, generate XML instead of HTML." (insert (url-insert-entities-in-string child)) (setq non-text t) (when pretty - (insert "\n" (make-string (+ column 2) ?\s))) + (insert "\n") + (indent-line-to indent)) (dom-print child pretty xml))) ;; If we inserted non-text child nodes, or a text node that ;; ends with a newline, then we indent the end tag. - (when (and pretty - (or (bolp) - non-text)) - (unless (bolp) - (insert "\n")) - (insert (make-string column ?\s))) + (when (and pretty (or (bolp) non-text)) + (or (bolp) (insert "\n")) + (indent-line-to column)) (insert (format "" (dom-tag dom))))))) (provide 'dom) diff --git a/test/lisp/dom-tests.el b/test/lisp/dom-tests.el index 47c2a7bb569..eecc4f39808 100644 --- a/test/lisp/dom-tests.el +++ b/test/lisp/dom-tests.el @@ -27,6 +27,7 @@ ;;; Code: (require 'dom) +(require 'svg) (require 'ert) ;; `defsubst's are not inlined inside `ert-deftest' (see Bug#24402), @@ -219,6 +220,59 @@ child results in an error." "<div class="default"> </div>" ""))))) +(ert-deftest dom-tests-print-svg () + "Test that `dom-print' correctly print a SVG DOM." + (let ((svg (svg-create 100 100))) + (svg-rectangle svg 0 0 "100%" "100%" :fill "blue") + (svg-text svg "A text" :x 0 :y 55 :stroke "yellow" :fill "yellow") + (with-temp-buffer + (dom-print svg t t) + (should + (equal + (buffer-string) + (concat + "\n" + " \n" + " A text\n" + "")))))) + +(ert-deftest dom-tests-print-html-boolean () + "Test that `dom-print' correctly print HTML boolean attributes." + (let ((dom (dom-node + "html" nil + (dom-node "head" nil + (dom-node "title" nil + "Test boolean attributes")) + (dom-node "body" nil + ;; The following checkboxes are checked + (dom-node "input" '((type . "checkbox") + (checked . ""))) + (dom-node "input" '((type . "checkbox") + (checked . "checked"))) + (dom-node "input" '((type . "checkbox") + (checked . "true"))) + (dom-node "input" '((type . "checkbox") + (checked . "false"))) + ;; The following checkbox is not checked + (dom-node "input" '((type . "checkbox") + (checked))) + )))) + (with-temp-buffer + (dom-print dom) + (should + (equal + (buffer-string) + (concat + "Test boolean attributes" + "" + "" + "" + "" + "" + "")))))) + (ert-deftest dom-test-search () (let ((dom '(a nil (b nil (c nil))))) (should (equal (dom-search dom (lambda (d) (eq (dom-tag d) 'a))) From b8b7c6fbfdd62dd830a3a946db1746821e1aec3f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 15 Feb 2025 14:53:59 +0200 Subject: [PATCH 273/279] ; Declare treesit.c functions * lisp/textmodes/html-ts-mode.el (treesit-search-subtree): * lisp/textmodes/yaml-ts-mode.el (treesit-node-child-by-field-name): Declare. --- lisp/textmodes/html-ts-mode.el | 1 + lisp/textmodes/yaml-ts-mode.el | 1 + 2 files changed, 2 insertions(+) diff --git a/lisp/textmodes/html-ts-mode.el b/lisp/textmodes/html-ts-mode.el index 7e6c3e0b7d1..0f07fbedeed 100644 --- a/lisp/textmodes/html-ts-mode.el +++ b/lisp/textmodes/html-ts-mode.el @@ -41,6 +41,7 @@ (declare-function treesit-parser-create "treesit.c") (declare-function treesit-node-type "treesit.c") +(declare-function treesit-search-subtree "treesit.c") (defcustom html-ts-mode-indent-offset 2 "Number of spaces for each indentation step in `html-ts-mode'." diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el index 72285d570f1..9b211902e14 100644 --- a/lisp/textmodes/yaml-ts-mode.el +++ b/lisp/textmodes/yaml-ts-mode.el @@ -33,6 +33,7 @@ (declare-function treesit-node-start "treesit.c") (declare-function treesit-node-end "treesit.c") (declare-function treesit-node-type "treesit.c") +(declare-function treesit-node-child-by-field-name "treesit.c") (defvar yaml-ts-mode--syntax-table (let ((table (make-syntax-table))) From 7f2508e6e1176f16e9e6ac5b1aae43f07bb2cd8a Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 15 Feb 2025 11:12:36 -0500 Subject: [PATCH 274/279] (diff-mode-test-font-lock): Fix spurious test failure * test/lisp/vc/diff-mode-tests.el (diff-mode-test-font-lock): Don't nitpick about non-face-affecting overlays. --- test/lisp/vc/diff-mode-tests.el | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/lisp/vc/diff-mode-tests.el b/test/lisp/vc/diff-mode-tests.el index 06309160e52..cd3f613f532 100644 --- a/test/lisp/vc/diff-mode-tests.el +++ b/test/lisp/vc/diff-mode-tests.el @@ -389,26 +389,26 @@ baz")))) 124 127 (face diff-context)))) ;; Test diff-font-lock-syntax. - (should (equal (mapcar (lambda (o) - (list (- (overlay-start o) diff-beg) - (- (overlay-end o) diff-beg) - (append (and (overlay-get o 'diff-mode) - `(diff-mode ,(overlay-get o 'diff-mode))) - (and (overlay-get o 'face) - `(face ,(overlay-get o 'face)))))) + (should (equal + (delq nil + (mapcar (lambda (o) + (when (overlay-get o 'face) + (list (- (overlay-start o) diff-beg) + (- (overlay-end o) diff-beg) + `( diff-mode ,(overlay-get o 'diff-mode) + face ,(overlay-get o 'face))))) (sort (overlays-in (point-min) (point-max)) - (lambda (a b) (< (overlay-start a) (overlay-start b))))) - '((0 127 (diff-mode fine)) - (0 127 (diff-mode syntax)) - (17 25 (diff-mode syntax face font-lock-preprocessor-face)) - (26 35 (diff-mode syntax face font-lock-string-face)) - (37 40 (diff-mode syntax face font-lock-type-face)) - (41 45 (diff-mode syntax face font-lock-function-name-face)) - (61 78 (diff-mode syntax face font-lock-string-face)) - (69 74 (diff-mode fine face diff-refine-removed)) - (91 108 (diff-mode syntax face font-lock-string-face)) - (99 104 (diff-mode fine face diff-refine-added)) - (114 120 (diff-mode syntax face font-lock-keyword-face)))))))) + (lambda (a b) + (< (overlay-start a) (overlay-start b)))))) + '((17 25 (diff-mode syntax face font-lock-preprocessor-face)) + (26 35 (diff-mode syntax face font-lock-string-face)) + (37 40 (diff-mode syntax face font-lock-type-face)) + (41 45 (diff-mode syntax face font-lock-function-name-face)) + (61 78 (diff-mode syntax face font-lock-string-face)) + (69 74 (diff-mode fine face diff-refine-removed)) + (91 108 (diff-mode syntax face font-lock-string-face)) + (99 104 (diff-mode fine face diff-refine-added)) + (114 120 (diff-mode syntax face font-lock-keyword-face)))))))) (ert-deftest diff-mode-test-font-lock-syntax-one-line () "Check diff syntax highlighting for one line with no newline at end." From 5fcf07ac096a588a561fae07d8177acd8e45498b Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 15 Feb 2025 17:12:52 +0100 Subject: [PATCH 275/279] Tramp: Don't require PuTTY 0.82 anymore * doc/misc/tramp.texi: Revert last change. * lisp/net/tramp-cache.el (with-tramp-saved-connection-properties): Adapt `tramp-verbose' when completing host names. * lisp/net/tramp-sh.el (tramp-methods) : Adapt `tramp-login-args' and `tramp-copy-args' arguments. (tramp-plink-option-exists-p): New defun. (tramp-ssh-or-plink-options): Rename from `tramp-ssh-controlmaster-options'. Adapt further plink options. (tramp-do-copy-or-rename-file-out-of-band) (tramp-maybe-open-connection): Adapt calls. * lisp/net/tramp.el (tramp-file-name-handler): Don't touch `tramp-verbose'. * test/lisp/net/tramp-tests.el (top): Set `vc-handled-backends' to nil. (tramp--test-enabled): Rearrange code. --- doc/misc/tramp.texi | 10 ++--- lisp/net/tramp-cache.el | 4 +- lisp/net/tramp-sh.el | 85 +++++++++++++++++++----------------- lisp/net/tramp.el | 12 ++--- test/lisp/net/tramp-tests.el | 29 ++++++------ 5 files changed, 71 insertions(+), 69 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index ac0bb63335c..86ffba29744 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -955,10 +955,9 @@ This is another method from the Kerberos suite. It behaves like @cindex @option{plink} method @item @option{plink} -@option{plink} method is for MS Windows users with the -PuTTY@footnote{It requires at least PuTTY 0.82.} implementation of -SSH@. It uses @samp{plink -ssh} to log in to the remote host. It -supports changing the remote login shell @command{/bin/sh}. +@option{plink} method is for MS Windows users with the PuTTY +implementation of SSH@. It uses @samp{plink -ssh} to log in to the +remote host. It supports changing the remote login shell @command{/bin/sh}. Check the @samp{Share SSH connections if possible} control for that session. @@ -1191,8 +1190,7 @@ This method supports the @samp{-p} argument. These methods are similar to @option{scp} or @option{sftp}, but they use the @command{plink} command to connect to the remote host, and they use @command{pscp} or @command{psftp} for transferring the files. -These programs are part of PuTTY@footnote{It requires at least PuTTY -0.82.}, an SSH implementation for MS Windows. +These programs are part of PuTTY, an SSH implementation for MS Windows. They support changing the remote login shell @command{/bin/sh}. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index e7ad565dc30..0c1f6181bf9 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -502,7 +502,9 @@ PROPERTIES is a list of file properties (strings)." (mapcar (lambda (property) (cons property (gethash property hash tramp-cache-undefined))) - ,properties))) + ,properties)) + ;; Avoid superfluous debug buffers during host name completion. + (tramp-verbose (if minibuffer-completing-file-name 0 tramp-verbose))) (tramp-message key 7 "Saved %s" values) (unwind-protect (progn ,@body) ;; Reset PROPERTIES. Recompute hash, it could have been flushed. diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index f85a371cded..ca890854f85 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -322,8 +322,6 @@ The string is used in `tramp-methods'.") `("plink" (tramp-login-program "plink") (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%c") - ;; Since PuTTY 0.82. - ("-legacy-stdio-prompts") ("-t") ("%h") ("\"") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" @@ -337,8 +335,6 @@ The string is used in `tramp-methods'.") `("plinkx" (tramp-login-program "plink") (tramp-login-args (("-load") ("%h") ("%c") ("-t") ("\"") - ;; Since PuTTY 0.82. - ("-legacy-stdio-prompts") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" tramp-terminal-type @@ -351,8 +347,6 @@ The string is used in `tramp-methods'.") `("pscp" (tramp-login-program "plink") (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%c") - ;; Since PuTTY 0.82. - ("-legacy-stdio-prompts") ("-t") ("%h") ("\"") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" @@ -363,9 +357,7 @@ The string is used in `tramp-methods'.") (tramp-remote-shell-login ("-l")) (tramp-remote-shell-args ("-c")) (tramp-copy-program "pscp") - (tramp-copy-args (("-l" "%u") ("-P" "%p") ("-scp") - ;; Since PuTTY 0.82. - ("-legacy-stdio-prompts") + (tramp-copy-args (("-l" "%u") ("-P" "%p") ("-scp") ("%c") ("-p" "%k") ("-q") ("-r"))) (tramp-copy-keep-date t) (tramp-copy-recursive t))) @@ -373,8 +365,6 @@ The string is used in `tramp-methods'.") `("psftp" (tramp-login-program "plink") (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%c") - ;; Since PuTTY 0.82. - ("-legacy-stdio-prompts") ("-t") ("%h") ("\"") (,(format "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'" @@ -385,9 +375,7 @@ The string is used in `tramp-methods'.") (tramp-remote-shell-login ("-l")) (tramp-remote-shell-args ("-c")) (tramp-copy-program "pscp") - (tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp") - ;; Since PuTTY 0.82. - ("-legacy-stdio-prompts") + (tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp") ("%c") ("-p" "%k"))) (tramp-copy-keep-date t))) @@ -2497,7 +2485,7 @@ The method used must be an out-of-band method." ;; Compose copy command. (setq options (format-spec - (tramp-ssh-controlmaster-options v) + (tramp-ssh-or-plink-options v) (format-spec-make ?t (tramp-get-connection-property (tramp-get-connection-process v) "temp-file" ""))) @@ -4909,41 +4897,60 @@ Goes through the list `tramp-inline-compress-commands'." (zerop (tramp-call-process vec "ssh" nil nil nil "-G" "-o" option "0.0.0.1")))) -(defun tramp-ssh-controlmaster-options (vec) - "Return the Control* arguments of the local ssh." +(defun tramp-plink-option-exists-p (vec option) + "Check, whether local plink OPTION is applicable." + ;; We don't want to cache it persistently. + (with-tramp-connection-property nil option + ;; "plink" with valid options returns "plink: no valid host name + ;; provided". We xcheck for this error message." + (with-temp-buffer + (tramp-call-process vec "plink" nil t nil option) + (not + (string-match-p + (rx (| (: "plink: unknown option \"" (literal option) "\"" ) + (: "plink: option \"" (literal option) + "\" not available in this tool" ))) + (buffer-string)))))) + +(defun tramp-ssh-or-plink-options (vec) + "Return additional arguments of the local ssh or plink." (cond ;; No options to be computed. - ((or (null tramp-use-connection-share) - (null (assoc "%c" (tramp-get-method-parameter vec 'tramp-login-args)))) - "") + ((null (assoc "%c" (tramp-get-method-parameter vec 'tramp-login-args))) "") - ;; Use plink option. + ;; Use plink options. ((string-match-p (rx "plink" (? ".exe") eol) (tramp-get-method-parameter vec 'tramp-login-program)) - (if (eq tramp-use-connection-share 'suppress) - "-noshare" "-share")) + (concat + (if (eq tramp-use-connection-share 'suppress) + "-noshare" "-share") + ;; Since PuTTY 0.82. + (when (tramp-plink-option-exists-p vec "-legacy-stdio-prompts") + " -legacy-stdio-prompts"))) ;; There is already a value to be used. ((and (eq tramp-use-connection-share t) (stringp tramp-ssh-controlmaster-options)) tramp-ssh-controlmaster-options) - ;; We can't auto-compute the options. - ((ignore-errors - (not (tramp-ssh-option-exists-p vec "ControlMaster=auto"))) - "") + ;; Use ssh options. + (tramp-use-connection-share + ;; We can't auto-compute the options. + (if (ignore-errors + (not (tramp-ssh-option-exists-p vec "ControlMaster=auto"))) + "" - ;; Determine the options. - (t (ignore-errors - ;; ControlMaster and ControlPath options are introduced in OpenSSH 3.9. - (concat - "-o ControlMaster=" - (if (eq tramp-use-connection-share 'suppress) + ;; Determine the options. + (ignore-errors + ;; ControlMaster and ControlPath options are introduced in OpenSSH 3.9. + (concat + "-o ControlMaster=" + (if (eq tramp-use-connection-share 'suppress) "no" "auto") - " -o ControlPath=" - (if (eq tramp-use-connection-share 'suppress) + " -o ControlPath=" + (if (eq tramp-use-connection-share 'suppress) "none" ;; Hashed tokens are introduced in OpenSSH 6.7. On macOS ;; we cannot use an absolute file name, it is too long. @@ -4957,10 +4964,10 @@ Goes through the list `tramp-inline-compress-commands'." (or small-temporary-file-directory tramp-compat-temporary-file-directory)))) - ;; ControlPersist option is introduced in OpenSSH 5.6. + ;; ControlPersist option is introduced in OpenSSH 5.6. (when (and (not (eq tramp-use-connection-share 'suppress)) (tramp-ssh-option-exists-p vec "ControlPersist=no")) - " -o ControlPersist=no")))))) + " -o ControlPersist=no"))))))) (defun tramp-scp-strict-file-name-checking (vec) "Return the strict file name checking argument of the local scp." @@ -5176,9 +5183,9 @@ connection if a previous connection has died for some reason." (let* ((current-host tramp-system-name) (target-alist (tramp-compute-multi-hops vec)) (previous-hop tramp-null-hop) - ;; We will apply `tramp-ssh-controlmaster-options' + ;; We will apply `tramp-ssh-or-plink-options' ;; only for the first hop. - (options (tramp-ssh-controlmaster-options vec)) + (options (tramp-ssh-or-plink-options vec)) (process-connection-type tramp-process-connection-type) (process-adaptive-read-buffering nil) ;; There are unfortunate settings for "cmdproxy" diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index be761a71fa7..a199417b12a 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2534,10 +2534,7 @@ Fall back to normal file name handler if no Tramp file name handler exists." ;; We flush connection properties ;; " process-name" and " process-buffer", ;; because the operations shall be applied - ;; in the main connection process. In order - ;; to avoid superfluous debug buffers during - ;; host name completion, we adapt - ;; `tramp-verbose'. + ;; in the main connection process. ;; If `non-essential' is non-nil, Tramp shall ;; not open a new connection. ;; If Tramp detects that it shouldn't continue @@ -2548,11 +2545,8 @@ Fall back to normal file name handler if no Tramp file name handler exists." ;; In both cases, we try the default handler then. (with-tramp-saved-connection-properties v '(" process-name" " process-buffer") - (let ((tramp-verbose - (if minibuffer-completing-file-name - 0 tramp-verbose))) - (tramp-flush-connection-property v " process-name") - (tramp-flush-connection-property v " process-buffer")) + (tramp-flush-connection-property v " process-name") + (tramp-flush-connection-property v " process-buffer") (setq result (catch 'non-essential (catch 'suppress diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 1077b944f0a..3be81449c9c 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -152,7 +152,8 @@ tramp-copy-size-limit nil tramp-error-show-message-timeout nil tramp-persistency-file-name nil - tramp-verbose 0) + tramp-verbose 0 + vc-handled-backends nil) (defconst tramp-test-name-prefix "tramp-test" "Prefix to use for temporary test files.") @@ -251,20 +252,20 @@ being the result.") (file-writable-p ert-remote-temporary-file-directory)))))) (when (cdr tramp--test-enabled-checked) - ;; Remove old test files. - (dolist (dir `(,temporary-file-directory - ,tramp-compat-temporary-file-directory - ,ert-remote-temporary-file-directory)) - (dolist (file (directory-files - dir 'full - (rx-to-string - `(: bos (? ".#") - (| ,tramp-test-name-prefix - ,(if (getenv "TRAMP_TEST_CLEANUP_TEMP_FILES") - tramp-temp-name-prefix 'unmatchable)))))) + (ignore-errors + ;; Remove old test files. + (dolist (dir `(,temporary-file-directory + ,tramp-compat-temporary-file-directory + ,ert-remote-temporary-file-directory)) + (dolist (file (directory-files + dir 'full + (rx-to-string + `(: bos (? ".#") + (| ,tramp-test-name-prefix + ,(if (getenv "TRAMP_TEST_CLEANUP_TEMP_FILES") + tramp-temp-name-prefix 'unmatchable)))))) - ;; Exclude sockets and FUSE mount points. - (ignore-errors + ;; Exclude sockets and FUSE mount points. (unless (or (string-prefix-p "srw" (file-attribute-modes (file-attributes file))) From 4cf53c436159ea54dbfe1a1e24515e2e6fbf9a6f Mon Sep 17 00:00:00 2001 From: Stephen Gildea Date: Sat, 15 Feb 2025 07:33:29 -0800 Subject: [PATCH 276/279] ; Info: time-stamp is documented best in the Emacs manual * lisp/info.el (Info-file-list-for-emacs): Remove entry pointing Info at time-stamp discussion in the Autotype document. --- lisp/info.el | 1 - 1 file changed, 1 deletion(-) diff --git a/lisp/info.el b/lisp/info.el index 7a34b43369e..b8ab5b19776 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -4678,7 +4678,6 @@ Advanced commands: ("java" . "ccmode") ("idl" . "ccmode") ("pike" . "ccmode") ("skeleton" . "autotype") ("auto-insert" . "autotype") ("copyright" . "autotype") ("executable" . "autotype") - ("time-stamp" . "autotype") ("tempo" . "autotype") ("hippie-expand" . "autotype") ("cvs" . "pcl-cvs") ("ada" . "ada-mode") "calc" ("calcAlg" . "calc") ("calcDigit" . "calc") ("calcVar" . "calc") From 504bdce73168257af14cd3b0200638fe9dd5c367 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 16 Feb 2025 11:49:16 -0500 Subject: [PATCH 277/279] (set-auto-mode--find-matching-alist-entry): Fix bug#75961 * lisp/files.el (set-auto-mode--find-matching-alist-entry): Run the MODE found in (REGEXP MODE t) before we replace it with something else. * test/lisp/files-tests.el (files-tests--bug75961): New test. --- lisp/files.el | 50 ++++++++++++++++++++++++---------------- test/lisp/files-tests.el | 16 +++++++++++++ 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/lisp/files.el b/lisp/files.el index a71d0c5c9d0..bf05939ebeb 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3469,27 +3469,37 @@ Also applies to `magic-fallback-mode-alist'.") If CASE-INSENSITIVE, the file system of file NAME is case-insensitive." (let (mode) (while name - (setq mode - (if case-insensitive - ;; Filesystem is case-insensitive. - (let ((case-fold-search t)) + (let ((newmode + (if case-insensitive + ;; Filesystem is case-insensitive. + (let ((case-fold-search t)) + (assoc-default name alist 'string-match)) + ;; Filesystem is case-sensitive. + (or + ;; First match case-sensitively. + (let ((case-fold-search nil)) (assoc-default name alist 'string-match)) - ;; Filesystem is case-sensitive. - (or - ;; First match case-sensitively. - (let ((case-fold-search nil)) - (assoc-default name alist 'string-match)) - ;; Fallback to case-insensitive match. - (and auto-mode-case-fold - (let ((case-fold-search t)) - (assoc-default name alist 'string-match)))))) - (if (and mode - (not (functionp mode)) - (consp mode) - (cadr mode)) - (setq mode (car mode) - name (substring name 0 (match-beginning 0))) - (setq name nil))) + ;; Fallback to case-insensitive match. + (and auto-mode-case-fold + (let ((case-fold-search t)) + (assoc-default name alist 'string-match))))))) + (when newmode + (when mode + ;; We had already found a mode but in a (REGEXP MODE t) + ;; entry, so we still have to run MODE. Let's do it now. + ;; FIXME: It's kind of ugly to run the function here. + ;; An alternative could be to return a list of functions and + ;; callers. + (set-auto-mode-0 mode t)) + (setq mode newmode)) + (if (and newmode + (not (functionp newmode)) + (consp newmode) + (cadr newmode)) + ;; It's a (REGEXP MODE t): Keep looking but remember the MODE. + (setq mode (car newmode) + name (substring name 0 (match-beginning 0))) + (setq name nil)))) mode)) (defun set-auto-mode--apply-alist (alist keep-mode-if-same dir-local) diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index 5e2c4eb2669..7f06c37a408 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1680,6 +1680,22 @@ The door of all subtleties! (should-not (eq (files-tests--check-mode "gdbinit.5") #'gdb-script-mode)) (should-not (eq (files-tests--check-mode ".gdbinit.py.in") #'gdb-script-mode))) +(ert-deftest files-tests--bug75961 () + (let* ((auto-mode-alist (cons '("\\.text\\'" text-mode t) auto-mode-alist)) + (called-fun nil) + (fun (lambda () (setq called-fun t)))) + (with-temp-buffer + (setq buffer-file-name "foo.text") + (normal-mode) + (should (derived-mode-p 'text-mode)) + (add-hook 'text-mode-hook fun) + (setq buffer-file-name "foo.html.text") + (should (not called-fun)) + (normal-mode) + (remove-hook 'text-mode-hook fun) + (should called-fun) + (should (derived-mode-p 'html-mode))))) + (defvar sh-shell) (defun files-tests--check-shebang (shebang expected-mode &optional expected-dialect) From e8470b79f1d56c4c887c0b5d2c326ad6449cbbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sun, 16 Feb 2025 13:52:28 +0000 Subject: [PATCH 278/279] Eglot: Improve fix to bug#66144 The :exit notification should also take an empty JSON object instead of JSON null as its parameters. * lisp/progmodes/eglot.el (eglot-shutdown): Use eglot--{} in :exit notifcation, too. --- lisp/progmodes/eglot.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index afa7d7b7e54..bd28174e7da 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1259,7 +1259,7 @@ SERVER." (progn (setf (eglot--shutdown-requested server) t) (eglot--request server :shutdown eglot--{} :timeout (or timeout 1.5)) - (jsonrpc-notify server :exit nil)) + (jsonrpc-notify server :exit eglot--{})) ;; Now ask jsonrpc.el to shut down the server. (jsonrpc-shutdown server (not preserve-buffers)) (unless preserve-buffers (kill-buffer (jsonrpc-events-buffer server))))) From fc189cb83cf7284344a737e75b3ee56487b1c386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?El=C3=ADas=20Gabriel=20P=C3=A9rez?= Date: Sun, 16 Feb 2025 13:21:52 -0600 Subject: [PATCH 279/279] Add gtk-redo icon to x-gtk-stock-map * lisp/term/pgtk-win.el (x-gtk-stock-map): Add gtk-redo. (Bug#76349) --- lisp/term/pgtk-win.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index fe9807f8c52..1c15234c49c 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -194,6 +194,7 @@ EVENT is a `preedit-text' event." ("etc/images/save" . ("document-save" "gtk-save")) ("etc/images/saveas" . ("document-save-as" "gtk-save-as")) ("etc/images/undo" . ("edit-undo" "gtk-undo")) + ("etc/images/redo" . ("edit-redo" "gtk-redo")) ("etc/images/cut" . ("edit-cut" "gtk-cut")) ("etc/images/copy" . ("edit-copy" "gtk-copy")) ("etc/images/paste" . ("edit-paste" "gtk-paste"))