diff --git a/ChangeLog.5 b/ChangeLog.5 index c74daeb3aed..4f27baa2d22 100644 --- a/ChangeLog.5 +++ b/ChangeLog.5 @@ -1,3 +1,306 @@ +2025-08-14 Eli Zaretskii + + * Version 30.2 released. + +2025-08-14 Eli Zaretskii + + * README: + * configure.ac: + * exec/configure.ac: + * java/AndroidManifest.xml.in (Version-code): + * nt/README.W32: + * msdos/sed2v2.inp: Bump Emacs version to 30.2. + + * ChangeLog.5: + * etc/AUTHORS: + * etc/HISTORY: Update for Emacs 30.2. + + * admin/admin.el (set-version): Fix handling of official releases. + +2025-08-07 Vinícius Moraes (tiny change) + + Handle remote file names in cmuscheme.el + + * lisp/cmuscheme.el (scheme-load-file, scheme-compile-file): Use + 'file-local-name' to handle file names on remote systems. + (Bug#79163) + +2025-08-06 Sean Whitton + + * lisp/vc/vc.el (vc-register): Fix interactive spec (bug#79183). + +2025-07-31 James Thomas + + * doc/misc/gnus.texi (Category Syntax): Update gnus-agent-predicate. + + This updates the Gnus manual due to recent code change (bug#79123). + +2025-07-28 Robert Pluim + + Prefer "tls" to "ssl" in documentation + + * doc/misc/gnus.texi (NNTP): Refer to 'nntp-open-tls-stream'. + (Direct Functions, Customizing the IMAP Connection): Add + commentary about desirability of STARTTLS. Correct + documentation about use of GnuTLS. Use 'tls in example. + * lisp/gnus/nnimap.el (nnimap-server-port): Mention 'tls in + preference to 'ssl. + * lisp/gnus/nntp.el (nntp-open-connection-function) + (nntp-never-echoes-commands): Document 'nntp-open-tls-stream' as + preferred to 'nntp-open-ssl-stream'. + +2025-07-26 Sean Whitton + + loaddefs-generate--rubric: Note about committing ldefs-boot.el + + * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--rubric): + Note that ldefs-boot.el should be committed on its own. + +2025-07-21 Jim Porter + + Fix Eshell call to 'string-suffix-p' when checking for trailing newline + + * lisp/eshell/esh-io.el (eshell--output-maybe-n): Fix call. + + * test/lisp/eshell/esh-io-tests.el + (esh-io-test/output-newline/add-newline) + (esh-io-test/output-newline/no-newline) + (esh-io-test/output-newline/no-extra-newline): New tests (bug#79063). + +2025-07-21 Robert Pluim + + * etc/PROBLEMS: Describe how to work around screen reader TAB issue + +2025-07-21 Sean Whitton + + (gnus)Scoring Tips: New tip regarding header continuation lines + + * doc/misc/gnus.texi (Scoring Tips): New "Continuation lines + when scoring on other headers" tip. + +2025-07-16 Ken Mankoff + + Fix :box attribute of faces in Leuven themes. + + * etc/themes/leuven-dark-theme.el: + * etc/themes/leuven-theme.el: Fix 'lui-highlight-face' face. + (Bug#79029) + +2025-07-09 Andrea Corallo + + Nativecomp don't error with undeclared types (bug#6573) (don't merge) + + Backporting f38e969e472 from trunk to emacs-30 + + * test/src/comp-resources/comp-test-funcs.el (comp-test-76573-1-f): New + function. + * lisp/emacs-lisp/comp-cstr.el (comp-supertypes): Don't error if 'type' + is unknown. + +2025-07-06 Eli Zaretskii + + Fix 'kill-ring-deindent-mode' + + * lisp/indent-aux.el + (kill-ring-deindent-buffer-substring-function): Fix deindenting + for modes which set 'indent-tab-mode' to nil. (Bug#77981) + + (cherry picked from commit 1c7fe501fedb41aaf5b22d82dab5a365f86e4c85) + +2025-07-04 Yuan Fu + + Handle ts_node_type return NULL (bug#78938) + + * src/treesit.c (treesit_traverse_match_predicate): Handle the + case when ts_node_type returns NULL. + (Ftreesit_node_type): Add some comment. + +2025-07-04 Eli Zaretskii + + Improve documentation of 'warning-display-at-bottom' + + * lisp/emacs-lisp/warnings.el (warning-display-at-bottom): + * doc/lispref/display.texi (Warning Options): + * doc/emacs/windows.texi (Temporary Displays): + * etc/NEWS: Improve documentation of 'warning-display-at-bottom'. + See https://lists.gnu.org/archive/html/emacs-devel/2025-07/msg00024.html + for more details. + +2025-07-04 Yuan Fu + + Handle the case when ts_node_type returns NULL (bug#78938) + + * src/treesit.c (Ftreesit_node_type): Handle NULL. + +2025-06-29 Jim Porter + + Populate the ':title' in EWW when defaulting to readable mode + + Do not merge to master. + + * lisp/net/eww.el (eww-display-document): Always render the full + document first to populate ':title' (bug#77299). + +2025-06-28 Liam Hupfer + + bug#78901: [PATCH] js-ts-mode: Fix auto-mode-alist regexp + + Align the js-ts-mode entry with the javascript-mode entries in the + default auto-mode-alist value in lisp/files.el. Otherwise, js-ts-mode is + not associated with .js files. + + * lisp/progmodes/js.el (js-ts-mode): Fix auto-mode-alist regexp. + + Fixes: 2023-01-20 6b2f85caa6ca "Make tree-sitter based modes optional" + +2025-06-25 Eli Zaretskii + + Fix 'insert-directory' in Turkish language-environment + + * lisp/files.el (insert-directory-clean, insert-directory): Use + case-sensitive search for "//DIRED//" and similar strings. + (Bug#78894) + +2025-06-25 Michael Albinus + + Fix job control in remote shell + + * lisp/net/tramp-sh.el (tramp-methods) : + Adapt `tramp-direct-async' argument. (Bug#71050, Bug#71259) + +2025-06-21 Eli Zaretskii + + Workaround for "M-x man" on macOS 15 and later + + * lisp/man.el (Man-init-defvars): Workaround for macOS Sed. Do + not merge to master. (Bug#77944) + +2025-06-11 Sean Whitton + + Insert missing step to make use of directory tracking OSC codes + + * doc/emacs/misc.texi (Interactive Shell): Say to add + comint-osc-process-output to comint-output-filter-function. + +2025-06-11 Robert Pluim + + * lisp/keymap.el (keymap-set): Refer to 'key-description'. (Bug#78714) + +2025-06-11 Yuan Fu + + Support new tree-sitter grammar filename format (bug#78754) + + Previously Emacs only looks for filenames like + libtree-sitter-json.so.0.0. Now Emacs also look for filenames + like libtree-sitter-json.so.15.0. + + * src/treesit.c: + (treesit_load_language_push_for_each_suffix): Add versioned + candidate to candidate list too. + +2025-06-10 Pip Cet + + Fix crash when evaluating "(signal nil 5)" (bug#78738) + + The docstring already warns against calling signal with a nil + error symbol, which is for internal use only, but we can avoid crashing + in this case. + + * src/eval.c (Fsignal): Produce a "peculiar error" for more arguments + involving non-lists. + +2025-06-08 Michael Albinus + + Adapt emba integration (don't merge) + + * test/infra/Dockerfile.emba (emacs-inotify): Don't install clangd. + + * test/infra/gitlab-ci.yml (.job-template): Make actions in + after_script more robust. + +2025-06-03 Xiyue Deng + + Make xoauth2 auth fail when a smtp server replies 334 (Bug#78366) + + * lisp/mail/smtpmail.el (smtpmail-try-auth-method): Throw error 535 + when receiving a "334 server challenge" reply. + + (cherry picked from commit 53371c959462a677a29ee869b3b6627facf3ed79) + +2025-05-31 Eli Zaretskii + + Revert "; * lisp/subr.el (setq-local): Doc fix (bug#78644)." + + This reverts commit cb9556d669c037c4e2f1a9c80adacad55948c706. + Some of its parts were not supposed to be installed. + +2025-05-28 Stephen Berman + + Fix bug in 'todo-jump-to-category' (bug#78608) + + * lisp/calendar/todo-mode.el (todo-jump-to-category): Eliminate + comparison of the number of Todo categories before and after + specifying the category to jump to and replace it by a check of + whether there are any items in the category, since an existing + category should always have at least one item (perhaps done or + archived). + +2025-05-27 Michael Albinus + + Fix gitlab-ci.yml (don't merge to master) + + * test/infra/gitlab-ci.yml (.job-template): Fix config.log name. + (test-filenotify-gio, test-eglot): Fix formatting. + +2025-05-25 Konstantin Kharlamov + + typescript-ts-mode: Improve function body indentation (bug#78121) + + Older code was calculating body indentation depending on function + parameters alignment. This is incorrect, because if parameters are + misaligned, so will the function body. Instead, use offset of the + previous standalone parent. + + * lisp/progmodes/typescript-ts-mode.el: + (typescript-ts-mode--indent-rules): Stop depending on function + parameters indentation for calculating body content and the closing + `}'. + * test/lisp/progmodes/typescript-ts-mode-resources/indent.erts: + (Function body with params misindented (bug#78121)): Add new test. + +2025-05-24 Eli Zaretskii + + Fix documentation of use-package's ':hook' keyword + + * doc/misc/use-package.texi (Hooks): Document how to add several + functions to the same hook (bug#77609). + +2025-05-22 Michael Albinus + + * test/infra/gitlab-ci.yml (.job-template): Make it more robust. + +2025-05-20 Stephen Berman + + Fix todo-mode item insertion bug (bug#78506) + + * lisp/calendar/todo-mode.el (todo-insert-item--next-param): Unset + transient keymap on completing default or copy item insertion + command, to ensure that the next Todo mode key is recognized. + +2025-05-19 Jostein Kjønigsen + + Add support for Pyrefly LSP for Python + + * lisp/progmodes/eglot.el (eglot-server-programs): Add config + for Pyrefly. (Bug#78492) + +2025-05-18 Michael Albinus + + Adapt Tramp version in customize-package-emacs-version-alist + + * lisp/net/trampver.el (customize-package-emacs-version-alist): + Add Tramp version integrated in Emacs 30.1. + 2025-05-17 Eli Zaretskii Fix saving abbrevs by 'abbrev-edit-save-buffer' @@ -1157,7 +1460,7 @@ This file records repository revisions from commit 1cda0967b4d3c815fc610794ad6a8fc2b913a3c5 (exclusive) to -commit 299d3a440121ff6692a85615ff97e6ad4dde91db (inclusive). +commit 49d64bfb1a4ca5fc8b3a4d215fb6cabbb9780f9b (inclusive). See ChangeLog.4 for earlier changes. ;; Local Variables: diff --git a/admin/admin.el b/admin/admin.el index 542556a65e0..7e761c3f1f4 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -128,8 +128,13 @@ Root must be the root of an Emacs source tree." (submatch (1+ (in "0-9.")))))) (set-version-in-file root "java/AndroidManifest.xml.in" (apply #'format "%02d%02d%02d000" - (mapcar #'string-to-number - (split-string version "\\."))) + (let ((ver-list + (mapcar #'string-to-number + (split-string version "\\.")))) + ;; Official releases are XX.YY, not XX.YY.ZZ + (if (= 2 (length ver-list)) + (setq ver-list (append ver-list '(0)))) + ver-list)) admin-android-version-code-regexp) (set-version-in-file root "nt/README.W32" version (rx (and "version" (1+ space) diff --git a/admin/authors.el b/admin/authors.el index b9f5f170fc0..66346b46091 100644 --- a/admin/authors.el +++ b/admin/authors.el @@ -187,6 +187,7 @@ files.") ("Mark D. Baushke" "Mark D Baushke") ("Mark E. Shoulson" "Mark Shoulson") ("Marko Kohtala" "Kohtala Marko") + ("Mattias Roux" "mattias@kojin\\.tech") ("Maxim Nikulin" "Max Nikulin") ("Agustín Martín" "Agustin Martin" "Agustín Martín Domingo") ("Martin Lorentzon" "Martin Lorentzson") diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt index 22e76a0ac2e..61d19e54b8e 100644 --- a/admin/make-tarball.txt +++ b/admin/make-tarball.txt @@ -388,9 +388,9 @@ add the new NEWS file as news/NEWS.xx.y Copy new etc/MACHINES to MACHINES and CONTRIBUTE to CONTRIBUTE For every new release, a banner is displayed on top of the emacs.html -page. Uncomment and the release banner in emacs.html. Keep it on the -page for about a month, then comment it again. The new release banner -looks like this: +page. Uncomment the release banner in emacs.html. Keep it on the page +for about a month, then comment it again. The new release banner looks +like this:
@@ -398,6 +398,16 @@ looks like this:
+Add the information about the new release in the "Releases" section of +emacs.html, which begins like this: + +
+
+ + + +

+ Also, make sure the copyright years at the bottom of emacs.html are up-to-date. diff --git a/admin/nt/dist-build/emacs.nsi b/admin/nt/dist-build/emacs.nsi index 9239eb07ec7..13278749871 100644 --- a/admin/nt/dist-build/emacs.nsi +++ b/admin/nt/dist-build/emacs.nsi @@ -70,6 +70,9 @@ Section # create uninstaller WriteUninstaller "$UninstallerPath" + # request to set x64 registry keys + SetRegView 64 + # add registry key to enable uninstall from control panel WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "GNU Emacs ${VERSION_BRANCH}" WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$\"$UninstallerPath$\"" diff --git a/admin/tree-sitter/treesit-admin.el b/admin/tree-sitter/treesit-admin.el index 2be6fe42f27..2e85d6b0d8c 100644 --- a/admin/tree-sitter/treesit-admin.el +++ b/admin/tree-sitter/treesit-admin.el @@ -83,6 +83,7 @@ go-ts-mode heex-ts-mode html-ts-mode + mhtml-ts-mode java-ts-mode js-ts-mode json-ts-mode @@ -107,6 +108,7 @@ go-ts-mode heex-ts-mode html-ts-mode + mhtml-ts-mode java-ts-mode js json-ts-mode diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi index c768910349f..72e660a2def 100644 --- a/doc/emacs/vc1-xtra.texi +++ b/doc/emacs/vc1-xtra.texi @@ -285,7 +285,11 @@ tree. Add a new working tree. @item C-x v w w -Visit this file in another working tree. +Visit this file or directory in another working tree. + +@item C-x v w s +Invoke @kbd{C-x p p} (@code{project-switch-project}) but limited to +other working trees. @item C-x v w x Delete a working tree you no longer need. @@ -313,12 +317,24 @@ new working tree. @findex vc-switch-working-tree Once your repository has other working trees, you can use the command @kbd{C-x v w w} (@code{vc-switch-working-tree}) to switch between them. -It tries to find the analogue of the current buffer's file -under another working tree. Typically the sets of workfiles -under different working trees differ more in file contents than in which -files do and do not exist. In other words, the file the -current buffer visits probably exists in other working trees too, and -this command lets you switch to those versions of the file. +It tries to find the analogue of the current buffer's file or directory +under another working tree. Typically the sets of workfiles under +different working trees differ more in file contents than in which files +do and do not exist. In other words, the file or directory the current +buffer visits probably exists in other working trees too, and this +command lets you switch to those versions of the file. + +@kindex C-x v w s +@findex vc-working-tree-switch-project +An alternative way to switch between working trees is @kbd{C-x v w s} +(@code{vc-working-tree-switch-project}). This prompts you to select a +working tree, and then displays a menu of commands to operate on it. +This is in fact just @kbd{C-x p p} (@code{project-switch-project}) +(@pxref{Switching Projects}) but with the selection of projects limited +to other working trees. The main difference between @kbd{C-x v w w} and +@kbd{C-x v w s} is that the former looks for an analogue of the current +buffer in the other working tree while the latter considers the other +working tree as a whole, independent project. @kindex C-x v w x @kindex C-x v w R diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi index f3f0902f364..9e262346edb 100644 --- a/doc/lispref/backups.texi +++ b/doc/lispref/backups.texi @@ -719,7 +719,7 @@ preserved, but this is up to the specific @code{revert-buffer-function} implementation. @end deffn -@defvar revert-buffer-in-progress-p +@defvar revert-buffer-in-progress @code{revert-buffer} binds this variable to a non-@code{nil} value while it is working. @end defvar @@ -852,6 +852,13 @@ 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 auto-revert-buffer-in-progress +@code{auto-revert-buffer} binds this variable to a non-@code{nil} value +while it is working. This can be used by major mode +@code{revert-buffer-function} implementations to suppress messages in +Auto Revert modes, for example. +@end defvar + @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 diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index ea6e07e05fb..1b2a21e160c 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -2742,6 +2742,14 @@ Indent calls to this function or macro according to @var{indent-spec}. This is typically used for macros, though it works for functions too. @xref{Indenting Macros}. +@cindex @code{autoload-macro} (@code{declare} spec) +@item (autoload-macro @var{value}) +This is used when defining a macro. If @var{value} is @samp{expand}, +any calls to the macro which follow an autoload comment will first be +expanded during generation of the autoloads. This declaration is used +as an alternative to hard-coding lists of macros to expand in +@code{loaddefs-generate--make-autoload}. @xref{Autoload}. + @item (interactive-only @var{value}) Set the function's @code{interactive-only} property to @var{value}. @xref{The interactive-only property}. diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 7fa64b72999..836d980ff0d 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -665,10 +665,12 @@ Building Emacs loads @file{loaddefs.el} and thus calls @code{autoload}. The same magic comment can copy any kind of form into @file{loaddefs.el}. The form following the magic comment is copied -verbatim, @emph{except} if it is one of the forms which the autoload -facility handles specially (e.g., by conversion into an -@code{autoload} call). The forms which are not copied verbatim are -the following: +verbatim, unless it is a form which the autoload facility handles +specially, by conversion directly into an @code{autoload} call, or by +recursively expanding the macro. Any macro can request expansion of +autoloads which call it during generation; @xref{autoload-macro expand}. + +The following forms are handled specially: @table @asis @item Definitions for function or function-like objects: @@ -684,8 +686,12 @@ and @code{define-overloadable-function} (see the commentary in @item Other definition types: @code{defcustom}, @code{defgroup}, @code{deftheme}, @code{defclass} -(@pxref{Top,EIEIO,,eieio,EIEIO}), and @code{define-skeleton} -(@pxref{Top,Autotyping,,autotype,Autotyping}). +(@pxref{Top,EIEIO,,eieio,EIEIO}), @code{define-skeleton} +(@pxref{Top,Autotyping,,autotype,Autotyping}), +@code{transient-define-prefix}, @code{transient-define-suffix}, +@code{transient-define-infix}, @code{transient-define-argument}, and +@code{transient-define-group} (@pxref{TOP,Transient,,transient,Transient +User and Developer Manual}). @end table You can also use a magic comment to execute a form at build time @@ -727,11 +733,50 @@ keep the line length down. @samp{(fn)} in the usage part of the documentation string is replaced with the function's name when the various help functions (@pxref{Help Functions}) display it. +@anchor{autoload-macro expand} If you write a function definition with an unusual macro that is not -one of the known and recognized function definition methods, use of an -ordinary magic autoload comment would copy the whole definition into -@code{loaddefs.el}. That is not desirable. You can put the desired -@code{autoload} call into @code{loaddefs.el} instead by writing this: +one of the known and recognized function definition methods, using an +ordinary magic autoload comment with a call to the macro would require +autoloading the macro definition itself to work. Doing so copies the +whole macro definition into the autoload file. If that is not desired, +you can use the special declare form @code{(autoload-macro expand)} in +your macro definition (@pxref{Declare Form}), instead of autoloading it. +This indicates to the autoload system that calls to your macro following +@samp{;;;###autoload} should be expanded, similar to how the special +functions listed above are handled. For example, a macro which wraps +@code{define-minor-mode} can request expansion, so that proper +@code{autoload} calls for the function it defines are generated. + +@cindex @code{:autoload-end} +The keyword symbol @code{:autoload-end} can be used in the expansion of +a macro to prevent including unwanted forms in the autoload output. Its +presence causes any further elements within the form where it appears to +be silently skipped. For example, if during autoload generation, a +macro's expansion includes: + +@example +(progn + (put my-mode 'visible-prop t) + :autoload-end + (put my-mode 'hidden-prop nil)) +@end example + +@noindent +the final form (@w{@code{(put my-mode 'hidden-prop nil)}}) will not be +copied into the autoload file. + +Note that, if a symbol in the @code{car} of an autoloaded form is found +to be undefined during autoload generation, the file in which the +associated @samp{;;;###autoload} appears will itself be loaded, to give +the macro a chance to be defined. Packages which use special loading +mechanisms, including loading their own @file{@var{package}-loaddefs.el} +file, should therefore gracefully handle load errors, since these files +may not yet exist during autoload generation. This can be done, e.g., +by setting the @var{no-error} argument of @code{require} non-@code{nil} +(@pxref{Named Features})). + +Alternatively, instead of expansion, you can put the desired +@code{autoload} call into @file{loaddefs.el} by writing this: @example ;;;###autoload (autoload 'foo "myfile") diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi index 3fd8f038bae..f049a2d23b1 100644 --- a/doc/lispref/streams.texi +++ b/doc/lispref/streams.texi @@ -1054,7 +1054,7 @@ This overrides @code{print-escape-nonascii}. This overrides @code{print-escape-multibyte}. @item charset-text-property This overrides @code{print-charset-text-property}. -@item unreadeable-function +@item unreadable-function This overrides @code{print-unreadable-function}. @item gensym This overrides @code{print-gensym}. @@ -1066,6 +1066,8 @@ This overrides @code{print-number-table}. This overrides @code{float-output-format}. @item integers-as-characters This overrides @code{print-integers-as-characters}. +@item symbols-bare +This overrides @code{print-symbols-bare}. @end table In the future, more overrides may be offered that do not map directly diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 7735e0d62a4..60bf8ecc37b 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -4716,9 +4716,9 @@ value visits file @var{filename} and goes to buffer position @var{position}. Restoring this type of position asks the user for confirmation first. -@item @code{(buffer @var{buffer-name})} -This represents a buffer; jumping to this value switches to buffer -@var{buffer-name}. +@item @code{(buffer @var{buffer})} +This represents a buffer; jumping to this value switches to that +@var{buffer}. @end table The functions in this section return unpredictable values unless diff --git a/doc/lispref/threads.texi b/doc/lispref/threads.texi index 3d9ebf08073..db6d0cf4d26 100644 --- a/doc/lispref/threads.texi +++ b/doc/lispref/threads.texi @@ -55,7 +55,7 @@ closure are shared by any threads invoking the closure. directly, but the current thread can be exited implicitly, and other threads can be signaled. -@defun make-thread function &optional name +@defun make-thread function &optional name buffer-disposition Create a new thread of execution which invokes @var{function}. When @var{function} returns, the thread exits. @@ -66,9 +66,23 @@ The new thread's current buffer is inherited from the current thread. used for debugging and informational purposes only; it has no meaning to Emacs. If @var{name} is provided, it must be a string. +@var{buffer-disposition} indicates what happens if the thread's current +buffer is about to be killed. If the value is @code{t}, killing the +buffer is not allowed. Any other value, including @code{nil} (which is +the default), means that the buffer is killed and the thread is assigned +another current buffer, and it's signaled the error +@code{thread-buffer-killed}. But if the value is the symbol +@code{silently}, the error is not signaled. + This function returns the new thread. @end defun +@findex thread-buffer-disposition +@findex thread-set-buffer-disposition +After a thread had been created, you can inspect or change its +buffer-disposition using functions @code{thread-buffer-disposition} and +@code{thread-set-buffer-disposition}. + @defun threadp object This function returns @code{t} if @var{object} represents an Emacs thread, @code{nil} otherwise. diff --git a/doc/misc/autotype.texi b/doc/misc/autotype.texi index c53be54d0af..377dcda3efd 100644 --- a/doc/misc/autotype.texi +++ b/doc/misc/autotype.texi @@ -273,13 +273,15 @@ empty file is visited. This is accomplished by putting @vindex auto-insert-alist What gets inserted, if anything, is determined by the variable -@code{auto-insert-alist}. The @sc{car} of each element of this list -is either a mode name, making the element applicable when a buffer is -in that mode, or a string, which is a regexp matched against a -buffer's file name (the latter enables you to distinguish between -different kinds of files that have the same mode in Emacs). The -@sc{car} of an element may also be a cons cell, consisting of mode -name or regexp, as above, and an additional descriptive string. +@code{auto-insert-alist}. The @sc{car} of each element of this list is +either a mode name, making the element applicable when a buffer is in +that mode, or a string, which is a regexp matched against a buffer's +file name (the latter enables you to distinguish between different kinds +of files that have the same mode in Emacs). It can also be a predicate +declared through a plist of the form @code{(predicate @var{function})}. +@var{function} should be a predicate function of no arguments. The +@sc{car} of an element may also be a cons cell, consisting of mode name +or regexp, as above, and an additional descriptive string. When a matching element is found, the @sc{cdr} says what to do. It may be a string, which is a file name, whose contents are to be inserted, if diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 21f12a38e0b..1dc616918d0 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -169,6 +169,7 @@ How file names, directories and localnames are mangled and managed * Localname deconstruction:: Breaking a localname into its components. * External packages:: Integration with external Lisp packages. * Extension packages:: Adding new methods to @value{tramp}. +* New operations:: Handling further operations in @value{tramp}. @end detailmenu @end menu @@ -5472,6 +5473,13 @@ Suppress reading the remote history file in @code{shell}. Set Disable excessive traces. Set @code{tramp-verbose} to 3 or lower, default being 3. Increase trace levels temporarily when hunting for bugs. + +@item +Use a package with @value{tramp} specific implementation of high-level +operations. For example, the GNU ELPA package @file{tramp-hlo} +implements specialized versions of @code{dir-locals--all-files}, +@code{locate-dominating-file} and @code{dir-locals-find-file} for +@value{tramp}'s @code{tramp-sh} backend (@pxref{New operations}). @end itemize @@ -6457,6 +6465,7 @@ programs. * Localname deconstruction:: Splitting a localname into its component parts. * External packages:: Integrating with external Lisp packages. * Extension packages:: Adding new methods to @value{tramp}. +* New operations:: Handling further operations in @value{tramp}. @end menu @@ -6721,11 +6730,107 @@ The trick is to wrap the function definition of @code{;;;###autoload} cookie. +@node New operations +@section Handling further operations in @value{tramp} + +By default, @value{tramp} handles the basic operations listed in +@ref{Magic File Names, , Magic File Name Operations, elisp}. +Sometimes, it is desired to support more complex operations directly, +mainly for performance reasons. + +An external package package could add an own implementation of an +operation to @value{tramp}, which avoids the performance overhead +caused by using the basic operations which are aware of remote files. +For example, it could implement this by using an own shell script +which collects the information on the remote host for this very +special purpose with one round-trip per-call. + +@defun tramp-add-external-operation operation function backend +This adds an implementation of @var{operation} to @value{tramp}'s +backend @var{backend}. @var{function} is the new implementation. + +Both @var{operation} and @var{function} shall be function symbols. +They must have the same argument list. The first argument is used to +determine, whether @value{tramp} is invoked (check for remote file +name syntax). It must be a string or nil, in the latter case +@code{default-directory} is used for the check. + +@var{backend}, also a symbol, is the feature name of a @value{tramp} +backend (except @code{tramp-ftp}). The new implementation will be +applied only for this backend. Example: + +@lisp +@group +(defun test-operation (file) + (message "Original implementation for %s" file)) +@end group + +@group +(defun handle-test-operation (file) + (message "Handler implementation for %s" file)) +@end group + +@group +(tramp-add-external-operation + #'test-operation #'handle-test-operation 'tramp-sh) +@end group +@end lisp + +Then we have the different use cases: + +@lisp +@group +;; Local file name. +(test-operation "/a/b") +@result{} "Original implementation for /a/b" +@end group + +@group +;; Remote file name, handled by `tramp-sh'. +(test-operation "/ssh::/a/b") +@result{} "Handler implementation for /ssh::/a/b" +@end group + +@group +;; Remote file name, handled by `tramp-gvfs'. +(test-operation "/sftp::/a/b") +@result{} "Original implementation for /sftp::/a/b" +@end group +@end lisp + +@var{function} is implemented like an ordinary @value{tramp} backend +handler, see the examples in @code{tramp--handle-*} and +@code{tramp-handle-*}. It can expect, that the first argument (or +@code{default-directory}, if that is @code{nil}) has remote file name +syntax. It shall use @value{tramp} internal macros and functions like +@code{with-parsed-tramp-file-name} and the different cache functions. + +If the same @var{function} shall be used for different @value{tramp} +backends, @code{tramp-add-external-operation} must be called for every +backend, respectively. +@end defun + +@defun tramp-remove-external-operation operation backend +The handler for @var{operation}, added by +@code{tramp-add-external-operation}, is removed from @var{backend}. +If there are handlers of @var{operation} for other @var{backend}s, +they are kept. Example: + +@lisp +@group +(tramp-remove-external-operation + #'test-operation 'tramp-sh) +@end group +@end lisp +@end defun + + @node Traces and Profiles @chapter How to Customize Traces @vindex tramp-verbose @vindex tramp-debug-to-file @vindex tramp-debug-command-messages +@vindex tramp-debug-buffer-limit @value{tramp} messages are raised with verbosity levels ranging from 0 to 10. @value{tramp} does not display all messages; only those with a @@ -6814,6 +6919,12 @@ strings), and the entry and exit messages for the function @code{tramp-file-name-handler}. This is intended for @value{tramp} maintainers, analyzing the remote commands for performance analysis. +The debug buffer can be very large, if @code{tramp-verbose} is high, +and @value{tramp} runs for a long time. If the buffer size exceeds +@code{tramp-debug-buffer-limit} (3GB by default), a warning will be +raised. This user option can be adapted to your needs; a value of 0 +means that there is no limit (no warning). + @node GNU Free Documentation License @appendix GNU Free Documentation License @@ -6841,7 +6952,7 @@ maintainers, analyzing the remote commands for performance analysis. @bye -@c TODO +@c TODO: @c @c * Say something about the .login and .profile files of the remote @c shells. @@ -6850,3 +6961,5 @@ maintainers, analyzing the remote commands for performance analysis. @c host and then send commands to it. @c @c * Consistent small or capitalized words especially in menus. +@c +@c * Starting with Emacs 29, use 'setopt' in the examples. diff --git a/etc/AUTHORS b/etc/AUTHORS index 9d289f0edf8..ff7c2cc4ee6 100644 --- a/etc/AUTHORS +++ b/etc/AUTHORS @@ -304,7 +304,7 @@ Anders Waldenborg: changed emacsclient.c Andrea Corallo: wrote comp-common.el comp-cstr-tests.el comp-cstr.el comp-run.el comp-tests.el comp.c comp.el syncdoc-type-hierarchy.el and changed pdumper.c lread.c bytecomp.el configure.ac startup.el - loadup.el comp.h lisp.h cl-macs.el cl-preloaded.el comp-test-funcs.el + loadup.el comp.h lisp.h cl-macs.el comp-test-funcs.el cl-preloaded.el subr.el Makefile.in data.c elisp-mode.el nadvice.el alloc.c byte-run.el emacs.c lisp/Makefile.in advice.el and 101 other files @@ -1740,7 +1740,7 @@ and co-wrote help-tests.el and changed xdisp.c display.texi w32.c msdos.c simple.el w32fns.c files.el fileio.c keyboard.c configure.ac emacs.c text.texi w32term.c dispnew.c frames.texi files.texi w32proc.c xfaces.c window.c - dispextern.h lisp.h and 1407 other files + dispextern.h lisp.h and 1409 other files Eliza Velasquez: changed server.el simple.el @@ -2625,7 +2625,7 @@ James TD Smith: changed org.el org-colview.el org-clock.el org.texi James Thomas: changed eww.el nnmail.el quail/indian.el gnus-cache.el - gnus-msg.el ind-util.el info-look.el progmodes/python.el + gnus-msg.el gnus.texi ind-util.el info-look.el progmodes/python.el James Troup: changed gnus-sum.el @@ -3198,8 +3198,8 @@ Joshua Datko: changed fortune.el Joshua Varner: changed intro.texi -Jostein Kjønigsen: changed csharp-mode.el typescript-ts-mode.el js.el - eglot.el progmodes/compile.el README dotnet-appconfig.rnc +Jostein Kjønigsen: changed csharp-mode.el typescript-ts-mode.el eglot.el + js.el progmodes/compile.el README dotnet-appconfig.rnc dotnet-packages-config.rnc dotnet-packages-props.rnc dotnet-resx.rnc json-ts-mode.el msbuild.rnc nuget.rnc nuspec.rnc nxml-mode.el schemas.xml treesit.el @@ -3443,6 +3443,8 @@ and changed pgg-gpg.el pgg.el progmodes/python.el locked-encrypted.png locked-encrypted.xpm pgg-pgp.el pgg-pgp5.el unlocked-encrypted.png unlocked-encrypted.xpm README edebug.el pgg.texi tips.texi +Ken Mankoff: changed leuven-dark-theme.el leuven-theme.el + Kenneth Stailey: changed alpha.h configure.ac ns32000.h openbsd.h pmax.h sparc.h unexalpha.c unexelf.c @@ -3564,11 +3566,11 @@ Koichi Arakawa: changed tramp-sh.el w32proc.c Konrad Hinsen: wrote ol-eshell.el and changed ob-python.el -Konstantin Kharlamov: changed smerge-mode.el diff-mode.el files.el - indent.erts typescript-ts-mode.el ada-mode.el alloc.c autorevert.el - calc-aent.el calc-ext.el calc-lang.el cc-mode.el cperl-mode.el - css-mode.el cua-rect.el dnd.el ebnf-abn.el ebnf-dtd.el ebnf-ebx.el - emacs-module-tests.el epg.el and 33 other files +Konstantin Kharlamov: changed indent.erts smerge-mode.el + typescript-ts-mode.el diff-mode.el files.el ada-mode.el alloc.c + autorevert.el calc-aent.el calc-ext.el calc-lang.el cc-mode.el + cperl-mode.el css-mode.el cua-rect.el dnd.el ebnf-abn.el ebnf-dtd.el + ebnf-ebx.el emacs-module-tests.el epg.el and 33 other files Konstantin Kliakhandler: changed org-agenda.el @@ -3727,6 +3729,8 @@ Lewis Perin: changed emacs-x86.manifest Liam Healy: changed outline.el +Liam Hupfer: changed js.el + Liam Stitt: changed url-file.el url-vars.el Liang Wang: changed etags.el @@ -5058,9 +5062,9 @@ Piotr Zieliński: wrote org-mouse.el Pip Cet: wrote image-circular-tests.el and changed xdisp.c comp.c byte-opt.el fns.c pdumper.c alloc.c - display.texi ftcrfont.c image.c sfnt.c xterm.c DEBUG bytecomp-tests.el - bytecomp.el ccl-tests.el ccl.c ccl.el cl-macs.el cmds.c comint.el - comp-test-funcs.el and 34 other files + display.texi eval.c ftcrfont.c image.c sfnt.c xterm.c DEBUG + bytecomp-tests.el bytecomp.el ccl-tests.el ccl.c ccl.el cl-macs.el + cmds.c comint.el and 34 other files Platon Pronko: changed tramp.el @@ -5538,10 +5542,10 @@ Sean O'Rourke: changed complete.el comint.el dabbrev.el find-func.el Sean Sieger: changed emacs-lisp-intro.texi Sean Whitton: wrote em-elecslash.el em-extpipe-tests.el em-extpipe.el -and changed vc-git.el project.el bindings.el server.el simple.el subr.el - vc-dispatcher.el vc.el window.el eshell-tests.el eshell.texi subr-x.el - .dir-locals.el cl-macs.el eshell-tests-helpers.el files.texi ftfont.c - remember.el startup.el term.el INSTALL and 38 other files +and changed vc-git.el project.el vc.el bindings.el server.el simple.el + subr.el vc-dispatcher.el window.el eshell-tests.el eshell.texi + subr-x.el .dir-locals.el cl-macs.el eshell-tests-helpers.el files.texi + ftfont.c remember.el startup.el term.el INSTALL and 40 other files Sebastian Fieber: changed gnus-art.el mm-decode.el mm-view.el @@ -6430,6 +6434,8 @@ and changed ps-prin1.ps ps-bdf.el ps-prin0.ps blank-mode.el ps-prin3.ps easymenu.el loading.texi menu-bar.el misc.texi progmodes/compile.el ps-print-def.el ps-vars.el +Vinícius Moraes: changed cmuscheme.el + Vitalie Spinu: changed comint.el eieio-base.el message.el ob-R.el ob-core.el ob-tangle.el subr.el @@ -6593,7 +6599,7 @@ Xi Lu: changed etags.c htmlfontify.el ruby-mode.el CTAGS.good_crlf man-tests.el man.el shortdoc.el tramp-sh.el Xiyue Deng: changed emacs-lisp-intro.texi strings.texi functions.texi - symbols.texi + smtpmail.el symbols.texi Xuan Wang: changed warnings.el diff --git a/etc/DEBUG b/etc/DEBUG index 25049ad42b4..dc1601a34f8 100644 --- a/etc/DEBUG +++ b/etc/DEBUG @@ -211,15 +211,19 @@ the debugger, but before running it, is the most efficient way of making sure control will be returned to the debugger when you need that. -'Fsignal' is a very useful place to put a breakpoint in. All Lisp -errors go through there. If you are only interested in errors that -would fire the Lisp debugger, breaking at 'maybe_call_debugger' is -useful. +The function 'debugger-trap' is a do-nothing interactive command that +exists to give control to the debugger. It is convenient to set a +breakpoint there to give control to the debugger when the function is +called. You can invoke it interactively with "M-x debugger-trap RET". +The src/.gdbinit file in the Emacs source distribution sets a breakpoint +in this function, so if you arrange for .gdbinit to be loaded, or load +it manually in a debugging session, the breakpoint is set for you +automatically. -Another technique for getting control to the debugger is to put a -breakpoint in some rarely used function. One such convenient function -is Fredraw_display, which you can invoke at will interactively with -"M-x redraw-display RET". +'Fsignal' is another very useful place to put a breakpoint in. All Lisp +errors go through there. If you are only interested in errors that +would fire the Lisp debugger, breaking at 'maybe_call_debugger' is a +useful alternative. It is also useful to have a guaranteed way to return to the debugger at any arbitrary time. When using X, this is easy: type C-z at the diff --git a/etc/HISTORY b/etc/HISTORY index bb8155de112..5758d5853d5 100644 --- a/etc/HISTORY +++ b/etc/HISTORY @@ -241,6 +241,8 @@ GNU Emacs 29.4 (2024-06-22) emacs-29.4 GNU Emacs 30.1 (2025-02-23) emacs-30.1 +GNU Emacs 30.2 (2025-08-14) emacs-30.2 + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/etc/NEWS b/etc/NEWS index e12a9dcb127..4a193484591 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -162,15 +162,26 @@ behavior, customize 'find-function-mode-lower-precedence' to non-nil. ** Minibuffer and Completions +++ -*** New user option 'completion-eager-display'. -This option configures whether completion commands should display the -"*Completions*" buffer immediately. When the option is set to t, all -completion commands show "*Completions*" immediately, respectively nil -disables the eager display for all commands. The default setting auto -enables eager completion only if requested by the command. -For more fine-grained control you can also toggle this feature by -category using the symbol 'eager-display' in the user option -'completion-category-overrides'. +*** Support for immediate display of the "*Completions*" buffer. +Whenever a minibuffer with completion is opened, the "*Completions*" +buffer will now be displayed immediately if the completion property +'eager-display', set by the completion table, is non-nil. This property +can be overridden for different completion categories by customizing +'completion-category-overrides'. Alternatively, the new user option +'completion-eager-display' can be set to t to force eager display of +"*Completions*" for all minibuffers, or nil to suppress this for all +minibuffers. + ++++ +*** Support for updating "*Completions*" as you type. +If the "*Completions*" buffer is displayed, it will now be updated as +you type if the completion property 'eager-update', set by the +completion table, is non-nil. This property can be overridden for +different completion categories by customizing +'completion-category-overrides'. Alternatively, the new user option +'completion-eager-update can be set to t to make "*Completions*" always +be updated as you type, or nil to suppress this always. Note that for +large or inefficient completion tables this can slow down typing. +++ *** New user option 'completion-pcm-leading-wildcard'. @@ -436,6 +447,11 @@ a buffer. The value must be a condition which is passed to With this user option, if non-nil (the default), the tab close button will change its appearance if the tab buffer has been modified. +--- +*** New user option 'tab-line-tabs-window-buffers-filter-function'. +This user option controls which buffers should appear in the tab line. +By default, this is set to not filter the buffers. + ** Project --- @@ -452,17 +468,31 @@ It is equivalent to running 'project-any-command' with The prompt now displays the chosen project on which to invoke a command. --- -*** The MAYBE-PROMPT argument of 'project-current' can be a string. -When such value is used, the 'project-prompter' is called with it as the -first argument. This is a way for the callers to indicate, for example, -the reason or the context why the project is asked for. +*** 'project-prompter' values may be called with up to three arguments. +These allow callers of the value of 'project-prompter' to specify a +prompt string; prompt the user to choose between a subset of all the +known projects; and disallow returning arbitrary directories. +See the docstring of 'project-prompter' for a full specification of +these new optional arguments. --- -*** New command 'project-find-matching-file'. +*** 'project-current' has a new optional argument, MAYBE-PROMPT. +If 'project-current' is called with this argument non-nil, then it is +passed to the 'project-prompter' to use as a prompt string. +Callers can use this to indicate the reason for which or context in +which Emacs should ask the user to select a project. + +--- +*** New command 'project-find-matching-buffer'. It can be used when switching between projects with similar file trees (such as Git worktrees of the same repository). It supports being invoked standalone or from the 'project-switch-commands' dispatch menu. +--- +*** New variable 'project-find-matching-buffer-function'. +Major modes can set this to major mode-specific functions to control how +'project-find-matching-buffer' finds matching buffers. + +++ *** New user option 'project-list-exclude'. This user option describes projects that should always be skipped by @@ -487,6 +517,13 @@ This is like 'C-x s', but only for this project's buffers. *** 'project-remember-project' can now be called interactively. +--- +*** 'project-shell' and 'project-eshell' support numeric prefix buffer naming. +They now accept numeric prefix arguments to select or create numbered +shell sessions. For example, 'C-2 C-x p s' switches to or creates a +buffer named "*name-of-project-shell<2>*". By comparison, a plain +universal argument as in 'C-u C-x p s' always creates a new session. + ** Registers *** New functions 'buffer-to-register' and 'file-to-register'. @@ -679,6 +716,15 @@ you could already use 'C-u C-x C-n' to clear the goal column. * Changes in Specialized Modes and Packages in Emacs 31.1 +** Autoinsert + ++++ +*** New condition for 'auto-insert-alist'. +'auto-insert-alist' now also allows to have a predicate taking no +argument as conditions. These types of conditions should be declared +with '(predicate FUNCTION)'. This allows to trigger 'auto-insert' +with finer grained control. + ** Register *** The "*Register Preview*" buffer shows only suitable registers. @@ -687,6 +733,12 @@ the default UI you get, i.e., when 'register-use-preview' is 'traditional'. ** Tree-sitter +*** New user option 'treesit-enabled-modes'. +You can customize it either to t to enable all available ts-modes, +or to select a list of ts-modes to enable. Depending on customization, +it modifies the variable 'major-mode-remap-alist' from the corresponding +variable 'treesit-major-mode-remap-alist' prepared by ts-mode packages. + *** New user option 'treesit-auto-install-grammar'. It controls the automatic installation of tree-sitter grammar libraries needed for tree-sitter based modes, if these grammar libraries are not @@ -878,6 +930,13 @@ 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. +** Lua-ts mode + +--- +*** New user option 'lua-ts-auto-close-block-comments'. +When non-nil, inserting a block comment "--[[" will close it by +inserting its respective "]]". By default, this is disabled. + ** Java-ts mode +++ @@ -894,6 +953,12 @@ option controls how much is indented for method chaining. ** PHP-ts mode +--- +*** 'php-ts-mode' now depends on 'mhtml-ts-mode'. +The direct dependency on js-ts-mode, css-ts-mode and html-ts-mode has +now been replaced by ‘mhtml-ts-mode’. Navigation, Outline and Imenu +work for all languages and code maintenance is easier. + --- *** 'php-ts-mode-run-php-webserver' can now accept a custom "php.ini" file. You can use the new optional argument CONFIG when calling @@ -902,6 +967,34 @@ the built-in Web server. Interactively, when invoked with a prefix argument, 'php-ts-mode-run-php-webserver' prompts for the config file as well as for other connection parameters. +--- +*** The option 'php-ts-mode-css-fontify-colors' has been removed. +'mhtml-ts-mode-css-fontify-colors' replaces this option. + +--- +*** New user option 'php-ts-mode-html-relative-indent'. +In buffers containing both PHP and HTML, this option allows you to +define how the PHP code should be indented relative to the position of +the HTML tags. + +--- +*** New user option 'php-ts-mode-html-indent-offset'. +Offset of PHP code block relative to HTML tags. + +--- +*** New user option 'php-ts-mode-find-sibling-rules'. +Rules for finding siblings of a PHP file. + +--- +*** New user option 'php-ts-mode-phpdoc-highlight-errors'. +When non nil, it highlights unknown PHPDOC tags using +'font-lock-warning-face' so that the user can identify them more easily. + +--- +*** New command 'php-ts-mode-show-ini'. +Show the location of the PHP ini files, if the buffer is associated to a remote +PHP file show the remote PHP ini files. + ** Rust-ts mode --- @@ -929,6 +1022,14 @@ characters in CJK texts. For example, 'A' is converted to 'A', '1' is converted to '1', etc. Companion commands 'halfwidth-region' and 'halfwidth-word' perform the opposite conversion. +** Texinfo mode + +--- +*** texinfo-mode now can auto-close the ``'' pairs. +Now inserting `` in 'texinfo-mode' will close it by inserting its +respective '', if 'electric-pair-mode' is enabled. + + ** ASM mode --- @@ -1112,6 +1213,14 @@ slot. Symbol macros are created for the accessor functions using If 'whitespace-style' includes 'missing-newline-at-eof' (which is the default), the 'whitespace-cleanup' function will now add the newline. +--- +*** 'whitespace-mode' now can prettify page delimiter characters (^L). +If 'page-delimiters' is set in 'whitespace-style', or the new minor mode +'whitespace-page-delimiters-mode' is on, the page delimiter characters +(^L) are displayed as a pretty horizontal line that spans the entire +width of the window. The new 'whitespace-page-delimiter' face can be +used to customize the appearence. + ** Bookmark --- @@ -1603,6 +1712,15 @@ This feature is experimental. --- *** Implementation of filesystem notifications for connection method "smb". ++++ +*** New functions to extend the set of operations with a remote implementation. +The new functions 'tramp-add-external-operation' and +'tramp-remove-external-operation' allow to add an implementation for +other operations but the defined set of magic file name operations. +This can be used by external ELPA packages for performance optimizations +in special cases. For more information, see "(tramp) New operations" in +the Tramp manual. + ** Diff --- @@ -1827,11 +1945,11 @@ restart Emacs. *** Support of 'electric-layout-mode' added. --- -*** DEL now deletes the text in the active region when point is between indentation. -The command 'python-indent-dedent-line-backspace' (by default bound to -'DEL') now deletes the text in the region and deactivates the mark if -Transient Mark mode is enabled, the mark is active, and prefix argument -is 1. +*** 'DEL' now deletes the text in the active region. +When point is between indentation, the command +'python-indent-dedent-line-backspace' (by default bound to 'DEL') now +deletes the text in the region and deactivates the mark if Transient +Mark mode is enabled, the mark is active, and prefix argument is 1. ** Tmm Menubar @@ -1892,6 +2010,7 @@ other working trees: - 'C-x v w c': Add a new working tree. - 'C-x v w w': Visit this file in another working tree. +- 'C-x v w s': Like 'C-x p p' but limited to other working trees. - 'C-x v w x': Delete a working tree you no longer need. - 'C-x v w R': Relocate a working tree to another file name. @@ -2158,6 +2277,16 @@ destination window is chosen using 'display-buffer-alist'. Example: display-buffer-use-some-window) (some-window . mru)))) +** Revert + ++++ +*** Variable 'revert-buffer-in-progress' has been renamed. +The old name, 'revert-buffer-in-progress-p', is kept as obsolete +variable alias. + +Symbol names with a trailing '-p' are reserved for predicates. Calling +a variable like this was a mistake. + ** Autorevert +++ @@ -2171,6 +2300,12 @@ 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 variable 'auto-revert-buffer-in-progress'. +'auto-revert-buffer' binds this variable to a non-nil value while it is +working. This can be used by major mode 'revert-buffer-function' +implementations to suppress messages in Auto Revert modes, for example. + ** Strokes -- @@ -2426,6 +2561,12 @@ modifier, it scrolls by year. The month and year navigation key bindings 'M-}', 'M-{', 'C-x ]' and 'C-x [' now have the alternative keys '}', '{', ']' and '['. +--- +*** Avoid modifying Calendar's user options. +The user options 'calendar-mark-holidays-flag' and +'calendar-mark-diary-entries-flag' are not modified anymore when +changing the marking state in the calendar buffer. + ** Calc *** New user option 'calc-string-maximum-character'. @@ -2472,10 +2613,10 @@ Use the byte-compiler instead; it provides more and more useful warnings. --- *** New user option 'newsticker-hide-old-feed-header'. It controls whether to automatically hide the header of feeds whose -items are all old or obsolete in the plainview *newsticker* buffer. +items are all old or obsolete in the plainview "*newsticker*" buffer. This is only visually interesting if the content of those feeds are also hidden (see 'newsticker-hide-old-items-in-newsticker-buffer' and -'newsticker-show-descriptions-of-new-items')." +'newsticker-show-descriptions-of-new-items'). --- *** New commands to hide and show headers of old newsticker feeds. @@ -2487,7 +2628,6 @@ or obsolete. ** CPerl mode *** Syntax of Perl up to version 5.42 is supported. - CPerl mode creates imenu entries for ":writer" generated accessors and recognizes the new functions "all" and "any". See https://perldoc.perl.org/5.42.0/perldelta for details. @@ -2599,6 +2739,21 @@ That is, if the PATH environment variable is unset or empty, 'exec-path' now acts as if PATH is the system default, which is "/bin:/usr/bin" on GNU/Linux systems. +--- +** New variable 'tty-cursor-movement-use-TAB-BS'. +The display optimization where the combination TAB characters + +BACKSPACE is used to move to a position on a TTY frame is now disabled +by default and controlled by this variable; it can be set to non-nil +to keep the old behavior. This change is to accomodate screen +readers. + ++++ +** A thread's current buffer can now be killed. +We introduce a new attribute for threads called buffer-disposition. +See the new argument in 'make-thread'. The default value allows the +thread's current buffer to be killed by another thread. This does not +apply to the main thread's buffer. + * Lisp Changes in Emacs 31.1 diff --git a/etc/NEWS.21 b/etc/NEWS.21 index ed7b69f18e6..2b6b6084c6e 100644 --- a/etc/NEWS.21 +++ b/etc/NEWS.21 @@ -1822,7 +1822,7 @@ separate Texinfo file. *** The PCL-CVS package available by either running M-x cvs-examine or by visiting a CVS administrative directory (with a prefix argument) -provides an alternative interface to VC-dired for CVS. It comes with +provides an alternative interface to VC-Dir for CVS. It comes with 'log-view-mode' to view RCS and SCCS logs and 'log-edit-mode' used to enter check-in log messages. diff --git a/etc/NEWS.30 b/etc/NEWS.30 index c52929b6d38..dfe6c5cafe6 100644 --- a/etc/NEWS.30 +++ b/etc/NEWS.30 @@ -15,32 +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'. - -* Installation Changes in Emacs 30.2 - - -* Startup Changes in Emacs 30.2 - * Changes in Emacs 30.2 - - -* Editing Changes in Emacs 30.2 - - -* Changes in Specialized Modes and Packages in Emacs 30.2 - - -* New Modes and Packages in Emacs 30.2 - - -* Incompatible Lisp Changes in Emacs 30.2 - - -* Lisp Changes in Emacs 30.2 - - -* Changes in Emacs 30.2 on Non-Free Operating Systems +Emacs 30.2 is a bug-fix release with no new features. * Installation Changes in Emacs 30.1 diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 10ff3871074..8f6c71a4b74 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -897,7 +897,7 @@ when parsing the archive." "Toggle alternative display. To avoid very long lines archive mode does not show all information. This function changes the set of information shown for each files." - (interactive) + (interactive nil archive-mode) (setq archive-alternate-display (not archive-alternate-display)) (setq-local archive-hidden-columns (if archive-alternate-display @@ -913,7 +913,8 @@ This function changes the set of information shown for each files." (list (intern (completing-read "Toggle visibility of: " '(Mode Ids Ratio Date&Time) - nil t)))) + nil t))) + archive-mode) (setq-local archive-hidden-columns (if (memq column archive-hidden-columns) (remove column archive-hidden-columns) @@ -1133,7 +1134,8 @@ NEW-NAME." (or (archive-get-marked ?*) (list (archive-get-descr)))))) (list names (read-file-name (format "Copy %s to: " (string-join names ", ")) - nil default-directory)))) + nil default-directory))) + archive-mode) (unless (consp files) (setq files (list files))) (when (and (> (length files) 1) @@ -1171,7 +1173,7 @@ NEW-NAME." (defun archive-extract (&optional other-window-p event) "In archive mode, extract this entry of the archive into its own buffer." - (interactive (list nil last-input-event)) + (interactive (list nil last-input-event) archive-mode) (if event (posn-set-point (event-end event))) (let* ((view-p (eq other-window-p 'view)) (descr (archive-get-descr)) @@ -1348,17 +1350,17 @@ NEW-NAME." (defun archive-extract-other-window () "In archive mode, find this member in another window." - (interactive) + (interactive nil archive-mode) (archive-extract t)) (defun archive-display-other-window () "In archive mode, display this member in another window." - (interactive) + (interactive nil archive-mode) (archive-extract 'display)) (defun archive-view () "In archive mode, view the member on this line." - (interactive) + (interactive nil archive-mode) (archive-extract 'view)) (defun archive-add-new-member (arcbuf name) @@ -1469,7 +1471,7 @@ NEW-NAME." (defun archive-flag-deleted (p &optional type) "In archive mode, mark this member to be deleted from the archive. With a prefix argument, mark that many files." - (interactive "p") + (interactive "p" archive-mode) (or type (setq type ?D)) (beginning-of-line) (let ((sign (if (>= p 0) +1 -1)) @@ -1488,18 +1490,18 @@ With a prefix argument, mark that many files." (defun archive-unflag (p) "In archive mode, un-mark this member if it is marked to be deleted. With a prefix argument, un-mark that many files forward." - (interactive "p") + (interactive "p" archive-mode) (archive-flag-deleted p ?\s)) (defun archive-unflag-backwards (p) "In archive mode, un-mark this member if it is marked to be deleted. With a prefix argument, un-mark that many members backward." - (interactive "p") + (interactive "p" archive-mode) (archive-flag-deleted (- p) ?\s)) (defun archive-unmark-all-files () "Remove all marks." - (interactive) + (interactive nil archive-mode) (let ((modified (buffer-modified-p)) (inhibit-read-only t)) (save-excursion @@ -1514,7 +1516,7 @@ With a prefix argument, un-mark that many members backward." "In archive mode, mark this member for group operations. With a prefix argument, mark that many members. Use \\[archive-unmark-all-files] to remove all marks." - (interactive "p") + (interactive "p" archive-mode) (archive-flag-deleted p ?*)) (defun archive-get-marked (mark &optional default) @@ -1532,20 +1534,20 @@ Use \\[archive-unmark-all-files] to remove all marks." ;;; Section: Operate (defun archive-next-line (p) - (interactive "p") + (interactive "p" archive-mode) (forward-line p) (or (eobp) (forward-char archive-file-name-indent))) (defun archive-previous-line (p) - (interactive "p") + (interactive "p" archive-mode) (archive-next-line (- p))) (defun archive-chmod-entry (new-mode) "Change the protection bits associated with all marked or this member. The new protection bits can either be specified as an octal number or as a relative change like \"g+rw\" as for chmod(2)." - (interactive "sNew mode (octal or symbolic): ") + (interactive "sNew mode (octal or symbolic): " archive-mode) (if archive-read-only (error "Archive is read-only")) (let ((func (archive-name "chmod-entry"))) (if (fboundp func) @@ -1556,7 +1558,7 @@ as a relative change like \"g+rw\" as for chmod(2)." (defun archive-chown-entry (new-uid) "Change the owner of all marked or this member." - (interactive "nNew uid: ") + (interactive "nNew uid: " archive-mode) (if archive-read-only (error "Archive is read-only")) (let ((func (archive-name "chown-entry"))) (if (fboundp func) @@ -1567,7 +1569,7 @@ as a relative change like \"g+rw\" as for chmod(2)." (defun archive-chgrp-entry (new-gid) "Change the group of all marked or this member." - (interactive "nNew gid: ") + (interactive "nNew gid: " archive-mode) (if archive-read-only (error "Archive is read-only")) (let ((func (archive-name "chgrp-entry"))) (if (fboundp func) @@ -1607,7 +1609,7 @@ as a relative change like \"g+rw\" as for chmod(2)." (defun archive-expunge () "Do the flagged deletions." - (interactive) + (interactive nil archive-mode) (archive--expunge-maybe-force nil)) (defun archive-*-expunge (archive files command) @@ -1616,7 +1618,7 @@ as a relative change like \"g+rw\" as for chmod(2)." (defun archive-rename-entry (newname) "Change the name associated with this entry in the archive file." - (interactive "sNew name: ") + (interactive "sNew name: " archive-mode) (if archive-read-only (error "Archive is read-only")) (if (string= newname "") (error "Archive members may not be given empty names")) @@ -1644,7 +1646,7 @@ as a relative change like \"g+rw\" as for chmod(2)." (defun archive-undo () "Undo in an archive buffer. This doesn't recover lost files, it just undoes changes in the buffer itself." - (interactive) + (interactive nil archive-mode) (let ((inhibit-read-only t)) (undo))) diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el index e7492d1b9ed..d5ccb7d1e0e 100644 --- a/lisp/autoinsert.el +++ b/lisp/autoinsert.el @@ -323,8 +323,11 @@ The document was typeset with ")) "A list specifying text to insert by default into a new file. Elements look like (CONDITION . ACTION) or ((CONDITION . DESCRIPTION) . ACTION). -CONDITION may be a regexp that must match the new file's name, or it may be -a symbol that must match the major mode for this element to apply. +CONDITION may be a regexp that must match the new file's name, or it +may be a symbol that must match the major mode for this element to apply. +CONDITION can also be a custom predicate of no arguments declared +with (predicate FUNCTION). Emacs will insert the text if the +predicate function returns non-nil. Only the first matching element is effective. Optional DESCRIPTION is a string for filling `auto-insert-prompt'. ACTION may be a skeleton to insert (see `skeleton-insert'), an absolute @@ -368,12 +371,24 @@ Matches the visited file name against the elements of `auto-insert-alist'." (pcase-lambda (`(,cond . ,action)) (if (atom cond) (setq desc cond) - (setq desc (cdr cond) - cond (car cond))) - (when (if (symbolp cond) - (derived-mode-p cond) + ;; if `cond' is a predicate, don't split it but set `desc' to a custom string + (if (and (consp cond) (equal (car cond) 'predicate)) + (setq desc "predicate") + (setq desc (cdr cond) + cond (car cond)))) + (when (cond + ;; `cond' should be a major-mode variable + ((symbolp cond) + (derived-mode-p cond)) + + ;; `cond' should be a predicate that takes no argument + ((and (consp cond) (equal (car cond) 'predicate)) + (funcall (cadr cond))) + + ;; cond should be a regexp + (t (and buffer-file-name - (string-match cond buffer-file-name))) + (string-match cond buffer-file-name)))) action)) auto-insert-alist))) (goto-char 1) diff --git a/lisp/autorevert.el b/lisp/autorevert.el index 2fae74ddc57..ccedaa759cb 100644 --- a/lisp/autorevert.el +++ b/lisp/autorevert.el @@ -329,6 +329,10 @@ seconds, in addition to using notification for those files." ;; Internal variables: +;;;###autoload +(defvar auto-revert-buffer-in-progress nil "\ +Non-nil if a `auto-revert-buffer' operation is in progress, nil otherwise.") + (defvar auto-revert-buffer-list () "List of buffers in Auto-Revert Mode. @@ -834,16 +838,15 @@ This is an internal function used by Auto-Revert Mode." t))))) eob eoblist) (when (timerp auto-revert--lockout-timer) - (cancel-timer auto-revert--lockout-timer)) - (setq auto-revert-notify-modified-p nil - auto-revert--last-time - (if revert (current-time) auto-revert--last-time) - auto-revert--lockout-timer nil) + (cancel-timer auto-revert--lockout-timer) + (setq auto-revert--lockout-timer nil)) (when revert (when (and auto-revert-verbose (not (eq revert 'fast))) (message "Reverting buffer `%s'" (buffer-name))) + (setq auto-revert-notify-modified-p nil + auto-revert--last-time (current-time)) ;; If point (or a window point) is at the end of the buffer, we ;; want to keep it at the end after reverting. This allows one ;; to tail a file. @@ -872,7 +875,7 @@ This is an internal function used by Auto-Revert Mode." ;; `preserve-modes' avoids changing the (minor) modes. But we do ;; want to reset the mode for VC, so we do it manually. (when (and (not auto-revert-tail-mode) (or revert auto-revert-check-vc-info)) - (let ((revert-buffer-in-progress-p t)) + (let ((revert-buffer-in-progress t)) (vc-refresh-state))))) (defun auto-revert-tail-handler (size) @@ -933,25 +936,25 @@ buffers not reverted last time due to user interruption." This is performed as specified by Auto-Revert and Global Auto-Revert Modes." - (if (not (buffer-live-p buf)) - (auto-revert-remove-current-buffer buf) - (with-current-buffer buf - ;; Test if someone has turned off Auto-Revert Mode - ;; in a non-standard way, for example by changing - ;; major mode. - (when (and (not auto-revert-mode) - (not auto-revert-tail-mode)) - (auto-revert-remove-current-buffer)) - (when (auto-revert-active-p) - ;; Enable file notification. - ;; Don't bother creating a notifier for non-file buffers - ;; unless it explicitly indicates that this works. - (when (and auto-revert-use-notify - (not auto-revert-notify-watch-descriptor) - (or buffer-file-name - buffer-auto-revert-by-notification)) - (auto-revert-notify-add-watch)) - (auto-revert-handler))))) + (let ((auto-revert-buffer-in-progress t)) + (if (not (buffer-live-p buf)) + (auto-revert-remove-current-buffer buf) + (with-current-buffer buf + ;; Test if someone has turned off Auto-Revert Mode in a + ;; non-standard way, for example by changing major mode. + (when (and (not auto-revert-mode) + (not auto-revert-tail-mode)) + (auto-revert-remove-current-buffer)) + (when (auto-revert-active-p) + ;; Enable file notification. + ;; Don't bother creating a notifier for non-file buffers + ;; unless it explicitly indicates that this works. + (when (and auto-revert-use-notify + (not auto-revert-notify-watch-descriptor) + (or buffer-file-name + buffer-auto-revert-by-notification)) + (auto-revert-notify-add-watch)) + (auto-revert-handler)))))) (defun auto-revert-buffers () "Revert buffers as specified by Auto-Revert and Global Auto-Revert Mode. diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el index 04bbc2cb8a4..04a42fcd38a 100644 --- a/lisp/calendar/calendar.el +++ b/lisp/calendar/calendar.el @@ -456,6 +456,12 @@ LEFT is the leftmost column associated with month segment N, FIRST and LAST are the first and last columns with day digits in, and LAST is the rightmost column.") +(defvar calendar-mark-holidays nil + "Variable version of the user option `calendar-mark-holidays-flag'.") + +(defvar calendar-mark-diary-entries nil + "Variable version of the user option `calendar-mark-diary-entries-flag'.") + (defun calendar-month-edges (segment) "Compute the month edge columns for month SEGMENT. Returns a list (LEFT FIRST LAST RIGHT), where LEFT is the @@ -1436,11 +1442,11 @@ Optional integers MON and YR are used instead of today's date." ;; For a full height window or a window that is horizontally ;; combined don't fit height to that of its buffer. (set-window-vscroll nil 0))) - (and calendar-mark-holidays-flag + (and calendar-mark-holidays ;; (calendar-date-is-valid-p today) ; useful for BC dates (calendar-mark-holidays)) (unwind-protect - (if calendar-mark-diary-entries-flag (diary-mark-entries)) + (if calendar-mark-diary-entries (diary-mark-entries)) (run-hooks (if today-visible 'calendar-today-visible-hook 'calendar-today-invisible-hook))))) @@ -1833,6 +1839,9 @@ For a complete description, see the info node `Calendar/Diary'. (make-local-variable 'calendar-mark-ring) (make-local-variable 'displayed-month) ; month in middle of window (make-local-variable 'displayed-year) ; year in middle of window + ;; Init with user options. + (setq calendar-mark-holidays calendar-mark-holidays-flag + calendar-mark-diary-entries calendar-mark-diary-entries-flag) ;; Most functions only work if displayed-month and displayed-year are set, ;; so let's make sure they're always set. Most likely, this will be reset ;; soon in calendar-generate, but better safe than sorry. @@ -2431,8 +2440,8 @@ interpreted as BC; -1 being 1 BC, and so on." (defun calendar-unmark () "Delete all diary/holiday marks/highlighting from the calendar." (interactive) - (setq calendar-mark-holidays-flag nil - calendar-mark-diary-entries-flag nil) + (setq calendar-mark-holidays nil + calendar-mark-diary-entries nil) (with-current-buffer calendar-buffer (mapc #'delete-overlay (overlays-in (point-min) (point-max))))) diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el index 3d8d827417e..056360bbede 100644 --- a/lisp/calendar/diary-lib.el +++ b/lisp/calendar/diary-lib.el @@ -1395,8 +1395,8 @@ marks. This is intended to deal with deleted diary entries." ;; ii) called via calendar-redraw (since calendar has already been ;; erased). ;; Use of REDRAW handles both of these cases. - (when (and redraw calendar-mark-diary-entries-flag) - (setq calendar-mark-diary-entries-flag nil) + (when (and redraw calendar-mark-diary-entries) + (setq calendar-mark-diary-entries nil) (calendar-redraw)) (let ((diary-marking-entries-flag t) (diary-buffer (find-buffer-visiting diary-file)) @@ -1417,7 +1417,7 @@ marks. This is intended to deal with deleted diary entries." ;; If including, caller has already verified it is readable. (insert-file-contents diary-file) (if (eq major-mode (default-value 'major-mode)) (diary-mode))) - (setq calendar-mark-diary-entries-flag t) + (setq calendar-mark-diary-entries t) (setq file-glob-attrs (nth 1 (diary-pull-attrs nil '()))) (with-syntax-table diary-syntax-table (save-excursion @@ -2243,7 +2243,7 @@ Prefix argument ARG makes the entry nonmarking." (defun diary-redraw-calendar () "If `calendar-buffer' is live and diary entries are marked, redraw it." - (and calendar-mark-diary-entries-flag + (and calendar-mark-diary-entries (save-excursion (calendar-redraw))) ;; Return value suitable for `write-contents-functions'. diff --git a/lisp/calendar/holidays.el b/lisp/calendar/holidays.el index b40c56abd86..28f3a0ae7f2 100644 --- a/lisp/calendar/holidays.el +++ b/lisp/calendar/holidays.el @@ -585,7 +585,7 @@ use instead of point." (with-current-buffer (if event (calendar-event-buffer event) (current-buffer)) - (setq calendar-mark-holidays-flag t) + (setq calendar-mark-holidays t) (message "Marking holidays...") (dolist (holiday (calendar-holiday-list)) (calendar-mark-visible-date (car holiday) calendar-holiday-marker)) diff --git a/lisp/cmuscheme.el b/lisp/cmuscheme.el index 51b183de347..0d591791d73 100644 --- a/lisp/cmuscheme.el +++ b/lisp/cmuscheme.el @@ -416,7 +416,7 @@ in the next one.") (setq scheme-prev-l/c-dir/file (cons (file-name-directory file-name) (file-name-nondirectory file-name))) (comint-send-string (scheme-proc) (concat "(load \"" - file-name + (file-local-name file-name) "\")\n"))) (defun scheme-compile-file (file-name) @@ -430,7 +430,7 @@ in the next one.") (setq scheme-prev-l/c-dir/file (cons (file-name-directory file-name) (file-name-nondirectory file-name))) (comint-send-string (scheme-proc) (concat "(compile-file \"" - file-name + (file-local-name file-name) "\")\n"))) diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el index 84380ee5c54..e5953f4a513 100644 --- a/lisp/completion-preview.el +++ b/lisp/completion-preview.el @@ -521,7 +521,9 @@ candidates or if there are multiple matching completions and (run-hook-wrapped 'completion-at-point-functions #'completion-preview--capf-wrapper) - (when-let* ((suffix (car suffixes))) + (when-let* ((suffix (car suffixes)) + (inhibit-quit t)) + ;; Critical section, do not quit upon receiving input here. (set-text-properties 0 (length suffix) (list 'face (if (cdr suffixes) 'completion-preview diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 59668f79bd7..ad602b00a3e 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -475,7 +475,9 @@ status message." nil))) (let ((omit-re (or regexp (dired-omit-regexp))) (old-modified-p (buffer-modified-p)) - (count (or init-count 0))) + (count (or init-count 0)) + (dired-omit-verbose + (and dired-omit-verbose (not auto-revert-buffer-in-progress)))) (unless (string= omit-re "") (let ((dired-marker-char dired-omit-marker-char)) (when dired-omit-verbose (message "Omitting...")) diff --git a/lisp/doc-view.el b/lisp/doc-view.el index b9bde21eaa8..30536cb4c6c 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -2143,7 +2143,11 @@ If FILE-NAME is nil, use the current file instead." (defun doc-view-initiate-display () ;; Switch to image display if possible. (if (doc-view-mode-p doc-view-doc-type) - (progn + ;; Inhibit the echo area display of the "Type C-c C-c..." message + ;; if the doc-view buffer is not shown in the selected window + ;; which can happen due to auto-reverting the buffer (bug#79145). + (let ((inhibit-message (not (eq (current-buffer) + (window-buffer))))) (doc-view-buffer-message) (setf (doc-view-current-page) (or (doc-view-current-page) 1)) (if (doc-view-already-converted-p) diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 6412c8cde22..49fd6084693 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -286,6 +286,12 @@ This is used by `declare'.") (list 'put (list 'quote name) ''edebug-form-spec (list 'quote spec))))) +(defalias 'byte-run--set-autoload-macro + #'(lambda (name _args spec) + (list 'function-put (list 'quote name) + ''autoload-macro (list 'quote spec))) + "Handle autoload-macro declarations") + (defalias 'byte-run--set-no-font-lock-keyword #'(lambda (name _args val) (list 'function-put (list 'quote name) @@ -365,8 +371,13 @@ This is used by `declare'.") (cons (list 'debug #'byte-run--set-debug) (cons - (list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword) - defun-declarations-alist)) + ;; macros can declare (autoload-macro expand) to request expansion + ;; during autoload generation of forms calling them. See + ;; `loaddefs-generate--make-autoload'. + (list 'autoload-macro #'byte-run--set-autoload-macro) + (cons + (list 'no-font-lock-keyword #'byte-run--set-no-font-lock-keyword) + defun-declarations-alist))) "List associating properties of macros to their macro expansion. Each element of the list takes the form (PROP FUN) where FUN is a function. For each (PROP . VALUES) in a macro's declaration, the FUN corresponding @@ -412,6 +423,8 @@ The return value is undefined. (if declarations (cons 'prog1 (cons def (car declarations))) def)))))) +;; Expand to defalias and related forms on autoload gen +(function-put 'defmacro 'autoload-macro 'expand) ; Since we cannot `declare' it ;; Now that we defined defmacro we can use it! (defmacro defun (name arglist &rest body) @@ -424,7 +437,9 @@ INTERACTIVE is an optional `interactive' specification. The return value is undefined. \(fn NAME ARGLIST [DOCSTRING] [DECL] [INTERACTIVE] BODY...)" - (declare (doc-string 3) (indent 2)) + (declare (doc-string 3) (indent 2) + ;; Expand to defalias on autoload gen + (autoload-macro expand)) (or name (error "Cannot define '%s' as a function" name)) (if (null (and (listp arglist) diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 4c6c6a0007c..e821b15378b 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -230,9 +230,11 @@ SPECIALIZERS-FUNCTION takes as first argument a tag value TAG (defmacro cl-defgeneric (name args &rest options-and-methods) "Create a generic function NAME. DOC-STRING is the base documentation for this class. A generic -function has no body, as its purpose is to decide which method body -is appropriate to use. Specific methods are defined with `cl-defmethod'. -With this implementation the ARGS are currently ignored. +function usually has no body, as its purpose is to decide which +method body is appropriate to use; ARGS are currently ignored if +there's no body. If BODY is present, it provides the default +implementation. +Specific implementation methods are defined with `cl-defmethod'. OPTIONS-AND-METHODS currently understands: - (:documentation DOCSTRING) - (declare DECLARATIONS) @@ -258,7 +260,9 @@ DEFAULT-BODY, if present, is used as the body of a default method. cl--generic-edebug-make-name in:method] lambda-doc def-body)]] - def-body))) + def-body)) + ;; Expand to defun and related forms on autoload definition + (autoload-macro expand)) (let* ((doc (if (stringp (car-safe options-and-methods)) (pop options-and-methods))) (declarations nil) diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index a076012cd30..08a6cbf209d 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -396,7 +396,9 @@ more details. [&optional ("interactive" interactive)] def-body)) (doc-string 3) - (indent 2)) + (indent 2) + ;; expand to function definition on autoload gen + (autoload-macro expand)) `(defun ,name ,@(cl--transform-lambda (cons args body) name))) ;;;###autoload @@ -414,7 +416,9 @@ and BODY is implicitly surrounded by (cl-block NAME ...). [&optional ("interactive" interactive)] def-body)) (doc-string 3) - (indent 2)) + (indent 2) + ;; expand (eventually) to function definition on autoload gen + (autoload-macro expand)) (require 'generator) `(iter-defun ,name ,@(cl--transform-lambda (cons args body) name))) @@ -473,7 +477,8 @@ more details. (declare (debug (&define name cl-macro-list cl-declarations-or-string def-body)) (doc-string 3) - (indent 2)) + (indent 2) + (autoload-macro expand)) ; expand to defmacro on autoload gen `(defmacro ,name ,@(cl--transform-lambda (cons args body) name))) (def-edebug-elem-spec 'cl-lambda-expr @@ -3087,7 +3092,9 @@ To see the documentation for a defined struct type, use sexp])] [&optional stringp] ;; All the above is for the following def-form. - &rest &or symbolp (symbolp &optional def-form &rest sexp)))) + &rest &or symbolp (symbolp &optional def-form &rest sexp))) + ;; expand to function definitions and related forms on autoload gen + (autoload-macro expand)) (let* ((name (if (consp struct) (car struct) struct)) (warning nil) (opts (cdr-safe struct)) diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index 46c99052090..ca921308877 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -222,10 +222,12 @@ INIT-VALUE LIGHTER KEYMAP. (indent defun) (debug (&define name string-or-null-p [&optional [¬ keywordp] sexp - &optional [¬ keywordp] sexp - &optional [¬ keywordp] sexp] + &optional [¬ keywordp] sexp + &optional [¬ keywordp] sexp] [&rest [keywordp sexp]] - def-body))) + def-body)) + ;; expand to the command definition on autoload gen + (autoload-macro expand)) (let* ((last-message (make-symbol "last-message")) (mode-name (symbol-name mode)) @@ -488,7 +490,9 @@ after running the major mode's hook. However, MODE is not turned on if the hook has explicitly disabled it. \(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)" - (declare (doc-string 2) (indent defun)) + (declare (doc-string 2) (indent defun) + ;; expand to the minor-mode definition on autoload gen + (autoload-macro expand)) (let* ((global-mode-name (symbol-name global-mode)) (mode-name (symbol-name mode)) (pretty-name (easy-mmode-pretty-mode-name mode)) @@ -499,8 +503,8 @@ on if the hook has explicitly disabled it. (MODE-enable-in-buffer (intern (concat global-mode-name "-enable-in-buffer"))) (minor-MODE-hook (intern (concat mode-name "-hook"))) - (MODE-set-explicitly (intern (concat mode-name "-set-explicitly"))) - (MODE-major-mode (intern (concat (symbol-name mode) "-major-mode"))) + (MODE-set-explicitly (intern (concat mode-name "--set-explicitly"))) + (MODE-major-mode (intern (concat global-mode-name "--major-mode"))) (MODE-predicate (intern (concat (replace-regexp-in-string "-mode\\'" "" global-mode-name) "-modes"))) diff --git a/lisp/emacs-lisp/generator.el b/lisp/emacs-lisp/generator.el index 344e11e245e..c01e559fd5c 100644 --- a/lisp/emacs-lisp/generator.el +++ b/lisp/emacs-lisp/generator.el @@ -675,7 +675,8 @@ encapsulates the state of a computation that produces a sequence of values. Callers can retrieve each value using `iter-next'." (declare (indent defun) (debug (&define name lambda-list lambda-doc &rest sexp)) - (doc-string 3)) + (doc-string 3) + (autoload-macro expand)) ; expand to the defun on autoload gen (cl-assert lexical-binding) (let* ((parsed-body (macroexp-parse-body body)) (declarations (car parsed-body)) diff --git a/lisp/emacs-lisp/inline.el b/lisp/emacs-lisp/inline.el index c015e2b57d0..027c24c465b 100644 --- a/lisp/emacs-lisp/inline.el +++ b/lisp/emacs-lisp/inline.el @@ -135,7 +135,8 @@ After VARS is handled, BODY is evaluated in the new environment." This is like `defmacro', but has several advantages. See Info node `(elisp)Defining Functions' for more details." ;; FIXME: How can this work with CL arglists? - (declare (indent defun) (debug defun) (doc-string 3)) + (declare (indent defun) (debug defun) (doc-string 3) + (autoload-macro expand)) ; expand to the defun on autoload gen (let ((doc (if (stringp (car-safe body)) (list (pop body)))) (declares (if (eq (car-safe (car-safe body)) 'declare) (pop body))) (cm-name (intern (format "%s--inliner" name))) diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index a8500759cf8..9e91a11204d 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -143,12 +143,37 @@ scanning for autoloads and will be in the `load-path'." 3) form)) +;; The following macros are known to define functions, and are treated +;; specially when encountered during autoload generation, translating +;; calls to them directly into appropriate (autoload function ...) +;; forms. +;; +;; An alternative to appearing on this list is for a macro to declare +;; (autoload-macro expand), so calls to it get expanded into more basic +;; forms during generation. Macros may be removed from this list once +;; they request such expansion and produce suitable output (e.g. by +;; employing :autoload-end to omit unneeded forms). +(defconst loaddefs--defining-macros + '( define-skeleton define-derived-mode define-compilation-mode + define-generic-mode define-globalized-minor-mode define-minor-mode + cl-defun defun* cl-defmacro defmacro* define-overloadable-function + transient-define-prefix transient-define-suffix transient-define-infix + transient-define-argument transient-define-group + ;; Obsolete; keep until the alias is removed. + easy-mmode-define-global-mode + easy-mmode-define-minor-mode + define-global-minor-mode)) + +(defvar loaddefs--load-error-files nil) (defun loaddefs-generate--make-autoload (form file &optional expansion) "Turn FORM into an autoload or defvar for source file FILE. Returns nil if FORM is not a special autoload form (i.e. a function definition or macro definition or a defcustom). If EXPANSION is non-nil, we're processing the macro expansion of an -expression, in which case we want to handle forms differently." +expression, in which case we want to handle forms differently. + +Note that macros can request expansion by including `(autoload-macro +expand)' among their `declare' forms." (let ((car (car-safe form)) expand) (cond ((and expansion (eq car 'defalias)) @@ -192,42 +217,58 @@ expression, in which case we want to handle forms differently." (setq form (copy-sequence form)) (setcdr (memq :autoload-end form) nil)) (let ((exps (delq nil (mapcar (lambda (form) - (loaddefs-generate--make-autoload - form file expansion)) + (unless (eq form :autoload-end) + (loaddefs-generate--make-autoload + form file expansion))) (cdr form))))) (when exps (cons 'progn exps))))) - ;; For complex cases, try again on the macro-expansion. - ((and (memq car '( define-globalized-minor-mode defun defmacro - define-minor-mode define-inline - cl-defun cl-defmacro cl-defgeneric - cl-defstruct pcase-defmacro iter-defun cl-iter-defun - ;; Obsolete; keep until the alias is removed. - easy-mmode-define-global-mode - easy-mmode-define-minor-mode - define-global-minor-mode)) - (macrop car) - (setq expand (let ((load-true-file-name file) - (load-file-name file)) - (macroexpand form))) - (memq (car expand) '(progn prog1 defalias))) + ;; For macros which request it, try again on their expansion. + ((progn + ;; If the car is an unknown symbol, we load the file first to + ;; give packages a chance to define their macros. + (unless (or (not (symbolp car)) (fboundp car) + ;; Special cases handled below + (memq car loaddefs--defining-macros) + (memq car '(defclass defcustom deftheme defgroup nil)) + (assoc file load-history) + (member file loaddefs--load-error-files)) + (let ((load-path (cons (file-name-directory file) load-path))) + (message "loaddefs-gen: loading file %s (for %s)" file car) + (condition-case e (load file) + (error + (push file loaddefs--load-error-files) ; do not attempt again + (warn "loaddefs-gen: load error\n\t%s" e))))) + (and (macrop car) + (eq 'expand (function-get car 'autoload-macro)) + (setq expand (let ((load-true-file-name file) + (load-file-name file)) + (macroexpand form))) + (or (and + ;; Previously, macros defined in this list would not + ;; see their expansions processed in place of + ;; themselves if such an expansion did not yield a + ;; `progn', `prog1' or `defalias' form. Not + ;; reproducing these conditions results in the + ;; omission of minor mode variables and suchlike in + ;; loaddefs.el when only the defuns in the + ;; macroexpansions are autoloaded. + (not (memq car '( define-globalized-minor-mode defun defmacro + define-minor-mode define-inline + cl-defun cl-defmacro cl-defgeneric + cl-defstruct pcase-defmacro iter-defun cl-iter-defun + ;; Obsolete; keep until the alias is removed. + easy-mmode-define-global-mode + easy-mmode-define-minor-mode + define-global-minor-mode))) + (not (eq car (car expand)))) + (memq (car expand) '(progn prog1 defalias))))) ;; Recurse on the expansion. (loaddefs-generate--make-autoload expand file 'expansion)) - ;; For special function-like operators, use the `autoload' function. - ((memq car '( define-skeleton define-derived-mode - define-compilation-mode define-generic-mode - define-globalized-minor-mode - define-minor-mode - cl-defun defun* cl-defmacro defmacro* - define-overloadable-function - transient-define-prefix transient-define-suffix - transient-define-infix transient-define-argument - transient-define-group - ;; Obsolete; keep until the alias is removed. - easy-mmode-define-global-mode - easy-mmode-define-minor-mode - define-global-minor-mode)) + ;; For known special macros which define functions, use `autoload' + ;; directly. + ((memq car loaddefs--defining-macros) (let* ((macrop (memq car '(defmacro cl-defmacro defmacro*))) (name (nth 1 form)) (args (pcase car @@ -268,8 +309,8 @@ expression, in which case we want to handle forms differently." t) (and (eq (car-safe (car body)) 'interactive) ;; List of modes or just t. - (or (if (nthcdr 1 (car body)) - (list 'quote (nthcdr 1 (car body))) + (or (if (nthcdr 2 (car body)) + (list 'quote (nthcdr 2 (car body))) t)))) ,(if macrop ''macro nil))))) diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index c68b8961ee3..cd6b5e42771 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -544,7 +544,9 @@ to this macro. By convention, DOC should use \"EXPVAL\" to stand for the result of evaluating EXP (first arg to `pcase'). \n(fn NAME ARGS [DOC] &rest BODY...)" - (declare (indent 2) (debug defun) (doc-string 3)) + (declare (indent 2) (debug defun) (doc-string 3) + ;; Expand to defun and related forms on autoload gen + (autoload-macro expand)) ;; Add the function via `fsym', so that an autoload cookie placed ;; on a pcase-defmacro will cause the macro to be loaded on demand. (let ((fsym (intern (format "%s--pcase-macroexpander" name))) diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el index be191d63b9e..fb5c2b1829f 100644 --- a/lisp/emacs-lisp/timer.el +++ b/lisp/emacs-lisp/timer.el @@ -356,7 +356,7 @@ This function is called, by name, directly by the C code." (defun run-at-time (time repeat function &rest args) "Perform an action at time TIME. Repeat the action every REPEAT seconds, if REPEAT is non-nil. -REPEAT may be an integer or floating point number. +REPEAT may be a non-negative integer or floating point number. TIME should be one of: - a string giving today's time like \"11:23pm\" @@ -386,10 +386,10 @@ This function returns a timer object which you can use in `cancel-timer'." (interactive "sRun at time: \nNRepeat interval: \naFunction: ") - (when (and repeat - (numberp repeat) - (< repeat 0)) - (error "Invalid repetition interval")) + (unless (or (null repeat) + (and (numberp repeat) + (>= repeat 0))) + (error "Invalid repetition interval: %s" repeat)) (let ((timer (timer-create))) ;; Special case: nil means "now" and is useful when repeating. @@ -433,6 +433,7 @@ This function returns a timer object which you can use in "Perform an action after a delay of SECS seconds. Repeat the action every REPEAT seconds, if REPEAT is non-nil. SECS and REPEAT may be integers or floating point numbers. +REPEAT, if non-nil, must be a non-negative number. The action is to call FUNCTION with arguments ARGS. This function returns a timer object which you can use in `cancel-timer'." diff --git a/lisp/external-completion.el b/lisp/external-completion.el index a1aa7ec9cb6..5fd29f801fe 100644 --- a/lisp/external-completion.el +++ b/lisp/external-completion.el @@ -5,6 +5,7 @@ ;; Version: 0.1 ;; Author: Stefan Monnier ;; Maintainer: João Távora +;; Package-Requires: ((emacs "26.1")) ;; Keywords: ;; This is a GNU ELPA :core package. Avoid functionality that is not @@ -117,10 +118,11 @@ EXPANDED-PATTERN." completion-category-defaults))) (let ((cache (make-hash-table :test #'equal))) (cl-flet ((lookup-internal (string point) - (let ((key (cons string point))) - (if (hash-table-contains-p key cache) - (gethash key cache) - (puthash key (funcall lookup string point) cache))))) + (let* ((key (cons string point)) + (probe (gethash key cache 'external--notfound))) + (if (eq probe 'external--notfound) + (puthash key (funcall lookup string point) cache) + probe)))) (lambda (string pred action) (pcase action (`metadata diff --git a/lisp/files.el b/lisp/files.el index 33eefcc1da3..84e9254ca46 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2533,7 +2533,7 @@ If a buffer exists visiting FILENAME, return that one, but verify that the file has not changed since visited or saved. The buffer is not selected, just returned to the caller. Optional second arg NOWARN non-nil means suppress any warning messages, -and also don't verify the that the file has not been changed since +and also don't verify that the file has not been changed since last visited or saved. Optional third arg RAWFILE non-nil means the file is read literally. Optional fourth arg WILDCARDS non-nil means do wildcard processing @@ -2887,7 +2887,7 @@ error in reading the file. WARN non-nil means warn if there exists an auto-save file more recent than the visited file. NOAUTO means don't mess with auto-save mode. Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER is ignored -\(see `revert-buffer-in-progress-p' for similar functionality). +\(see `revert-buffer-in-progress' for similar functionality). Fifth arg NOMODES non-nil means don't alter the file's modes. Finishes by calling the functions in `find-file-hook' unless NOMODES is non-nil." @@ -7107,9 +7107,10 @@ hook functions. The function `revert-buffer--default' runs this. A customized `revert-buffer-function' need not run this hook.") -(defvar revert-buffer-in-progress-p nil +(define-obsolete-variable-alias + 'revert-buffer-in-progress-p 'revert-buffer-in-progress "31.1") +(defvar revert-buffer-in-progress nil "Non-nil if a `revert-buffer' operation is in progress, nil otherwise.") - (defvar revert-buffer-internal-hook) ;; `revert-buffer-function' was defined long ago to be a function of only @@ -7168,7 +7169,7 @@ revert buffers without querying for confirmation.) Optional third argument PRESERVE-MODES non-nil means don't alter the files modes. Normally we reinitialize them using `normal-mode'. -This function binds `revert-buffer-in-progress-p' non-nil while it operates. +This function binds `revert-buffer-in-progress' non-nil while it operates. This function calls the function that `revert-buffer-function' specifies to do the work, with arguments IGNORE-AUTO and NOCONFIRM. @@ -7189,7 +7190,7 @@ preserve markers and overlays, at the price of being slower." ;; reversal of the argument sense. So I'm just changing the user ;; interface, but leaving the programmatic interface the same. (interactive (list (not current-prefix-arg))) - (let ((revert-buffer-in-progress-p t) + (let ((revert-buffer-in-progress t) (revert-buffer-preserve-modes preserve-modes) restore-functions) (run-hook-wrapped 'revert-buffer-restore-functions diff --git a/lisp/gnus/nnrss.el b/lisp/gnus/nnrss.el index e166fa8424f..60282167409 100644 --- a/lisp/gnus/nnrss.el +++ b/lisp/gnus/nnrss.el @@ -496,7 +496,8 @@ which RSS 2.0 allows." (defun nnrss-read-server-data (server) (setq nnrss-server-data nil) (let ((file (nnrss-make-filename "nnrss" server)) - (file-name-coding-system nnmail-pathname-coding-system)) + (file-name-coding-system nnmail-pathname-coding-system) + (warning-inhibit-types '((files missing-lexbind-cookie)))) (when (file-exists-p file) (load file nil t t)))) @@ -505,7 +506,7 @@ which RSS 2.0 allows." (let ((coding-system-for-write nnrss-file-coding-system) (file-name-coding-system nnmail-pathname-coding-system)) (with-temp-file (nnrss-make-filename "nnrss" server) - (insert (format ";; -*- coding: %s; -*-\n" + (insert (format ";; -*- coding: %s; lexical-binding:t -*-\n" nnrss-file-coding-system)) (gnus-prin1 `(setq nnrss-group-alist ',nnrss-group-alist)) (insert "\n") @@ -520,7 +521,8 @@ which RSS 2.0 allows." (setq nnrss-group-max (or (cadr pair) 0)) (setq nnrss-group-min (+ nnrss-group-max 1))) (let ((file (nnrss-make-filename group server)) - (file-name-coding-system nnmail-pathname-coding-system)) + (file-name-coding-system nnmail-pathname-coding-system) + (warning-inhibit-types '((files missing-lexbind-cookie)))) (when (file-exists-p file) (load file nil t t) (dolist (e nnrss-group-data) @@ -535,7 +537,7 @@ which RSS 2.0 allows." (let ((coding-system-for-write nnrss-file-coding-system) (file-name-coding-system nnmail-pathname-coding-system)) (with-temp-file (nnrss-make-filename group server) - (insert (format ";; -*- coding: %s; -*-\n" + (insert (format ";; -*- coding: %s; lexical-binding:t -*-\n" nnrss-file-coding-system)) (gnus-prin1 `(setq nnrss-group-data ',nnrss-group-data))))) diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 9cd30107002..e9601d52e33 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -2253,13 +2253,14 @@ is enabled in the Help buffer." (describe-function major)))) (insert " mode") (when-let* ((file-name (find-lisp-object-file-name major nil))) - (insert (format " defined in %s:\n\n" + (insert (format " defined in %s" (buttonize (help-fns-short-filename file-name) (lambda (_) (help-function-def--button-function major file-name)))))) - (insert (help-split-fundoc (documentation major) nil 'doc) + (insert ":\n\n" + (help-split-fundoc (documentation major) nil 'doc) (with-current-buffer buffer (help-fns--list-local-commands))) (ensure-empty-lines 1) diff --git a/lisp/help.el b/lisp/help.el index 8b29a10e0cf..e6c5ea54812 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -2285,53 +2285,54 @@ ARGLIST can also be t or a string of the form \"(FUN ARG1 ARG2 ...)\"." "Return a formal argument list for the function DEF. If PRESERVE-NAMES is non-nil, return a formal arglist that uses the same names as used in the original source code, when possible." - ;; Handle symbols aliased to other symbols. - (if (and (symbolp def) (fboundp def)) (setq def (indirect-function def))) - ;; Advice wrappers have "catch all" args, so fetch the actual underlying - ;; function to find the real arguments. - (setq def (advice--cd*r def)) - ;; If definition is a macro, find the function inside it. - (if (eq (car-safe def) 'macro) (setq def (cdr def))) - (cond - ((and (closurep def) (listp (aref def 0))) (aref def 0)) - ((eq (car-safe def) 'lambda) (nth 1 def)) - ((and (featurep 'native-compile) - (subrp def) - (listp (subr-native-lambda-list def))) - (subr-native-lambda-list def)) - ((or (and (byte-code-function-p def) (integerp (aref def 0))) - (subrp def) (module-function-p def)) - (or (when preserve-names - (let* ((doc (condition-case nil (documentation def 'raw) (error nil))) - (docargs (if doc (car (help-split-fundoc doc nil)))) - (arglist (if docargs - (cdar (read-from-string (downcase docargs))))) - (valid t)) - ;; Check validity. - (dolist (arg arglist) - (unless (and (symbolp arg) - (let ((name (symbol-name arg))) - (if (and (> (length name) 0) (eq (aref name 0) ?&)) - (memq arg '(&rest &optional)) - (not (string-search "." name))))) - (setq valid nil))) - (when valid arglist))) - (let* ((arity (func-arity def)) - (max (cdr arity)) - (min (car arity)) - (arglist ())) - (dotimes (i min) - (push (intern (concat "arg" (number-to-string (1+ i)))) arglist)) - (when (and (integerp max) (> max min)) - (push '&optional arglist) - (dotimes (i (- max min)) - (push (intern (concat "arg" (number-to-string (+ 1 i min)))) - arglist))) - (unless (integerp max) (push '&rest arglist) (push 'rest arglist)) - (nreverse arglist)))) - ((and (autoloadp def) (not (eq (nth 4 def) 'keymap))) - "[Arg list not available until function definition is loaded.]") - (t t))) + (let ((orig-def def) + ;; Advice wrappers have "catch all" args, so fetch the actual underlying + ;; function to find the real arguments. + (def (advice--cd*r + (indirect-function def)))) ;; Follow aliases to other symbols. + ;; If definition is a macro, find the function inside it. + (if (eq (car-safe def) 'macro) (setq def (cdr def))) + (cond + ((and (closurep def) (listp (aref def 0))) (aref def 0)) + ((eq (car-safe def) 'lambda) (nth 1 def)) + ((and (featurep 'native-compile) + (subrp def) + (listp (subr-native-lambda-list def))) + (subr-native-lambda-list def)) + ((or (and (byte-code-function-p def) (integerp (aref def 0))) + (subrp def) (module-function-p def)) + (or (when preserve-names + (let* ((doc (ignore-errors (documentation orig-def 'raw))) + (docargs (if doc (car (help-split-fundoc doc nil)))) + (arglist (if docargs + (cdar (read-from-string (downcase docargs))))) + (valid t)) + ;; Check validity. + (dolist (arg arglist) + (unless (and (symbolp arg) + (let ((name (symbol-name arg))) + (if (and (> (length name) 0) + (eq (aref name 0) ?&)) + (memq arg '(&rest &optional)) + (not (string-search "." name))))) + (setq valid nil))) + (when valid arglist))) + (let* ((arity (func-arity def)) + (max (cdr arity)) + (min (car arity)) + (arglist ())) + (dotimes (i min) + (push (intern (concat "arg" (number-to-string (1+ i)))) arglist)) + (when (and (integerp max) (> max min)) + (push '&optional arglist) + (dotimes (i (- max min)) + (push (intern (concat "arg" (number-to-string (+ 1 i min)))) + arglist))) + (unless (integerp max) (push '&rest arglist) (push 'rest arglist)) + (nreverse arglist)))) + ((and (autoloadp def) (not (eq (nth 4 def) 'keymap))) + "[Arg list not available until function definition is loaded.]") + (t t)))) (defun help--make-usage (function arglist) (cons (if (symbolp function) function 'anonymous) diff --git a/lisp/indent-aux.el b/lisp/indent-aux.el index eeb8f1ee6bb..47d21f86649 100644 --- a/lisp/indent-aux.el +++ b/lisp/indent-aux.el @@ -50,13 +50,16 @@ is yanked." (delete-and-extract-region beg end) (buffer-substring beg end)))) (with-temp-buffer - ;; Indent/deindent the same as the major mode in the original - ;; buffer. - (setq indent-tabs-mode i-t-m) - (insert text) - (indent-rigidly (point-min) (point-max) - (- indentation)) - (buffer-string)))) + ;; We bind inhibit-read-only non-nil in case the copied text has + ;; read-only properties. + (let ((inhibit-read-only t)) + ;; Indent/deindent the same as the major mode in the original + ;; buffer. + (setq indent-tabs-mode i-t-m) + (insert text) + (indent-rigidly (point-min) (point-max) + (- indentation)) + (buffer-string))))) ;;;###autoload (define-minor-mode kill-ring-deindent-mode diff --git a/lisp/isearch.el b/lisp/isearch.el index 68519b7a820..5a79076c63d 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -1751,7 +1751,9 @@ You can update the global isearch variables by setting new values to ;; This is so that the user can do anything without failure, ;; like switch buffers and start another isearch, and return. (condition-case nil - (isearch-done t t) + (progn + (isearch-done t t) + (isearch-clean-overlays)) (exit nil)) ; was recursive editing ;; Save old point and isearch-other-end before reading from minibuffer @@ -1824,6 +1826,7 @@ You can update the global isearch variables by setting new values to (progn ;; (sit-for 1) ;; needed if isearch-done does: (message "") (isearch-done) + (isearch-clean-overlays) ;; The search done message is confusing when the string ;; is empty, so erase it. (if (equal isearch-string "") @@ -3790,19 +3793,20 @@ Optional third argument, if t, means if fail just return nil (no error). ;; point returns to the original location which surely is not contain ;; in any of these overlays, se we are safe in this case too. (defun isearch-open-necessary-overlays (ov) - (let ((inside-overlay (and (> (point) (overlay-start ov)) - (<= (point) (overlay-end ov)))) - ;; If this exists it means that the overlay was opened using - ;; this function, not by us tweaking the overlay properties. - (fct-temp (overlay-get ov 'isearch-open-invisible-temporary))) - (when (or inside-overlay (not fct-temp)) - ;; restore the values for the `invisible' properties. - (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible)) - (overlay-put ov 'isearch-invisible nil)) - (if inside-overlay - (funcall (overlay-get ov 'isearch-open-invisible) ov) - (if fct-temp - (funcall fct-temp ov t))))) + (when (overlay-buffer ov) + (let ((inside-overlay (and (> (point) (overlay-start ov)) + (<= (point) (overlay-end ov)))) + ;; If this exists it means that the overlay was opened using + ;; this function, not by us tweaking the overlay properties. + (fct-temp (overlay-get ov 'isearch-open-invisible-temporary))) + (when (or inside-overlay (not fct-temp)) + ;; restore the values for the `invisible' properties. + (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible)) + (overlay-put ov 'isearch-invisible nil)) + (if inside-overlay + (funcall (overlay-get ov 'isearch-open-invisible) ov) + (if fct-temp + (funcall fct-temp ov t)))))) ;; This is called when exiting isearch. It closes the temporary ;; opened overlays, except the ones that contain the latest match. @@ -3827,16 +3831,17 @@ Optional third argument, if t, means if fail just return nil (no error). (let ((overlays isearch-opened-overlays)) (setq isearch-opened-overlays nil) (dolist (ov overlays) - (if (isearch-intersects-p beg end (overlay-start ov) (overlay-end ov)) - (push ov isearch-opened-overlays) - (let ((fct-temp (overlay-get ov 'isearch-open-invisible-temporary))) - (if fct-temp - ;; If this exists it means that the overlay was opened - ;; using this function, not by us tweaking the overlay - ;; properties. - (funcall fct-temp ov t) - (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible)) - (overlay-put ov 'isearch-invisible nil))))))) + (when (overlay-buffer ov) + (if (isearch-intersects-p beg end (overlay-start ov) (overlay-end ov)) + (push ov isearch-opened-overlays) + (let ((fct-temp (overlay-get ov 'isearch-open-invisible-temporary))) + (if fct-temp + ;; If this exists it means that the overlay was opened + ;; using this function, not by us tweaking the overlay + ;; properties. + (funcall fct-temp ov t) + (overlay-put ov 'invisible (overlay-get ov 'isearch-invisible)) + (overlay-put ov 'isearch-invisible nil)))))))) (defun isearch-range-invisible (beg end) diff --git a/lisp/man.el b/lisp/man.el index 9e1d294b1ec..49873c5a87b 100644 --- a/lisp/man.el +++ b/lisp/man.el @@ -1123,7 +1123,14 @@ for the current invocation." (and (not (equal default-entry "")) default-entry)) #'Man-completion-table - nil nil nil 'Man-topic-history default-entry))) + nil nil nil 'Man-topic-history + `(,default-entry + ,@(when (use-region-p) + (list (string-replace + " " "-" + (buffer-substring-no-properties + (region-beginning) + (region-end))))))))) (if Man-cache-completion-results-flag (read) (let ((Man-completion-cache)) (read)))))) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 122459be062..f0994adbb70 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1064,6 +1064,24 @@ metadata." (const :tag "If requested by the completion command" auto)) :version "31.1") +(defcustom completion-eager-update 'auto + "Whether the *Completions* buffer should update as you type. + +If `t', always update as you type. + +If `auto', only update if the completion property `eager-update' is +non-nil, whether set by the completion table or by +`completion-category-overrides' or by `completion-category-defaults'. + +If nil, never update as you type. + +This only affects the *Completions* buffer if it is already +displayed." + :type '(choice (const :tag "Don't update as you type" nil) + (const :tag "Auto-update based on the category" auto) + (const :tag "Always update as you type" t)) + :version "31.1") + (defcustom completion-auto-help t "Non-nil means automatically provide help for invalid completion input. If the value is t, the *Completions* buffer is displayed whenever completion @@ -2634,12 +2652,43 @@ The candidate will still be chosen by `choose-completion' unless (goto-char (or (next-single-property-change (point) 'completion--string) (point-max))))) +(defun completion--eager-update-p (start) + "Return non-nil if *Completions* should be automatically updated. + +If `completion-eager-update' is the symbol `auto', checks completion +metadata for the string from START to point." + (if (eq completion-eager-update 'auto) + (completion-metadata-get (completion--field-metadata start) 'eager-update) + completion-eager-update)) + +(defun completions--background-update () + "Try to update *Completions* without blocking input. + +This function uses `while-no-input' and sets `non-essential' to t +so that the update is less likely to interfere with user typing." + (while-no-input + (let ((non-essential t)) + (redisplay) + (cond + (completion-in-region-mode (completion-help-at-point t)) + ((completion--eager-update-p (minibuffer-prompt-end)) + (minibuffer-completion-help)))))) + +(defun completions--post-command-update () + "Update displayed *Completions* buffer after command, once." + (remove-hook 'post-command-hook #'completions--post-command-update) + (when (and completion-eager-update (get-buffer-window "*Completions*" 0)) + (completions--background-update))) + (defun completions--after-change (_start _end _old-len) "Update displayed *Completions* buffer after change in buffer contents." - (when completion-auto-deselect + (when (or completion-auto-deselect completion-eager-update) (when-let* ((window (get-buffer-window "*Completions*" 0))) - (with-selected-window window - (completions--deselect))))) + (when completion-auto-deselect + (with-selected-window window + (completions--deselect))) + (when completion-eager-update + (add-hook 'post-command-hook #'completions--post-command-update))))) (defun minibuffer-completion-help (&optional start end) "Display a list of possible completions of the current minibuffer contents." @@ -2730,7 +2779,7 @@ The candidate will still be chosen by `choose-completion' unless (body-function . ,#'(lambda (window) (with-current-buffer mainbuf - (when completion-auto-deselect + (when (or completion-auto-deselect completion-eager-update) (add-hook 'after-change-functions #'completions--after-change nil t)) ;; Remove the base-size tail because `sort' requires a properly ;; nil-terminated list. @@ -3119,7 +3168,7 @@ The completion method is determined by `completion-at-point-functions'." (car res))) (cdr res))))) -(defun completion-help-at-point () +(defun completion-help-at-point (&optional only-if-eager) "Display the completions on the text around point. The completion method is determined by `completion-at-point-functions'." (interactive) @@ -3146,7 +3195,8 @@ The completion method is determined by `completion-at-point-functions'." `(,start ,(copy-marker end t) ,collection ,(plist-get plist :predicate))) (completion-in-region-mode 1) - (minibuffer-completion-help start end))) + (when (or (not only-if-eager) (completion--eager-update-p start)) + (minibuffer-completion-help start end)))) (`(,hookfun . ,_) ;; The hook function already performed completion :-( ;; Not much we can do at this point. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 2d240e8756b..5d6c053868b 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -573,9 +573,9 @@ Emacs dired can't find files." "touch -t %s %s %s") (format-time-string "%Y-%m-%dT%H:%M:%S.%NZ" time t) nofollow quoted-name (tramp-get-remote-null-device v) - (format-time-string "%Y-%m-%dT%H:%M:%S" time t) + (format-time-string "%Y-%m-%dT%H:%M:%S" time) nofollow quoted-name (tramp-get-remote-null-device v) - (format-time-string "%Y%m%d%H%M.%S" time t) + (format-time-string "%Y%m%d%H%M.%S" time) nofollow quoted-name))))) (defun tramp-adb-handle-copy-file diff --git a/lisp/net/tramp-message.el b/lisp/net/tramp-message.el index 5131e5fced9..7f66f7d8087 100644 --- a/lisp/net/tramp-message.el +++ b/lisp/net/tramp-message.el @@ -94,6 +94,15 @@ This increases `tramp-verbose' to 6 if necessary." :type 'boolean :link '(info-link :tag "Tramp manual" "(tramp) Traces and Profiles")) +(defcustom tramp-debug-buffer-limit (* 3 1024 1024 1024) ;3GB + "The upper limit of a Tramp debug buffer. +If the size of a debug buffer exceeds this limit, a warning is raised. +Set it to 0 if there is no limit." + :group 'tramp + :version "31.1" + :type 'natnum + :link '(info-link :tag "Tramp manual" "(tramp) Traces and Profiles")) + (defconst tramp-debug-outline-regexp (rx ;; Timestamp. (+ digit) ":" (+ digit) ":" (+ digit) "." (+ digit) blank @@ -281,7 +290,14 @@ ARGUMENTS to actually emit the message (if applicable)." (when tramp-debug-to-file (ignore-errors (write-region - point (point-max) (tramp-get-debug-file-name vec) 'append)))))))) + point (point-max) (tramp-get-debug-file-name vec) 'append)))) + (when (and (natnump tramp-debug-buffer-limit) + (not (zerop tramp-debug-buffer-limit)) + (> (point-max) tramp-debug-buffer-limit)) + (setq-local tramp-debug-buffer-limit nil) + (lwarn + 'tramp :warning + "Tramp debug buffer %S exceeds the limit" (current-buffer))))))) ;;;###tramp-autoload (defun tramp-message (vec-or-proc level fmt-string &rest arguments) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 576f09b764b..3c1f36fa8de 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1633,7 +1633,10 @@ of." "-t %s" (format-time-string "%Y%m%d%H%M.%S" (tramp-defined-time time) t)) "") - (if (eq flag 'nofollow) "-h" "") + (if (and (eq flag 'nofollow) + (tramp-get-connection-property v "touch-h")) + "-h" + "") (tramp-shell-quote-argument localname)))))) (defun tramp-sh-handle-get-home-directory (vec &optional user) @@ -3669,6 +3672,8 @@ are \"file-exists-p\", \"file-readable-p\", \"file-directory-p\" and (defun tramp-sh-handle-vc-registered (file) "Like `vc-registered' for Tramp files." (when vc-handled-backends + ;; Starting with Emacs 31, use `revert-buffer-in-progress'. + (with-suppressed-warnings ((obsolete revert-buffer-in-progress-p)) (let ((inhibit-message (or revert-buffer-in-progress-p inhibit-message)) (temp-message (unless revert-buffer-in-progress-p ""))) (with-temp-message temp-message @@ -3728,7 +3733,7 @@ are \"file-exists-p\", \"file-readable-p\", \"file-directory-p\" and ;; Run. (tramp-with-demoted-errors v "Error in 2nd pass of `vc-registered': %s" - (tramp-run-real-handler #'vc-registered (list file)))))))))) + (tramp-run-real-handler #'vc-registered (list file))))))))))) ;;;###tramp-autoload (defun tramp-sh-file-name-handler (operation &rest args) @@ -5887,12 +5892,12 @@ Nonexistent directories are removed from spec." "Determine remote `touch' command." (with-tramp-connection-property vec "touch" (tramp-message vec 5 "Finding a suitable `touch' command") - (let ((result (tramp-find-executable - vec "touch" (tramp-get-remote-path vec))) - (tmpfile (tramp-make-tramp-temp-name vec))) - ;; Busyboxes do support the "-t" option only when they have been - ;; built with the DESKTOP config option. Let's check it. - (when result + (when-let* ((result (tramp-find-executable + vec "touch" (tramp-get-remote-path vec))) + (tmpfile (tramp-make-tramp-temp-name vec))) + (prog1 result + ;; Busyboxes do support the "-t" option only when they have + ;; been built with the DESKTOP config option. Let's check it. (tramp-set-connection-property vec "touch-t" (tramp-send-command-and-check @@ -5902,8 +5907,13 @@ Nonexistent directories are removed from spec." result (format-time-string "%Y%m%d%H%M.%S") (tramp-file-local-name tmpfile)))) - (delete-file tmpfile)) - result))) + ;; The touch command included in busybox (version 1.30.1-6) on + ;; OpenWrt does not have the option "-h". + (tramp-set-connection-property + vec "touch-h" + (tramp-send-command-and-check + vec (format "%s -h %s" result (tramp-file-local-name tmpfile)))) + (delete-file tmpfile))))) (defun tramp-get-remote-df (vec) "Determine remote `df' command." diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 28364de83f1..fdda945f120 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -295,7 +295,7 @@ See `tramp-actions-before-shell' for more info.") (set-file-acl . tramp-smb-handle-set-file-acl) (set-file-modes . tramp-smb-handle-set-file-modes) (set-file-selinux-context . ignore) - (set-file-times . ignore) + (set-file-times . tramp-smb-handle-set-file-times) (set-visited-file-modtime . tramp-handle-set-visited-file-modtime) (shell-command . tramp-handle-shell-command) (start-file-process . tramp-smb-handle-start-file-process) @@ -1534,6 +1534,15 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-error v 'file-error "Error while changing file's mode %s" filename)))))) +(defun tramp-smb-handle-set-file-times (filename &optional time _flag) + "Like `set-file-times' for Tramp files." + (tramp-skeleton-set-file-modes-times-uid-gid filename + (tramp-smb-send-command + v (format + "utimes %s -1 -1 %s -1" + (tramp-smb-shell-quote-localname v) + (format-time-string "%Y:%m:%d-%H:%M:%S" (tramp-defined-time time)))))) + ;; We use BUFFER also as connection buffer during setup. Because of ;; this, its original contents must be saved, and restored once ;; connection has been setup. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 2208ce880d7..503b370cb3d 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2380,6 +2380,9 @@ arguments to pass to the OPERATION." signal-hook-function) (apply operation args))) +(defvar tramp-file-name-for-operation-external nil + "List of operations added by external packages.") + ;; We handle here all file primitives. Most of them have the file ;; name as first parameter; nevertheless we check for them explicitly ;; in order to be signaled if a new primitive appears. This @@ -2387,6 +2390,10 @@ arguments to pass to the OPERATION." ;; syntactical means whether a foreign method must be called. It would ;; ease the life if `file-name-handler-alist' would support a decision ;; function as well but regexp only. +;; Operations added by external packages are kept in +;; `tramp-file-name-for-operation-external'. They expect the file +;; name to be checked as first argument or, if there isn't any +;; argument, `default-directory'. (defun tramp-file-name-for-operation (operation &rest args) "Return file name related to OPERATION file primitive. ARGS are the arguments OPERATION has been called with. @@ -2396,40 +2403,40 @@ first argument of `expand-file-name' is absolute and not remote. Must be handled by the callers." (cond ;; FILE resp DIRECTORY. - ((member operation - '(access-file byte-compiler-base-file-name delete-directory - delete-file diff-latest-backup-file directory-file-name - directory-files directory-files-and-attributes dired-compress-file - dired-uncache file-acl file-accessible-directory-p file-attributes - file-directory-p file-executable-p file-exists-p file-local-copy - file-locked-p file-modes file-name-as-directory - file-name-case-insensitive-p file-name-directory - file-name-nondirectory file-name-sans-versions - file-notify-add-watch file-ownership-preserved-p file-readable-p - file-regular-p file-remote-p file-selinux-context file-symlink-p - file-system-info file-truename file-writable-p - find-backup-file-name get-file-buffer - insert-directory insert-file-contents load lock-file make-directory - make-lock-file-name set-file-acl set-file-modes - set-file-selinux-context set-file-times substitute-in-file-name - unhandled-file-name-directory unlock-file vc-registered - ;; Emacs 28- only. - make-directory-internal - ;; Emacs 29+ only. - abbreviate-file-name - ;; Tramp internal magic file name function. - tramp-set-file-uid-gid)) + ((memq operation + '(access-file byte-compiler-base-file-name delete-directory + delete-file diff-latest-backup-file directory-file-name + directory-files directory-files-and-attributes dired-compress-file + dired-uncache file-acl file-accessible-directory-p file-attributes + file-directory-p file-executable-p file-exists-p file-local-copy + file-locked-p file-modes file-name-as-directory + file-name-case-insensitive-p file-name-directory + file-name-nondirectory file-name-sans-versions + file-notify-add-watch file-ownership-preserved-p file-readable-p + file-regular-p file-remote-p file-selinux-context file-symlink-p + file-system-info file-truename file-writable-p + find-backup-file-name get-file-buffer + insert-directory insert-file-contents load lock-file make-directory + make-lock-file-name set-file-acl set-file-modes + set-file-selinux-context set-file-times substitute-in-file-name + unhandled-file-name-directory unlock-file vc-registered + ;; Emacs 28- only. + make-directory-internal + ;; Emacs 29+ only. + abbreviate-file-name + ;; Tramp internal magic file name function. + tramp-set-file-uid-gid)) (if (file-name-absolute-p (nth 0 args)) (nth 0 args) default-directory)) ;; STRING FILE. ((eq operation 'make-symbolic-link) (nth 1 args)) ;; FILE DIRECTORY resp FILE1 FILE2. - ((member operation - '(add-name-to-file copy-directory copy-file - file-equal-p file-in-directory-p - file-name-all-completions file-name-completion - file-newer-than-file-p rename-file)) + ((memq operation + '(add-name-to-file copy-directory copy-file + file-equal-p file-in-directory-p + file-name-all-completions file-name-completion + file-newer-than-file-p rename-file)) (cond ((tramp-tramp-file-p (nth 0 args)) (nth 0 args)) ((file-name-absolute-p (nth 1 args)) (nth 1 args)) @@ -2446,31 +2453,39 @@ Must be handled by the callers." (nth 2 args) default-directory)) ;; BUFFER. - ((member operation - '(make-auto-save-file-name - set-visited-file-modtime verify-visited-file-modtime)) + ((memq operation + '(make-auto-save-file-name + set-visited-file-modtime verify-visited-file-modtime)) (buffer-file-name (if (bufferp (nth 0 args)) (nth 0 args) (current-buffer)))) ;; COMMAND. - ((member operation - '(exec-path make-nearby-temp-file make-process process-file - shell-command start-file-process temporary-file-directory - ;; Emacs 29+ only. - list-system-processes memory-info process-attributes - ;; Emacs 30+ only. - file-group-gid file-user-uid)) + ((memq operation + '(exec-path make-nearby-temp-file make-process process-file + shell-command start-file-process temporary-file-directory + ;; Emacs 29+ only. + list-system-processes memory-info process-attributes + ;; Emacs 30+ only. + file-group-gid file-user-uid)) default-directory) ;; PROC. - ((member operation '(file-notify-rm-watch file-notify-valid-p)) + ((memq operation '(file-notify-rm-watch file-notify-valid-p)) (when (processp (nth 0 args)) (tramp-get-default-directory (process-buffer (nth 0 args))))) ;; VEC. - ((member operation - '(tramp-get-home-directory tramp-get-remote-gid - tramp-get-remote-groups tramp-get-remote-uid)) + ((memq operation + '(tramp-get-home-directory tramp-get-remote-gid + tramp-get-remote-groups tramp-get-remote-uid)) (tramp-make-tramp-file-name (nth 0 args))) + ;; FILE resp DIRECTORY. + ((and (memq operation tramp-file-name-for-operation-external) + (or (stringp (nth 0 args)) (null (nth 0 args)))) + (if (and (stringp (nth 0 args)) (file-name-absolute-p (nth 0 args))) + (nth 0 args) + default-directory)) ;; Unknown file primitive. - (t (error "Unknown file I/O primitive: %s" operation)))) + (t (unless (member 'remote-file-error debug-ignored-errors) + (tramp-error + nil 'remote-file-error "Unknown file I/O primitive: %s" operation))))) (defun tramp-find-foreign-file-name-handler (vec &optional _operation) "Return foreign file name handler if exists." @@ -2494,6 +2509,63 @@ Must be handled by the callers." res (cdr elt)))) res))) +(defun tramp-add-external-operation (operation function backend) + "Add FUNTION to Tramp BACKEND as handler for OPERATION. +OPERATION must not be one of the magic operations listed in Info +node `(elisp) Magic File Names'. FUNCTION must have the same argument +list as OPERATION. BACKEND, a symbol, must be one of the Tramp backend +packages like `tramp-sh' (except `tramp-ftp')." + (require backend) + (when-let* ((fnha + (intern-soft + (concat (symbol-name backend) "-file-name-handler-alist"))) + ((boundp fnha))) + ;; Make BACKEND aware of the new operation. + (add-to-list fnha (cons operation function)) + (unless (memq operation tramp-file-name-for-operation-external) + ;; Make Tramp aware of the new operation. + (add-to-list 'tramp-file-name-for-operation-external operation) + (put #'tramp-file-name-handler + 'operations + (cons operation (get 'tramp-file-name-handler 'operations))) + ;; Add an advice for OPERATION, in order to invoke the handler FUNCTION. + (advice-add + operation :around + `(lambda (orig-fun &rest args) + (if-let* ((handler + (find-file-name-handler + (or (car args) default-directory) #',operation))) + (apply handler #',operation args) + (apply orig-fun args))) + `((name . ,(concat "tramp-advice-" (symbol-name operation)))))))) + +(defun tramp-remove-external-operation (operation backend) + "Remove OPERATION from Tramp BACKEND as handler for OPERATION. +OPERATION must not be one of the magic operations listed in Info +node `(elisp) Magic File Names'. BACKEND, a symbol, must be one of the +Tramp backend packages like `tramp-sh'." + ;; Remove OPERATION from BACKEND. + (when-let* ((fnha + (intern-soft + (concat (symbol-name backend) "-file-name-handler-alist"))) + ((boundp fnha))) + (setf (alist-get operation (symbol-value fnha) nil 'remove) nil)) + ;; Check, whether OPERATION is still used in any backend. + (unless (seq-some + (lambda (item) + (when-let* + ((fnha (intern-soft (concat (symbol-name (cdr item)) "-alist"))) + ((boundp fnha))) + (alist-get operation (symbol-value fnha)))) + tramp-foreign-file-name-handler-alist) + ;; Make Tramp unaware of OPERATION. + (setq tramp-file-name-for-operation-external + (delq operation tramp-file-name-for-operation-external)) + (put #'tramp-file-name-handler + 'operations (delq operation (get 'tramp-file-name-handler 'operations))) + ;; Remove the advice for OPERATION. + (advice-remove operation (concat "tramp-advice-" (symbol-name operation))))) + ;; Main function. ;;;###autoload (defun tramp-file-name-handler (operation &rest args) @@ -2900,7 +2972,7 @@ not in completion mode." BODY is the backend specific code." (declare (indent 2) (debug t)) `(ignore-error file-missing - (delete-dups (delq nil + (delete-dups (delq nil (delete "" (let* ((case-fold-search read-file-name-completion-ignore-case) (result (progn ,@body))) ;; Some storage systems do not return "." and "..". @@ -2917,7 +2989,7 @@ BODY is the backend specific code." (dolist (elt completion-regexp-list x) (unless (string-match-p elt x) (throw 'match nil)))))) result) - result)))))) + result))))))) (defvar tramp--last-hop-directory nil "Tracks the directory from which to run login programs.") diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el index d8a928b1f9f..49fc4103cc7 100644 --- a/lisp/org/org-src.el +++ b/lisp/org/org-src.el @@ -665,7 +665,8 @@ Leave point in edit buffer." "Fontify code block between START and END using LANG's syntax. This function is called by Emacs's automatic fontification, as long as `org-src-fontify-natively' is non-nil." - (let ((modified (buffer-modified-p)) native-tab-width) + (let ((modified (buffer-modified-p)) + (native-tab-width tab-width)) (remove-text-properties start end '(face nil)) (let ((lang-mode (org-src-get-lang-mode lang))) (when (fboundp lang-mode) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 5155193c603..55240c3869a 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -65,11 +65,9 @@ ;; ;; will turn on the c++-ts-mode for C++ source files. ;; -;; - If you have both C and C++ grammars installed, add -;; -;; (load "c-ts-mode") -;; -;; to your init file. +;; - If you have both C and C++ grammars installed, customize +;; 'treesit-enabled-modes' and select 'c-ts-mode', +;; 'c++-mode', 'c-or-c++-mode'. ;; ;; You can also turn on these modes manually in a buffer. Doing so ;; will set up Emacs to use the C/C++ modes defined here for other @@ -1675,21 +1673,14 @@ the code is C or C++, and based on that chooses whether to enable 'c-ts-mode))) (funcall (major-mode-remap mode)))) -(when (treesit-ready-p 'cpp) - (setq major-mode-remap-defaults - (assq-delete-all 'c++-mode major-mode-remap-defaults)) - (add-to-list 'major-mode-remap-defaults '(c++-mode . c++-ts-mode))) - -(when (treesit-ready-p 'c) - (setq major-mode-remap-defaults - (assq-delete-all 'c-mode major-mode-remap-defaults)) - (add-to-list 'major-mode-remap-defaults '(c-mode . c-ts-mode))) - -(when (and (treesit-ready-p 'cpp) - (treesit-ready-p 'c)) - (setq major-mode-remap-defaults - (assq-delete-all 'c-or-c++-mode major-mode-remap-defaults)) - (add-to-list 'major-mode-remap-defaults '(c-or-c++-mode . c-or-c++-ts-mode))) +;;;###autoload +(when (treesit-available-p) + (add-to-list 'treesit-major-mode-remap-alist + '(c-mode . c-ts-mode)) + (add-to-list 'treesit-major-mode-remap-alist + '(c++-mode . c++-ts-mode)) + (add-to-list 'treesit-major-mode-remap-alist + '(c-or-c++-mode . c-or-c++-ts-mode))) (provide 'c-ts-mode) (provide 'c++-ts-mode) diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el index 2f2d1b6e2a0..3f879e37ba2 100644 --- a/lisp/progmodes/cmake-ts-mode.el +++ b/lisp/progmodes/cmake-ts-mode.el @@ -255,9 +255,22 @@ Return nil if there is no name or if NODE is not a defun node." (derived-mode-add-parents 'cmake-ts-mode '(cmake-mode)) -(if (treesit-ready-p 'cmake) - (add-to-list 'auto-mode-alist - '("\\(?:CMakeLists\\.txt\\|\\.cmake\\)\\'" . cmake-ts-mode))) +;;;###autoload +(defun cmake-ts-mode-maybe () + "Enable `cmake-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'cmake) + (eq treesit-enabled-modes t) + (memq 'cmake-ts-mode treesit-enabled-modes)) + (cmake-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + (add-to-list 'auto-mode-alist + '("\\(?:CMakeLists\\.txt\\|\\.cmake\\)\\'" . cmake-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(cmake-mode . cmake-ts-mode))) (provide 'cmake-ts-mode) diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 958ccf05672..fb05389ba91 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -1219,12 +1219,15 @@ Key bindings: "local_function_statement") eos)) - (treesit-major-mode-setup) - - (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-ts-mode))) + (treesit-major-mode-setup)) (derived-mode-add-parents 'csharp-ts-mode '(csharp-mode)) +;;;###autoload +(when (treesit-available-p) + (add-to-list 'treesit-major-mode-remap-alist + '(csharp-mode . csharp-ts-mode))) + (provide 'csharp-mode) ;;; csharp-mode.el ends here diff --git a/lisp/progmodes/dockerfile-ts-mode.el b/lisp/progmodes/dockerfile-ts-mode.el index fe0c9e23acc..79a2197c078 100644 --- a/lisp/progmodes/dockerfile-ts-mode.el +++ b/lisp/progmodes/dockerfile-ts-mode.el @@ -202,11 +202,24 @@ Return nil if there is no name or if NODE is not a stage node." (derived-mode-add-parents 'dockerfile-ts-mode '(dockerfile-mode)) -(if (treesit-ready-p 'dockerfile) - (add-to-list 'auto-mode-alist - ;; NOTE: We can't use `rx' here, as it breaks bootstrap. - '("\\(?:Dockerfile\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\'" - . dockerfile-ts-mode))) +;;;###autoload +(defun dockerfile-ts-mode-maybe () + "Enable `dockerfile-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'dockerfile) + (eq treesit-enabled-modes t) + (memq 'dockerfile-ts-mode treesit-enabled-modes)) + (dockerfile-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + (add-to-list 'auto-mode-alist + ;; NOTE: We can't use `rx' here, as it breaks bootstrap. + '("\\(?:Dockerfile\\(?:\\..*\\)?\\|\\.[Dd]ockerfile\\)\\'" + . dockerfile-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(dockerfile-mode . dockerfile-ts-mode))) (provide 'dockerfile-ts-mode) diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index 8b43c032424..05ad76d100f 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -806,12 +806,24 @@ Return nil if NODE is not a defun node or doesn't have a name." (derived-mode-add-parents 'elixir-ts-mode '(elixir-mode)) -(if (treesit-ready-p 'elixir) - (progn - (add-to-list 'auto-mode-alist '("\\.elixir\\'" . elixir-ts-mode)) - (add-to-list 'auto-mode-alist '("\\.ex\\'" . elixir-ts-mode)) - (add-to-list 'auto-mode-alist '("\\.exs\\'" . elixir-ts-mode)) - (add-to-list 'auto-mode-alist '("mix\\.lock" . elixir-ts-mode)))) +;;;###autoload +(defun elixir-ts-mode-maybe () + "Enable `elixir-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'elixir) + (eq treesit-enabled-modes t) + (memq 'elixir-ts-mode treesit-enabled-modes)) + (elixir-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + (add-to-list 'auto-mode-alist '("\\.elixir\\'" . elixir-ts-mode-maybe)) + (add-to-list 'auto-mode-alist '("\\.ex\\'" . elixir-ts-mode-maybe)) + (add-to-list 'auto-mode-alist '("\\.exs\\'" . elixir-ts-mode-maybe)) + (add-to-list 'auto-mode-alist '("mix\\.lock" . elixir-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(elixir-mode . elixir-ts-mode))) (provide 'elixir-ts-mode) diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el index b003b75b0e4..aa3a74d30fa 100644 --- a/lisp/progmodes/executable.el +++ b/lisp/progmodes/executable.el @@ -180,7 +180,7 @@ command to find the next error. The buffer is also in `comint-mode' and `compilation-shell-minor-mode', so that you can answer any prompts." (interactive (list (read-string "Run script: " (or executable-command - buffer-file-name)))) + (file-local-name buffer-file-name))))) (require 'compile) (save-some-buffers (not compilation-ask-about-save)) (setq-local executable-command command) diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index e911faf603d..bdfcf51a5ff 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -1406,6 +1406,26 @@ Interactively, with a prefix arg, FORCE is t." (cl-reduce #'max (mapcar #'cadr flymake--recent-changes)))))) (setq flymake--recent-changes nil) + ;; Delete all overlays that didn't come from one of the + ;; current diagnostic functions. + ;; Sometimes diagnostic functions are removed from + ;; `flymake-diagnostic-functions' (e.g. by eglot). This + ;; leaves overlays in the buffer which otherwise won't be + ;; cleaned up until `flymake-mode' is restarted. + ;; See bug#78862 + (maphash (lambda (backend state) + (unless (memq backend flymake-diagnostic-functions) + ;; Delete all overlays + (dolist (diag (flymake--state-diags state)) + (let ((ov (flymake--diag-overlay diag))) + (flymake--delete-overlay ov))) + ;; Set the list of diagnostics to nil to + ;; avoid trying to delete them again. + ;; We keep the state object itself around in + ;; case there's still diagnostics in flight, + ;; so we don't break things. + (setf (flymake--state-diags state) nil))) + flymake--state) (run-hook-wrapped 'flymake-diagnostic-functions (lambda (backend) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index e8e4c9af29d..40f3de0bc15 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -359,10 +359,21 @@ (derived-mode-add-parents 'go-ts-mode '(go-mode)) -(if (treesit-ready-p 'go) - ;; FIXME: Should we instead put `go-mode' in `auto-mode-alist' - ;; and then use `major-mode-remap-defaults' to map it to `go-ts-mode'? - (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))) +;;;###autoload +(defun go-ts-mode-maybe () + "Enable `go-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'go) + (eq treesit-enabled-modes t) + (memq 'go-ts-mode treesit-enabled-modes)) + (go-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(go-mode . go-ts-mode))) (defun go-ts-mode--defun-name (node &optional skip-prefix) "Return the defun name of NODE. @@ -622,8 +633,21 @@ what the parent of the node would be if it were a node." (derived-mode-add-parents 'go-mod-ts-mode '(go-mod-mode)) -(if (treesit-ready-p 'gomod t) - (add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode))) +;;;###autoload +(defun go-mod-ts-mode-maybe () + "Enable `go-mod-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'gomod) + (eq treesit-enabled-modes t) + (memq 'go-mod-ts-mode treesit-enabled-modes)) + (go-mod-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + (add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(go-mod-mode . go-mod-ts-mode))) ;;;; go.work support. @@ -711,7 +735,20 @@ what the parent of the node would be if it were a node." (treesit-major-mode-setup))) ;;;###autoload -(add-to-list 'auto-mode-alist '("/go\\.work\\'" . go-work-ts-mode)) +(defun go-work-ts-mode-maybe () + "Enable `go-work-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'gowork) + (eq treesit-enabled-modes t) + (memq 'go-work-ts-mode treesit-enabled-modes)) + (go-work-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + (add-to-list 'auto-mode-alist '("/go\\.work\\'" . go-work-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(go-work-mode . go-work-ts-mode))) (provide 'go-ts-mode) diff --git a/lisp/progmodes/heex-ts-mode.el b/lisp/progmodes/heex-ts-mode.el index c478750a73e..41634d0e6a4 100644 --- a/lisp/progmodes/heex-ts-mode.el +++ b/lisp/progmodes/heex-ts-mode.el @@ -265,10 +265,23 @@ Return nil if NODE is not a defun node or doesn't have a name." (derived-mode-add-parents 'heex-ts-mode '(heex-mode)) -(if (treesit-ready-p 'heex) - ;; Both .heex and the deprecated .leex files should work - ;; with the tree-sitter-heex grammar. - (add-to-list 'auto-mode-alist '("\\.[hl]?eex\\'" . heex-ts-mode))) +;;;###autoload +(defun heex-ts-mode-maybe () + "Enable `heex-ts-mode' when its grammar is available." + (if (or (treesit-language-available-p 'heex) + (eq treesit-enabled-modes t) + (memq 'heex-ts-mode treesit-enabled-modes)) + (heex-ts-mode) + (fundamental-mode))) + +;;;###autoload +(when (treesit-available-p) + ;; Both .heex and the deprecated .leex files should work + ;; with the tree-sitter-heex grammar. + (add-to-list 'auto-mode-alist '("\\.[hl]?eex\\'" . heex-ts-mode-maybe)) + ;; To be able to toggle between an external package and core ts-mode: + (add-to-list 'treesit-major-mode-remap-alist + '(heex-mode . heex-ts-mode))) (provide 'heex-ts-mode) ;;; heex-ts-mode.el ends here diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 0fe35a4df8b..e989d1b3f5d 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -524,8 +524,10 @@ Return nil if there is no name or if NODE is not a defun node." (derived-mode-add-parents 'java-ts-mode '(java-mode)) -(if (treesit-ready-p 'java) - (add-to-list 'auto-mode-alist '("\\.java\\'" . java-ts-mode))) +;;;###autoload +(when (treesit-available-p) + (add-to-list 'treesit-major-mode-remap-alist + '(java-mode . java-ts-mode))) (provide 'java-ts-mode) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index bed2ef0616a..c44b2adf146 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -4105,13 +4105,15 @@ See `treesit-thing-settings' for more information.") ;; Outline minor mode (setq-local treesit-outline-predicate js-ts-mode--outline-predicate) - (treesit-major-mode-setup) - - (add-to-list 'auto-mode-alist - '("\\(\\.js[mx]?\\|\\.har\\)\\'" . js-ts-mode)))) + (treesit-major-mode-setup))) (derived-mode-add-parents 'js-ts-mode '(js-mode)) +;;;###autoload +(when (treesit-available-p) + (add-to-list 'treesit-major-mode-remap-alist + '(javascript-mode . js-ts-mode))) + (defvar js-ts--s-p-query (when (treesit-available-p) (treesit-query-compile 'javascript @@ -4142,6 +4144,7 @@ See `treesit-thing-settings' for more information.") :syntax-table js-mode-syntax-table (js--mode-setup) ;Reuse most of `js-mode', but not as parent (bug#67463). (setq-local js-enabled-frameworks nil) + (setq-local editorconfig-indent-size-vars '(js-indent-level)) ;; Speed up `syntax-ppss': JSON files can be big but can't hold ;; regexp matchers nor #! thingies (and `js-enabled-frameworks' is nil). (setq-local syntax-propertize-function #'ignore)) diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el index a18f3c342c0..b0db0a12210 100644 --- a/lisp/progmodes/json-ts-mode.el +++ b/lisp/progmodes/json-ts-mode.el @@ -181,9 +181,10 @@ Return nil if there is no name or if NODE is not a defun node." (derived-mode-add-parents 'json-ts-mode '(json-mode)) -(if (treesit-ready-p 'json) - (add-to-list 'auto-mode-alist - '("\\.json\\'" . json-ts-mode))) +;;;###autoload +(when (treesit-available-p) + (add-to-list 'treesit-major-mode-remap-alist + '(js-json-mode . json-ts-mode))) (provide 'json-ts-mode) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 5e58d4c071d..07a8f0aef55 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -74,6 +74,11 @@ :safe 'natnump :version "30.1") +(defcustom lua-ts-auto-close-block-comments nil + "If non-nil, inserting a block comment \"--[[\" will insert its respective \"]]\"." + :type 'boolean + :version "31.1") + (defcustom lua-ts-luacheck-program "luacheck" "Location of the Luacheck program." :type 'file @@ -675,6 +680,14 @@ Calls REPORT-FN directly." (setq-local comment-start-skip "--\\s-*") (setq-local comment-end "") + ;; Pairs. + (when (and lua-ts-auto-close-block-comments + (boundp 'electric-pair-pairs)) + (setq-local electric-pair-pairs + (cons + '("--\\[\\[" . "\n]") + electric-pair-pairs))) + ;; Font-lock. (setq-local treesit-font-lock-settings lua-ts--font-lock-settings) (setq-local treesit-font-lock-feature-list @@ -756,9 +769,22 @@ Calls REPORT-FN directly." (derived-mode-add-parents 'lua-ts-mode '(lua-mode)) -(when (treesit-ready-p 'lua) - (add-to-list 'auto-mode-alist '("\\.lua\\'" . lua-ts-mode)) - (add-to-list 'interpreter-mode-alist '("\\ and