emacs-diffs
[Top][All Lists]
Advanced

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

feature/android 2fa5583d96 2/2: Merge remote-tracking branch 'origin/mas


From: Po Lu
Subject: feature/android 2fa5583d96 2/2: Merge remote-tracking branch 'origin/master' into feature/android
Date: Wed, 11 Jan 2023 03:07:53 -0500 (EST)

branch: feature/android
commit 2fa5583d96fe78ff66d6fd41f18e54e4e20ea7d6
Merge: 494bedde32 033f2cc614
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/android
---
 doc/emacs/files.texi                               |   5 +
 doc/emacs/misc.texi                                | 177 +++++++++++----------
 doc/lispref/files.texi                             |   5 +
 doc/lispref/functions.texi                         |  14 ++
 doc/lispref/help.texi                              |  18 +--
 doc/lispref/modes.texi                             |   8 +-
 doc/lispref/parsing.texi                           |  14 +-
 doc/lispref/symbols.texi                           |  17 ++
 doc/misc/org.org                                   |  11 +-
 doc/misc/tramp.texi                                |   7 +-
 etc/NEWS                                           |   9 ++
 etc/NEWS.29                                        |   8 +-
 lisp/align.el                                      |   3 +-
 lisp/char-fold.el                                  |  18 ++-
 lisp/erc/erc-networks.el                           |   6 +
 lisp/erc/erc-track.el                              |  12 +-
 lisp/erc/erc.el                                    |   6 +-
 lisp/files.el                                      |   6 +
 lisp/font-lock.el                                  |   9 +-
 lisp/minibuffer.el                                 |   2 +-
 lisp/net/ange-ftp.el                               |   3 +-
 lisp/net/tramp-adb.el                              |  12 +-
 lisp/net/tramp-crypt.el                            |   8 +-
 lisp/net/tramp-fuse.el                             |   8 +-
 lisp/net/tramp-gvfs.el                             |  21 ++-
 lisp/net/tramp-sh.el                               |  12 +-
 lisp/net/tramp-smb.el                              |  29 ++--
 lisp/net/tramp-sudoedit.el                         |  19 +--
 lisp/net/tramp.el                                  |  38 +++--
 lisp/org/ob-core.el                                |  14 +-
 lisp/org/ob-shell.el                               |   2 +-
 lisp/org/org-macs.el                               |  11 +-
 lisp/org/org-persist.el                            |   2 +-
 lisp/org/org-table.el                              |   1 +
 lisp/org/org-version.el                            |   2 +-
 lisp/org/org.el                                    |  22 +--
 lisp/org/ox.el                                     |   1 -
 lisp/progmodes/c-ts-mode.el                        | 174 ++++++++++++++------
 lisp/progmodes/cc-fonts.el                         |   4 +-
 lisp/progmodes/go-ts-mode.el                       | 107 ++++++++-----
 lisp/progmodes/gud.el                              |   5 +-
 lisp/progmodes/js.el                               |   5 +-
 lisp/progmodes/project.el                          |   2 +-
 lisp/progmodes/python.el                           |  36 ++++-
 lisp/progmodes/ruby-ts-mode.el                     |  17 +-
 lisp/progmodes/typescript-ts-mode.el               |  22 +--
 lisp/progmodes/xref.el                             |   2 +-
 lisp/simple.el                                     | 131 ++++++++++-----
 lisp/textmodes/reftex-cite.el                      |   2 +-
 lisp/treesit.el                                    |  61 +++----
 lisp/vc/diff-mode.el                               |  14 +-
 src/callint.c                                      |  12 +-
 src/gnutls.c                                       |   4 +
 src/pgtkfns.c                                      |   2 +-
 src/print.c                                        |   9 +-
 test/lisp/erc/erc-scenarios-base-association.el    |  49 ++++++
 test/lisp/erc/erc-services-tests.el                |   9 +-
 test/lisp/erc/resources/erc-d/erc-d-t.el           |   2 +-
 .../erc/resources/networks/merge-server/track.eld  |  44 +++++
 test/lisp/net/tramp-tests.el                       |  44 ++++-
 test/lisp/progmodes/python-tests.el                |  10 ++
 test/lisp/progmodes/ruby-mode-resources/ruby.rb    |   2 +-
 62 files changed, 906 insertions(+), 423 deletions(-)

diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi
index 6a9103d3a0..42e252c417 100644
--- a/doc/emacs/files.texi
+++ b/doc/emacs/files.texi
@@ -1888,6 +1888,11 @@ following in the Trash directory:
 liable to also delete this @code{.dir-locals.el} file, so this should
 only be done if you delete files from the Trash directory manually.
 
+@vindex remote-file-name-inhibit-delete-by-moving-to-trash
+  If the variable @code{remote-file-name-inhibit-delete-by-moving-to-trash}
+is non-@code{nil}, remote files are never moved to the Trash.  They
+are deleted instead.
+
 @ifnottex
   If a file is under version control (@pxref{Version Control}), you
 should delete it using @kbd{M-x vc-delete-file} instead of @kbd{M-x
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index c706b727e6..88d4188d14 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -2702,40 +2702,16 @@ when point is on the first byte of a multibyte sequence 
in the file.
 @cindex restore session
 @cindex remember editing session
 @cindex reload files
-@cindex desktop
 
-@vindex desktop-restore-frames
-   Use the desktop library to save the state of Emacs from one session
-to another.  Once you save the Emacs @dfn{desktop}---the buffers,
-their file names, major modes, buffer positions, and so on---then
-subsequent Emacs sessions reload the saved desktop.  By default,
-the desktop also tries to save the frame and window configuration.
-To disable this, set @code{desktop-restore-frames} to @code{nil}.
-(See that variable's documentation for some related options
-that you can customize to fine-tune this behavior.)
-
-@vindex desktop-files-not-to-save
-Information about buffers visiting remote files is not saved by
-default.  Customize the variable @code{desktop-files-not-to-save} to
-change this.
-
-@vindex frameset-filter-alist
-   When the desktop restores the frame and window configuration, it
-uses the recorded values of frame parameters, disregarding any
-settings for those parameters you have in your init file (@pxref{Init
-File}).  This means that frame parameters such as fonts and faces for
-the restored frames will come from the desktop file, where they were
-saved when you exited your previous Emacs session; any settings for
-those parameters in your init file will be ignored.  To disable this,
-customize the value of @code{frameset-filter-alist} to filter out the
-frame parameters you don't want to be restored.
+@cindex desktop configuration
+  You can use the desktop library to save the state of Emacs from one
+session to another.  The saved Emacs @dfn{desktop configuration}
+includes the buffers, their file names, major modes, buffer positions,
+window and frame configuration, and some important global variables.
 
-@findex desktop-save
 @vindex desktop-save-mode
-  You can save the desktop manually with the command @kbd{M-x
-desktop-save}.  You can also enable automatic saving of the desktop
-when you exit Emacs, and automatic restoration of the last saved
-desktop when Emacs starts: use the Customization buffer (@pxref{Easy
+@findex desktop-save-mode
+  To enable this feature, use the Customization buffer (@pxref{Easy
 Customization}) to set @code{desktop-save-mode} to @code{t} for future
 sessions, or add this line in your init file (@pxref{Init File}):
 
@@ -2743,51 +2719,34 @@ sessions, or add this line in your init file 
(@pxref{Init File}):
 (desktop-save-mode 1)
 @end example
 
-@findex desktop-change-dir
-@findex desktop-revert
 @vindex desktop-path
+@vindex desktop-auto-save-timeout
   If you turn on @code{desktop-save-mode} in your init file, then when
-Emacs starts, it looks for a saved desktop in the current directory.
-(More precisely, it looks in the directories specified by
-@code{desktop-path}, and uses the first desktop it finds.)
-Thus, you can have separate saved desktops in different directories,
-and the starting directory determines which one Emacs reloads.  You
-can save the current desktop and reload one saved in another directory
-by typing @kbd{M-x desktop-change-dir}.  Typing @kbd{M-x
-desktop-revert} reverts to the desktop previously reloaded.
-
-  Specify the option @samp{--no-desktop} on the command line when you
-don't want it to reload any saved desktop.  This turns off
-@code{desktop-save-mode} for the current session.  Starting Emacs with
-the @samp{--no-init-file} option also disables desktop reloading,
-since it bypasses the init file, where @code{desktop-save-mode} is
-usually turned on.
-
-@vindex desktop-restore-eager
-  By default, all the buffers in the desktop are restored in one go.
-However, this may be slow if there are a lot of buffers in the
-desktop.  You can specify the maximum number of buffers to restore
-immediately with the variable @code{desktop-restore-eager}; the
-remaining buffers are restored lazily, when Emacs is idle.
-
-@findex desktop-clear
-@vindex desktop-globals-to-clear
-@vindex desktop-clear-preserve-buffers-regexp
-  Type @kbd{M-x desktop-clear} to empty the Emacs desktop.  This kills
-all buffers except for internal ones, and clears the global variables
-listed in @code{desktop-globals-to-clear}.  If you want this to
-preserve certain buffers, customize the variable
-@code{desktop-clear-preserve-buffers-regexp}, whose value is a regular
-expression matching the names of buffers not to kill.
+Emacs starts, it looks for a saved desktop in @code{desktop-path}
+(which defaults to @code{user-emacs-directory} and then your home
+directory) and uses the first desktop it finds.  While Emacs runs with
+@code{desktop-save-mode} turned on, it by default auto-saves the
+desktop whenever any of the desktop configuration changes.  The
+variable @code{desktop-auto-save-timeout} determines how frequently
+Emacs checks for modifications to your desktop.  The desktop is also
+saved when you exit Emacs.
 
-  If you want to save minibuffer history from one session to
-another, use the @code{savehist} library.
+@cindex disable restoring of desktop configuration
+  Specify the option @samp{--no-desktop} on the Emacs command line
+when you don't want it to reload any saved desktop configurations.
+This turns off @code{desktop-save-mode} for the current session.
+Starting Emacs with the @samp{--no-init-file} option also disables
+desktop reloading, since it bypasses the init file, where
+@code{desktop-save-mode} is usually turned on.
 
-@vindex desktop-auto-save-timeout
-  While Emacs runs with @code{desktop-save-mode} turned on, it by
-default auto-saves the desktop whenever any of it changes.  The
-variable @code{desktop-auto-save-timeout} determines how frequently
-Emacs checks for modifications to your desktop.
+@findex desktop-change-dir
+@findex desktop-revert
+  You can have separate saved desktop configurations in different
+directories; starting Emacs from a directory where you have a saved
+desktop configuration will restore that configuration.  You can save
+the current desktop and reload the one saved in another directory by
+typing @kbd{M-x desktop-change-dir}.  Typing @kbd{M-x desktop-revert}
+reverts to the previously reloaded desktop.
 
 @vindex desktop-load-locked-desktop
   The file in which Emacs saves the desktop is locked while the
@@ -2798,12 +2757,13 @@ will by default ask you whether to use the locked 
desktop file.  You
 can avoid the question by customizing the variable
 @code{desktop-load-locked-desktop} to either @code{nil}, which means
 never load the desktop in this case, or @code{t}, which means load the
-desktop without asking.  Finally, the @code{check-pid} value means to
-load the file if the Emacs process that has locked the desktop is not
-running on the local machine.  This should not be used in
-circumstances where the locking Emacs might still be running on
-another machine.  This could be the case in multi-user environments
-where your home directory is mounted remotely using NFS or similar.
+desktop without asking.  You can also customize the variable to the
+special value @code{check-pid}, which means to load the file if the
+Emacs process that has locked the desktop is not running on the local
+machine.  This should not be used in circumstances where the locking
+Emacs might still be running on another machine, which could be the
+case in multi-user environments where your home directory is mounted
+remotely using NFS or similar.
 
 @cindex desktop restore in daemon mode
   When Emacs starts in daemon mode, it cannot ask you any questions,
@@ -2813,10 +2773,67 @@ the desktop in daemon mode is somewhat problematic for 
other reasons:
 e.g., the daemon cannot use GUI features, so parameters such as frame
 position, size, and decorations cannot be restored.  For that reason,
 you may wish to delay restoring the desktop in daemon mode until the
-first client connects, by calling @code{desktop-read} in a hook
-function that you add to @code{server-after-make-frame-hook}
+first client connects, by calling @code{desktop-read} (see below) in a
+hook function that you add to @code{server-after-make-frame-hook}
 (@pxref{Creating Frames,,, elisp, The Emacs Lisp Reference Manual}).
 
+@findex desktop-save
+@findex desktop-read
+  Whenever you want, you can use the command @kbd{M-x desktop-save} to
+force immediate saving of the current desktop.  This is useful either
+if you do not want to use the automatic desktop restoration, and thus
+don't turn on @code{desktop-save-mode}, or when you have made
+significant changes to the desktop, and want to make sure the
+configuration doesn't get lost if Emacs or your system crashes.  You
+can use @kbd{M-x desktop-read} to restore a previously-saved desktop
+if the current Emacs session didn't load any desktop yet.
+
+@vindex desktop-restore-frames
+  By default, the desktop tries to save and restore the frame and
+window configuration.  To disable this, set
+@code{desktop-restore-frames} to @code{nil}.  (See that variable's
+documentation for some related options that you can customize to
+fine-tune this behavior.)
+
+@vindex frameset-filter-alist
+  When the desktop restores the frame and window configuration, it
+uses the recorded values of frame parameters, disregarding any
+settings for those parameters you have in your init file (@pxref{Init
+File}).  This means that frame parameters such as fonts and faces for
+the restored frames will come from the desktop file, where they were
+saved when you exited your previous Emacs session; any settings for
+those parameters in your init file will be ignored.  To disable this,
+customize the value of @code{frameset-filter-alist} to filter out the
+frame parameters you don't want to be restored; they will then be set
+according to your customizations in the init file.
+
+@vindex desktop-files-not-to-save
+  Information about buffers visiting remote files is not saved by
+default.  Customize the variable @code{desktop-files-not-to-save} to
+change this.
+
+@vindex desktop-restore-eager
+  By default, all the buffers in the desktop are restored in one go.
+However, this may be slow if there are a lot of buffers in the
+desktop.  You can specify the maximum number of buffers to restore
+immediately with the variable @code{desktop-restore-eager}; the
+remaining buffers are restored lazily, when Emacs is idle.
+
+@findex desktop-clear
+@vindex desktop-globals-to-clear
+@vindex desktop-clear-preserve-buffers-regexp
+  Type @kbd{M-x desktop-clear} to empty the Emacs desktop; this can be
+useful, for example, if you want to switch to another desktop by
+invoking @kbd{M-x desktop-read} next.  The @code{desktop-clear}
+command kills all buffers except for internal ones, and clears the
+global variables listed in @code{desktop-globals-to-clear}.  If you
+want it to preserve certain buffers, customize the variable
+@code{desktop-clear-preserve-buffers-regexp}, whose value is a regular
+expression matching the names of buffers not to kill.
+
+  If you want to save minibuffer history from one session to
+another, use the @code{savehist} library.
+
 @node Recursive Edit
 @section Recursive Editing Levels
 @cindex recursive editing level
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 91643530f7..5cc4c1e7dd 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -1871,6 +1871,11 @@ no prefix argument is given, and @code{nil} otherwise.
 See also @code{delete-directory} in @ref{Create/Delete Dirs}.
 @end deffn
 
+@defopt remote-file-name-inhibit-delete-by-moving-to-trash
+If this variable is non-@code{nil}, remote files are never moved to
+the Trash.  They are deleted instead.
+@end defopt
+
 @cindex file permissions, setting
 @cindex permissions, file
 @cindex file modes, setting
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 3a8eddb93e..f5572e447d 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -685,6 +685,20 @@ Here are some examples:
 @end group
 @end example
 
+@cindex defining functions dynamically
+Most Emacs functions are part of the source code of Lisp programs, and
+are defined when the Emacs Lisp reader reads the program source before
+executing it.  However, you can also define functions dynamically at
+run time, e.g., by generating @code{defun} calls when your program's
+code is executed.  If you do this, be aware that Emacs's Help
+commands, such as @kbd{C-h f}, which present in the @file{*Help*}
+buffer a button to jump to the function's definition, might be unable
+to find the source code because generating a function dynamically
+usually looks very different from the usual static calls to
+@code{defun}.  You can make the job of finding the code which
+generates such functions easier by using the @code{definition-name}
+property, @pxref{Standard Properties}.
+
 @cindex override existing functions
 @cindex redefine existing functions
 Be careful not to redefine existing functions unintentionally.
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index de5ed76c7f..59b6b6dab1 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -69,14 +69,14 @@ Variables}.  The string is stored in the variable's
 @cindex @file{DOC} (documentation) file
   Sometimes, Emacs does not keep documentation strings in memory.
 There are two such circumstances.  Firstly, to save memory, the
-documentation for preloaded functions and variables (including
-primitives) is kept in a file named @file{DOC}, in the directory
-specified by @code{doc-directory} (@pxref{Accessing Documentation}).
-Secondly, when a function or variable is loaded from a byte-compiled
-file, Emacs avoids loading its documentation string (@pxref{Docs and
-Compilation}).  In both cases, Emacs looks up the documentation string
-from the file only when needed, such as when the user calls @kbd{C-h
-f} (@code{describe-function}) for a function.
+documentation for primitive functions (@pxref{What Is a Function}) and
+built-in variables is kept in a file named @file{DOC}, in the
+directory specified by @code{doc-directory} (@pxref{Accessing
+Documentation}).  Secondly, when a function or variable is loaded from
+a byte-compiled file, Emacs avoids loading its documentation string
+(@pxref{Docs and Compilation}).  In both cases, Emacs looks up the
+documentation string from the file only when needed, such as when the
+user calls @kbd{C-h f} (@code{describe-function}) for a function.
 
   Documentation strings can contain special @dfn{key substitution
 sequences}, referring to key bindings which are looked up only when
@@ -303,7 +303,7 @@ for in the directory @code{doc-directory}.  Usually 
@var{filename} is
 @defvar doc-directory
 This variable holds the name of the directory which should contain the
 file @code{"DOC"} that contains documentation strings for
-built-in and preloaded functions and variables.
+built-in functions and variables.
 
 In most cases, this is the same as @code{data-directory}.  They may be
 different when you run Emacs from the directory where you built it,
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index b2dd294ea2..ff372edb3f 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -4936,10 +4936,10 @@ Each @var{matcher} or @var{anchor} is a function that 
takes three
 arguments: @var{node}, @var{parent}, and @var{bol}.  The argument
 @var{bol} is the buffer position whose indentation is required: the
 position of the first non-whitespace character after the beginning of
-the line.  The argument @var{node} is the largest (highest-in-tree)
-node that starts at that position; and @var{parent} is the parent of
-@var{node}.  However, when that position is in a whitespace or inside
-a multi-line string, no node can start at that position, so
+the line.  The argument @var{node} is the largest node that starts at
+that position (and is not a root node); and @var{parent} is the parent
+of @var{node}.  However, when that position is in a whitespace or
+inside a multi-line string, no node can start at that position, so
 @var{node} is @code{nil}.  In that case, @var{parent} would be the
 smallest node that spans that position.
 
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index 9635427f94..b55af912f9 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -540,11 +540,15 @@ This function returns the list of @var{parser}'s notifier 
functions.
 Here's some terminology and conventions we use when documenting
 tree-sitter functions.
 
-We talk about a node being ``smaller'' or ``larger'', and ``lower'' or
-``higher''.  A smaller and lower node is lower in the syntax tree and
-therefore spans a smaller portion of buffer text; a larger and higher
-node is higher up in the syntax tree, it contains many smaller nodes
-as its children, and therefore spans a larger portion of text.
+A node in a syntax tree spans some portion of the program text in the
+buffer.  We say that a node is ``smaller'' or ``larger'' than another
+if it spans, respectively, a smaller or larger portion of buffer text
+than the other node.  Since nodes that are deeper (``lower'') in the
+tree are children of the nodes that are ``higher'' in the tree, it
+follows that a lower node will always be smaller than a node that is
+higher in the node hierarchy.  A node that is higher up in the syntax
+tree contains one or more smaller nodes as its children, and therefore
+spans a larger portion of buffer text.
 
 When a function cannot find a node, it returns @code{nil}.  For
 convenience, all functions that take a node as argument and return
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index 183367c0cd..5b53cbe310 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -555,6 +555,23 @@ value, saved value, customized-but-unsaved value, and 
themed values.
 Do not set them directly; they are managed by @code{defcustom} and
 related functions.  @xref{Variable Definitions}.
 
+@item definition-name
+This property is used to find the definition of a symbol in the source
+code, when it might be hard to find the definition by textual search
+of the source file.  For example, a @code{define-derived-mode}
+(@pxref{Derived Modes}) might define a mode-specific function or a
+variable implicitly; or your Lisp program might generate a run-time
+call to @code{defun} to define a function (@pxref{Defining
+Functions}).  In these and similar cases, the @code{definition-name}
+property of the symbol should be another symbol whose definition can
+be found by textual search and whose code defines the original symbol.
+In the example with @code{define-derived-mode}, the value of this
+property of the functions and variables it defines should be the mode
+symbol.  The Emacs Help commands such as @kbd{C-h f} (@pxref{Help,,,
+emacs, The GNU Emacs Manual}) use this property to show the definition
+of a symbol via a button in the @file{*Help*} buffer where the
+symbol's documentation is shown.
+
 @item disabled
 If the value is non-@code{nil}, the named function is disabled as a
 command.  @xref{Disabling Commands}.
diff --git a/doc/misc/org.org b/doc/misc/org.org
index ed3eb0626f..7ca2cce9e7 100644
--- a/doc/misc/org.org
+++ b/doc/misc/org.org
@@ -1249,11 +1249,12 @@ After the drawer.
 #+findex: org-insert-drawer
 You can interactively insert a drawer at point by calling
 ~org-insert-drawer~, which is bound to {{{kbd(C-c C-x d)}}}.  With an
-active region, this command puts the region inside the drawer.  With
-a prefix argument, this command calls ~org-insert-property-drawer~,
-which creates a =PROPERTIES= drawer right below the current headline.
-Org mode uses this special drawer for storing properties (see
-[[*Properties and Columns]]).  You cannot use it for anything else.
+active region, this command puts the region inside the drawer.  With a
+prefix argument, this command calls non-interactive function
+~org-insert-property-drawer~, which creates a =PROPERTIES= drawer
+right below the current headline.  Org mode uses this special drawer
+for storing properties (see [[*Properties and Columns]]).  You cannot use
+it for anything else.
 
 Completion over drawer keywords is also possible using
 {{{kbd(M-TAB)}}}[fn:6].
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 7f66dc9e84..a8a59f982f 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -5215,9 +5215,10 @@ them, @ref{Misc File Ops, Trashing , , emacs}.
 @ifnotinfo
 them.
 @end ifnotinfo
-Remote files are always trashed to the local trash, except remote
-encrypted files (@pxref{Keeping files encrypted}), which are deleted
-anyway.
+Remote files are always trashed to the local trash, except the user
+option @code{remote-file-name-inhibit-delete-by-moving-to-trash} is
+non-@code{nil}, or it is a remote encrypted file (@pxref{Keeping files
+encrypted}), which are deleted anyway.
 
 If Emacs is configured to use the XDG conventions for the trash
 directory, remote files cannot be restored with the respective tools,
diff --git a/etc/NEWS b/etc/NEWS
index 690e9c3faa..3aa8f2abb7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -45,6 +45,11 @@ example, as part of preview for iconified frames.
 ** 'write-region-inhibit-fsync' now defaults to t in interactive mode,
 as it has in batch mode since Emacs 24.
 
++++
+** New user option 'remote-file-name-inhibit-delete-by-moving-to-trash'.
+When non-nil, this option suppresses moving remote files to the local
+trash when deleting.  Default is nil.
+
 
 * Editing Changes in Emacs 30.1
 
@@ -52,6 +57,10 @@ as it has in batch mode since Emacs 24.
 Emacs now can set this variable to customize the behavior of the
 'transpose-sexps' function.
 
+** New function 'transpose-sexps-default-function'.
+The previous implementation is moved into its own function, to be
+bound by transpose-sexps-function'.
+
 ** New function 'treesit-transpose-sexps'.
 treesit.el now unconditionally sets 'transpose-sexps-function' for all
 Tree-sitter modes.  This functionality utilizes the new
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 5901b2718e..a28f5c9a65 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -797,10 +797,10 @@ filter/sentinel error has been handled.
 ** New faces for font-lock.
 These faces are primarily meant for use with tree-sitter.  They are:
 'font-lock-bracket-face', 'font-lock-delimiter-face',
-'font-lock-escape-face', 'font-lock-number-face',
-'font-lock-regexp-face',
-'font-lock-misc-punctuation-face', 'font-lock-operator-face',
-'font-lock-property-face', and 'font-lock-punctuation-face'.
+'font-lock-escape-face', 'font-lock-misc-punctuation-face',
+'font-lock-number-face', 'font-lock-operator-face',
+'font-lock-property-face', and 'font-lock-punctuation-face',
+'font-lock-regexp-face'.
 
 +++
 ** New face 'variable-pitch-text'.
diff --git a/lisp/align.el b/lisp/align.el
index 569186d241..79a75dcec7 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -179,7 +179,8 @@ If nil, then no messages will ever be printed to the 
minibuffer."
   :type '(choice (const :tag "Align a large region silently" nil) integer)
   :group 'align)
 
-(defcustom align-c++-modes '(c++-mode c-mode java-mode)
+(defcustom align-c++-modes '( c++-mode c-mode java-mode
+                              c-ts-mode c++-ts-mode)
   "A list of modes whose syntax resembles C/C++."
   :type '(repeat symbol)
   :group 'align)
diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index eff2f5558b..6da2dae847 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -436,7 +436,23 @@ specify the character).  With no input, i.e. when CHAR is 
nil,
 describe all available character equivalences of `char-fold-to-regexp'.
 Optional argument LAX (interactively, the prefix argument), if
 non-nil, means also include partially matching ligatures and
-non-canonical equivalences."
+non-canonical equivalences.
+
+Each line of the display shows the equivalences in two different
+ways separated by a colon:
+
+    - as the literal character or sequence
+    - using an ASCII-only escape syntax
+
+For example, for the letter \\='r\\=', the first line is
+
+    r: ?\\N{LATIN SMALL LETTER R}
+
+which is for the requested character itself, and a later line has
+
+    ṟ: ?\\N{LATIN SMALL LETTER R}?\\N{COMBINING MACRON BELOW}
+
+which clearly shows what the constituent characters are."
   (interactive (list (ignore-errors
                        (read-char-by-name
                         (format-prompt "Unicode name, single char, or hex"
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index 4044be08f9..95fd8990c9 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1366,6 +1366,11 @@ ANNOUNCED is the server's reported host name."
                erc-server-connected t
                erc-networks--id nid))))))
 
+(defvar erc-networks--copy-server-buffer-functions nil
+  "Abnormal hook run in new server buffers when deduping.
+Passed the existing buffer to be killed, whose contents have
+already been copied over to the current, replacement buffer.")
+
 (defun erc-networks--copy-over-server-buffer-contents (existing name)
   "Kill off existing server buffer after copying its contents.
 Must be called from the replacement buffer."
@@ -1386,6 +1391,7 @@ Must be called from the replacement buffer."
         erc-kill-server-hook
         erc-kill-buffer-hook)
     (erc-networks--insert-transplanted-content text)
+    (run-hook-with-args 'erc-networks--copy-server-buffer-functions existing)
     (kill-buffer name)))
 
 ;; This stands alone for testing purposes
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index 61c0c66abf..7fd7b53602 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -521,7 +521,9 @@ keybindings will not do anything useful."
        (add-hook 'erc-disconnected-hook #'erc-modified-channels-update))
      ;; enable the tracking keybindings
      (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
-     (erc-track-minor-mode-maybe)))
+     (erc-track-minor-mode-maybe))
+   (add-hook 'erc-networks--copy-server-buffer-functions
+             #'erc-track--replace-killed-buffer))
   ;; Disable:
   ((when (boundp 'erc-track-when-inactive)
      (erc-track-remove-from-mode-line)
@@ -539,7 +541,9 @@ keybindings will not do anything useful."
      ;; disable the tracking keybindings
      (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
      (when erc-track-minor-mode
-       (erc-track-minor-mode -1)))))
+       (erc-track-minor-mode -1)))
+   (remove-hook 'erc-networks--copy-server-buffer-functions
+                #'erc-track--replace-killed-buffer)))
 
 (defcustom erc-track-when-inactive nil
   "Enable channel tracking even for visible buffers, if you are inactive."
@@ -942,6 +946,10 @@ reverse it."
   (interactive "p")
   (erc-track--switch-buffer 'switch-to-buffer-other-window arg))
 
+(defun erc-track--replace-killed-buffer (existing)
+  (when-let ((found (assq existing erc-modified-channels-alist)))
+    (setcar found (current-buffer))))
+
 (provide 'erc-track)
 
 ;;; erc-track.el ends here
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 6315d5aa48..ba7db15cf8 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -323,7 +323,8 @@ A typical value would be \((\"Libera.Chat\" \"MODE\")
   \(\"OFTC\" \"JOIN\" \"QUIT\"))."
   :version "25.1"
   :group 'erc-ignore
-  :type 'erc-message-type)
+  :type '(alist :key-type string :value-type erc-message-type
+                :options ("Libera.Chat")))
 
 (defcustom erc-channel-hide-list nil
   "A list of IRC channels to hide message types from.
@@ -331,7 +332,8 @@ A typical value would be \((\"#emacs\" \"QUIT\" \"JOIN\")
   \(\"#erc\" \"NICK\")."
   :version "25.1"
   :group 'erc-ignore
-  :type 'erc-message-type)
+  :type '(alist :key-type string :value-type erc-message-type
+                :options ("#emacs")))
 
 (defcustom erc-disconnected-hook nil
   "Run this hook with arguments (NICK IP REASON) when disconnected.
diff --git a/lisp/files.el b/lisp/files.el
index e1b7a990b1..d0167bf381 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6336,6 +6336,12 @@ RECURSIVE if DIRECTORY is nonempty."
                  directory-exists))
        (files--force recursive #'delete-directory-internal directory))))))
 
+(defcustom remote-file-name-inhibit-delete-by-moving-to-trash nil
+  "Whether remote files shall be moved to the Trash.
+This overrules any setting of `delete-by-moving-to-trash'."
+  :version "30.1"
+  :type 'boolean)
+
 (defun file-equal-p (file1 file2)
   "Return non-nil if files FILE1 and FILE2 name the same file.
 If FILE1 or FILE2 does not exist, the return value is unspecified."
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 99df8fb9e0..1fa45379b9 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1183,7 +1183,7 @@ This function is the default 
`font-lock-fontify-region-function'."
            (setq font-lock-syntactically-fontified end))
          (font-lock-fontify-syntactic-keywords-region start end)))
      (unless font-lock-keywords-only
-       (funcall font-lock-fontify-syntactically-function beg end loudly))
+       (font-lock-fontify-syntactically-region beg end loudly))
      (font-lock-fontify-keywords-region beg end loudly)
      `(jit-lock-bounds ,beg . ,end))))
 
@@ -1531,6 +1531,12 @@ START should be at the beginning of a line."
 (defvar font-lock-comment-end-skip nil
   "If non-nil, Font Lock mode uses this instead of `comment-end-skip'.")
 
+(defun font-lock-fontify-syntactically-region (beg end &optional loudly)
+  "Syntactically fontify the text between BEG and END.
+If LOUDLY is non-nil, print status messages while fontifying.
+This works by calling `font-lock-fontify-syntactically-function'."
+  (funcall font-lock-fontify-syntactically-function beg end loudly))
+
 (defun font-lock-default-fontify-syntactically (start end &optional loudly)
   "Put proper face on each string and comment between START and END.
 START should be at the beginning of a line."
@@ -2369,7 +2375,6 @@ in which C preprocessor directives are used, e.g. 
`asm-mode' and
 
 (define-obsolete-function-alias 'font-lock-after-fontify-buffer #'ignore 
"29.1")
 (define-obsolete-function-alias 'font-lock-after-unfontify-buffer #'ignore 
"29.1")
-(define-obsolete-function-alias 'font-lock-fontify-syntactically-region 
#'font-lock-default-fontify-syntactically "29.1")
 
 
 (provide 'font-lock)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index f47299bd0d..21d4607e7c 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -986,7 +986,7 @@ already visible.
 If the value is `visible', the *Completions* buffer is displayed
 whenever completion is requested but cannot be done for the first time,
 but remains visible thereafter, and the list of completions in it is
-updated for subsequent attempts to complete.."
+updated for subsequent attempts to complete."
   :type '(choice (const :tag "Don't show" nil)
                  (const :tag "Show only when cannot complete" t)
                  (const :tag "Show after second failed completion attempt" 
lazy)
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 41c28672aa..a14122f815 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -3534,7 +3534,8 @@ system TYPE.")
   (setq file (expand-file-name file))
   (let ((parsed (ange-ftp-ftp-name file)))
     (if parsed
-        (if (and delete-by-moving-to-trash trash)
+        (if (and delete-by-moving-to-trash trash
+                (not remote-file-name-inhibit-delete-by-moving-to-trash))
            (move-file-to-trash file)
          (let* ((host (nth 0 parsed))
                 (user (nth 1 parsed))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 619d29bb4d..493a9fb39a 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -424,14 +424,10 @@ Emacs dired can't find files."
 
 (defun tramp-adb-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (with-parsed-tramp-file-name filename nil
-    (tramp-flush-file-properties v localname)
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (tramp-adb-barf-unless-okay
-       v (format "rm %s" (tramp-shell-quote-argument localname))
-       "Couldn't delete %s" filename))))
+  (tramp-skeleton-delete-file filename trash
+    (tramp-adb-barf-unless-okay
+     v (format "rm %s" (tramp-shell-quote-argument localname))
+     "Couldn't delete %s" filename)))
 
 (defun tramp-adb-handle-file-name-all-completions (filename directory)
   "Like `file-name-all-completions' for Tramp files."
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 61d1c52961..507fd43241 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -689,17 +689,17 @@ absolute file names."
     (directory &optional recursive _trash)
   "Like `delete-directory' for Tramp files."
   (with-parsed-tramp-file-name (expand-file-name directory) nil
-    (tramp-flush-directory-properties v localname)
     (let (tramp-crypt-enabled)
-      (delete-directory (tramp-crypt-encrypt-file-name directory) recursive))))
+      (delete-directory (tramp-crypt-encrypt-file-name directory) recursive))
+    (tramp-flush-directory-properties v localname)))
 
 ;; Encrypted files won't be trashed.
 (defun tramp-crypt-handle-delete-file (filename &optional _trash)
   "Like `delete-file' for Tramp files."
   (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-flush-file-properties v localname)
     (let (tramp-crypt-enabled)
-      (delete-file (tramp-crypt-encrypt-file-name filename)))))
+      (delete-file (tramp-crypt-encrypt-file-name filename)))
+    (tramp-flush-file-properties v localname)))
 
 (defun tramp-crypt-handle-directory-files
     (directory &optional full match nosort count)
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index c8754e2b03..b846caadc1 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -34,15 +34,13 @@
 (defun tramp-fuse-handle-delete-directory
     (directory &optional recursive trash)
   "Like `delete-directory' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name directory) nil
-    (tramp-flush-directory-properties v localname)
+  (tramp-skeleton-delete-directory directory recursive trash
     (delete-directory (tramp-fuse-local-file-name directory) recursive trash)))
 
 (defun tramp-fuse-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (delete-file (tramp-fuse-local-file-name filename) trash)
-    (tramp-flush-file-properties v localname)))
+  (tramp-skeleton-delete-file filename trash
+    (delete-file (tramp-fuse-local-file-name filename) trash)))
 
 (defvar tramp-fuse-remove-hidden-files nil
   "Remove hidden files from directory listings.")
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index bb81b3eb66..cca7a5fe24 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1139,18 +1139,15 @@ file names."
 
 (defun tramp-gvfs-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-flush-file-properties v localname)
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (unless (and (tramp-gvfs-send-command
-                   v "gvfs-rm" (tramp-gvfs-url-file-name filename))
-                  (not (tramp-gvfs-info filename)))
-       ;; Propagate the error.
-       (with-current-buffer (tramp-get-connection-buffer v)
-         (goto-char (point-min))
-         (tramp-error-with-buffer
-          nil v 'file-error "Couldn't delete %s" filename))))))
+  (tramp-skeleton-delete-file filename trash
+    (unless (and (tramp-gvfs-send-command
+                 v "gvfs-rm" (tramp-gvfs-url-file-name filename))
+                (not (tramp-gvfs-info filename)))
+      ;; Propagate the error.
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (goto-char (point-min))
+       (tramp-error-with-buffer
+        nil v 'file-error "Couldn't delete %s" filename)))))
 
 (defun tramp-gvfs-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files."
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index fbdd40dd1d..4647600071 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2567,14 +2567,10 @@ The method used must be an out-of-band method."
 
 (defun tramp-sh-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (setq filename (expand-file-name (expand-file-name filename)))
-  (with-parsed-tramp-file-name filename nil
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (tramp-barf-unless-okay
-       v (format "rm -f %s" (tramp-shell-quote-argument localname))
-       "Couldn't delete %s" filename))
-    (tramp-flush-file-properties v localname)))
+  (tramp-skeleton-delete-file filename trash
+    (tramp-barf-unless-okay
+     v (format "rm -f %s" (tramp-shell-quote-argument localname))
+       "Couldn't delete %s" filename)))
 
 ;; Dired.
 
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index f31865d498..d6f3cca973 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -695,24 +695,17 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
 
 (defun tramp-smb-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (when (file-exists-p filename)
-    (with-parsed-tramp-file-name filename nil
-      ;; We must also flush the cache of the directory, because
-      ;; `file-attributes' reads the values from there.
-      (tramp-flush-file-properties v localname)
-      (if (and delete-by-moving-to-trash trash)
-         (move-file-to-trash filename)
-       (unless (tramp-smb-send-command
-                v (format
-                   "%s %s"
-                   (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
-                   (tramp-smb-shell-quote-localname v)))
-         ;; Error.
-         (with-current-buffer (tramp-get-connection-buffer v)
-           (goto-char (point-min))
-           (search-forward-regexp tramp-smb-errors nil t)
-           (tramp-error v 'file-error "%s `%s'" (match-string 0) 
filename)))))))
+  (tramp-skeleton-delete-file filename trash
+    (unless (tramp-smb-send-command
+            v (format
+               "%s %s"
+               (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
+               (tramp-smb-shell-quote-localname v)))
+      ;; Error.
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (goto-char (point-min))
+       (search-forward-regexp tramp-smb-errors nil t)
+       (tramp-error v 'file-error "%s `%s'" (match-string 0) filename)))))
 
 (defun tramp-smb-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files."
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index c4e1d32f52..2660dbb1fa 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -347,17 +347,14 @@ absolute file names."
 
 (defun tramp-sudoedit-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-flush-file-properties v localname)
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (unless (tramp-sudoedit-send-command
-              v "rm" "-f" (file-name-unquote localname))
-       ;; Propagate the error.
-       (with-current-buffer (tramp-get-connection-buffer v)
-         (goto-char (point-min))
-         (tramp-error-with-buffer
-          nil v 'file-error "Couldn't delete %s" filename))))))
+  (tramp-skeleton-delete-file filename trash
+    (unless (tramp-sudoedit-send-command
+            v "rm" "-f" (file-name-unquote localname))
+      ;; Propagate the error.
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (goto-char (point-min))
+       (tramp-error-with-buffer
+        nil v 'file-error "Couldn't delete %s" filename)))))
 
 (defun tramp-sudoedit-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 4bf0fdefc0..b8475b7cb4 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3399,15 +3399,35 @@ BODY is the backend specific code."
 BODY is the backend specific code."
   (declare (indent 3) (debug t))
   `(with-parsed-tramp-file-name (expand-file-name ,directory) nil
-    (if (and delete-by-moving-to-trash ,trash)
-       ;; Move non-empty dir to trash only if recursive deletion was
-       ;; requested.
-       (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
-           (tramp-error
-            v 'file-error "Directory is not empty, not moving to trash")
-         (move-file-to-trash ,directory))
-      ,@body)
-    (tramp-flush-directory-properties v localname)))
+     (let ((delete-by-moving-to-trash
+           (and delete-by-moving-to-trash
+                ;; This variable exists since Emacs 30.1.
+                (not (bound-and-true-p
+                      remote-file-name-inhibit-delete-by-moving-to-trash)))))
+       (if (and delete-by-moving-to-trash ,trash)
+          ;; Move non-empty dir to trash only if recursive deletion was
+          ;; requested.
+          (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
+              (tramp-error
+               v 'file-error "Directory is not empty, not moving to trash")
+            (move-file-to-trash ,directory))
+        ,@body)
+       (tramp-flush-directory-properties v localname))))
+
+(defmacro tramp-skeleton-delete-file (filename &optional trash &rest body)
+  "Skeleton for `tramp-*-handle-delete-file'.
+BODY is the backend specific code."
+  (declare (indent 2) (debug t))
+  `(with-parsed-tramp-file-name (expand-file-name ,filename) nil
+     (let ((delete-by-moving-to-trash
+           (and delete-by-moving-to-trash
+                ;; This variable exists since Emacs 30.1.
+                (not (bound-and-true-p
+                      remote-file-name-inhibit-delete-by-moving-to-trash)))))
+       (if (and delete-by-moving-to-trash ,trash)
+          (move-file-to-trash ,filename)
+        ,@body)
+       (tramp-flush-file-properties v localname))))
 
 (defmacro tramp-skeleton-directory-files
     (directory &optional full match nosort count &rest body)
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 9bb77f7920..93cdf6ae86 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1690,6 +1690,7 @@ shown below.
                         (append
                          (split-string (if (stringp raw-result)
                                            raw-result
+                                          ;; FIXME: Arbitrary code evaluation.
                                          (eval raw-result t)))
                          (cdr (assq :result-params params))))))
     (append
@@ -2860,6 +2861,7 @@ parameters when merging lists."
                                  (split-string
                                   (cond ((stringp value) value)
                                          ((functionp value) (funcall value))
+                                         ;; FIXME: Arbitrary code evaluation.
                                          (t (eval value t)))))))
          (`(:exports . ,value)
           (setq exports (funcall merge
@@ -3188,16 +3190,8 @@ situations in which is it not appropriate."
        ((and (not inhibit-lisp-eval)
              (or (memq (string-to-char cell) '(?\( ?' ?` ?\[))
                  (string= cell "*this*")))
-         ;; Prevent arbitrary function calls.
-         (if (and (memq (string-to-char cell) '(?\( ?`))
-                  (not (org-babel-confirm-evaluate
-                      ;; See `org-babel-get-src-block-info'.
-                      (list "emacs-lisp" cell
-                            '((:eval . yes)) nil (format "%s" cell)
-                            nil nil))))
-             ;; Not allowed.
-             (user-error "Evaluation of elisp code %S aborted." cell)
-          (eval (read cell) t)))
+         ;; FIXME: Arbitrary code evaluation.
+        (eval (read cell) t))
        ((save-match-data
            (and (string-match "^[[:space:]]*\"\\(.*\\)\"[[:space:]]*$" cell)
                 (not (string-match "[^\\]\"" (match-string 1 cell)))))
diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el
index 4a60186cd5..2c30a26056 100644
--- a/lisp/org/ob-shell.el
+++ b/lisp/org/ob-shell.el
@@ -79,7 +79,7 @@ is modified outside the Customize interface."
             ,(format "Execute a block of %s commands with Babel." name)
             (let ((shell-file-name ,name)
                    (org-babel-prompt-command
-                    (or (alist-get ,name org-babel-shell-set-prompt-commands)
+                    (or (cdr (assoc ,name org-babel-shell-set-prompt-commands))
                         (alist-get t org-babel-shell-set-prompt-commands))))
               (org-babel-execute:shell body params))))
     (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 72929cdd26..07c668a807 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -372,18 +372,23 @@ be set to a buffer or a buffer name.  `shell-command' 
then uses
 it for output."
   (let* ((base-name (file-name-base source))
         (full-name (file-truename source))
-        (out-dir (or (file-name-directory source) "./"))
+         (relative-name (file-relative-name source))
+        (out-dir (if (file-name-directory source)
+                      ;; Expand "~".  Shell expansion will be disabled
+                      ;; in the shell command call.
+                      (file-name-directory full-name)
+                    "./"))
         (output (expand-file-name (concat base-name "." ext) out-dir))
         (time (file-attribute-modification-time (file-attributes output)))
         (err-msg (if (stringp err-msg) (concat ".  " err-msg) "")))
     (save-window-excursion
       (pcase process
-       ((pred functionp) (funcall process (shell-quote-argument source)))
+       ((pred functionp) (funcall process (shell-quote-argument 
relative-name)))
        ((pred consp)
         (let ((log-buf (and log-buf (get-buffer-create log-buf)))
               (spec (append spec
                             `((?b . ,(shell-quote-argument base-name))
-                              (?f . ,(shell-quote-argument source))
+                              (?f . ,(shell-quote-argument relative-name))
                               (?F . ,(shell-quote-argument full-name))
                               (?o . ,(shell-quote-argument out-dir))
                               (?O . ,(shell-quote-argument output))))))
diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el
index c3650c167e..336496efbf 100644
--- a/lisp/org/org-persist.el
+++ b/lisp/org/org-persist.el
@@ -753,12 +753,12 @@ with `org-persist-write'."
 When ASSOCIATED is `all', unregister CONTAINER everywhere."
   (unless org-persist--index (org-persist--load-index))
   (setq container (org-persist--normalize-container container))
-  (setq associated (org-persist--normalize-associated associated))
   (if (eq associated 'all)
       (mapc (lambda (collection)
               (when (member container (plist-get collection :container))
                 (org-persist-unregister container (plist-get collection 
:associated))))
             org-persist--index)
+    (setq associated (org-persist--normalize-associated associated))
     (let ((collection (org-persist--find-index `(:container ,container 
:associated ,associated))))
       (when collection
         (if (= (length (plist-get collection :container)) 1)
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 06cf919db7..fac9e68c12 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -2614,6 +2614,7 @@ location of point."
 
        (if lispp
            (setq ev (condition-case nil
+                         ;; FIXME: Arbitrary code evaluation.
                         (eval (eval (read form)))
                       (error "#ERROR"))
                  ev (if (numberp ev) (number-to-string ev) ev)
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index dd6d92d8e5..942cc4eae8 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made."
 (defun org-git-version ()
   "The Git version of Org mode.
 Inserted by installing Org or when a release is made."
-   (let ((org-git-version "release_9.6-81-g563a43"))
+   (let ((org-git-version "release_9.6-90-ga6523f"))
      org-git-version))
 
 (provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 21764f3d43..8d226c2c5a 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -4898,16 +4898,20 @@ The following commands are available:
             (= (point-min) (point-max)))
     (insert "#    -*- mode: org -*-\n\n"))
   (unless org-inhibit-startup
+    (when (or org-startup-align-all-tables org-startup-shrink-all-tables)
+      (org-table-map-tables
+       (cond ((and org-startup-align-all-tables
+                  org-startup-shrink-all-tables)
+             (lambda () (org-table-align) (org-table-shrink)))
+            (org-startup-align-all-tables #'org-table-align)
+            (t #'org-table-shrink))
+       t))
+    ;; Suppress modification hooks to speed up the startup.
+    ;; However, do it only when text properties/overlays, but not
+    ;; buffer text are actually modified.  We still need to track text
+    ;; modifications to make cache updates work reliably.
     (org-unmodified
      (when org-startup-with-beamer-mode (org-beamer-mode))
-     (when (or org-startup-align-all-tables org-startup-shrink-all-tables)
-       (org-table-map-tables
-       (cond ((and org-startup-align-all-tables
-                   org-startup-shrink-all-tables)
-              (lambda () (org-table-align) (org-table-shrink)))
-             (org-startup-align-all-tables #'org-table-align)
-             (t #'org-table-shrink))
-       t))
      (when org-startup-with-inline-images (org-display-inline-images))
      (when org-startup-with-latex-preview (org-latex-preview '(16)))
      (unless org-inhibit-startup-visibility-stuff 
(org-cycle-set-startup-visibility))
@@ -8855,7 +8859,7 @@ keywords relative to each registered export back-end."
     "EXCLUDE_TAGS:" "FILETAGS:" "INCLUDE:" "INDEX:" "KEYWORDS:" "LANGUAGE:"
     "MACRO:" "OPTIONS:" "PROPERTY:" "PRINT_BIBLIOGRAPHY" "PRIORITIES:"
     "SELECT_TAGS:" "SEQ_TODO:" "SETUPFILE:" "STARTUP:" "TAGS:" "TITLE:" "TODO:"
-    "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:"))
+    "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:" "EXPORT_FILE_NAME:"))
 
 (defcustom org-structure-template-alist
   '(("a" . "export ascii")
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 62fc8d583e..12767267a7 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -6757,7 +6757,6 @@ Return file name as a string."
          (cond
           (pub-dir (concat (file-name-as-directory pub-dir)
                            (file-name-nondirectory base-name)))
-          ((file-name-absolute-p base-name) base-name)
           (t base-name))))
     ;; If writing to OUTPUT-FILE would overwrite original file, append
     ;; EXTENSION another time to final name.
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index e76966e766..e929fe1dd8 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -122,9 +122,13 @@ MODE is either `c' or `cpp'."
            ((node-is "else") parent-bol 0)
            ((node-is "case") parent-bol 0)
            ((node-is "preproc_arg") no-indent)
+           (c-ts-mode--comment-2nd-line-matcher
+            c-ts-mode--comment-2nd-line-anchor
+            1)
            ((and (parent-is "comment") c-ts-mode--looking-at-star)
             c-ts-mode--comment-start-after-first-star -1)
            ((parent-is "comment") prev-adaptive-prefix 0)
+           (c-ts-mode--top-level-label-matcher point-min 1)
            ((node-is "labeled_statement") parent-bol 0)
            ((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
            ((match "preproc_ifdef" "compound_statement") point-min 0)
@@ -138,6 +142,7 @@ MODE is either `c' or `cpp'."
            ((parent-is "function_definition") parent-bol 0)
            ((parent-is "conditional_expression") first-sibling 0)
            ((parent-is "assignment_expression") parent-bol 
c-ts-mode-indent-offset)
+           ((parent-is "concatenated_string") parent-bol 
c-ts-mode-indent-offset)
            ((parent-is "comma_expression") first-sibling 0)
            ((parent-is "init_declarator") parent-bol c-ts-mode-indent-offset)
            ((parent-is "parenthesized_expression") first-sibling 1)
@@ -151,7 +156,9 @@ MODE is either `c' or `cpp'."
            ((parent-is "call_expression") parent 0)
            ((parent-is "enumerator_list") parent-bol c-ts-mode-indent-offset)
            ,@(when (eq mode 'cpp)
-               '(((node-is "access_specifier") parent-bol 0)))
+               '(((node-is "access_specifier") parent-bol 0)
+                 ;; Indent the body of namespace definitions.
+                 ((parent-is "declaration_list") parent-bol 
c-ts-mode-indent-offset)))
            ((parent-is "field_declaration_list") parent-bol 
c-ts-mode-indent-offset)
            ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset)
            ((parent-is "if_statement") parent-bol c-ts-mode-indent-offset)
@@ -167,7 +174,12 @@ MODE is either `c' or `cpp'."
        ((match "while" "do_statement") parent 0)
        ,@common)
       (k&r ,@common)
-      (linux ,@common)
+      (linux
+       ;; Reference:
+       ;; https://www.kernel.org/doc/html/latest/process/coding-style.html,
+       ;; and script/Lindent in Linux kernel repository.
+       ((node-is "labeled_statement") point-min 0)
+       ,@common)
       (bsd
        ((parent-is "if_statement") parent-bol 0)
        ((parent-is "for_statement") parent-bol 0)
@@ -190,6 +202,17 @@ MODE is either `c' or `cpp'."
              ('linux (alist-get 'linux (c-ts-mode--indent-styles mode)))))))
     `((,mode ,@style))))
 
+(defun c-ts-mode--top-level-label-matcher (node &rest _)
+  "A matcher that matches a top-level label.
+NODE should be a labeled_statement."
+  (let ((func (treesit-parent-until
+               node (lambda (n)
+                      (equal (treesit-node-type n)
+                             "function_definition")))))
+    (and (equal (treesit-node-type node)
+                "labeled_statement")
+         (not (treesit-node-top-level func "function_definition")))))
+
 (defun c-ts-mode--bracket-children-anchor (_n parent &rest _)
   "This anchor is used for children of a compound_statement.
 So anything inside a {} block.  PARENT should be the
@@ -205,11 +228,10 @@ beginning of grandparent."
            (treesit-node-parent parent)
          parent)))))
 
-(defun c-ts-mode--looking-at-star (&rest _)
+(defun c-ts-mode--looking-at-star (_n _p bol &rest _)
   "A tree-sitter simple indent matcher.
-Matches if there is a \"*\" after point (ignoring whitespace in
-between)."
-  (looking-at (rx (* (syntax whitespace)) "*")))
+Matches if there is a \"*\" after BOL."
+  (eq (char-after bol) ?*))
 
 (defun c-ts-mode--comment-start-after-first-star (_n parent &rest _)
   "A tree-sitter simple indent anchor.
@@ -221,6 +243,35 @@ Assumes PARENT is a comment node."
         (match-end 0)
       (point))))
 
+(defun c-ts-mode--comment-2nd-line-matcher (_n parent &rest _)
+  "Matches if point is at the second line of a block comment.
+PARENT should be a comment node."
+  (and (equal (treesit-node-type parent) "comment")
+       (save-excursion
+         (forward-line -1)
+         (back-to-indentation)
+         (eq (point) (treesit-node-start parent)))))
+
+(defun c-ts-mode--comment-2nd-line-anchor (&rest _)
+  "Return appropriate anchor for the second line of a comment.
+
+If the first line is /* alone, return the position right after
+the star; if the first line is /* followed by some text, return
+the position right before the text minus 1.
+
+Use an offset of 1 with this anchor."
+  (save-excursion
+    (forward-line -1)
+    (back-to-indentation)
+    (when (looking-at comment-start-skip)
+      (goto-char (match-end 0))
+      (if (looking-at (rx (* (or " " "\t")) eol))
+          ;; Only /* at the first line.
+          (progn (skip-chars-backward " \t")
+                 (point))
+        ;; There is something after /* at the first line.
+        (1- (point))))))
+
 ;;; Font-lock
 
 (defvar c-ts-mode--preproc-keywords
@@ -419,20 +470,29 @@ MODE is either `c' or `cpp'."
 
 ;;; Font-lock helpers
 
-(defun c-ts-mode--declarator-identifier (node)
-  "Return the identifier of the declarator node NODE."
+(defun c-ts-mode--declarator-identifier (node &optional qualified)
+  "Return the identifier of the declarator node NODE.
+
+If QUALIFIED is non-nil, include the names space part of the
+identifier and return a qualified_identifier."
   (pcase (treesit-node-type node)
     ;; Recurse.
     ((or "attributed_declarator" "parenthesized_declarator")
-     (c-ts-mode--declarator-identifier (treesit-node-child node 0 t)))
+     (c-ts-mode--declarator-identifier (treesit-node-child node 0 t)
+                                       qualified))
     ((or "pointer_declarator" "reference_declarator")
-     (c-ts-mode--declarator-identifier (treesit-node-child node -1)))
+     (c-ts-mode--declarator-identifier (treesit-node-child node -1)
+                                       qualified))
     ((or "function_declarator" "array_declarator" "init_declarator")
      (c-ts-mode--declarator-identifier
-      (treesit-node-child-by-field-name node "declarator")))
+      (treesit-node-child-by-field-name node "declarator")
+      qualified))
     ("qualified_identifier"
-     (c-ts-mode--declarator-identifier
-      (treesit-node-child-by-field-name node "name")))
+     (if qualified
+         node
+       (c-ts-mode--declarator-identifier
+        (treesit-node-child-by-field-name node "name")
+        qualified)))
     ;; Terminal case.
     ((or "identifier" "field_identifier")
      node)))
@@ -534,9 +594,11 @@ Return nil if NODE is not a defun node or doesn't have a 
name."
    (pcase (treesit-node-type node)
      ((or "function_definition" "declaration")
       (c-ts-mode--declarator-identifier
-       (treesit-node-child-by-field-name node "declarator")))
+       (treesit-node-child-by-field-name node "declarator")
+       t))
      ((or "struct_specifier" "enum_specifier"
-          "union_specifier" "class_specifier")
+          "union_specifier" "class_specifier"
+          "namespace_definition")
       (treesit-node-child-by-field-name node "name")))
    t))
 
@@ -568,6 +630,23 @@ Ie, NODE is not nested."
                          node "declarator"))
                        "function_declarator")))))
 
+(defun c-ts-mode--defun-for-class-in-imenu-p (node)
+  "Check if NODE is a valid entry for the Class subindex.
+
+Basically, if NODE is a class, return non-nil; if NODE is a
+function but is under a class, return non-nil; if NODE is a
+top-level function, return nil.
+
+This is for the Class subindex in
+`treesit-simple-imenu-settings'."
+  (pcase (treesit-node-type node)
+    ;; The Class subindex only has class_specifier and
+    ;; function_definition.
+    ("class_specifier" t)
+    ("function_definition"
+     ;; Return t if this function is nested in a class.
+     (treesit-node-top-level node "class_specifier"))))
+
 (defun c-ts-mode--defun-skipper ()
   "Custom defun skipper for `c-ts-mode' and friends.
 Structs in C ends with a semicolon, but the semicolon is not
@@ -741,7 +820,8 @@ Set up:
                                   "struct_specifier"
                                   "enum_specifier"
                                   "union_specifier"
-                                  "class_specifier"))
+                                  "class_specifier"
+                                  "namespace_definition"))
                     #'c-ts-mode--defun-valid-p))
   (setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
   (setq-local treesit-defun-name-function #'c-ts-mode--defun-name)
@@ -772,7 +852,7 @@ Set up:
                   ("Class" ,(rx bos (or "class_specifier"
                                         "function_definition")
                                 eos)
-                   ,pred nil))))
+                   c-ts-mode--defun-for-class-in-imenu-p nil))))
 
   (setq-local treesit-font-lock-feature-list
               '(( comment definition)
@@ -782,49 +862,49 @@ Set up:
 
 ;;;###autoload
 (define-derived-mode c-ts-mode c-ts-base-mode "C"
-  "Major mode for editing C, powered by tree-sitter."
-  :group 'c
-
-  (unless (treesit-ready-p 'c)
-    (error "Tree-sitter for C isn't available"))
-
-  (treesit-parser-create 'c)
-
-  ;; Comments.
-  (setq-local comment-start "/* ")
-  (setq-local comment-end " */")
-
-  (setq-local treesit-simple-indent-rules
-              (c-ts-mode--set-indent-style 'c))
+  "Major mode for editing C, powered by tree-sitter.
 
-  ;; Font-lock.
-  (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
+This mode is independent from the classic cc-mode.el based
+`c-mode', so configuration variables of that mode, like
+`c-basic-offset', don't affect this mode."
+  :group 'c
 
-  (treesit-major-mode-setup))
+  (when (treesit-ready-p 'c)
+    (treesit-parser-create 'c)
+    ;; Comments.
+    (setq-local comment-start "/* ")
+    (setq-local comment-end " */")
+    ;; Indent.
+    (setq-local treesit-simple-indent-rules
+                (c-ts-mode--set-indent-style 'c))
+    ;; Font-lock.
+    (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
+    (treesit-major-mode-setup)))
 
 ;;;###autoload
 (define-derived-mode c++-ts-mode c-ts-base-mode "C++"
   "Major mode for editing C++, powered by tree-sitter."
   :group 'c++
 
-  (unless (treesit-ready-p 'cpp)
-    (error "Tree-sitter for C++ isn't available"))
+  (when (treesit-ready-p 'cpp)
+    (setq-local treesit-text-type-regexp
+                (regexp-opt '("comment"
+                              "raw_string_literal")))
 
-  (setq-local treesit-text-type-regexp
-              (regexp-opt '("comment"
-                            "raw_string_literal")))
+    (treesit-parser-create 'cpp)
 
-  (treesit-parser-create 'cpp)
-  (setq-local syntax-propertize-function
-              #'c-ts-mode--syntax-propertize)
+    ;; Syntax.
+    (setq-local syntax-propertize-function
+                #'c-ts-mode--syntax-propertize)
 
-  (setq-local treesit-simple-indent-rules
-              (c-ts-mode--set-indent-style 'cpp))
+    ;; Indent.
+    (setq-local treesit-simple-indent-rules
+                (c-ts-mode--set-indent-style 'cpp))
 
-  ;; Font-lock.
-  (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp))
+    ;; Font-lock.
+    (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 
'cpp))
 
-  (treesit-major-mode-setup))
+    (treesit-major-mode-setup)))
 
 (provide 'c-ts-mode)
 
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index d84c4f8ad8..4dcc3e0ade 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -2530,8 +2530,8 @@ higher."
                   (get-text-property (match-beginning 0) 'fontified)
                   (not (memq (c-get-char-property (match-beginning 0) 'face)
                              c-literal-faces)))
-             (c-put-font-lock-face (match-beginning 0) (match-end 0)
-                                   font-lock-type-face))
+             (put-text-property (match-beginning 0) (match-end 0)
+                                'fontified nil))
            (dolist (win-boundary window-boundaries)
              (when (and (< (match-beginning 0) (cdr win-boundary))
                         (> (match-end 0) (car win-boundary))
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 1d6a8a30db..64e761d2f7 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -36,6 +36,7 @@
 (declare-function treesit-node-child-by-field-name "treesit.c")
 (declare-function treesit-node-start "treesit.c")
 (declare-function treesit-node-type "treesit.c")
+(declare-function treesit-search-subtree "treesit.c")
 
 (defcustom go-ts-mode-indent-offset 4
   "Number of spaces for each indentation step in `go-ts-mode'."
@@ -173,44 +174,6 @@
    '((ERROR) @font-lock-warning-face))
   "Tree-sitter font-lock settings for `go-ts-mode'.")
 
-(defun go-ts-mode--imenu ()
-  "Return Imenu alist for the current buffer."
-  (let* ((node (treesit-buffer-root-node))
-         (func-tree (treesit-induce-sparse-tree
-                     node "function_declaration" nil 1000))
-         (type-tree (treesit-induce-sparse-tree
-                     node "type_spec" nil 1000))
-         (func-index (go-ts-mode--imenu-1 func-tree))
-         (type-index (go-ts-mode--imenu-1 type-tree)))
-    (append
-     (when func-index `(("Function" . ,func-index)))
-     (when type-index `(("Type" . ,type-index))))))
-
-(defun go-ts-mode--imenu-1 (node)
-  "Helper for `go-ts-mode--imenu'.
-Find string representation for NODE and set marker, then recurse
-the subtrees."
-  (let* ((ts-node (car node))
-         (children (cdr node))
-         (subtrees (mapcan #'go-ts-mode--imenu-1
-                           children))
-         (name (when ts-node
-                 (treesit-node-text
-                  (pcase (treesit-node-type ts-node)
-                    ("function_declaration"
-                     (treesit-node-child-by-field-name ts-node "name"))
-                    ("type_spec"
-                     (treesit-node-child-by-field-name ts-node "name"))))))
-         (marker (when ts-node
-                   (set-marker (make-marker)
-                               (treesit-node-start ts-node)))))
-    (cond
-     ((or (null ts-node) (null name)) subtrees)
-     (subtrees
-      `((,name ,(cons name marker) ,@subtrees)))
-     (t
-      `((,name . ,marker))))))
-
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
 
@@ -228,14 +191,30 @@ the subtrees."
     (setq-local comment-end "")
     (setq-local comment-start-skip (rx "//" (* (syntax whitespace))))
 
+    ;; Navigation.
+    (setq-local treesit-defun-type-regexp
+                (regexp-opt '("method_declaration"
+                              "function_declaration"
+                              "type_declaration")))
+    (setq-local treesit-defun-name-function #'go-ts-mode--defun-name)
+
     ;; Imenu.
-    (setq-local imenu-create-index-function #'go-ts-mode--imenu)
-    (setq-local which-func-functions nil)
+    (setq-local treesit-simple-imenu-settings
+                `(("Function" "\\`function_declaration\\'" nil nil)
+                  ("Method" "\\`method_declaration\\'" nil nil)
+                  ("Struct" "\\`type_declaration\\'" go-ts-mode--struct-node-p 
nil)
+                  ("Interface" "\\`type_declaration\\'" 
go-ts-mode--interface-node-p nil)
+                  ("Type" "\\`type_declaration\\'" 
go-ts-mode--other-type-node-p nil)
+                  ("Alias" "\\`type_declaration\\'" go-ts-mode--alias-node-p 
nil)))
 
     ;; Indent.
     (setq-local indent-tabs-mode t
                 treesit-simple-indent-rules go-ts-mode--indent-rules)
 
+    ;; Electric
+    (setq-local electric-indent-chars
+                (append "{}()" electric-indent-chars))
+
     ;; Font-lock.
     (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings)
     (setq-local treesit-font-lock-feature-list
@@ -247,6 +226,54 @@ the subtrees."
 
     (treesit-major-mode-setup)))
 
+(defun go-ts-mode--defun-name (node)
+  "Return the defun name of NODE.
+Return nil if there is no name or if NODE is not a defun node."
+  (pcase (treesit-node-type node)
+    ("function_declaration"
+     (treesit-node-text
+      (treesit-node-child-by-field-name
+       node "name")
+      t))
+    ("method_declaration"
+     (let* ((receiver-node (treesit-node-child-by-field-name node "receiver"))
+            (type-node (treesit-search-subtree receiver-node 
"type_identifier"))
+            (name-node (treesit-node-child-by-field-name node "name")))
+       (concat
+        "(" (treesit-node-text type-node) ")."
+        (treesit-node-text name-node))))
+    ("type_declaration"
+     (treesit-node-text
+      (treesit-node-child-by-field-name
+       (treesit-node-child node 0 t) "name")
+      t))))
+
+(defun go-ts-mode--interface-node-p (node)
+  "Return t if NODE is an interface."
+  (and
+   (string-equal "type_declaration" (treesit-node-type node))
+   (treesit-search-subtree node "interface_type" nil nil 2)))
+
+(defun go-ts-mode--struct-node-p (node)
+  "Return t if NODE is a struct."
+  (and
+   (string-equal "type_declaration" (treesit-node-type node))
+   (treesit-search-subtree node "struct_type" nil nil 2)))
+
+(defun go-ts-mode--alias-node-p (node)
+  "Return t if NODE is a type alias."
+  (and
+   (string-equal "type_declaration" (treesit-node-type node))
+   (treesit-search-subtree node "type_alias" nil nil 1)))
+
+(defun go-ts-mode--other-type-node-p (node)
+  "Return t if NODE is a type, other than interface, struct or alias."
+  (and
+   (string-equal "type_declaration" (treesit-node-type node))
+   (not (go-ts-mode--interface-node-p node))
+   (not (go-ts-mode--struct-node-p node))
+   (not (go-ts-mode--alias-node-p node))))
+
 ;; go.mod support.
 
 (defvar go-mod-ts-mode--syntax-table
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 20692d6c8d..92e018aaec 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -3561,8 +3561,9 @@ Treats actions as defuns."
        (kill-local-variable 'gdb-define-alist)
        (remove-hook 'after-save-hook #'gdb-create-define-alist t))))
 
-(defcustom gud-tooltip-modes '(gud-mode c-mode c++-mode fortran-mode
-                                       python-mode)
+(defcustom gud-tooltip-modes '( gud-mode c-mode c++-mode fortran-mode
+                               python-mode c-ts-mode c++-ts-mode
+                                python-ts-mode)
   "List of modes for which to enable GUD tooltips."
   :type '(repeat (symbol :tag "Major mode"))
   :group 'tooltip)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 881f4a83b1..902d4fa7ab 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3542,7 +3542,10 @@ This function is intended for use in 
`after-change-functions'."
              (identifier)
              (identifier)
              @font-lock-function-name-face)
-      value: (array (number) (function))))
+      value: (array (number) (function)))
+     (import_clause (identifier) @font-lock-variable-name-face)
+     (import_clause (named_imports (import_specifier (identifier))
+                                   @font-lock-variable-name-face)))
 
    :language 'javascript
    :feature 'property
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 730998727c..dc87cb8e15 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,7 +1,7 @@
 ;;; project.el --- Operations on the current project  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
-;; Version: 0.9.3
+;; Version: 0.9.4
 ;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
 
 ;; This is a GNU ELPA :core package.  Avoid using functionality that
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 59164d7d50..21d16db287 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1067,11 +1067,28 @@ fontified."
                                "expression_statement"))
                    'font-lock-doc-face
                  'font-lock-string-face)))
-    (when (eq (char-after string-beg) ?f)
-      (cl-incf string-beg))
+    ;; Don't highlight string prefixes like f/r/b.
+    (save-excursion
+      (goto-char string-beg)
+      (when (search-forward "\"" string-end t)
+        (setq string-beg (match-beginning 0))))
     (treesit-fontify-with-override
      string-beg string-end face override start end)))
 
+(defun python--treesit-fontify-string-interpolation
+    (node _ start end &rest _)
+  "Fontify string interpolation.
+NODE is the string node.  Do not fontify the initial f for
+f-strings.  START and END mark the region to be
+fontified."
+  ;; This is kind of a hack, it basically removes the face applied by
+  ;; the string feature, so that following features can apply their
+  ;; face.
+  (let ((n-start (treesit-node-start node))
+        (n-end (treesit-node-end node)))
+    (remove-text-properties
+     (max start n-start) (min end n-end) '(face))))
+
 (defvar python--treesit-settings
   (treesit-font-lock-rules
    :feature 'comment
@@ -1082,10 +1099,12 @@ fontified."
    :language 'python
    '((string) @python--treesit-fontify-string)
 
+   ;; HACK: This feature must come after the string feature and before
+   ;; other features.  Maybe we should make string-interpolation an
+   ;; option rather than a feature.
    :feature 'string-interpolation
    :language 'python
-   :override t
-   '((interpolation (identifier) @font-lock-variable-name-face))
+   '((interpolation) @python--treesit-fontify-string-interpolation)
 
    :feature 'definition
    :language 'python
@@ -3766,15 +3785,16 @@ the python shell:
                         (line-beginning-position)
                       start))))
          (substring (buffer-substring-no-properties start end))
-         (starts-at-point-min-p (save-restriction
-                                  (widen)
-                                  (= (point-min) start)))
+         (starts-at-first-line-p (save-restriction
+                                   (widen)
+                                   (goto-char start)
+                                   (= (line-number-at-pos) 1)))
          (encoding (python-info-encoding))
          (toplevel-p (zerop (save-excursion
                               (goto-char start)
                               (python-util-forward-comment 1)
                               (current-indentation))))
-         (fillstr (cond (starts-at-point-min-p
+         (fillstr (cond (starts-at-first-line-p
                          nil)
                         ((not no-cookie)
                          (concat
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index 5f5de50043..d68b57966b 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -82,6 +82,16 @@
 (require 'ruby-mode)
 
 (declare-function treesit-parser-create "treesit.c")
+(declare-function treesit-induce-sparse-tree "treesit.c")
+(declare-function treesit-node-child-by-field-name "treesit.c")
+(declare-function treesit-search-subtree "treesit.c")
+(declare-function treesit-node-parent "treesit.c")
+(declare-function treesit-node-next-sibling "treesit.c")
+(declare-function treesit-node-type "treesit.c")
+(declare-function treesit-node-child "treesit.c")
+(declare-function treesit-node-end "treesit.c")
+(declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-string "treesit.c")
 
 (defgroup ruby-ts nil
   "Major mode for editing Ruby code."
@@ -304,7 +314,12 @@ values of OVERRIDE"
      (array_pattern
       (identifier) @font-lock-variable-name-face)
      (keyword_pattern
-      key: (hash_key_symbol) @font-lock-variable-name-face)
+      value: (identifier) @font-lock-variable-name-face)
+     (keyword_pattern
+      key: (hash_key_symbol) @font-lock-variable-name-face
+      !value)
+     (as_pattern
+      name: (identifier) @font-lock-variable-name-face)
      (in_clause
       pattern: (identifier) @font-lock-variable-name-face))
 
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 0a79ae0124..0786150d90 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -194,7 +194,13 @@ Argument LANGUAGE is either `typescript' or `tsx'."
       name: (array_pattern
              (identifier)
              (identifier) @font-lock-function-name-face)
-      value: (array (number) (function))))
+      value: (array (number) (function)))
+
+     (catch_clause
+      parameter: (identifier) @font-lock-variable-name-face)
+
+     (import_clause (identifier) @font-lock-variable-name-face)
+     (import_clause (named_imports (import_specifier (identifier)) 
@font-lock-variable-name-face)))
 
    :language language
    :override t
@@ -223,17 +229,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
       parameters:
       [(_ (identifier) @font-lock-variable-name-face)
        (_ (_ (identifier) @font-lock-variable-name-face))
-       (_ (_ (_ (identifier) @font-lock-variable-name-face)))])
-
-     (return_statement (identifier) @font-lock-variable-name-face)
-
-     (binary_expression left: (identifier) @font-lock-variable-name-face)
-     (binary_expression right: (identifier) @font-lock-variable-name-face)
-
-     (arguments (identifier) @font-lock-variable-name-face)
-
-     (parenthesized_expression (identifier) @font-lock-variable-name-face)
-     (parenthesized_expression (_ (identifier) @font-lock-variable-name-face)))
+       (_ (_ (_ (identifier) @font-lock-variable-name-face)))]))
 
    :language language
    :override t
@@ -245,8 +241,6 @@ Argument LANGUAGE is either `typescript' or `tsx'."
 
      (pair key: (property_identifier) @font-lock-variable-name-face)
 
-     (pair value: (identifier) @font-lock-variable-name-face)
-
      ((shorthand_property_identifier) @font-lock-property-face)
 
      ((shorthand_property_identifier_pattern)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index d5cee9fa84..916d83d407 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
 ;;; xref.el --- Cross-referencing commands              -*-lexical-binding:t-*-
 
 ;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
-;; Version: 1.6.0
+;; Version: 1.6.1
 ;; Package-Requires: ((emacs "26.1"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
diff --git a/lisp/simple.el b/lisp/simple.el
index 690968ca93..f571217723 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2207,15 +2207,39 @@ to get different commands to edit and resubmit."
   "Predicate to use to determine which commands to include when completing.
 If it's nil, include all the commands.
 If it's a function, it will be called with two parameters: the
-symbol of the command and a buffer.  The predicate should return
-non-nil if the command should be present when doing \\`M-x TAB'
-in that buffer."
+symbol of the command and the current buffer.  The predicate should
+return non-nil if the command should be considered as a completion
+candidate for \\`M-x' in that buffer.
+
+Several predicate functions suitable for various optional behaviors
+are available:
+
+  `command-completion-default-include-p'
+         This excludes from completion candidates those commands
+         which have been marked specific to modes other than the
+         current buffer's mode.  Commands that are not specific
+         to any mode are included.
+
+  `command-completion-using-modes-p'
+         This includes in completion candidates only commands
+         marked as specific to the current buffer's mode.
+
+  `command-completion-using-modes-and-keymaps-p'
+         This includes commands marked as specific to the current
+         buffer's modes and commands that have keybindings in the
+         current buffer's active local keymaps.  It also includes
+         several commands, like Cuztomize commands, which should
+         always be avaliable."
   :version "28.1"
   :group 'completion
   :type '(choice (const :tag "Don't exclude any commands" nil)
                  (const :tag "Exclude commands irrelevant to current buffer's 
mode"
                         command-completion-default-include-p)
-                 (function :tag "Other function")))
+                 (const :tag "Include only commands relevant to current 
buffer's mode"
+                        command-completion-using-modes-p)
+                 (const :tag "Commands relevant to current buffer's mode or 
bound in its keymaps"
+                        command-completion-using-modes-and-keymaps-p)
+                 (function :tag "Other predicate function")))
 
 (defun execute-extended-command-cycle ()
   "Choose the next version of the extended command predicates.
@@ -2401,6 +2425,35 @@ or (if one of MODES is a minor mode), if it is switched 
on in BUFFER."
                         #'eq)
       (seq-intersection modes global-minor-modes #'eq)))
 
+(defun command-completion-using-modes-and-keymaps-p (symbol buffer)
+  "Return non-nil if SYMBOL is marked for BUFFER's mode or bound in its 
keymaps."
+  (with-current-buffer buffer
+      (let ((keymaps
+             ;; The major mode's keymap and any active minor modes.
+             (nconc
+              (and (current-local-map) (list (current-local-map)))
+              (mapcar
+               #'cdr
+               (seq-filter
+                (lambda (elem)
+                  (symbol-value (car elem)))
+                minor-mode-map-alist)))))
+        (or (command-completion-using-modes-p symbol buffer)
+            ;; Include commands that are bound in a keymap in the
+            ;; current buffer.
+            (and (where-is-internal symbol keymaps)
+                 ;; But not if they have a command predicate that
+                 ;; says that they shouldn't.  (This is the case
+                 ;; for `ignore' and `undefined' and similar
+                 ;; commands commonly found in keymaps.)
+                 (or (null (get symbol 'completion-predicate))
+                     (funcall (get symbol 'completion-predicate)
+                              symbol buffer)))
+            ;; Include customize-* commands (do we need a list of such
+            ;; "always available" commands? customizable?)
+            (string-match-p "customize-" (symbol-name symbol))))))
+
+
 (defun command-completion-button-p (category buffer)
   "Return non-nil if there's a button of CATEGORY at point in BUFFER."
   (with-current-buffer buffer
@@ -2502,7 +2555,11 @@ Also see `suggest-key-bindings'."
 (defun execute-extended-command (prefixarg &optional command-name typed)
   "Read a command name, then read the arguments and call the command.
 To pass a prefix argument to the command you are
-invoking, give a prefix argument to `execute-extended-command'."
+invoking, give a prefix argument to `execute-extended-command'.
+
+This command provides completion when reading the command name.
+Which completion candidates are shown can be controlled by
+customizing `read-extended-command-predicate'."
   (declare (interactive-only command-execute))
   ;; FIXME: Remember the actual text typed by the user before completion,
   ;; so that we don't later on suggest the same shortening.
@@ -8436,37 +8493,39 @@ are interchanged."
   (interactive "*p")
   (transpose-subr 'forward-word arg))
 
-(defvar transpose-sexps-function
-  (lambda (arg)
-    ;; Here we should try to simulate the behavior of
-    ;; (cons (progn (forward-sexp x) (point))
-    ;;       (progn (forward-sexp (- x)) (point)))
-    ;; Except that we don't want to rely on the second forward-sexp
-    ;; putting us back to where we want to be, since forward-sexp-function
-    ;; might do funny things like infix-precedence.
-    (if (if (> arg 0)
-           (looking-at "\\sw\\|\\s_")
-         (and (not (bobp))
-              (save-excursion
-                 (forward-char -1)
-                 (looking-at "\\sw\\|\\s_"))))
-        ;; Jumping over a symbol.  We might be inside it, mind you.
-       (progn (funcall (if (> arg 0)
-                           #'skip-syntax-backward #'skip-syntax-forward)
-                       "w_")
-              (cons (save-excursion (forward-sexp arg) (point)) (point)))
-      ;; Otherwise, we're between sexps.  Take a step back before jumping
-      ;; to make sure we'll obey the same precedence no matter which
-      ;; direction we're going.
-      (funcall (if (> arg 0) #'skip-syntax-backward #'skip-syntax-forward)
-               " .")
-      (cons (save-excursion (forward-sexp arg) (point))
-           (progn (while (or (forward-comment (if (> arg 0) 1 -1))
-                             (not (zerop (funcall (if (> arg 0)
-                                                      #'skip-syntax-forward
-                                                    #'skip-syntax-backward)
-                                                  ".")))))
-                  (point)))))
+(defun transpose-sexps-default-function (arg)
+  "Default method to locate a pair of points for transpose-sexps."
+  ;; Here we should try to simulate the behavior of
+  ;; (cons (progn (forward-sexp x) (point))
+  ;;       (progn (forward-sexp (- x)) (point)))
+  ;; Except that we don't want to rely on the second forward-sexp
+  ;; putting us back to where we want to be, since forward-sexp-function
+  ;; might do funny things like infix-precedence.
+  (if (if (> arg 0)
+         (looking-at "\\sw\\|\\s_")
+       (and (not (bobp))
+            (save-excursion
+               (forward-char -1)
+               (looking-at "\\sw\\|\\s_"))))
+      ;; Jumping over a symbol.  We might be inside it, mind you.
+      (progn (funcall (if (> arg 0)
+                         #'skip-syntax-backward #'skip-syntax-forward)
+                     "w_")
+            (cons (save-excursion (forward-sexp arg) (point)) (point)))
+    ;; Otherwise, we're between sexps.  Take a step back before jumping
+    ;; to make sure we'll obey the same precedence no matter which
+    ;; direction we're going.
+    (funcall (if (> arg 0) #'skip-syntax-backward #'skip-syntax-forward)
+             " .")
+    (cons (save-excursion (forward-sexp arg) (point))
+         (progn (while (or (forward-comment (if (> arg 0) 1 -1))
+                           (not (zerop (funcall (if (> arg 0)
+                                                    #'skip-syntax-forward
+                                                  #'skip-syntax-backward)
+                                                ".")))))
+                (point)))))
+
+(defvar transpose-sexps-function #'transpose-sexps-default-function
   "If non-nil, `transpose-sexps' delegates to this function.
 
 This function takes one argument ARG, a number.  Its expected
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index 77373707d6..6beae81625 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -636,7 +636,7 @@ command, it will add another key, ignoring the value of
 
 The regular expression uses an expanded syntax: && is interpreted as `and'.
 Thus, `aaaa&&bbb' matches entries which contain both `aaaa' and `bbb'.
-While entering the regexp, completion on knows citation keys is possible.
+While entering the regexp, completion on known citation keys is possible.
 `=' is a good regular expression to match all entries in all files."
   (interactive)
 
diff --git a/lisp/treesit.el b/lisp/treesit.el
index a7f453a889..25b2c70ce0 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1143,20 +1143,17 @@ See `treesit-simple-indent-presets'.")
                   (point))))
         (cons 'prev-adaptive-prefix
               (lambda (_n parent &rest _)
-                (save-excursion
-                  (re-search-backward
-                   (rx (not (or " " "\t" "\n"))) nil t)
-                  (beginning-of-line)
-                  (and (>= (point) (treesit-node-start parent))
-                       ;; `adaptive-fill-regexp' will not match "/*",
-                       ;; so we need to also try `comment-start-skip'.
-                       (or (and adaptive-fill-regexp
-                                (looking-at adaptive-fill-regexp)
-                                (> (- (match-end 0) (match-beginning 0)) 0)
-                                (match-end 0))
-                           (and comment-start-skip
-                                (looking-at comment-start-skip)
-                                (match-end 0)))))))
+                (let ((comment-start-bol
+                       (save-excursion
+                         (goto-char (treesit-node-start parent))
+                         (line-beginning-position))))
+                  (save-excursion
+                    (forward-line -1)
+                    (and (>= (point) comment-start-bol)
+                         adaptive-fill-regexp
+                         (looking-at adaptive-fill-regexp)
+                         (> (match-end 0) (match-beginning 0))
+                         (match-end 0))))))
         ;; TODO: Document.
         (cons 'grand-parent
               (lambda (_n parent &rest _)
@@ -1187,9 +1184,12 @@ See `treesit-simple-indent-presets'.")
                          res))))
         (cons 'or (lambda (&rest fns)
                     (lambda (node parent bol &rest _)
-                      (seq-find
-                       (lambda (fn) (funcall fn node parent bol))
-                       fns))))
+                      (let (res)
+                        (catch 'break
+                          (dolist (fn fns)
+                            (setq res (funcall fn node parent bol))
+                            (and res (throw 'break t))))
+                        res))))
         (cons 'not (lambda (fn)
                      (lambda (node parent bol &rest _)
                        (not (funcall fn node parent bol)))))
@@ -1338,10 +1338,10 @@ and returns
     (ANCHOR . OFFSET).
 
 BOL is the position of the beginning of the line; NODE is the
-\"largest\" node that starts at BOL; PARENT is its parent; ANCHOR
-is a point (not a node), and OFFSET is a number.  Emacs finds the
-column of ANCHOR and adds OFFSET to it as the final indentation
-of the current line.")
+\"largest\" node that starts at BOL (and isn't a root node);
+PARENT is its parent; ANCHOR is a point (not a node), and OFFSET
+is a number.  Emacs finds the column of ANCHOR and adds OFFSET to
+it as the final indentation of the current line.")
 
 (defun treesit--indent-1 ()
   "Indent the current line.
@@ -1359,10 +1359,13 @@ Return (ANCHOR . OFFSET).  This function is used by
                 ((treesit-language-at (point))
                  (treesit-node-at bol (treesit-language-at (point))))
                 (t (treesit-node-at bol))))
+         (root (treesit-parser-root-node
+                (treesit-node-parser smallest-node)))
          (node (treesit-parent-while
                 smallest-node
                 (lambda (node)
-                  (eq bol (treesit-node-start node))))))
+                  (and (eq bol (treesit-node-start node))
+                       (not (treesit-node-eq node root)))))))
     (let*
         ((parser (if smallest-node
                      (treesit-node-parser smallest-node)
@@ -2447,11 +2450,15 @@ in the region."
                   (window-start) (window-end) treesit--explorer-language))
            ;; Only highlight the current top-level construct.
            ;; Highlighting the whole buffer is slow and unnecessary.
-           (top-level (treesit-node-first-child-for-pos
-                       root (if (eolp)
-                                (max (point-min) (1- (point)))
-                              (point))
-                       t))
+           ;; But if the buffer is small (ie, used in playground
+           ;; style), just highlight the whole buffer.
+           (top-level (if (< (buffer-size) 4000)
+                          root
+                        (treesit-node-first-child-for-pos
+                         root (if (eolp)
+                                  (max (point-min) (1- (point)))
+                                (point))
+                         t)))
            ;; Only highlight node when region is active, if we
            ;; highlight node at point the syntax tree is too jumpy.
            (nodes-hl
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index acfd2c30f0..eb01dede56 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -485,17 +485,19 @@ use the face `diff-removed' for removed lines, and the 
face
          ;; if below, use `diff-added'.
          (save-match-data
            (let ((limit (save-excursion (diff-beginning-of-hunk))))
-             (if (save-excursion (re-search-backward 
diff-context-mid-hunk-header-re limit t))
-                 diff-indicator-added-face
-               diff-indicator-removed-face)))))
+              (when (< limit (point))
+                (if (save-excursion (re-search-backward 
diff-context-mid-hunk-header-re limit t))
+                   diff-indicator-added-face
+                 diff-indicator-removed-face))))))
      (2 (if diff-use-changed-face
            'diff-changed-unspecified
          ;; Otherwise, use the same method as above.
          (save-match-data
            (let ((limit (save-excursion (diff-beginning-of-hunk))))
-             (if (save-excursion (re-search-backward 
diff-context-mid-hunk-header-re limit t))
-                 'diff-added
-               'diff-removed))))))
+             (when (< limit (point))
+                (if (save-excursion (re-search-backward 
diff-context-mid-hunk-header-re limit t))
+                   'diff-added
+                 'diff-removed)))))))
     ("^\\(?:Index\\|revno\\): \\(.+\\).*\n"
      (0 'diff-header) (1 'diff-index prepend))
     ("^\\(?:index .*\\.\\.\\|diff \\).*\n" . 'diff-header)
diff --git a/src/callint.c b/src/callint.c
index c60a376b95..d8d2b27845 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -105,11 +105,13 @@ If the string begins with `^' and `shift-select-mode' is 
non-nil,
 You may use `@', `*', and `^' together.  They are processed in the
  order that they appear, before reading any arguments.
 
-If MODES is present, it should be a list of mode names (symbols) that
-this command is applicable for.  The main effect of this is that
-`M-x TAB' (by default) won't list this command if the current buffer's
-mode doesn't match the list.  That is, if either the major mode isn't
-derived from them, or (when it's a minor mode) the mode isn't in effect.
+If MODES is present, it should be one or more mode names (symbols)
+for which this command is applicable.  This is so that `M-x TAB'
+will be able to exclude this command from the list of completion
+candidates if the current buffer's mode doesn't match the list.
+Which commands are excluded from the list of completion
+candidates based on this information is controlled by the value
+of `read-extended-command-predicate', which see.
 
 usage: (interactive &optional ARG-DESCRIPTOR &rest MODES)  */
        attributes: const)
diff --git a/src/gnutls.c b/src/gnutls.c
index e8528381ef..ca7e9fc4c7 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -2405,6 +2405,9 @@ gnutls_symmetric_aead (bool encrypting, 
gnutls_cipher_algorithm_t gca,
       aead_auth_size = aend_byte - astart_byte;
     }
 
+  /* Only block ciphers require that ISIZE be a multiple of the block
+     size, and AEAD ciphers are not block ciphers.  */
+#if 0
   ptrdiff_t expected_remainder = encrypting ? 0 : cipher_tag_size;
   ptrdiff_t cipher_block_size = gnutls_cipher_get_block_size (gca);
 
@@ -2414,6 +2417,7 @@ gnutls_symmetric_aead (bool encrypting, 
gnutls_cipher_algorithm_t gca,
            "is not %"pD"d greater than a multiple of the required %"pD"d"),
            gnutls_cipher_get_name (gca), desc,
           isize, expected_remainder, cipher_block_size);
+#endif
 
   ret = ((encrypting ? gnutls_aead_cipher_encrypt : gnutls_aead_cipher_decrypt)
         (acipher, vdata, vsize, aead_auth_data, aead_auth_size,
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 6b3a0459d3..6e5bb22375 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1902,7 +1902,7 @@ parse_resource_key (const char *res_key, char 
*setting_key)
 
   /* check existence of setting_key */
   GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default ();
-  GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, 
FALSE);
+  GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, 
TRUE);
   if (!scm)
     return NULL;       /* *.schema.xml is not installed. */
   if (!g_settings_schema_has_key (scm, setting_key))
diff --git a/src/print.c b/src/print.c
index bc6d5487c1..d656774b9c 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2039,8 +2039,13 @@ print_vectorlike (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag,
       /* Now the node must be up-to-date, and calling functions like
         Ftreesit_node_start will not signal.  */
       bool named = treesit_named_node_p (XTS_NODE (obj)->node);
-      const char *delim1 = named ? "(" : "\"";
-      const char *delim2 = named ? ")" : "\"";
+      /* We used to use () as delimiters for named nodes, but that
+        confuses pretty-printing a tad bit.  There might be more
+        little breakages here and there if we print parenthesizes
+        inside an object, so I guess better not do it.
+        (bug#60696)  */
+      const char *delim1 = named ? "" : "\"";
+      const char *delim2 = named ? "" : "\"";
       print_c_string (delim1, printcharfun);
       print_string (Ftreesit_node_type (obj), printcharfun);
       print_c_string (delim2, printcharfun);
diff --git a/test/lisp/erc/erc-scenarios-base-association.el 
b/test/lisp/erc/erc-scenarios-base-association.el
index 1e280d0fdd..a40a4cb755 100644
--- a/test/lisp/erc/erc-scenarios-base-association.el
+++ b/test/lisp/erc/erc-scenarios-base-association.el
@@ -26,7 +26,9 @@
 
 (declare-function erc-network-name "erc-networks")
 (declare-function erc-network "erc-networks")
+(declare-function erc-track-get-active-buffer "erc-track" (arg))
 (defvar erc-autojoin-channels-alist)
+(defvar erc-track-mode)
 (defvar erc-network)
 
 ;; Two networks, same channel name, no confusion (no bouncer).  Some
@@ -190,4 +192,51 @@
       (with-current-buffer "#chan@barnet"
         (erc-d-t-search-for 10 "I'll bid adieu")))))
 
+;; Some modules may need to perform housekeeping when a newly
+;; connected server buffer is deemed a duplicate after its persistent
+;; network context is discovered on MOTD end.  One such module is
+;; `track', which needs to rid its list of modified channels of the
+;; buffer being killed.  Without this, a user may encounter an
+;; "Attempt to display deleted buffer" error when they try switching
+;; to it.
+
+(ert-deftest erc-scenarios-networks-merge-server-track ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "networks/merge-server")
+       (dumb-server (erc-d-run "localhost" t 'track 'track))
+       (port (process-contact dumb-server :service))
+       (erc-server-flood-penalty 0.1)
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester")
+        (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+        (should erc-track-mode)
+        (funcall expect 5 "changed mode for tester")
+        (erc-cmd-JOIN "#chan")))
+
+    (ert-info ("Join channel and quit")
+      (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+        (funcall expect 5 "The hour that fools should ask")
+        (erc-cmd-QUIT ""))
+      (with-current-buffer "FooNet"
+        (funcall expect 5 "finished")))
+
+    (ert-info ("Reconnect")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester")
+        (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+        (funcall expect 5 "changed mode for tester")))
+
+    (with-current-buffer "#chan"
+      (funcall expect 5 "The hour that fools should ask")
+      ;; Simulate the old `erc-track-switch-buffer'
+      (switch-to-buffer (erc-track-get-active-buffer 1))
+      (erc-d-t-wait-for 10 (eq (get-buffer "FooNet") (current-buffer)))
+      (erc-cmd-QUIT ""))))
+
 ;;; erc-scenarios-base-association.el ends here
diff --git a/test/lisp/erc/erc-services-tests.el 
b/test/lisp/erc/erc-services-tests.el
index b1d36d868e..9181a47ee3 100644
--- a/test/lisp/erc/erc-services-tests.el
+++ b/test/lisp/erc/erc-services-tests.el
@@ -248,7 +248,8 @@
     (let ((auth-sources (list plstore-file))
           (auth-source-do-cache nil))
       (erc-services-tests--auth-source-standard
-       #'erc-services-test--call-with-plstore))))
+       #'erc-services-test--call-with-plstore))
+    (kill-buffer (get-file-buffer plstore-file))))
 
 (ert-deftest erc--auth-source-search--plstore-announced ()
   (ert-with-temp-file plstore-file
@@ -264,7 +265,8 @@
     (let ((auth-sources (list plstore-file))
           (auth-source-do-cache nil))
       (erc-services-tests--auth-source-announced
-       #'erc-services-test--call-with-plstore))))
+       #'erc-services-test--call-with-plstore))
+    (kill-buffer (get-file-buffer plstore-file))))
 
 (ert-deftest erc--auth-source-search--plstore-overrides ()
   (ert-with-temp-file plstore-file
@@ -296,7 +298,8 @@
     (let ((auth-sources (list plstore-file))
           (auth-source-do-cache nil))
       (erc-services-tests--auth-source-overrides
-       #'erc-services-test--call-with-plstore))))
+       #'erc-services-test--call-with-plstore))
+    (kill-buffer (get-file-buffer plstore-file))))
 
 ;; auth-source JSON backend
 
diff --git a/test/lisp/erc/resources/erc-d/erc-d-t.el 
b/test/lisp/erc/resources/erc-d/erc-d-t.el
index 282c193b70..7b2adf4f07 100644
--- a/test/lisp/erc/resources/erc-d/erc-d-t.el
+++ b/test/lisp/erc/resources/erc-d/erc-d-t.el
@@ -32,7 +32,7 @@
     (dolist (buf (buffer-list))
       (with-current-buffer buf
         (when (or erc-d-u--process-buffer
-                  (derived-mode-p 'erc-mode))
+                  (derived-mode-p 'erc-mode 'erc-dcc-chat-mode))
           (push buf buflist))))
     (dolist (buf buflist)
       (when (and (boundp 'erc-server-flood-timer)
diff --git a/test/lisp/erc/resources/networks/merge-server/track.eld 
b/test/lisp/erc/resources/networks/merge-server/track.eld
new file mode 100644
index 0000000000..4a97f92f72
--- /dev/null
+++ b/test/lisp/erc/resources/networks/merge-server/track.eld
@@ -0,0 +1,44 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 10 "USER user 0 * :unknown")
+ (0.00 ":irc.example.net NOTICE * :*** Looking up your hostname...")
+ (0.01 ":irc.example.net NOTICE tester :*** Could not resolve your hostname: 
Domain not found; using your IP address (10.0.2.100) instead.")
+ (0.10 ":irc.example.net 001 tester :Welcome to the FooNet IRC Network 
tester!user@10.0.2.100")
+ (0.02 ":irc.example.net 002 tester :Your host is irc.example.net, running 
version InspIRCd-3")
+ (0.02 ":irc.example.net 003 tester :This server was created 05:58:57 Jan 04 
2023")
+ (0.01 ":irc.example.net 004 tester irc.example.net InspIRCd-3 BIRcgikorsw 
ACHIKMORTXabcefghijklmnopqrstvz :HIXabefghjkloqv")
+ (0.00 ":irc.example.net 005 tester ACCEPT=30 AWAYLEN=200 BOT=B CALLERID=g 
CASEMAPPING=ascii CHANLIMIT=#:20 CHANMODES=IXbeg,k,Hfjl,ACKMORTcimnprstz 
CHANNELLEN=64 CHANTYPES=# ELIST=CMNTU ESILENCE=CcdiNnPpTtx EXCEPTS=e :are 
supported by this server")
+ (0.02 ":irc.example.net 005 tester EXTBAN=,ACORTUacjrwz HOSTLEN=64 INVEX=I 
KEYLEN=32 KICKLEN=255 LINELEN=512 MAXLIST=I:100,X:100,b:100,e:100,g:100 
MAXTARGETS=20 MODES=20 MONITOR=30 NAMELEN=128 NAMESX NETWORK=FooNet :are 
supported by this server")
+ (0.01 ":irc.example.net 005 tester NICKLEN=30 PREFIX=(qaohv)~&@%+ SAFELIST 
SILENCE=32 STATUSMSG=~&@%+ TOPICLEN=307 UHNAMES USERIP USERLEN=10 
USERMODES=,,s,BIRcgikorw WHOX :are supported by this server")
+ (0.01 ":irc.example.net 251 tester :There are 2 users and 0 invisible on 2 
servers")
+ (0.01 ":irc.example.net 253 tester 1 :unknown connections")
+ (0.01 ":irc.example.net 254 tester 1 :channels formed")
+ (0.00 ":irc.example.net 255 tester :I have 2 clients and 1 servers")
+ (0.00 ":irc.example.net 265 tester :Current local users: 2  Max: 3")
+ (0.00 ":irc.example.net 266 tester :Current global users: 2  Max: 3")
+ (0.00 ":irc.example.net 375 tester :irc.example.net message of the day")
+ (0.00 ":irc.example.net 372 tester :  Have fun with the image!")
+ (0.00 ":irc.example.net 376 tester :End of message of the day."))
+
+((mode 10 "MODE tester +i")
+ (0.00 ":irc.example.net 501 tester x :is not a recognised user mode.")
+ (0.00 ":NickServ!NickServ@services.int NOTICE tester :Welcome to FooNet, 
tester! Here on FooNet, we provide services to enable the registration of 
nicknames and channels! For details, type \2/msg NickServ help\2 and \2/msg 
ChanServ help\2.")
+ (0.02 ":tester!user@10.0.2.100 MODE tester :+i"))
+
+((join 10 "JOIN #chan")
+ (0.01 ":tester!user@10.0.2.100 JOIN :#chan"))
+
+((mode 10 "MODE #chan")
+ (0.01 ":irc.example.net 353 tester = #chan :@alice bob tester")
+ (0.01 ":irc.example.net 366 tester #chan :End of /NAMES list.")
+ (0.00 ":alice!alice@0::1 PRIVMSG #chan :tester, welcome!")
+ (0.02 ":bob!bob@0::1 PRIVMSG #chan :tester, welcome!")
+ (0.02 ":irc.example.net 324 tester #chan :+nt")
+ (0.01 ":irc.example.net 329 tester #chan :1672811954")
+ (0.07 ":alice!alice@0::1 PRIVMSG #chan :bob: This afternoon, sir ? well, she 
shall be there.")
+ (0.05 ":bob!bob@0::1 PRIVMSG #chan :alice: The hour that fools should ask."))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.04 "ERROR :Closing link: (user@10.0.2.100) [Quit: \2ERC\2]"))
+
+((drop 1 DROP))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 90f6fcd6b1..dd3de27d3b 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -80,6 +80,9 @@
 (defvar remote-file-name-inhibit-locks)
 (defvar dired-copy-dereference)
 
+;; Declared in Emacs 30.
+(defvar remote-file-name-inhibit-delete-by-moving-to-trash)
+
 ;; `ert-resource-file' was introduced in Emacs 28.1.
 (unless (macrop 'ert-resource-file)
   (eval-and-compile
@@ -2345,7 +2348,24 @@ This checks also `file-name-as-directory', 
`file-name-directory',
                (expand-file-name
                 (file-name-nondirectory tmp-name) trash-directory))))
          (delete-directory trash-directory 'recursive)
-         (should-not (file-exists-p trash-directory)))))))
+         (should-not (file-exists-p trash-directory))))
+
+      ;; Setting `remote-file-name-inhibit-delete-by-moving-to-trash'
+      ;; prevents trashing remote files.
+      (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
+           (delete-by-moving-to-trash t)
+           (remote-file-name-inhibit-delete-by-moving-to-trash t))
+       (make-directory trash-directory)
+       (should-not (file-exists-p tmp-name))
+       (write-region "foo" nil tmp-name)
+       (should (file-exists-p tmp-name))
+       (delete-file tmp-name 'trash)
+       (should-not (file-exists-p tmp-name))
+       (should-not
+        (file-exists-p
+         (expand-file-name (file-name-nondirectory tmp-name) trash-directory)))
+       (delete-directory trash-directory 'recursive)
+       (should-not (file-exists-p trash-directory))))))
 
 (ert-deftest tramp-test08-file-local-copy ()
   "Check `file-local-copy'."
@@ -2953,7 +2973,23 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
             "%s/%s/%s/bla" trash-directory (file-name-nondirectory tmp-name1)
             (file-name-nondirectory tmp-name2))))
          (delete-directory trash-directory 'recursive)
-         (should-not (file-exists-p trash-directory)))))))
+         (should-not (file-exists-p trash-directory))))
+
+      ;; Setting `remote-file-name-inhibit-delete-by-moving-to-trash'
+      ;; prevents trashing remote files.
+      (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
+           (delete-by-moving-to-trash t)
+           (remote-file-name-inhibit-delete-by-moving-to-trash t))
+       (make-directory trash-directory)
+       (make-directory tmp-name1)
+       (should (file-directory-p tmp-name1))
+       (delete-directory tmp-name1 nil 'trash)
+       (should-not (file-exists-p tmp-name1))
+       (should-not
+        (file-exists-p
+         (expand-file-name (file-name-nondirectory tmp-name1) 
trash-directory)))
+       (delete-directory trash-directory 'recursive)
+       (should-not (file-exists-p trash-directory))))))
 
 (ert-deftest tramp-test15-copy-directory ()
   "Check `copy-directory'."
@@ -7518,6 +7554,8 @@ Since it unloads Tramp, it shall be the last test to run."
          ;; `tramp-register-archive-file-name-handler' is autoloaded
          ;; in Emacs < 29.1.
          (not (eq 'tramp-register-archive-file-name-handler x))
+         ;; `tramp-compat-rx' is autoloaded in Emacs 29.1.
+         (not (eq 'tramp-compat-rx x))
          (not (string-match-p
                (rx bol "tramp" (? "-archive") (** 1 2 "-") "test")
                (symbol-name x)))
@@ -7577,6 +7615,8 @@ If INTERACTIVE is non-nil, the tests are run 
interactively."
 ;; * file-equal-p (partly done in `tramp-test21-file-links')
 ;; * file-in-directory-p
 ;; * file-name-case-insensitive-p
+;; * memory-info
+;; * tramp-get-home-directory
 ;; * tramp-get-remote-gid
 ;; * tramp-get-remote-groups
 ;; * tramp-get-remote-uid
diff --git a/test/lisp/progmodes/python-tests.el 
b/test/lisp/progmodes/python-tests.el
index eac558db10..df71990278 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -4520,6 +4520,16 @@ def foo():
                      (python-tests-look-at "\"\"\""))
                     "# -*- coding: utf-8 -*-\n\nif True:\n    a = 1\n    b = 
2\n\n"))))
 
+(ert-deftest python-shell-buffer-substring-18 ()
+  "Check substring from the part of the first line."
+  (python-tests-with-temp-buffer
+   "s = 'test'
+"
+   (should (string= (python-shell-buffer-substring
+                     (python-tests-look-at "'test'")
+                     (pos-eol))
+                    "'test'"))))
+
 
 
 ;;; Shell completion
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb 
b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
index bfae948b25..3f0dfdf68b 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -513,7 +513,7 @@ foo bar, {
 case translation
 in ['th', orig_text, 'en', trans_text]
   puts "English translation: #{orig_text} => #{trans_text}"
-in {'th' => orig_text, 'ja' => trans_text}
+in {th: orig_text, ja: trans_text} => whole
   puts "Japanese translation: #{orig_text} => #{trans_text}"
 end
 



reply via email to

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