emacs-diffs
[Top][All Lists]
Advanced

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

master eacdac3c6e 3/5: Merge from origin/emacs-29


From: Stefan Kangas
Subject: master eacdac3c6e 3/5: Merge from origin/emacs-29
Date: Thu, 15 Dec 2022 15:34:52 -0500 (EST)

branch: master
commit eacdac3c6e43459104d25594cebc930b2a081f17
Merge: 037889c4a9 a15cd55044
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Merge from origin/emacs-29
    
    a15cd55044c ; Don't quote nil in comments
    da39200c4be ; Checkdoc fixes in dired-aux.el
    fd403a5c5a8 Fix ruby-add-log-current-method after nested class defini...
    2ca06aed7b3 Add indent rules to js/typescript/tsx-ts-mode (bug#60074)
    a54d5f500c1 Improve fontification in csharp-ts-mode (bug#59897)
    3db2f560bb7 Revert "Add expression for generic_name in csharp-ts-mode"
    1985762fbd7 Introduce support for TOML config-format
    622838b957e Fix handling of % when searching in .tex or .dtx files
    3b226b60248 Treat C++ classes as defuns in C Tree-sitter mode (bug#60...
    480f41c7deb Add < and > to the syntax table in c++-ts-mode (bug#60049)
    fbf0d3b796a Improve fontifications in Typescript mode
    f93a5180a61 Update the documentation of overlays (bug#59996)
    d51b66ed540 ; Improve description of scoping and let-bindings
    752f9dde631 ; Fix a typo in window.el
    102a3e3b445 Don't send erc-sasl-user as USER command argument
    f0c90888781 Set erc-network to a "given" ID instead of failing
    09c0c6b2ba3 Limit casemapping to appropriate ranges in ERC
    44b04c0ac1c Actually accept non-symbols as IDs in erc-open
    75f26646d4a ; Be nicer when updating browse-url var in erc-compat
    0155fc67be3 Respect a nil erc-session-password when reconnecting
    9ac80e8a6e4 Add dedicated auth-source section in ERC manual
    2d96a18cd09 ; * lisp/emacs-lisp/shortdoc.el: fix mistakes in previous...
    1d3cbba7dfa ; * lisp/progmodes/cmake-ts-mode.el (auto-mode-alist): $ ...
    0cc199f1a61 Better shortdoc examples
    931d97bf563 Shortdoc: read and evaluate strings after :eval
    be165f75332 Fix Tramp tests in eglot-tests, prefix tests uniquely
    8c30cb90ba9 * lisp/vc/vc-git.el (vc-git-checkin): Use make-nearby-tem...
    3efe4df1d20 Delete temp files after icalendar tests
    
    # Conflicts:
    #       etc/NEWS
---
 admin/notes/tree-sitter/build-module/batch.sh      |   4 +-
 doc/lispref/display.texi                           | 120 +++----
 doc/lispref/internals.texi                         |  16 +-
 doc/lispref/variables.texi                         |  27 +-
 doc/misc/erc.texi                                  | 344 +++++++++++++--------
 etc/ERC-NEWS                                       |   4 +-
 etc/NEWS.29                                        |  39 ++-
 lisp/dired-aux.el                                  |  53 ++--
 lisp/emacs-lisp/shortdoc.el                        | 154 ++++++---
 lisp/emacs-lisp/subr-x.el                          |   2 +-
 lisp/erc/erc-common.el                             |  16 +-
 lisp/erc/erc-compat.el                             |   7 +-
 lisp/erc/erc-networks.el                           |  57 +++-
 lisp/erc/erc-sasl.el                               |  27 +-
 lisp/erc/erc-services.el                           |   2 +-
 lisp/erc/erc.el                                    |  47 ++-
 lisp/external-completion.el                        |   2 +-
 lisp/org/ob-clojure.el                             |   4 +-
 lisp/org/org-persist.el                            |   2 +-
 lisp/progmodes/c-ts-mode.el                        |  12 +-
 lisp/progmodes/cmake-ts-mode.el                    |   2 +-
 lisp/progmodes/csharp-mode.el                      |  14 +-
 lisp/progmodes/js.el                               |   3 +
 lisp/progmodes/ruby-mode.el                        |  38 ++-
 lisp/progmodes/typescript-ts-mode.el               |  45 ++-
 lisp/subr.el                                       |   2 +-
 lisp/textmodes/reftex.el                           |  11 +-
 lisp/textmodes/toml-ts-mode.el                     | 187 +++++++++++
 lisp/vc/vc-git.el                                  |   2 +-
 lisp/window.el                                     |   2 +-
 src/buffer.c                                       |  17 +-
 test/lisp/calendar/icalendar-tests.el              |   3 +-
 test/lisp/erc/erc-networks-tests.el                |   7 +-
 test/lisp/erc/erc-scenarios-base-netid-samenet.el  |   3 +
 test/lisp/erc/erc-scenarios-misc.el                |   5 +-
 test/lisp/erc/erc-scenarios-services-misc.el       |  59 ++++
 test/lisp/erc/erc-tests.el                         |   3 +
 .../erc/resources/base/local-modules/fourth.eld    |   2 +-
 test/lisp/erc/resources/erc-scenarios-common.el    |   2 +-
 .../networks/announced-missing/foonet.eld          |   3 -
 .../erc/resources/services/auth-source/recon.eld   |  48 +++
 test/lisp/progmodes/eglot-tests.el                 | 117 +++----
 test/lisp/progmodes/ruby-mode-tests.el             |  27 ++
 43 files changed, 1089 insertions(+), 452 deletions(-)

diff --git a/admin/notes/tree-sitter/build-module/batch.sh 
b/admin/notes/tree-sitter/build-module/batch.sh
index c395449977..e7ef45cf57 100755
--- a/admin/notes/tree-sitter/build-module/batch.sh
+++ b/admin/notes/tree-sitter/build-module/batch.sh
@@ -1,6 +1,7 @@
 #!/bin/bash
 
 languages=(
+    'bash'
     'c'
     'cmake'
     'cpp'
@@ -13,8 +14,9 @@ languages=(
     'json'
     'python'
     'rust'
-    'typescript'
+    'toml'
     'tsx'
+    'typescript'
 )
 
 for language in "${languages[@]}"
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 13dc228261..4111a86aa7 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -1460,7 +1460,8 @@ You can use @dfn{overlays} to alter the appearance of a 
buffer's text on
 the screen, for the sake of presentation features.  An overlay is an
 object that belongs to a particular buffer, and has a specified
 beginning and end.  It also has properties that you can examine and set;
-these affect the display of the text within the overlay.
+these affect the display of the text within the overlaid portion of
+the buffer.
 
 Editing the text of the buffer adjusts the beginning and end of each
 overlay so that it stays with the text.  When you create the overlay,
@@ -1482,7 +1483,7 @@ inside the overlay or outside, and likewise for the end 
of the overlay.
   This section describes the functions to create, delete and move
 overlays, and to examine their contents.  Overlay changes are not
 recorded in the buffer's undo list, since the overlays are not
-part of the buffer's contents.
+considered part of the buffer's contents.
 
 @defun overlayp object
 This function returns @code{t} if @var{object} is an overlay.
@@ -1504,15 +1505,14 @@ When that happens, the overlay is by default not 
deleted, but you can
 cause it to be deleted by giving it the @samp{evaporate} property
 (@pxref{Overlay Properties, evaporate property}).
 
-The arguments @var{front-advance} and @var{rear-advance} specify the
-marker insertion type for the start of the overlay and for the end of
-the overlay, respectively.  @xref{Marker Insertion Types}.  If they
-are both @code{nil}, the default, then the overlay extends to include
-any text inserted at the beginning, but not text inserted at the end.
-If @var{front-advance} is non-@code{nil}, text inserted at the
-beginning of the overlay is excluded from the overlay.  If
-@var{rear-advance} is non-@code{nil}, text inserted at the end of the
-overlay is included in the overlay.
+The arguments @var{front-advance} and @var{rear-advance} specify what
+happens when text is inserted at the beginning (i.e., before
+@var{start}) and at the end.  If they are both @code{nil}, the
+default, then the overlay extends to include any text inserted at the
+beginning, but not text inserted at the end.  If @var{front-advance}
+is non-@code{nil}, text inserted at the beginning of the overlay is
+excluded from the overlay.  If @var{rear-advance} is non-@code{nil},
+text inserted at the end of the overlay is included in the overlay.
 @end defun
 
 @defun overlay-start overlay
@@ -1531,36 +1531,36 @@ returns @code{nil} if @var{overlay} has been deleted.
 @end defun
 
 @defun delete-overlay overlay
-This function deletes @var{overlay}.  The overlay continues to exist as
-a Lisp object, and its property list is unchanged, but it ceases to be
-attached to the buffer it belonged to, and ceases to have any effect on
-display.
+This function deletes the specified @var{overlay}.  The overlay
+continues to exist as a Lisp object, and its property list is
+unchanged, but it ceases to be attached to the buffer it belonged to,
+and ceases to have any effect on display.
 
 A deleted overlay is not permanently disconnected.  You can give it a
 position in a buffer again by calling @code{move-overlay}.
 @end defun
 
 @defun move-overlay overlay start end &optional buffer
-This function moves @var{overlay} to @var{buffer}, and places its bounds
-at @var{start} and @var{end}.  Both arguments @var{start} and @var{end}
-must specify buffer positions; they may be integers or markers.
+This function moves @var{overlay} to @var{buffer}, and places its
+bounds at @var{start} and @var{end} in that buffer.  Both arguments
+@var{start} and @var{end} must specify buffer positions; they may be
+integers or markers.
 
 If @var{buffer} is omitted, @var{overlay} stays in the same buffer it
-was already associated with; if @var{overlay} was deleted, it goes into
-the current buffer.
+was already associated with; if @var{overlay} was previously deleted
+(and thus isn't associated with any buffer), it goes into the current
+buffer.
 
 The return value is @var{overlay}.
 
-This is the only valid way to change the endpoints of an overlay.  Do
-not try modifying the markers in the overlay by hand, as that fails to
-update other vital data structures and can cause some overlays to be
-lost.
+This function is the only valid way to change the endpoints of an
+overlay.
 @end defun
 
 @defun remove-overlays &optional start end name value
 This function removes all the overlays between @var{start} and
-@var{end} whose property @var{name} has the value @var{value}.  It can
-move the endpoints of the overlays in the region, or split them.
+@var{end} whose property @var{name} has the specified @var{value}.  It
+can move the endpoints of the overlays in the region, or split them.
 
 If @var{name} is omitted or @code{nil}, it means to delete all overlays in
 the specified region.  If @var{start} and/or @var{end} are omitted or
@@ -1571,20 +1571,24 @@ current buffer.
 
 @defun copy-overlay overlay
 This function returns a copy of @var{overlay}.  The copy has the same
-endpoints and properties as @var{overlay}.  However, the marker
+endpoints and properties as @var{overlay}.  However, the text
 insertion type for the start of the overlay and for the end of the
-overlay are set to their default values (@pxref{Marker Insertion
-Types}).
+overlay are set to their default values.
 @end defun
 
   Here are some examples:
 
 @example
+@group
 ;; @r{Create an overlay.}
 (setq foo (make-overlay 1 10))
      @result{} #<overlay from 1 to 10 in display.texi>
+@end group
+@group
 (overlay-start foo)
      @result{} 1
+@end group
+@group
 (overlay-end foo)
      @result{} 10
 (overlay-buffer foo)
@@ -1595,6 +1599,8 @@ Types}).
 ;; @r{Verify the property is present.}
 (overlay-get foo 'happy)
      @result{} t
+@end group
+@group
 ;; @r{Move the overlay.}
 (move-overlay foo 5 20)
      @result{} #<overlay from 5 to 20 in display.texi>
@@ -1602,6 +1608,8 @@ Types}).
      @result{} 5
 (overlay-end foo)
      @result{} 20
+@end group
+@group
 ;; @r{Delete the overlay.}
 (delete-overlay foo)
      @result{} nil
@@ -1615,6 +1623,8 @@ foo
      @result{} nil
 (overlay-buffer foo)
      @result{} nil
+@end group
+@group
 ;; @r{Undelete the overlay.}
 (move-overlay foo 1 20)
      @result{} #<overlay from 1 to 20 in display.texi>
@@ -1625,26 +1635,14 @@ foo
      @result{} 20
 (overlay-buffer foo)
      @result{} #<buffer display.texi>
+@end group
+@group
 ;; @r{Moving and deleting the overlay does not change its properties.}
 (overlay-get foo 'happy)
      @result{} t
+@end group
 @end example
 
-  Emacs stores the overlays of each buffer in two lists, divided
-around an arbitrary center position.  One list extends backwards
-through the buffer from that center position, and the other extends
-forwards from that center position.  The center position can be anywhere
-in the buffer.
-
-@defun overlay-recenter pos
-This function recenters the overlays of the current buffer around
-position @var{pos}.  That makes overlay lookup faster for positions
-near @var{pos}, but slower for positions far away from @var{pos}.
-@end defun
-
-  A loop that scans the buffer forwards, creating overlays, can run
-faster if you do @code{(overlay-recenter (point-max))} first.
-
 @node Overlay Properties
 @subsection Overlay Properties
 @cindex overlay properties
@@ -1701,15 +1699,15 @@ If you want to specify a priority value, use either 
@code{nil}
 (or zero), or a positive integer.  Any other value has undefined behavior.
 
 The priority matters when two or more overlays cover the same
-character and both specify the same property; the one whose
-@code{priority} value is larger overrides the other.  (For the
-@code{face} property, the higher priority overlay's value does not
-completely override the other value; instead, its face attributes
-override the face attributes of the lower priority @code{face}
-property.)  If two overlays have the same priority value, and one is
-nested in the other, then the inner one will prevail over the outer
-one.  If neither is nested in the other then you should not make
-assumptions about which overlay will prevail.
+character and both specify the same property with different values;
+the one whose @code{priority} value is larger overrides the other.
+(For the @code{face} property, the higher priority overlay's value
+does not completely override the other value; instead, its face
+attributes override the face attributes of the @code{face} property
+whose priority is lower.)  If two overlays have the same priority
+value, and one is nested in the other, then the inner one will prevail
+over the outer one.  If neither is nested in the other then you should
+not make assumptions about which overlay will prevail.
 
 Currently, all overlays take priority over text properties.
 
@@ -1770,7 +1768,7 @@ avoided.
 This property is used instead of @code{face} when the mouse is within
 the range of the overlay.  However, Emacs ignores all face attributes
 from this property that alter the text size (e.g., @code{:height},
-@code{:weight}, and @code{:slant}).  Those attributes are always the
+@code{:weight}, and @code{:slant}); those attributes are always the
 same as in the unhighlighted text.
 
 @item display
@@ -1783,9 +1781,8 @@ or shorter, higher or lower, wider or narrower, or 
replaced with an image.
 @item help-echo
 @kindex help-echo @r{(overlay property)}
 If an overlay has a @code{help-echo} property, then when you move the
-mouse onto the text in the overlay, Emacs displays a help string in the
-echo area, or in the tooltip window.  For details see @ref{Text
-help-echo}.
+mouse onto the text in the overlay, Emacs displays a help string in
+the echo area, or as a tooltip.  For details see @ref{Text help-echo}.
 
 @item field
 @kindex field @r{(overlay property)}
@@ -1852,7 +1849,8 @@ The @code{intangible} property on an overlay works just 
like the
 Properties}, for details.
 
 @item isearch-open-invisible
-This property tells incremental search how to make an invisible overlay
+This property tells incremental search (@pxref{Incremental Search,,,
+emacs, The GNU Emacs Manual}) how to make an invisible overlay
 visible, permanently, if the final match overlaps it.  @xref{Invisible
 Text}.
 
@@ -1864,13 +1862,15 @@ visible, temporarily, during the search.  
@xref{Invisible Text}.
 @kindex before-string @r{(overlay property)}
 This property's value is a string to add to the display at the beginning
 of the overlay.  The string does not appear in the buffer in any
-sense---only on the screen.
+sense---only on the screen.  Note that if the text at the beginning of
+the overlay is made invisible, the string will not be displayed.
 
 @item after-string
 @kindex after-string @r{(overlay property)}
 This property's value is a string to add to the display at the end of
 the overlay.  The string does not appear in the buffer in any
-sense---only on the screen.
+sense---only on the screen.  Note that if the text at the end of the
+overlay is made invisible, the string will not be displayed.
 
 @item line-prefix
 This property specifies a display spec to prepend to each
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index c4e724d761..3174056ed8 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -2423,19 +2423,6 @@ Buffers}), and avoids slowing down internal or temporary 
buffers, such
 as those created by @code{with-temp-buffer} (@pxref{Definition of
 with-temp-buffer,, Current Buffer}).
 
-@item overlay_center
-This field holds the current overlay center position.  @xref{Managing
-Overlays}.
-
-@item overlays_before
-@itemx overlays_after
-These fields hold, respectively, a list of overlays that end at or
-before the current overlay center, and a list of overlays that end
-after the current overlay center.  @xref{Managing Overlays}.
-@code{overlays_before} is sorted in order of decreasing end position,
-and @code{overlays_after} is sorted in order of increasing beginning
-position.
-
 @item name
 A Lisp string that names the buffer.  It is guaranteed to be unique.
 @xref{Buffer Names}.  This and the following fields have their names
@@ -2562,6 +2549,9 @@ buffer-local (@pxref{Buffer-Local Variables}), whose 
corresponding
 variable names have underscores replaced with dashes.  For instance,
 @code{mode_line_format} stores the value of @code{mode-line-format}.
 
+@item overlays
+The inveral tree containing this buffer's overlays.
+
 @item last_selected_window
 This is the last window that was selected with this buffer in it, or @code{nil}
 if that window no longer displays this buffer.
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 7206f2acd2..750aeabf65 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -188,15 +188,18 @@ It determines the value returned by evaluating the 
variable symbol,
 and it is the binding acted on by @code{setq}.
 
   For most purposes, you can think of the current binding as the
-innermost local binding, or the global binding if there is no
-local binding.  To be more precise, a rule called the @dfn{scoping
-rule} determines where in a program a local binding takes effect.  The
+innermost local binding, or the global binding if there is no local
+binding.  To be more precise, a rule called the @dfn{scoping rule}
+determines where in a program a local binding takes effect.  The
 default scoping rule in Emacs Lisp is called @dfn{dynamic scoping},
 which simply states that the current binding at any given point in the
 execution of a program is the most recently-created binding for that
 variable that still exists.  For details about dynamic scoping, and an
 alternative scoping rule called @dfn{lexical scoping}, @pxref{Variable
-Scoping}.
+Scoping}.  Lately Emacs is moving towards using lexical binding in
+more and more places, with the goal of eventually making lexical
+binding the default.  In particular, all Emacs Lisp source files and
+the @file{*scratch*} buffer use lexical scoping.
 
   The special forms @code{let} and @code{let*} exist to create local
 bindings:
@@ -266,6 +269,17 @@ Compare the following example with the example above for 
@code{let}.
      @result{} (1 1)
 @end group
 @end example
+
+@noindent
+Basically, the @code{let*} binding of @code{x} and @code{y} in the
+previous example is equivalent to using nested @code{let} bindings:
+
+@example
+(let ((y 1))
+  (let ((z y))
+    (list y z)))
+@end example
+
 @end defspec
 
 @defspec letrec (bindings@dots{}) forms@dots{}
@@ -974,6 +988,11 @@ binding can also be accessed from the Lisp debugger.}.  It 
also has
 binding can live on even after the binding construct has finished
 executing, by means of special objects called @dfn{closures}.
 
+  The dynamic binding was (and still is) the default in Emacs for many
+years, but lately Emacs is moving towards using lexical binding in
+more and more places, with the goal of eventually making that the
+default.
+
   The following subsections describe dynamic binding and lexical
 binding in greater detail, and how to enable lexical binding in Emacs
 Lisp programs.
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index 5ad739a77e..2ab2e90894 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -570,10 +570,20 @@ toggle never mutates @code{erc-modules}.
 
 @menu
 * Connecting::                  Ways of connecting to an IRC server.
-* SASL::                        Authenticating via SASL
+* SASL::                        Authenticating via SASL.
 * Sample Configuration::        An example configuration file.
 * Integrations::                Integrations available for ERC.
 * Options::                     Options that are available for ERC.
+
+@detailmenu
+--- Detailed Node Listing ---
+
+Integrations
+
+* URL::                         Opening IRC URLs in ERC.
+* auth-source::                 Retrieving auth-source entries with ERC.
+
+@end detailmenu
 @end menu
 
 @node Connecting
@@ -643,7 +653,7 @@ while helpers, like @code{erc-compute-nick}, will determine 
other
 parameters, and some, like @code{client-certificate}, will just be
 @code{nil}.
 
-@anchor{ERC client-certificate}
+@anchor{client-certificate}
 To use a certificate with @code{erc-tls}, specify the optional
 @var{client-certificate} keyword argument, whose value should be as
 described in the documentation of @code{open-network-stream}: if
@@ -687,6 +697,8 @@ machine irc.libera.chat key /home/bandali/my-cert.key cert 
/home/bandali/my-cert
 
 @xref{Help for users,,,auth, Emacs auth-source Library}, for more on the
 @file{.authinfo}/@file{.netrc} backend of @code{auth-source}.
+For other uses of auth-source throughout ERC, @pxref{auth-source,
+ERC's auth-source integration}.
 @end defun
 
 @subheading Server
@@ -778,9 +790,9 @@ ERC should automatically attempt to connect with another 
nickname.
 You can manually set another nickname with the /NICK command.
 @end defopt
 
-@anchor{ERC username}
+@anchor{username parameter}
 @subheading User
-@cindex user
+@cindex username parameter
 
 @defun erc-compute-user &optional user
 Determine a suitable value to send as the first argument of the
@@ -803,8 +815,27 @@ A permanent username value to send for all connections.  
It should be
 a string abiding by the rules of the network.
 @end defopt
 
+@anchor{password parameter}
+@anchor{server password}
+@cindex password, server
 @subheading Password
-@cindex password
+
+This parameter was traditionally meant to specify a @dfn{server
+password} to be sent along with the IRC @samp{PASS} command.  However,
+such passwords aren't widely used.  Instead, networks typically expect
+them, when present, to convey other authentication information.  In
+the case of account-services (a.k.a., ``NickServ'') credentials, this
+typically involves a special syntax, such as @samp{myuser:mypass}.
+IRC bouncers often do something similar but include a pre-configured
+network-ID component, for example, @samp{bncuser/mynet:bncpass}.
+
+In general, if you have @emph{not} been asked by your network or
+bouncer to specify a repurposed server password, you should instead
+consider setting up @samp{services} or, preferably, @samp{sasl}, both
+ERC modules (@pxref{Modules}).  In addition to performing
+network-account authentication, these obviate the need for this
+parameter completely, although both can optionally borrow it for their
+own purposes.  (@xref{SASL, SASL in ERC}.)
 
 @defopt erc-prompt-for-password
 If non-@code{nil} (the default), @kbd{M-x erc} and @kbd{M-x erc-tls}
@@ -814,109 +845,9 @@ invocations of @code{erc} and @code{erc-tls}.
 
 @noindent
 If you prefer, you can set this option to @code{nil} and use the
-@code{auth-source} mechanism to store your password.  For instance, if
-the option @code{auth-sources} contains @file{~/.authinfo}, put
-something like the following in that file:
-
-@example
-machine irc.example.net login mynick password sEcReT
-@end example
-
-@noindent
-For server passwords, that is, passwords sent for the IRC @samp{PASS}
-command, the @samp{host} field (@w{@code{machine irc.example.net}} in
-the above example)
-corresponds to the @var{server} parameter used by @code{erc} and
-@code{erc-tls}.  Unfortunately, specifying a network, like
-@samp{Libera.Chat}, or a specific network server, like
-@samp{platinum.libera.chat}, won't normally work for looking up a server
-password because such information isn't available during opening
-introductions.  (Actually, ERC @emph{can} find entries with arbitrary
-@samp{host} values for any context, including server passwords, but
-that requires customizing the more advanced options below.)
-
-If ERC can't find a suitable server password, it will just skip the IRC
-@samp{PASS} command altogether, something users may want when using
-CertFP or engaging NickServ via ERC's ``services'' module.  If that is
-what you'd like to do, you can also customize the option
-@code{erc-auth-source-server-function} to @code{nil} to skip
-server-password lookup for all servers.  Note that some networks and
-IRCds may accept account-services authentication via server password
-using the nonstandard @samp{mynick:sEcReT} convention.
-
-As just mentioned, you can also use @code{auth-source} to authenticate
-to account services the traditional way, through a bot called
-@samp{NickServ}.  To tell ERC to do that, set
-@code{erc-use-auth-source-for-nickserv-password} to @code{t}.  For
-these and most other queries, entries featuring custom identifiers and
-networks are matched first, followed by network-specific servers and
-dialed endpoints (typically, the @var{server} argument passed to
-@code{erc}). The following netrc-style entries appear in order of
-precedence:
-
-@example
-machine Libera/cellphone login MyNick password sEcReT
-machine Libera.Chat login MyNick password sEcReT
-machine zirconium.libera.chat login MyNick password sEcReT
-machine irc.libera.chat login MyNick password sEcReT
-@end example
-
-@noindent
-Remember that field labels vary per backend, so @samp{machine} (in
-netrc's case) maps to auth-source's generalized notion of a host,
-hence the @samp{:host} keyword property.  Also, be sure to mind the
-syntax of your chosen backend medium.  For example, always quote
-channel names in a netrc file.
-
-If this all seems overly nuanced or just plain doesn't appeal to you,
-see options @code{erc-auth-source-services-function} and friends, described
-below.  These let you query auth-source your way.  Most users can
-simply ignore the passed-in arguments and get by with something like
-the following:
-
-@lisp
-(defun my-fancy-auth-source-func (&rest _)
-  (let* ((host (read-string "host: " nil nil "default"))
-         (pass (auth-source-pick-first-password :host host)))
-    (if (and pass (string-search "libera" host))
-        (concat "MyNick:" pass)
-      pass)))
-@end lisp
-
-Lastly, ERC also consults @code{auth-source} to find ``keys'' that may
-be required by certain channels you join.  When modifying a
-traditional @code{auth-source} entry for this purpose, put the channel
-name in the @samp{user} field (for example, @samp{login "#fsf"}, in
-netrc's case).  The actual key goes in the @samp{password} (or
-@samp{secret}) field.
-
-@noindent
-For details, @pxref{Top,,auth-source, auth, Emacs auth-source Library}.
-
-@anchor{ERC auth-source functions}
-@defopt erc-auth-source-server-function
-@end defopt
-@defopt erc-auth-source-services-function
-@end defopt
-@defopt erc-auth-source-join-function
-
-ERC calls these functions with keyword arguments recognized by
-@code{auth-source-search}, namely, those deemed most relevant to the
-current context, if any.  For example, with NickServ queries,
-@code{:user} is the ``desired'' nickname rather than the current one.
-Generalized names, like @code{:user} and @code{:host}, are always used
-over back-end specific ones, like @code{:login} or @code{:machine}.
-ERC expects a string to use as the secret or @code{nil}, if the search
-fails.
-
-@findex erc-auth-source-search
-The default value for all three options is the function
-@code{erc-auth-source-search}.  It tries to merge relevant contextual
-parameters with those provided or discovered from the logical connection
-or the underlying transport.  Some auth-source back ends may not be
-compatible; netrc, plstore, json, secrets, and pass are currently
-supported.
-@end defopt
+auth-source facility to retrieve a server password, although hitting
+@kbd{RET} at the prompt may achieve the same effect.
+@xref{auth-source, ERC's auth-source integration}, for more.
 
 @subheading Full name
 
@@ -946,8 +877,8 @@ This can be either a string or a function to call.
 @end defopt
 
 
-@subheading ID
 @anchor{Network Identifier}
+@subheading ID
 
 ERC uses an abstract designation, called @dfn{network context
 identifier}, for referring to a connection internally.  While normally
@@ -1002,7 +933,7 @@ first is lowercase without delims (@samp{deadbeef}) and 
the second
 uppercase with colon seps (@samp{DE:AD:BE:EF}).  These days, there's
 usually a @samp{CERT ADD} command offered by NickServ that can
 register you automatically if you issue it while connected with a
-client cert.  (@pxref{ERC client-certificate}).
+client cert.  @xref{client-certificate}.
 
 Additional considerations:
 @enumerate
@@ -1038,30 +969,32 @@ ERC> /msg NickServ set property \
 This should be your network account username, typically the same one
 registered with nickname services.  Specify this when your NickServ
 login differs from the @code{:user} you're connecting with.
-(@pxref{ERC username})
+@xref{username parameter}.
 @end defopt
 
 @defopt erc-sasl-password
-As noted elsewhere, the @code{:password} parameter for @code{erc-tls}
-was originally intended for traditional ``server passwords,'' but these
-aren't really used any more.  As such, this option defaults to
-borrowing that parameter for its own uses, thus allowing you to call
-@code{erc-tls} with @code{:password} set to your NickServ password.
+As noted elsewhere, the entry-point @code{:password} param was
+originally intended for traditional ``server passwords,'' but these
+aren't really used any more (@pxref{password parameter}).  As such,
+this option defaults to borrowing that parameter for its own uses,
+thus allowing you to call @code{erc-tls} with @code{:password} set to
+your NickServ password.
 
 You can also set this to a nonemtpy string, and ERC will send that
 when needed, no questions asked.  Or, if you'd rather use auth-source,
 set @code{erc-sasl-auth-source-function} to a function, and ERC will
-perform an auth-source query instead.  As last resort in all cases,
-ERC will prompt you for input.
+perform an auth-source query instead.  In all cases, ERC will prompt
+you for input as a last resort.
 
 Lastly, if your mechanism is @code{ecdsa-nist256p-challenge}, this
 option should instead hold the file name of your key.
 @end defopt
 
+@anchor{SASL auth-source function}
 @defopt erc-sasl-auth-source-function
 This is nearly identical to the other ERC @samp{auth-source} function
-options (@pxref{ERC auth-source functions}) except that the default
-value here is @code{nil}, meaning you have to set it to something like
+options (@pxref{auth-source functions}) except that the default value
+here is @code{nil}, meaning you have to set it to something like
 @code{erc-auth-source-search} for queries to be performed.  For
 convenience, this module provides the following as a possible value:
 
@@ -1163,9 +1096,9 @@ both networks.
 
 @subheading Troubleshooting
 
-@strong{Warning:} ERC's SASL offering is currently limited by a lack
-of support for proper IRCv3 capability negotiation.  In most cases,
-this shouldn't affect your ability to authenticate.
+First and foremost, please know that ERC's SASL offering is currently
+limited by a lack of support for proper IRCv3 capability negotiation.
+In most cases, this shouldn't affect your ability to authenticate.
 
 If you're struggling, remember that your SASL password is almost
 always your NickServ password.  When in doubt, try restoring all SASL
@@ -1260,12 +1193,19 @@ stuff, to the current ERC buffer."
 @section Integrations
 @cindex integrations
 
-@subheading URL
+@menu
+* auth-source::                 Retrieving auth-source entries with ERC.
+@end menu
+
+@anchor{URL}
+@subsection URL
+@cindex URL
+
 For anything to work, you'll want to set @code{url-irc-function} to
 @code{url-irc-erc}.  As a rule of thumb, libraries relying directly on
 @code{url-retrieve} should be fine out the box from Emacs 29.1 onward.
 On older versions of Emacs, you may need to @code{(require 'erc)}
-beforehand. @pxref{Retrieving URLs,,, url, URL}.
+beforehand.  @xref{Retrieving URLs,,, url, URL}.
 
 For other apps and libraries, such as those relying on the
 higher-level @code{browse-url}, you'll oftentimes be asked to specify
@@ -1282,6 +1222,160 @@ need a function as well:
 @noindent
 Users on Emacs 28 and below may need to use @code{browse-url} instead.
 
+@node auth-source
+@subsection auth-source
+@cindex auth-source
+
+You can configure ERC to use the built-in auth-source library for
+looking up passwords. @xref{Top,,auth-source, auth, Emacs auth-source
+Library}, for general info on setting up various backends, but keep in
+mind that some of these may not be compatible.  Those currently
+supported are netrc, plstore, json, secrets, and pass.  To get started
+with the default backend, netrc, put a line like the following in your
+@file{~/.authinfo.gpg} (or any file named in the option
+@code{auth-sources}):
+
+@example
+machine irc.example.net login mynick password sEcReT
+@end example
+
+@subsubheading Server Passwords
+When retrieving passwords to accompany the IRC @samp{PASS} command
+(@pxref{password parameter}), ERC asks auth-source to match the
+@var{server} parameter of @code{erc-tls} against each entry's
+@samp{host} field (@w{@code{machine irc.example.net}} in the above
+example).  Unfortunately, specifying a network, like
+@samp{Libera.Chat}, or a specific network server, like
+@samp{platinum.libera.chat}, won't normally work for looking up a
+server password because that information isn't available during
+opening introductions.  (Actually, ERC @emph{can} find entries with
+arbitrary @samp{host} values for any context, including server
+passwords, but that requires customizing the more advanced options
+below.)
+
+If ERC can't find a suitable server password, it will just skip the
+IRC @samp{PASS} command altogether, something users may want when
+using CertFP or engaging NickServ via ERC's @code{services} module.
+If that appeals to you, consider customizing the option
+@code{erc-auth-source-server-function} to @code{nil} to skip
+server-password lookup for all servers.  Note that some networks and
+IRCds may accept account-services authentication via server password.
+Also, some ERC modules may commandeer the @code{erc-tls}
+@var{password} parameter for their own ends, which likely don't
+involve a server password.
+
+@subsubheading The @samp{services} module
+You can use auth-source to authenticate to account services the
+traditional way through a bot called @samp{NickServ}.  To do so, add
+@code{services} to @code{erc-modules} and set the option
+@code{erc-use-auth-source-for-nickserv-password} to @code{t}.  After
+that, expect the @samp{user} parameter in relevant auth-source queries
+to be your current nickname.
+
+Most of the time, a query's precise contextual details (such as
+whether a nick was granted or forcibly assigned) shouldn't affect how
+you define entries in your backend.  However, if something isn't quite
+working, you may want to investigate the interplay between the option
+@code{erc-nickserv-identify-mode} and account services.  In
+particular, if you find yourself facing nicks suffixed with an
+@code{erc-nick-uniquifier} (the infamous @samp{`}), check that the
+network's entry in @code{erc-nickserv-alist} is up to date, and do let
+us know if something's off (@pxref{Getting Help and Reporting Bugs}).
+Of course, if you've had your fill of fiddling with this module,
+consider switching to SASL for what's likely a more consistent
+auth-source experience.  (@xref{SASL}.)
+
+@subsubheading Default query behavior
+When preparing entries for your backend, it may help to get a feel for
+how ERC and its modules conduct searches, especially when exploring a
+new context, such as channel keys.  (Hint: in such situations, try
+temporarily setting the variable @code{auth-source-debug} to @code{t}
+and checking @samp{*Messages*} periodically for insights into how
+auth-source is operating.)  Overall, though, ERC tries to be
+consistent in performing queries across various authentication
+contexts.  Here's what to expect with respect to the @samp{host}
+field, which, by default, most heavily influences the fate of a query:
+
+@enumerate
+@item
+entries featuring custom identifiers and networks are matched first
+(@pxref{Network Identifier})
+@item
+followed by network-specific servers
+@item
+and, finally, dialed endpoints (typically the @var{server} argument
+passed to @code{erc-tls})
+@end enumerate
+
+@noindent
+The following netrc-style entries appear in order of precedence:
+
+@example
+machine Libera/cellphone login MyNick password sEcReT
+machine Libera.Chat login MyNick password sEcReT
+machine zirconium.libera.chat login MyNick password sEcReT
+machine irc.libera.chat login MyNick password sEcReT
+@end example
+
+@noindent
+Remember that field labels vary per backend, so @samp{machine} (in
+netrc's case) maps to auth-source's generalized notion of a host,
+hence the @samp{:host} keyword parameter to @code{auth-source-search}.
+Also, be sure to mind the syntax of your chosen backend medium.  For
+example, always quote channel names in a netrc file.
+
+Lastly, if this all seems overly nuanced or just plain doesn't appeal
+to you, please see options @code{erc-auth-source-services-function}
+and friends, described just below.
+
+@subsubheading Custom query functions
+These let you query auth-source your way.  Most users can
+simply ignore the passed-in arguments and get by with something like
+the following:
+
+@lisp
+(defun my-fancy-auth-source-func (&rest _)
+  (let* ((host (read-string "host: " nil nil "default"))
+         (pass (auth-source-pick-first-password :host host)))
+    (if (and pass (string-search "libera" host))
+        (concat "MyNick:" pass)
+      pass)))
+@end lisp
+
+@anchor{auth-source functions}
+@defopt erc-auth-source-server-function
+@end defopt
+@defopt erc-auth-source-services-function
+@end defopt
+@defopt erc-auth-source-join-function
+
+ERC calls these functions with keyword arguments recognized by
+@code{auth-source-search}, namely, those deemed most relevant to the
+current context, if any.  For example, when identifying to services,
+@code{:user} contains your current nickname.  Generalized parameter
+names, like @code{:user} and @code{:host}, are always preferred over
+backend specific ones, like @code{:login} or @code{:machine}.  In
+return, ERC expects a string if the search succeeds or @code{nil} if
+it fails.
+
+@findex erc-auth-source-search
+The default value for all three options is the function
+@code{erc-auth-source-search}.  It tries to merge relevant contextual
+parameters with those provided or discovered from the logical
+connection or the underlying transport.
+
+For using auth-source along with SASL, @pxref{SASL auth-source
+function}.
+@end defopt
+
+@subsubheading Channel keys
+ERC also consults @code{auth-source} to find ``keys'' that may be
+required by certain channels you join.  When modifying a traditional
+@code{auth-source} entry for this purpose, put the channel name in the
+@samp{user} field (for example, @samp{login "#fsf"}, in netrc's case).
+The actual key goes in the @samp{password} (or @samp{secret}) field.
+
+
 @node Options
 @section Options
 @cindex options
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index d0d84d0a98..76439f1d06 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -45,8 +45,8 @@ With the overhaul of the services module temporarily shelved 
and the
 transition to SASL-based authentication still underway, users may feel
 left in the lurch to endure yet another release cycle of backtick
 hell.  For some, auth-source may provide a workaround in the form of
-nonstandard server passwords.  See the "Connection" node in the manual
-under the subheading "Password".
+nonstandard server passwords.  See the section titled "auth-source" in
+the Integrations chapter of ERC's manual.
 
 ** Rudimentary SASL support has arrived.
 A new module, 'erc-sasl', now ships with ERC 5.5.  See the SASL
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 6cb531cd0f..662c3125e0 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -105,16 +105,6 @@ configuration on X is known to have problems, such as 
undesirable
 frame positioning and various issues with keyboard input of sequences
 such as 'C-;' and 'C-S-u'.
 
----
-** The implementation of overlays has changed.
-Emacs now uses an implementation of overlays that is much more
-efficient than the original one, and should speed up all the
-operations that involve overlays, especially when there are lots of
-them in a buffer.  However, no changes in behavior of overlays should
-be visible on the Lisp or user level, with the exception of better
-performance and the order of overlays returned by functions that don't
-promise any particular order.
-
 ---
 ** The docstrings of preloaded files are not in "etc/DOC" any more.
 Instead, they're fetched as needed from the corresponding ".elc" file,
@@ -3081,6 +3071,35 @@ which-func.
 
 * Incompatible Lisp Changes in Emacs 29.1
 
++++
+** The implementation of overlays has changed.
+Emacs now uses an implementation of overlays that is much more
+efficient than the original one, and should speed up all the
+operations that involve overlays, especially when there are lots of
+them in a buffer.
+
+As result of this, some minor incompatibilities in behavior could be
+observed, as described below.  Except those minor incompatibilities,
+no other changes in behavior of overlays should be visible on the Lisp
+or user level, with the exception of better performance and the order
+of overlays returned by functions that don't promise any particular
+order.
+
+*** The function 'overlay-recenter' is now a no-op.
+This function does nothing, and in particular has no effect on the
+value returned by 'overlay-lists'.  The purpose of 'overlay-recenter'
+was to allow more efficient lookup of overlays around certain buffer
+position; however with the new implementation the lookup of overlays
+is efficient regardless of their position, and there's no longer any
+need to "optimize" the lookup, nor any notion of "center" of the
+overlays.
+
+*** The function 'overlay-lists' returns one unified list of overlays.
+This function used to return a cons of two lists, one with overlays
+before the "center" position, the other after that "center".  It now
+returns a list whose 'car' is the list of all the buffer overlays, and
+whose 'cdr' is always nil.
+
 +++
 ** 'format-prompt' now uses 'substitute-command-keys'.
 This means that both the prompt and 'minibuffer-default-prompt-format'
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 5e1745069f..7499e590a0 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -1,7 +1,6 @@
 ;;; dired-aux.el --- less commonly used parts of dired -*- lexical-binding: t 
-*-
 
-;; Copyright (C) 1985-1986, 1992, 1994, 1998, 2000-2022 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1985-2022 Free Software Foundation, Inc.
 
 ;; Author: Sebastian Kremer <sk@thp.uni-koeln.de>.
 ;; Maintainer: emacs-devel@gnu.org
@@ -25,7 +24,7 @@
 
 ;;; Commentary:
 
-;; The parts of dired mode not normally used.  This is a space-saving hack
+;; The parts of Dired mode not normally used.  This is a space-saving hack
 ;; to avoid having to load a large mode when all that's wanted are a few
 ;; functions.
 
@@ -37,8 +36,6 @@
 ;;; Code:
 
 (require 'cl-lib)
-;; We need macros in dired.el to compile properly,
-;; and we call subroutines in it too.
 (require 'dired)
 
 (defvar dired-create-files-failures nil
@@ -135,7 +132,7 @@ substituted, and will be passed through normally to the 
shell.
 
 %s
 
-\(Press ^ to %s markers below these occurrences.)
+(Press ^ to %s markers below these occurrences.)
 "
    "`"
    (string (aref command (car char-positions)))
@@ -298,7 +295,7 @@ With prefix arg, prompt for argument SWITCHES which is 
options for `diff'."
 
 ;;;###autoload
 (defun dired-compare-directories (dir2 predicate)
-  "Mark files with different file attributes in two dired buffers.
+  "Mark files with different file attributes in two Dired buffers.
 Compare file attributes of files in the current directory
 with file attributes in directory DIR2 using PREDICATE on pairs of files
 with the same name.  Mark files for which PREDICATE returns non-nil.
@@ -312,8 +309,8 @@ PREDICATE is a Lisp expression that can refer to the 
following variables:
     fa1, fa2       - list of file attributes
                      returned by function `file-attributes'
 
-    where 1 refers to attribute of file in the current dired buffer
-    and 2 to attribute of file in second dired buffer.
+    where 1 refers to attribute of file in the current Dired buffer
+    and 2 to attribute of file in second Dired buffer.
 
 Examples of PREDICATE:
 
@@ -489,7 +486,8 @@ List has a form of (file-name full-file-name 
(attribute-list))."
 (defun dired-do-chmod (&optional arg)
   "Change the mode of the marked (or next ARG) files.
 Both octal numeric modes like `644' and symbolic modes like `g+w'
-are supported.  Type M-n to pull the file attributes of the file
+are supported.  Type \\<minibuffer-local-completion-map>\
+\\[next-history-element] to pull the file attributes of the file
 at point into the minibuffer.
 
 See Info node `(coreutils)File permissions' for more information.
@@ -538,7 +536,8 @@ has no effect on MS-Windows."
 ;;;###autoload
 (defun dired-do-chgrp (&optional arg)
   "Change the group of the marked (or next ARG) files.
-Type M-n to pull the file attributes of the file at point
+Type \\<minibuffer-local-completion-map>\\[next-history-element] \
+to pull the file attributes of the file at point
 into the minibuffer."
   (interactive "P")
   (if (and (memq system-type '(ms-dos windows-nt))
@@ -549,7 +548,8 @@ into the minibuffer."
 ;;;###autoload
 (defun dired-do-chown (&optional arg)
   "Change the owner of the marked (or next ARG) files.
-Type M-n to pull the file attributes of the file at point
+Type \\<minibuffer-local-completion-map>\\[next-history-element] \
+to pull the file attributes of the file at point
 into the minibuffer."
   (interactive "P")
   (if (and (memq system-type '(ms-dos windows-nt))
@@ -561,7 +561,8 @@ into the minibuffer."
 (defun dired-do-touch (&optional arg)
   "Change the timestamp of the marked (or next ARG) files.
 This calls touch.
-Type M-n to pull the file attributes of the file at point
+Type Type \\<minibuffer-local-completion-map>\\[next-history-element] \
+to pull the file attributes of the file at point
 into the minibuffer."
   (interactive "P")
   (dired-do-chxxx "Timestamp" dired-touch-program 'touch arg))
@@ -761,7 +762,7 @@ with a prefix argument."
 (defvar dired-aux-files)
 
 (defun dired-minibuffer-default-add-shell-commands ()
-  "Return a list of all commands associated with current dired files.
+  "Return a list of all commands associated with current Dired files.
 This function is used to add all related commands retrieved by `mailcap'
 to the end of the list of defaults just after the default value."
   (interactive)
@@ -774,7 +775,7 @@ to the end of the list of defaults just after the default 
value."
 
 ;; This is an extra function so that you can redefine it, e.g., to use gmhist.
 (defun dired-read-shell-command (prompt arg files)
-  "Read a dired shell command.
+  "Read a Dired shell command.
 PROMPT should be a format string with one \"%s\" format sequence,
 which is replaced by the value returned by `dired-mark-prompt',
 with ARG and FILES as its arguments.  FILES should be a list of
@@ -921,11 +922,11 @@ Also see the `dired-confirm-shell-command' variable."
 
 ;; Might use {,} for bash or csh:
 (defvar dired-mark-prefix ""
-  "Prepended to marked files in dired shell commands.")
+  "Prepended to marked files in Dired shell commands.")
 (defvar dired-mark-postfix ""
-  "Appended to marked files in dired shell commands.")
+  "Appended to marked files in Dired shell commands.")
 (defvar dired-mark-separator " "
-  "Separates marked files in dired shell commands.")
+  "Separates marked files in Dired shell commands.")
 
 (defun dired-shell-stuff-it (command file-list on-each &optional _raw-arg)
   ;; "Make up a shell command line from COMMAND and FILE-LIST.
@@ -1336,7 +1337,7 @@ See `dired-guess-shell-alist-user'."
 (defun dired-kill-line (&optional arg)
   "Kill the current line (not the files).
 With a prefix argument, kill that many lines starting with the current line.
-\(A negative argument kills backward.)"
+(A negative argument kills backward.)"
   (interactive "P")
   (setq arg (prefix-numeric-value arg))
   (let (buffer-read-only file)
@@ -1844,7 +1845,7 @@ See Info node `(emacs)Subdir switches' for more details."
     (message "Redisplaying...done")))
 
 (defun dired-reset-subdir-switches ()
-  "Set `dired-switches-alist' to nil and revert dired buffer."
+  "Set `dired-switches-alist' to nil and revert Dired buffer."
   (interactive)
   (setq dired-switches-alist nil)
   (revert-buffer))
@@ -1880,7 +1881,7 @@ See Info node `(emacs)Subdir switches' for more details."
 (defvar dired-omit-localp)
 
 (defun dired-add-entry (filename &optional marker-char relative)
-  "Add a new dired entry for FILENAME.
+  "Add a new Dired entry for FILENAME.
 Optionally mark it with MARKER-CHAR (a character, else uses
 `dired-marker-char').  Note that this adds the entry `out of order'
 if files are sorted by time, etc.
@@ -2008,7 +2009,7 @@ files matching `dired-omit-regexp'."
 
 ;;;###autoload
 (defun dired-remove-file (file)
-  "Remove entry FILE on each dired buffer.
+  "Remove entry FILE on each Dired buffer.
 Note this doesn't delete FILE in the file system.
 See `dired-delete-file' in case you wish that."
   (dired-fun-in-all-buffers
@@ -2107,7 +2108,7 @@ option are non-nil, renaming a directory named `old_name' 
to
 `new_name' does not exists already, it will be created and
 `old_name' be moved into it.  If only `new_name' (without the
 trailing /) is given or this option or
-`dired-create-destination-dirs' is `nil', `old_name' will be
+`dired-create-destination-dirs' is nil, `old_name' will be
 renamed to `new_name'."
   :type '(choice
           (const :tag
@@ -3077,7 +3078,7 @@ Type \\`SPC' or \\`y' to %s one file, \\`DEL' or \\`n' to 
skip to next,
 ;;;###autoload
 (defun dired-maybe-insert-subdir (dirname &optional
                                          switches no-error-if-not-dir-p)
-  "Insert this subdirectory into the same dired buffer.
+  "Insert this subdirectory into the same Dired buffer.
 If it is already present, just move to it (type \\[dired-do-redisplay] to 
refresh),
   else inserts it at its natural place (as `ls -lR' would have done).
 With a prefix arg, you may edit the ls switches used for this listing.
@@ -3427,7 +3428,7 @@ Lower levels are unaffected."
 
 ;;;###autoload
 (defun dired-tree-up (arg)
-  "Go up ARG levels in the dired tree."
+  "Go up ARG levels in the Dired tree."
   (interactive "p")
   (let ((dir (dired-current-directory)))
     (while (>= arg 1)
@@ -3439,7 +3440,7 @@ Lower levels are unaffected."
 
 ;;;###autoload
 (defun dired-tree-down ()
-  "Go down in the dired tree."
+  "Go down in the Dired tree."
   (interactive)
   (let ((dir (dired-current-directory)) ; has slash
        pos case-fold-search)           ; filenames are case sensitive
diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el
index 8328324715..6704db3cc5 100644
--- a/lisp/emacs-lisp/shortdoc.el
+++ b/lisp/emacs-lisp/shortdoc.el
@@ -251,18 +251,17 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
    :eval (string-glyph-decompose "Å"))
   "Predicates for Strings"
   (string-equal
-   :eval (string-equal "foo" "foo"))
+   :eval (string-equal "abc" "abc")
+   :eval (string-equal "abc" "ABC"))
   (string-equal-ignore-case
    :eval (string-equal-ignore-case "foo" "FOO"))
-  (eq
-   :eval (eq "foo" "foo"))
-  (eql
-   :eval (eql "foo" "foo"))
   (equal
    :eval (equal "foo" "foo"))
   (cl-equalp
    :eval (cl-equalp "Foo" "foo"))
   (stringp
+   :eval (stringp "a")
+   :eval (stringp 'a)
    :eval "(stringp ?a)")
   (string-empty-p
    :no-manual t
@@ -271,16 +270,16 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
    :no-manual t
    :eval (string-blank-p " \n"))
   (string-lessp
-   :eval (string-lessp "foo" "bar")
+   :eval (string-lessp "abc" "def")
    :eval (string-lessp "pic4.png" "pic32.png")
-   :eval (string-lessp "1.1" "1 2"))
+   :eval (string-lessp "1.1" "1.2"))
   (string-greaterp
    :eval (string-greaterp "foo" "bar"))
   (string-version-lessp
    :eval (string-version-lessp "pic4.png" "pic32.png")
-   :eval (string-version-lessp "1.1" "1 2"))
+   :eval (string-version-lessp "1.9.3" "1.10.2"))
   (string-collate-lessp
-   :eval (string-collate-lessp "1.1" "1 2"))
+   :eval (string-collate-lessp "abc" "abd"))
   (string-prefix-p
    :eval (string-prefix-p "foo" "foobar"))
   (string-suffix-p
@@ -297,7 +296,8 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
   "Converting Strings"
   (string-to-number
    :eval (string-to-number "42")
-   :eval (string-to-number "deadbeef" 16))
+   :eval (string-to-number "deadbeef" 16)
+   :eval (string-to-number "2.5e+03"))
   (number-to-string
    :eval (number-to-string 42))
   "Data About Strings"
@@ -627,8 +627,7 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
   (nconc
    :eval (nconc (list 1) (list 2 3 4)))
   (delq
-   :eval (delq 2 (list 1 2 3 4))
-   :eval (delq "a" (list "a" "b" "c" "d")))
+   :eval (delq 'a (list 'a 'b 'c 'd)))
   (delete
    :eval (delete 2 (list 1 2 3 4))
    :eval (delete "a" (list "a" "b" "c" "d")))
@@ -670,29 +669,25 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
    :eval (nlistp '(1 . 2)))
   "Finding Elements"
   (memq
-   :eval (memq 2 '(1 2 3))
-   :eval (memq 2.0 '(1.0 2.0 3.0))
-   :eval (memq "b" '("a" "b" "c")))
+   :eval (memq 'b '(a b c)))
+  (memql
+   :eval (memql 2.0 '(1.0 2.0 3.0)))
   (member
    :eval (member 2 '(1 2 3))
    :eval (member "b" '("a" "b" "c")))
   (remq
-   :eval (remq 2 '(1 2 3 2 4 2))
-   :eval (remq "b" '("a" "b" "c")))
-  (memql
-   :eval (memql 2.0 '(1.0 2.0 3.0)))
+   :eval (remq 'b '(a b c)))
   (member-ignore-case
    :eval (member-ignore-case "foo" '("bar" "Foo" "zot")))
   "Association Lists"
   (assoc
-   :eval (assoc 'b '((a 1) (b 2))))
+   :eval (assoc "b" '(("a" . 1) ("b" . 2))))
   (rassoc
-   :eval (rassoc '2 '((a . 1) (b . 2))))
+   :eval (rassoc "b" '((1 . "a") (2 . "b"))))
   (assq
-   :eval (assq 'b '((a 1) (b 2)))
-   :eval (assq "a" '(("a" 1) ("b" 2))))
+   :eval (assq 'b '((a . 1) (b . 2))))
   (rassq
-   :eval (rassq '2 '((a . 1) (b . 2))))
+   :eval (rassq 'b '((1 . a) (2 . b))))
   (assoc-string
    :eval (assoc-string "foo" '(("a" 1) (foo 2))))
   (alist-get
@@ -725,6 +720,88 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
   (safe-length
    :eval (safe-length '(a b c))))
 
+(define-short-documentation-group symbol
+  "Making symbols"
+  (intern
+   :eval (intern "abc"))
+  (intern-soft
+   :eval (intern-soft "Phooey!"))
+  (make-symbol
+   :eval (make-symbol "abc"))
+  "Comparing symbols"
+  (eq
+   :eval (eq 'abc 'abc)
+   :eval (eq 'abc 'abd))
+  (eql
+   :eval (eql 'abc 'abc))
+  (equal
+   :eval (equal 'abc 'abc))
+  "Name"
+  (symbol-name
+   :eval (symbol-name 'abc)))
+
+(define-short-documentation-group comparison
+  "General-purpose"
+  (eq
+   :eval (eq 'a 'a)
+   :eval "(eq ?A ?A)"
+   :eval (let ((x (list 'a "b" '(c) 4 5.0)))
+           (eq x x)))
+  (eql
+   :eval (eql 2 2)
+   :eval (eql 2.0 2.0)
+   :eval (eql 2.0 2))
+  (equal
+   :eval (equal "abc" "abc")
+   :eval (equal 2.0 2.0)
+   :eval (equal 2.0 2)
+   :eval (equal '(a "b" (c) 4.0) '(a "b" (c) 4.0)))
+  (cl-equalp
+   :eval (cl-equalp 2 2.0)
+   :eval (cl-equalp "ABC" "abc"))
+  "Numeric"
+  (=
+   :args (number &rest numbers)
+   :eval (= 2 2)
+   :eval (= 2.0 2.0)
+   :eval (= 2.0 2)
+   :eval (= 4 4 4 4))
+  (/=
+   :eval (/= 4 4))
+  (<
+   :args (number &rest numbers)
+   :eval (< 4 4)
+   :eval (< 1 2 3))
+  (<=
+   :args (number &rest numbers)
+   :eval (<= 4 4)
+   :eval (<= 1 2 2 3))
+  (>
+   :args (number &rest numbers)
+   :eval (> 4 4)
+   :eval (> 3 2 1))
+  (>=
+   :args (number &rest numbers)
+   :eval (>= 4 4)
+   :eval (>= 3 2 2 1))
+  "String"
+  (string-equal
+   :eval (string-equal "abc" "abc")
+   :eval (string-equal "abc" "ABC"))
+  (string-equal-ignore-case
+   :eval (string-equal-ignore-case "abc" "ABC"))
+  (string-lessp
+   :eval (string-lessp "abc" "abd")
+   :eval (string-lessp "abc" "abc")
+   :eval (string-lessp "pic4.png" "pic32.png"))
+  (string-greaterp
+   :eval (string-greaterp "abd" "abc")
+   :eval (string-greaterp "abc" "abc"))
+  (string-version-lessp
+   :eval (string-version-lessp "pic4.png" "pic32.png")
+   :eval (string-version-lessp "1.9.3" "1.10.2"))
+  (string-collate-lessp
+   :eval (string-collate-lessp "abc" "abd")))
 
 (define-short-documentation-group vector
   "Making Vectors"
@@ -1131,13 +1208,10 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
    :args (number &rest numbers)
    :eval (= 4 4)
    :eval (= 4.0 4.0)
-   :eval (= 4 5 6 7))
-  (eq
-   :eval (eq 4 4)
-   :eval (eq 4.0 4.0))
+   :eval (= 4 4.0)
+   :eval (= 4 4 4 4))
   (eql
    :eval (eql 4 4)
-   :eval (eql 4 "4")
    :eval (eql 4.0 4.0))
   (/=
    :eval (/= 4 4))
@@ -1148,15 +1222,15 @@ A FUNC form can have any number of `:no-eval' (or 
`:no-value'),
   (<=
    :args (number &rest numbers)
    :eval (<= 4 4)
-   :eval (<= 1 2 3))
+   :eval (<= 1 2 2 3))
   (>
    :args (number &rest numbers)
    :eval (> 4 4)
-   :eval (> 1 2 3))
+   :eval (> 3 2 1))
   (>=
    :args (number &rest numbers)
    :eval (>= 4 4)
-   :eval (>= 1 2 3))
+   :eval (>= 3 2 2 1))
   (zerop
    :eval (zerop 0))
   (cl-plusp
@@ -1440,14 +1514,16 @@ function's documentation in the Info manual"))
                do
                (cl-case type
                  (:eval
+                  (insert "  ")
                   (if (stringp value)
-                      (insert "  " value "\n")
-                    (insert "  ")
-                    (prin1 value (current-buffer))
-                    (insert "\n")
-                    (insert "    " double-arrow " ")
-                    (prin1 (eval value) (current-buffer))
-                    (insert "\n")))
+                      (insert value)
+                    (prin1 value (current-buffer)))
+                  (insert "\n    " double-arrow " ")
+                  (let ((expr (if (stringp value)
+                                  (car (read-from-string value))
+                                value)))
+                    (prin1 (eval expr) (current-buffer)))
+                    (insert "\n"))
                  (:no-eval*
                   (if (stringp value)
                       (insert "  " value "\n")
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 0486baba83..4896f4c293 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -399,7 +399,7 @@ this defaults to the current buffer."
   "Query the user for a process and return the process object."
   ;; Currently supports only the PROCESS argument.
   ;; Must either return a list containing a process, or signal an error.
-  ;; (Returning `nil' would mean the current buffer's process.)
+  ;; (Returning nil would mean the current buffer's process.)
   (unless (fboundp 'process-list)
     (error "Asynchronous subprocesses are not supported on this system"))
   ;; Local function to return cons of a complete-able name, and the
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index a4046ba9b3..e662c06daa 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -301,17 +301,11 @@ nil."
 (defun erc-downcase (string)
   "Return a downcased copy of STRING with properties.
 Use the CASEMAPPING ISUPPORT parameter to determine the style."
-  (let* ((mapping (erc--get-isupport-entry 'CASEMAPPING 'single))
-         (inhibit-read-only t))
-    (if (equal mapping "ascii")
-        (downcase string)
-      (with-temp-buffer
-        (insert string)
-        (translate-region (point-min) (point-max)
-                          (if (equal mapping "rfc1459-strict")
-                              erc--casemapping-rfc1459-strict
-                            erc--casemapping-rfc1459))
-        (buffer-string)))))
+  (with-case-table (pcase (erc--get-isupport-entry 'CASEMAPPING 'single)
+                     ("ascii" ascii-case-table)
+                     ("rfc1459-strict" erc--casemapping-rfc1459-strict)
+                     (_ erc--casemapping-rfc1459))
+    (downcase string)))
 
 (define-inline erc-get-channel-user (nick)
   "Find NICK in the current buffer's `erc-channel-users' hash table."
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index bd93254758..77625398ab 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -391,8 +391,11 @@ If START or END is negative, it counts from the end."
 
 (cond ((fboundp 'browse-url-irc)) ; 29
       ((boundp 'browse-url-default-handlers) ; 28
-       (cl-pushnew '("\\`irc6?s?://" . erc-compat--29-browse-url-irc)
-                   browse-url-default-handlers))
+       (setf (alist-get "\\`irc6?s?://" browse-url-default-handlers
+                        nil nil (lambda (a _)
+                                  (and (stringp a)
+                                       (string-match-p a "irc://localhost"))))
+             #'erc-compat--29-browse-url-irc))
       ((boundp 'browse-url-browser-function) ; 27
        (require 'browse-url)
        (let ((existing browse-url-browser-function))
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index 19a7ab8643..fd8bed470a 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -60,6 +60,7 @@
 (declare-function erc-buffer-filter "erc" (predicate &optional proc))
 (declare-function erc-current-nick "erc" nil)
 (declare-function erc-display-error-notice "erc" (parsed string))
+(declare-function erc-display-message "erc" (parsed type buffer msg &rest 
args))
 (declare-function erc-error "erc" (&rest args))
 (declare-function erc-get-buffer "erc" (target &optional proc))
 (declare-function erc-server-buffer "erc" nil)
@@ -1260,24 +1261,45 @@ given by the `RPL_ISUPPORT' NETWORK parameter."
                return name)
       (and-let* ((vanity (erc--get-isupport-entry 'NETWORK 'single))
                  ((intern vanity))))
+      (erc-networks--id-given erc-networks--id)
       erc-networks--name-missing-sentinel))
 
-(defun erc-networks--set-name (_proc parsed)
+(defvar erc-networks--allow-unknown-network nil
+  "Whether to ignore a failure in identifying the network.
+If you need this as a user option, please say so via \\[erc-bug].
+Otherwise, expect it to vanish at any time.") ; Bug#59976
+
+(defun erc-networks--set-name (proc parsed)
   "Set `erc-network' to the value returned by `erc-networks--determine'.
-Signal an error when the network cannot be determined."
+Print an error message when the network cannot be determined before
+shutting down the connection."
   ;; Always update (possibly clobber) current value, if any.
-  (let ((name (erc-networks--determine)))
-    (when (eq name erc-networks--name-missing-sentinel)
-      ;; This can happen theoretically, e.g., if you're editing some
-      ;; settings interactively on a proxy service that impersonates IRC
-      ;; but aren't being proxied through to a real network.  The
+  (pcase (setq erc-network (erc-networks--determine))
+    ((and (pred (eq (erc-networks--id-given erc-networks--id)))
+          (let m (format "Couldn't determine network. Using given ID `%s'."
+                         erc-network)))
+     (erc-display-message parsed 'notice nil m)
+     nil)
+    ((and
+      (guard (eq erc-network erc-networks--name-missing-sentinel))
+      ;; This can happen theoretically, e.g., when adjusting settings
+      ;; on a proxy service that partially impersonates IRC but isn't
+      ;; currently conveying anything through to a real network.  The
       ;; service may send a 422 but no NETWORK param (or *any* 005s).
-      (let ((m (concat "Failed to determine network. Please set entry for "
-                       erc-server-announced-name " in `erc-networks-alist'.")))
-        (erc-display-error-notice parsed m)
-        (erc-error "Failed to determine network"))) ; beep
-    (setq erc-network name))
-  nil)
+      (let m (concat "Failed to determine network.  Please set entry for \""
+                     erc-server-announced-name "\" in `erc-networks-alist'"
+                     " or consider calling `erc-tls' with the keyword `:id'."
+                     "  See Info:\"(erc) Network Identifier\" for more.")))
+     (require 'info)
+     (erc-display-error-notice parsed m)
+     (if erc-networks--allow-unknown-network
+         (progn
+           (erc-display-error-notice
+            parsed (format "Continuing anyway with network set to `%s'."
+                           erc-network))
+           nil)
+       (delete-process proc)
+       'error))))
 
 ;; This lives here in this file because all the other "on connect"
 ;; MOTD stuff ended up here (but perhaps that needs to change).
@@ -1287,11 +1309,12 @@ Signal an error when the network cannot be determined."
 Copy source (prefix) from MOTD-ish message as a last resort."
   ;; The 004 handler never ran; see 2004-03-10 Diane Murray in change log
   (unless erc-server-announced-name
-    (erc-display-error-notice parsed "Failed to determine server name.")
+    (setq erc-server-announced-name (erc-response.sender parsed))
     (erc-display-error-notice
-     parsed (concat "If this was unexpected, consider reporting it via "
-                    (substitute-command-keys "\\[erc-bug]") "."))
-    (setq erc-server-announced-name (erc-response.sender parsed)))
+     parsed (concat "Failed to determine server name. Using \""
+                    erc-server-announced-name "\" instead."
+                    "  If this was unexpected, consider reporting it via "
+                    (substitute-command-keys "\\[erc-bug]") ".")))
   nil)
 
 (defun erc-unset-network-name (_nick _ip _reason)
diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el
index 5b2c93988a..78d02a4638 100644
--- a/lisp/erc/erc-sasl.el
+++ b/lisp/erc/erc-sasl.el
@@ -102,7 +102,7 @@ ERC binds all options defined in this library, such as
 `erc-sasl-password', to their values from entry-point invocation.
 In return, ERC expects a string to send as the SASL password, or
 nil, in which case, ERC will prompt the for input.  See info
-node `(erc) Connecting' for details on ERC's auth-source
+node `(erc) auth-source' for details on ERC's auth-source
 integration."
   :type '(choice (function-item erc-sasl-auth-source-password-as-host)
                  (function-item erc-auth-source-search)
@@ -414,17 +414,30 @@ This doesn't solicit or validate a suite of supported 
mechanisms."
                                        " "))
   (erc-sasl--destroy proc))
 
+(defvar erc-sasl--send-cap-ls nil
+  "Whether to send an opening \"CAP LS\" command.
+This is an escape hatch for picky servers.  If you need it turned
+into a user option, please let ERC know via \\[erc-bug].
+Otherwise, expect it to disappear in subsequent versions.")
+
 (cl-defmethod erc--register-connection (&context (erc-sasl-mode (eql t)))
-  "Send speculative/pipelined CAP and AUTHENTICATE and hope for the best."
+  "Send speculative CAP and pipelined AUTHENTICATE and hope for the best."
   (if-let* ((c (erc-sasl--state-client erc-sasl--state))
             (m (sasl-mechanism-name (sasl-client-mechanism c))))
       (progn
-        (erc-server-send "CAP REQ :sasl")
-        (if (and erc-session-password
-                 (eq :password (alist-get 'password erc-sasl--options)))
-            (let (erc-session-password)
-              (erc-login))
+        (erc-server-send (if erc-sasl--send-cap-ls "CAP LS" "CAP REQ :sasl"))
+        (let ((erc-session-password
+               (and erc-session-password
+                    (not (eq :password (alist-get 'password 
erc-sasl--options)))
+                    erc-session-password))
+              (erc-session-username
+               ;; The username may contain a colon or a space
+               (if (eq :user (alist-get 'user erc-sasl--options))
+                   (erc-current-nick)
+                 erc-session-username)))
           (erc-login))
+        (when erc-sasl--send-cap-ls
+          (erc-server-send "CAP REQ :sasl"))
         (erc-server-send (format "AUTHENTICATE %s" m)))
     (erc-sasl--destroy erc-server-process)))
 
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index 48953288d1..c2d91ca9d6 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -180,7 +180,7 @@ Called with a subset of keyword parameters known to
 `auth-source-search' and relevant to authenticating to nickname
 services.  In return, ERC expects a string to send as the
 password, or nil, to fall through to the next method, such as
-prompting.  See info node `(erc) Connecting' for details."
+prompting.  See info node `(erc) auth-source' for details."
   :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
   :type '(choice (const erc-auth-source-search)
                  (const nil)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 6bb2e013c3..5e78096da5 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -219,7 +219,7 @@ parameters and authentication."
 This variable only exists for legacy reasons.  It's not customizable and
 is limited to a single server password.  Users looking for similar
 functionality should consider auth-source instead.  See info
-node `(auth) Top' and info node `(erc) Connecting'.")
+node `(auth) Top' and info node `(erc) auth-source'.")
 
 (make-obsolete-variable 'erc-password "use auth-source instead" "29.1")
 
@@ -407,15 +407,27 @@ erc-channel-user struct.")
   "Hash table of users on the current server.
 It associates nicknames with `erc-server-user' struct instances.")
 
-(defconst erc--casemapping-rfc1459
-  (make-translation-table
-   '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|) (?~  . ?^))
-   (mapcar (lambda (c) (cons c (+ c 32))) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")))
-
 (defconst erc--casemapping-rfc1459-strict
-  (make-translation-table
-   '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|))
-   (mapcar (lambda (c) (cons c (+ c 32))) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")))
+  (let ((tbl (copy-sequence ascii-case-table))
+        (cup (copy-sequence (char-table-extra-slot ascii-case-table 0))))
+    (set-char-table-extra-slot tbl 0 cup)
+    (set-char-table-extra-slot tbl 1 nil)
+    (set-char-table-extra-slot tbl 2 nil)
+    (pcase-dolist (`(,uc . ,lc) '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|)))
+      (aset tbl uc lc)
+      (aset tbl lc lc)
+      (aset cup uc uc))
+    tbl))
+
+(defconst erc--casemapping-rfc1459
+  (let ((tbl (copy-sequence erc--casemapping-rfc1459-strict))
+        (cup (copy-sequence (char-table-extra-slot
+                             erc--casemapping-rfc1459-strict 0))))
+    (set-char-table-extra-slot tbl 0 cup)
+    (aset tbl ?~ ?^)
+    (aset tbl ?^ ?^)
+    (aset cup ?~ ?~)
+    tbl))
 
 (defun erc-add-server-user (nick user)
   "This function is for internal use only.
@@ -1607,11 +1619,12 @@ same manner."
     (if (and (with-suppressed-warnings ((obsolete erc-reuse-buffers))
                erc-reuse-buffers)
              id)
-        (progn
-          (when-let* ((buf (get-buffer (symbol-name id)))
+        (let ((string (symbol-name (erc-networks--id-symbol
+                                    (erc-networks--id-create id)))))
+          (when-let* ((buf (get-buffer string))
                       ((erc-server-process-alive buf)))
-            (user-error  "Session with ID %S already exists" id))
-          (symbol-name id))
+            (user-error  "Session with ID %S already exists" string))
+          string)
       (generate-new-buffer-name (if (and server port)
                                     (if (with-suppressed-warnings
                                             ((obsolete erc-reuse-buffers))
@@ -1970,7 +1983,7 @@ Returns the buffer for the given server or channel."
   (let* ((target (and channel (erc--target-from-string channel)))
          (buffer (erc-get-buffer-create server port nil target id))
          (old-buffer (current-buffer))
-         (old-vars (and (not connect) (buffer-local-variables)))
+         (old-vars (and target (buffer-local-variables)))
          (old-recon-count erc-server-reconnect-count)
          (old-point nil)
          (delayed-modules nil)
@@ -3208,7 +3221,7 @@ if any.  In return, ERC expects a string to send as the 
server
 password, or nil, to skip the \"PASS\" command completely.  An
 explicit `:password' argument to entry-point commands `erc' and
 `erc-tls' also inhibits lookup, as does setting this option to
-nil.  See info node `(erc) Connecting' for details."
+nil.  See info node `(erc) auth-source' for details."
   :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
   :group 'erc
   :type '(choice (const erc-auth-source-search)
@@ -3223,7 +3236,7 @@ channel.  In return, ERC expects a string to use as the 
channel
 \"key\", or nil to just join the channel normally.  Setting the
 option itself to nil tells ERC to always forgo consulting
 auth-source for channel keys.  For more information, see info
-node `(erc) Connecting'."
+node `(erc) auth-source'."
   :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
   :group 'erc
   :type '(choice (const erc-auth-source-search)
@@ -6451,6 +6464,8 @@ non-nil value is found.
 When `erc-auth-source-server-function' is non-nil, call it with NICK for
 the user field and use whatever it returns as the server password."
   (or password (and erc-auth-source-server-function
+                    (not erc--server-reconnecting)
+                    (not erc--target)
                     (funcall erc-auth-source-server-function :user nick))))
 
 (defun erc-compute-full-name (&optional full-name)
diff --git a/lisp/external-completion.el b/lisp/external-completion.el
index 8dd75b7719..e1c3d76314 100644
--- a/lisp/external-completion.el
+++ b/lisp/external-completion.el
@@ -154,7 +154,7 @@ EXPANDED-PATTERN."
              ;;   very often doesn't equate the full set of candidates
              ;;   (many tools cap to sth like 100-1000 results).
              ;;
-             ;; * when `_method' is `nil' or `lambda' which some
+             ;; * when `_method' is nil or `lambda' which some
              ;;   frontends will invoke.  Here, `all' should be
              ;;   sufficient information for `complete-with-action' to
              ;;   do the job correctly.
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index b424cf48ff..b045b4e6e5 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -248,8 +248,8 @@ or set the `:backend' header argument"))))
                                "value")))
                result0)))
       (ob-clojure-string-or-list
-       ;; Filter out s-expressions that return `nil' (string "nil"
-       ;; from nrepl eval) or comment forms (actual `nil' from nrepl)
+       ;; Filter out s-expressions that return nil (string "nil"
+       ;; from nrepl eval) or comment forms (actual nil from nrepl)
        (reverse (delete "" (mapcar (lambda (r)
                                     (replace-regexp-in-string "nil" "" (or r 
"")))
                                   result0)))))))
diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el
index 1a32ed0102..9645dea7d9 100644
--- a/lisp/org/org-persist.el
+++ b/lisp/org/org-persist.el
@@ -134,7 +134,7 @@
 ;; from the persistent storage at the end of Emacs session.  The
 ;; expiry condition can be set when saving/registering data
 ;; containers.  The expirty condition can be `never' - data will never
-;; expire; `nil' - data will expire at the end of current Emacs session;
+;; expire; nil - data will expire at the end of current Emacs session;
 ;; a number - data will expire after the number days from last access;
 ;; a function - data will expire if the function, called with a single
 ;; argument - collection, returns non-nil.
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index e6b6156ddd..864dfa81c4 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -83,6 +83,14 @@ follows the form of `treesit-simple-indent-rules'."
     table)
   "Syntax table for `c-ts-mode'.")
 
+(defvar c++-ts-mode--syntax-table
+  (let ((table (make-syntax-table c-ts-mode--syntax-table)))
+    ;; Template delimiters.
+    (modify-syntax-entry ?<  "("     table)
+    (modify-syntax-entry ?>  ")"     table)
+    table)
+  "Syntax table for `c++-ts-mode'.")
+
 (defun c-ts-mode--indent-styles (mode)
   "Indent rules supported by `c-ts-mode'.
 MODE is either `c' or `cpp'."
@@ -555,7 +563,8 @@ the subtrees."
                             "type_definition"
                             "struct_specifier"
                             "enum_specifier"
-                            "union_specifier")))
+                            "union_specifier"
+                            "class_specifier")))
 
   ;; Nodes like struct/enum/union_specifier can appear in
   ;; function_definitions, so we need to find the top-level node.
@@ -616,6 +625,7 @@ the subtrees."
 (define-derived-mode c++-ts-mode c-ts-base-mode "C++"
   "Major mode for editing C++, powered by tree-sitter."
   :group 'c++
+  :syntax-table c++-ts-mode--syntax-table
 
   (unless (treesit-ready-p 'cpp)
     (error "Tree-sitter for C++ isn't available"))
diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el
index 15934a290b..fc25d2ba5f 100644
--- a/lisp/progmodes/cmake-ts-mode.el
+++ b/lisp/progmodes/cmake-ts-mode.el
@@ -196,7 +196,7 @@ the subtrees."
 
 ;;;###autoload
 (add-to-list 'auto-mode-alist
-             '("\\(?:CMakeLists\\.txt\\|\\.cmake\\)$" . cmake-ts-mode))
+             '("\\(?:CMakeLists\\.txt\\|\\.cmake\\)\\'" . cmake-ts-mode))
 
 ;;;###autoload
 (define-derived-mode cmake-ts-mode prog-mode "CMake"
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el
index 1fd051db3c..9e8b22c6ab 100644
--- a/lisp/progmodes/csharp-mode.el
+++ b/lisp/progmodes/csharp-mode.el
@@ -784,10 +784,6 @@ compilation and evaluation time conflicts."
      (invocation_expression
       (member_access_expression
        (generic_name (identifier) @font-lock-function-name-face)))
-     (invocation_expression
-      (member_access_expression
-       expression: (identifier) @font-lock-variable-name-face
-       name: (generic_name (type_argument_list (identifier)))))
      (invocation_expression
       (member_access_expression
        ((identifier) @font-lock-variable-name-face
@@ -795,7 +791,15 @@ compilation and evaluation time conflicts."
      (invocation_expression
       (identifier) @font-lock-function-name-face)
      (invocation_expression
-      (member_access_expression (identifier) @font-lock-function-name-face))
+      (member_access_expression
+       expression: (identifier) @font-lock-variable-name-face))
+     (invocation_expression
+      function: [(generic_name (identifier)) @font-lock-function-name-face
+                 (generic_name (type_argument_list
+                                ["<"] @font-lock-bracket-face
+                                (identifier) @font-lock-type-face
+                                [">"] @font-lock-bracket-face)
+                               )])
 
      (catch_declaration
       ((identifier) @font-lock-type-face))
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 13dce853bc..e0625951b6 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3445,12 +3445,15 @@ This function is intended for use in 
`after-change-functions'."
        ((parent-is "pair") parent-bol js-indent-level)
        ((parent-is "arrow_function") parent-bol js-indent-level)
        ((parent-is "parenthesized_expression") parent-bol js-indent-level)
+       ((parent-is "binary_expression") parent-bol js-indent-level)
        ((parent-is "class_body") parent-bol js-indent-level)
        ((parent-is ,switch-case) parent-bol js-indent-level)
        ((parent-is "statement_block") parent-bol js-indent-level)
 
        ;; JSX
        ((parent-is "jsx_opening_element") parent js-indent-level)
+       ((match "<" "jsx_fragment") parent 0)
+       ((parent-is "jsx_fragment") parent js-indent-level)
        ((node-is "jsx_closing_element") parent 0)
        ((node-is "jsx_text") parent js-indent-level)
        ((parent-is "jsx_element") parent js-indent-level)
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 17467b5554..4ac289d529 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -1611,7 +1611,8 @@ For example:
 See `add-log-current-defun-function'."
   (condition-case nil
       (save-excursion
-        (let* ((indent 0) mname mlist
+        (let* ((indent (ruby--add-log-current-indent))
+               mname mlist
                (start (point))
                (make-definition-re
                 (lambda (re &optional method-name?)
@@ -1626,18 +1627,30 @@ See `add-log-current-defun-function'."
                (definition-re (funcall make-definition-re ruby-defun-beg-re t))
                (module-re (funcall make-definition-re "\\(class\\|module\\)")))
           ;; Get the current method definition (or class/module).
-          (when (re-search-backward definition-re nil t)
+          (when (catch 'found
+                  (while (and (re-search-backward definition-re nil t)
+                              (if (if (string-equal "def" (match-string 1))
+                                      ;; We're inside a method.
+                                      (if (ruby-block-contains-point start)
+                                          t
+                                        ;; Try to match a method only once.
+                                        (setq definition-re module-re)
+                                        nil)
+                                    ;; Class/module. For performance,
+                                    ;; comparing indentation.
+                                    (or (not (numberp indent))
+                                        (> indent (current-indentation))))
+                                  (throw 'found t)
+                                t))))
             (goto-char (match-beginning 1))
             (if (not (string-equal "def" (match-string 1)))
                 (setq mlist (list (match-string 2)))
-              ;; We're inside the method. For classes and modules,
-              ;; this check is skipped for performance.
-              (when (ruby-block-contains-point start)
-                (setq mname (match-string 2))))
+              (setq mname (match-string 2)))
             (setq indent (current-column))
             (beginning-of-line))
           ;; Walk up the class/module nesting.
-          (while (and (> indent 0)
+          (while (and indent
+                      (> indent 0)
                       (re-search-backward module-re nil t))
             (goto-char (match-beginning 1))
             (when (< (current-column) indent)
@@ -1691,6 +1704,17 @@ See `add-log-current-defun-function'."
         (ruby-forward-sexp))
       (> (point) pt))))
 
+(defun ruby--add-log-current-indent ()
+  (save-excursion
+    (back-to-indentation)
+    (cond
+     ((looking-at "[[:graph:]]")
+      (current-indentation))
+     (ruby-use-smie
+      (smie-indent-calculate))
+     (t
+      (ruby-calculate-indent)))))
+
 (defun ruby-brace-to-do-end (orig end)
   (let (beg-marker end-marker)
     (goto-char end)
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 6a5a6e0de2..171a379375 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -92,9 +92,12 @@ Argument LANGUAGE is either `typescript' or `tsx'."
      ((parent-is "class_body") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "arrow_function") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "parenthesized_expression") parent-bol 
typescript-ts-mode-indent-offset)
+     ((parent-is "binary_expression") parent-bol 
typescript-ts-mode-indent-offset)
 
      ,@(when (eq language 'tsx)
          `(((parent-is "jsx_opening_element") parent 
typescript-ts-mode-indent-offset)
+           ((match "<" "jsx_fragment") parent 0)
+           ((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset)
            ((node-is "jsx_closing_element") parent 0)
            ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset)
            ((node-is "/") parent 0)
@@ -225,7 +228,31 @@ Argument LANGUAGE is either `typescript' or `tsx'."
      (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))
+     (arguments (identifier) @font-lock-variable-name-face)
+
+     (parenthesized_expression (identifier) @font-lock-variable-name-face)
+     (parenthesized_expression (_ (identifier)) @font-lock-variable-name-face))
+
+   :language language
+   :override t
+   :feature 'property
+   `((property_signature
+      name: (property_identifier) @font-lock-property-face)
+     (public_field_definition
+      name: (property_identifier) @font-lock-property-face)
+     (member_expression
+      object: (identifier) @font-lock-variable-name-face)
+     (member_expression
+      property: (_) @font-lock-property-face)
+
+     (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)
+      @font-lock-property-face))
 
    :language language
    :override t
@@ -291,22 +318,8 @@ Argument LANGUAGE is either `typescript' or `tsx'."
    :override t
    '((escape_sequence) @font-lock-escape-face)
 
-   :language language
-   :override t
-   :feature 'property
-   `((property_signature
-      name: (property_identifier) @font-lock-property-face)
-     (public_field_definition
-      name: (property_identifier) @font-lock-property-face)
 
-     (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)
-      @font-lock-property-face))))
+   ))
 
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-ts-mode))
diff --git a/lisp/subr.el b/lisp/subr.el
index 21f43092d4..e142eaa810 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3855,7 +3855,7 @@ If MESSAGE is nil, instructions to type EXIT-CHAR are 
displayed there."
   (let ((o1 (if (overlay-buffer o)
                 (make-overlay (overlay-start o) (overlay-end o)
                               ;; FIXME: there's no easy way to find the
-                              ;; insertion-type of the two markers.
+                              ;; insertion-type of overlay's start and end.
                               (overlay-buffer o))
               (let ((o1 (make-overlay (point-min) (point-min))))
                 (delete-overlay o1)
diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el
index f815419ea4..126b3777f5 100644
--- a/lisp/textmodes/reftex.el
+++ b/lisp/textmodes/reftex.el
@@ -1004,10 +1004,13 @@ This enforces rescanning the buffer on next use."
                   reftex-section-levels))
 
     ;; Calculate the regular expressions
-    (let* (
-;          (wbol "\\(\\`\\|[\n\r]\\)[ \t]*")
-           (wbol "\\(^\\)%?[ \t]*") ; Need to keep the empty group because
-                                    ; match numbers are hard coded
+    (let* (;; (wbol "\\(\\`\\|[\n\r]\\)[ \t]*")
+           ;; Need to keep the empty group because match numbers are
+           ;; hard coded
+           (wbol (concat "\\(^\\)"
+                         (when (string-suffix-p ".dtx" (buffer-file-name) t)
+                           "%")
+                         "[ \t]*"))
            (label-re (concat "\\(?:"
                             (mapconcat #'identity reftex-label-regexps "\\|")
                             "\\)"))
diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el
new file mode 100644
index 0000000000..26a3eb69d8
--- /dev/null
+++ b/lisp/textmodes/toml-ts-mode.el
@@ -0,0 +1,187 @@
+;;; toml-ts-mode.el --- tree-sitter support for TOML  -*- lexical-binding: t; 
-*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; Author     : Jostein Kjønigsen <jostein@kjonigsen.net>
+;; Maintainer : Jostein Kjønigsen <jostein@kjonigsen.net>
+;; Created    : December 2022
+;; Keywords   : toml languages tree-sitter
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+
+;;; Code:
+
+(require 'treesit)
+
+(declare-function treesit-parser-create "treesit.c")
+(declare-function treesit-induce-sparse-tree "treesit.c")
+(declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-child-by-field-name "treesit.c")
+
+(defcustom toml-ts-mode-indent-offset 2
+  "Number of spaces for each indentation step in `toml-ts-mode'."
+  :version "29.1"
+  :type 'integer
+  :safe 'integerp
+  :group 'toml)
+
+(defvar toml-ts-mode--syntax-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?_  "_"     table)
+    (modify-syntax-entry ?\\ "\\"    table)
+    (modify-syntax-entry ?=  "."     table)
+    (modify-syntax-entry ?\' "\""    table)
+    (modify-syntax-entry ?#  "<"   table)
+    (modify-syntax-entry ?\n "> b"  table)
+    (modify-syntax-entry ?\^m "> b" table)
+    table)
+  "Syntax table for `toml-ts-mode'.")
+
+(defvar toml-ts-mode--indent-rules
+  `((toml
+     ((node-is "]") parent-bol 0)
+     ((parent-is "string") parent-bol toml-ts-mode-indent-offset)
+     ((parent-is "array") parent-bol toml-ts-mode-indent-offset))))
+
+(defvar toml-ts-mode--font-lock-settings
+  (treesit-font-lock-rules
+   :language 'toml
+   :feature 'comment
+   '((comment) @font-lock-comment-face)
+
+   :language 'toml
+   :feature 'constant
+   '((boolean) @font-lock-constant-face)
+
+   :language 'toml
+   :feature 'delimiter
+   '((["="]) @font-lock-delimiter-face)
+
+   :language 'toml
+   :feature 'number
+   '([(integer) (float) (local_date) (local_date_time) (local_time)]
+     @font-lock-number-face)
+
+   :language 'toml
+   :feature 'string
+   '((string) @font-lock-string-face)
+
+   :language 'toml
+   :feature 'escape-sequence
+   :override t
+   '((escape_sequence) @font-lock-escape-face)
+
+   :language 'toml
+   :feature 'pair
+   :override t            ; Needed for overriding string face on keys.
+   '((bare_key) @font-lock-property-face
+     (quoted_key) @font-lock-property-face
+     (table ("[" @font-lock-bracket-face
+             (_) @font-lock-type-face
+             "]" @font-lock-bracket-face))
+     (table_array_element ("[[" @font-lock-bracket-face
+                           (_) @font-lock-type-face
+                           "]]" @font-lock-bracket-face))
+     (table (quoted_key) @font-lock-type-face)
+     (table (dotted_key (quoted_key)) @font-lock-type-face))
+
+   :language 'toml
+   :feature 'error
+   :override t
+   '((ERROR) @font-lock-warning-face))
+  "Font-lock settings for TOML.")
+
+(defun toml-ts-mode--get-table-name (node)
+  "Obtains the header-name for the associated tree-sitter `NODE'."
+  (if node
+      (treesit-node-text
+       (car (cdr (treesit-node-children node))))
+    "Root table"))
+
+(defun toml-ts-mode--imenu-1 (node)
+  "Helper for `toml-ts-mode--imenu'.
+Find string representation for NODE and set marker, then recurse
+the subtrees."
+  (let* ((ts-node (car node))
+         (subtrees (mapcan #'toml-ts-mode--imenu-1 (cdr node)))
+         (name (toml-ts-mode--get-table-name ts-node))
+         (marker (when ts-node
+                   (set-marker (make-marker)
+                               (treesit-node-start ts-node)))))
+    (cond
+     ((null ts-node) subtrees)
+     (subtrees
+      `((,name ,(cons name marker) ,@subtrees)))
+     (t
+      `((,name . ,marker))))))
+
+(defun toml-ts-mode--imenu ()
+  "Return Imenu alist for the current buffer."
+  (let* ((node (treesit-buffer-root-node))
+         (table-tree (treesit-induce-sparse-tree
+                      node "^table$" nil 1000))
+         (table-array-tree (treesit-induce-sparse-tree
+                            node "^table_array_element$" nil 1000))
+         (table-index (toml-ts-mode--imenu-1 table-tree))
+         (table-array-index (toml-ts-mode--imenu-1 table-array-tree)))
+    (append
+     (when table-index `(("Headers" . ,table-index)))
+     (when table-array-index `(("Arrays" . ,table-array-index))))))
+
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.toml\\'" . toml-ts-mode))
+
+;;;###autoload
+(define-derived-mode toml-ts-mode text-mode "TOML"
+  "Major mode for editing TOML, powered by tree-sitter."
+  :group 'toml-mode
+  :syntax-table toml-ts-mode--syntax-table
+
+  (when (treesit-ready-p 'toml)
+    (treesit-parser-create 'toml)
+
+    ;; Comments
+    (setq-local comment-start "# ")
+    (setq-local commend-end "")
+
+    ;; Indent.
+    (setq-local treesit-simple-indent-rules toml-ts-mode--indent-rules)
+
+    ;; Navigation.
+    (setq-local treesit-defun-type-regexp
+                (rx (or "table" "table_array_element")))
+
+    ;; Font-lock.
+    (setq-local treesit-font-lock-settings toml-ts-mode--font-lock-settings)
+    (setq-local treesit-font-lock-feature-list
+                '((comment)
+                  (constant number pair string)
+                  (escape-sequence)
+                  (delimiter error)))
+
+    ;; Imenu.
+    (setq-local imenu-create-index-function #'toml-ts-mode--imenu)
+    (setq-local which-func-functions nil) ;; Piggyback on imenu
+
+    (treesit-major-mode-setup)))
+
+(provide 'toml-ts-mode)
+
+;;; toml-ts-mode.el ends here
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 83138a6d10..2876a983fb 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1048,7 +1048,7 @@ It is based on `log-edit-mode', and has Git-specific 
extensions."
                         (string-replace file-diff "" vc-git-patch-string))
                 (user-error "Index not empty"))
               (setq pos (point))))))
-      (let ((patch-file (make-temp-file "git-patch")))
+      (let ((patch-file (make-nearby-temp-file "git-patch")))
         (with-temp-file patch-file
           (insert vc-git-patch-string))
         (unwind-protect
diff --git a/lisp/window.el b/lisp/window.el
index a11293d372..7d8ee48635 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4636,7 +4636,7 @@ omitted in calls from `switch-to-next-buffer'."
                     (catch 'found
                       (dolist (regexp switch-to-prev-buffer-skip-regexp)
                         (when (string-match-p regexp (buffer-name buffer))
-                          (throw 'tag t)))))))))
+                          (throw 'found t)))))))))
 
 (defun switch-to-prev-buffer (&optional window bury-or-kill)
   "In WINDOW switch to previous buffer.
diff --git a/src/buffer.c b/src/buffer.c
index 69f27c9f47..9a30faa0e1 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -3898,11 +3898,11 @@ the value is (point-min).  */)
 /* These functions are for debugging overlays.  */
 
 DEFUN ("overlay-lists", Foverlay_lists, Soverlay_lists, 0, 0, 0,
-       doc: /* Return a pair of lists giving all the overlays of the current 
buffer.
-The car has all the overlays before the overlay center;
-the cdr has all the overlays after the overlay center.
-Recentering overlays moves overlays between these lists.
-The lists you get are copies, so that changing them has no effect.
+       doc: /* Return a list giving all the overlays of the current buffer.
+
+For backward compatibility, the value is actually a list that
+holds another list; the overlays are in the inner list.
+The list you get is a copy, so that changing it has no effect.
 However, the overlays you get are the real objects that the buffer uses. */)
   (void)
 {
@@ -3918,7 +3918,12 @@ However, the overlays you get are the real objects that 
the buffer uses. */)
 DEFUN ("overlay-recenter", Foverlay_recenter, Soverlay_recenter, 1, 1, 0,
        doc: /* Recenter the overlays of the current buffer around position POS.
 That makes overlay lookup faster for positions near POS (but perhaps slower
-for positions far away from POS).  */)
+for positions far away from POS).
+
+Since Emacs 29.1, this function is a no-op, because the implementation
+of overlays changed and their lookup is now fast regardless of their
+position in the buffer.  In particular, this function no longer affects
+the value returned by `overlay-lists'.  */)
   (Lisp_Object pos)
 {
   CHECK_FIXNUM_COERCE_MARKER (pos);
diff --git a/test/lisp/calendar/icalendar-tests.el 
b/test/lisp/calendar/icalendar-tests.el
index fa55eea95e..baf4846c8f 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -63,7 +63,8 @@
 
 (defun icalendar-tests--get-error-string-for-export (diary-string)
   "Call icalendar-export for DIARY-STRING and return resulting error-string."
-  (let ((file (make-temp-file "export.ics")))
+  (ert-with-temp-file file
+    :suffix "-export.ics"
     (with-temp-buffer
       (insert diary-string)
       (icalendar-export-region (point-min) (point-max) file))
diff --git a/test/lisp/erc/erc-networks-tests.el 
b/test/lisp/erc/erc-networks-tests.el
index fc12bf7ce3..e883174e28 100644
--- a/test/lisp/erc/erc-networks-tests.el
+++ b/test/lisp/erc/erc-networks-tests.el
@@ -1171,6 +1171,8 @@
     (let (erc-server-announced-name
           (erc--isupport-params (make-hash-table))
           erc-network
+          erc-quit-hook
+          (erc-server-process (erc-networks-tests--create-live-proc))
           calls)
       (erc-mode)
 
@@ -1183,10 +1185,7 @@
 
         (ert-info ("Signals when table empty and NETWORK param unset")
           (setq erc-server-announced-name "irc.fake.gnu.org")
-          (let ((err (should-error (erc-networks--set-name
-                                    nil (make-erc-response)))))
-            (should (string-match-p "failed" (cadr err)))
-            (should (eq (car err) 'error)))
+          (should (eq 'error (erc-networks--set-name nil (make-erc-response))))
           (should (string-match-p (rx "*** Failed") (car (pop calls)))))))
 
     (erc-networks-tests--clean-bufs)))
diff --git a/test/lisp/erc/erc-scenarios-base-netid-samenet.el 
b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
index 3cd8b7dfa1..1436712251 100644
--- a/test/lisp/erc/erc-scenarios-base-netid-samenet.el
+++ b/test/lisp/erc/erc-scenarios-base-netid-samenet.el
@@ -40,6 +40,9 @@
        (erc-server-flood-margin 30)
        erc-serv-buf-a erc-serv-buf-b)
 
+    (when (and id-a (zerop (random 2))) (setq id-a (symbol-name id-a)))
+    (when (and id-b (zerop (random 2))) (setq id-b (symbol-name id-b)))
+
     (ert-info ("Connect to foonet with nick tester")
       (with-current-buffer
           (setq erc-serv-buf-a (erc :server "127.0.0.1"
diff --git a/test/lisp/erc/erc-scenarios-misc.el 
b/test/lisp/erc/erc-scenarios-misc.el
index 3fa05ee8a6..f1696088a4 100644
--- a/test/lisp/erc/erc-scenarios-misc.el
+++ b/test/lisp/erc/erc-scenarios-misc.el
@@ -98,11 +98,10 @@
                                 :nick "tester"
                                 :full-name "tester")
         (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
-        (let ((err (should-error (sleep-for 1))))
-          (should (string-match-p "Failed to determine" (cadr err))))
         (funcall expect 1 "Failed to determine")
         (funcall expect 1 "Failed to determine")
-        (should-not erc-network)
+        (funcall expect 1 "Connection failed")
+        (should (string-prefix-p "Unknown" (erc-network-name)))
         (should (string= erc-server-announced-name "irc.foonet.org"))))))
 
 ;; Targets that are host/server masks like $*, $$*, and #* are routed
diff --git a/test/lisp/erc/erc-scenarios-services-misc.el 
b/test/lisp/erc/erc-scenarios-services-misc.el
index 680750d2d7..44e04e5150 100644
--- a/test/lisp/erc/erc-scenarios-services-misc.el
+++ b/test/lisp/erc/erc-scenarios-services-misc.el
@@ -84,4 +84,63 @@
 
     (should-not (memq 'services erc-modules))))
 
+;; A user with `services' enabled connects, quits, and reconnects.  An
+;; entry in their netrc matches the network ID, which isn't known when
+;; `erc-auth-source-server-function' runs -- initially *or* on
+;; reconnect.  It's only seen by `erc-auth-source-services-function'.
+
+(ert-deftest erc-scenarios-services-auth-source-reconnect ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "services/auth-source")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'recon 'recon))
+       (port (process-contact dumb-server :service))
+       (netrc-file (make-temp-file
+                    "auth-source-test" nil nil
+                    "machine FooNet login tester password changeme\n"))
+       (auth-sources (list netrc-file))
+       (auth-source-do-cache nil)
+       (erc-modules (cons 'services erc-modules))
+       (erc-use-auth-source-for-nickserv-password t) ; do consult
+       (erc-prompt-for-nickserv-password nil) ; don't prompt
+       (erc-nickserv-alist
+        (cons '(FooNet
+                "NickServ!NickServ@services.int"
+                "This nickname is registered. Please choose"
+                "NickServ" "IDENTIFY" nil nil "You are now identified for ")
+              erc-nickserv-alist))
+       (expect (erc-d-t-make-expecter))
+       (erc-scenarios-common-extra-teardown (lambda ()
+                                              (delete-file netrc-file))))
+
+    (ert-info ("Server password omitted from initial connection")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :user "tester"
+                                :full-name "tester")
+        (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
+        (ert-info ("Services module authenticates")
+          (funcall expect 10 "This nickname is registered.")
+          (funcall expect 3 "You are now identified"))
+        (erc-cmd-JOIN "#chan")
+        (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
+          (funcall expect 10 "the gallants desire it"))
+        (erc-cmd-QUIT "")
+        (funcall expect 3 "finished")))
+
+    (ert-info ("Server password withheld on reconnect")
+      (with-current-buffer "#chan"
+        (erc-cmd-RECONNECT))
+      (with-current-buffer "FooNet"
+        (funcall expect 10 "This nickname is registered.")
+        (funcall expect 3 "You are now identified")
+        (with-current-buffer "#chan" ; autojoined
+          (funcall expect 10 "the gallants desire it"))
+        (erc-cmd-QUIT "")
+        (funcall expect 3 "finished")))
+
+    (erc-services-mode -1)))
+
 ;;; erc-scenarios-services-misc.el ends here
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el
index 4d0d69cd7b..51c562f525 100644
--- a/test/lisp/erc/erc-tests.el
+++ b/test/lisp/erc/erc-tests.el
@@ -428,18 +428,21 @@
 
     (ert-info ("ascii")
       (puthash 'CASEMAPPING  '("ascii") erc--isupport-params)
+      (should (equal (erc-downcase "ABC 123 ΔΞΩΣ") "abc 123 ΔΞΩΣ"))
       (should (equal (erc-downcase "Bob[m]`") "bob[m]`"))
       (should (equal (erc-downcase "Tilde~") "tilde~" ))
       (should (equal (erc-downcase "\\O/") "\\o/" )))
 
     (ert-info ("rfc1459")
       (puthash 'CASEMAPPING  '("rfc1459") erc--isupport-params)
+      (should (equal (erc-downcase "ABC 123 ΔΞΩΣ") "abc 123 ΔΞΩΣ"))
       (should (equal (erc-downcase "Bob[m]`") "bob{m}`" ))
       (should (equal (erc-downcase "Tilde~") "tilde^" ))
       (should (equal (erc-downcase "\\O/") "|o/" )))
 
     (ert-info ("rfc1459-strict")
       (puthash 'CASEMAPPING  '("rfc1459-strict") erc--isupport-params)
+      (should (equal (erc-downcase "ABC 123 ΔΞΩΣ") "abc 123 ΔΞΩΣ"))
       (should (equal (erc-downcase "Bob[m]`") "bob{m}`"))
       (should (equal (erc-downcase "Tilde~") "tilde~" ))
       (should (equal (erc-downcase "\\O/") "|o/" )))))
diff --git a/test/lisp/erc/resources/base/local-modules/fourth.eld 
b/test/lisp/erc/resources/base/local-modules/fourth.eld
index fd6d62b6cc..4ac5dcbd38 100644
--- a/test/lisp/erc/resources/base/local-modules/fourth.eld
+++ b/test/lisp/erc/resources/base/local-modules/fourth.eld
@@ -1,7 +1,7 @@
 ;; -*- mode: lisp-data; -*-
 ((cap 10 "CAP REQ :sasl"))
 ((nick 10 "NICK tester`"))
-((user 10 "USER tester 0 * :tester"))
+((user 10 "USER tester` 0 * :tester"))
 
 ((authenticate 10 "AUTHENTICATE PLAIN")
  (0.0 ":irc.foonet.org CAP * ACK sasl")
diff --git a/test/lisp/erc/resources/erc-scenarios-common.el 
b/test/lisp/erc/resources/erc-scenarios-common.el
index d77b32984b..57d4658e75 100644
--- a/test/lisp/erc/resources/erc-scenarios-common.el
+++ b/test/lisp/erc/resources/erc-scenarios-common.el
@@ -185,7 +185,7 @@ Dialog resource directories are located by expanding the 
variable
 (defun erc-scenarios-common-assert-initial-buf-name (id port)
   ;; Assert no limbo period when explicit ID given
   (should (string= (if id
-                       (symbol-name id)
+                       (format "%s" id)
                      (format "127.0.0.1:%d" port))
                    (buffer-name))))
 
diff --git a/test/lisp/erc/resources/networks/announced-missing/foonet.eld 
b/test/lisp/erc/resources/networks/announced-missing/foonet.eld
index 79b0fb462a..4481f27663 100644
--- a/test/lisp/erc/resources/networks/announced-missing/foonet.eld
+++ b/test/lisp/erc/resources/networks/announced-missing/foonet.eld
@@ -3,6 +3,3 @@
 ((user 1 "USER user 0 * :tester")
  (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat 
Network tester")
  (0 ":irc.foonet.org 422 tester :MOTD File is missing"))
-
-((mode-user 1.2 "MODE tester +i")
- (0 ":tester MODE tester :+Zi"))
diff --git a/test/lisp/erc/resources/services/auth-source/recon.eld 
b/test/lisp/erc/resources/services/auth-source/recon.eld
new file mode 100644
index 0000000000..40ea3c9157
--- /dev/null
+++ b/test/lisp/erc/resources/services/auth-source/recon.eld
@@ -0,0 +1,48 @@
+;; -*- mode: lisp-data; -*-
+((nick 10 "NICK tester"))
+((user 5 "USER tester 0 * :tester")
+ (0.00 ":irc.foonet.net NOTICE * :*** Looking up your hostname...")
+ (0.04 ":irc.foonet.net NOTICE tester :*** Could not resolve your hostname: 
Domain not found; using your IP address (10.0.2.100) instead.")
+ (0.06 ":irc.foonet.net 001 tester :Welcome to the FooNet IRC Network 
tester!tester@10.0.2.100")
+ (0.01 ":irc.foonet.net 002 tester :Your host is irc.foonet.net, running 
version InspIRCd-3")
+ (0.01 ":irc.foonet.net 003 tester :This server was created 08:32:24 Dec 05 
2022")
+ (0.01 ":irc.foonet.net 004 tester irc.foonet.net InspIRCd-3 BIRcgikorsw 
ACHIKMORTXabcefghijklmnopqrstvz :HIXabefghjkloqv")
+ (0.01 ":irc.foonet.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.01 ":irc.foonet.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.foonet.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.foonet.net 251 tester :There are 2 users and 0 invisible on 2 
servers")
+ (0.00 ":irc.foonet.net 253 tester 1 :unknown connections")
+ (0.00 ":irc.foonet.net 254 tester 1 :channels formed")
+ (0.00 ":irc.foonet.net 255 tester :I have 2 clients and 1 servers")
+ (0.00 ":irc.foonet.net 265 tester :Current local users: 2  Max: 3")
+ (0.00 ":irc.foonet.net 266 tester :Current global users: 2  Max: 3")
+ (0.00 ":irc.foonet.net 375 tester :irc.foonet.net message of the day")
+ (0.00 ":irc.foonet.net 372 tester :Have fun!")
+ (0.00 ":irc.foonet.net 376 tester :End of message of the day."))
+
+((mode-a 10 "MODE tester +i")
+ (0.00 ":irc.foonet.net 501 tester x :is not a recognised user mode.")
+ (0.04 ":tester!tester@10.0.2.100 MODE tester :+i")
+ (0.00 ":NickServ!NickServ@services.int NOTICE tester :This nickname is 
registered. Please choose a different nickname, or identify via \2/msg NickServ 
identify <password>\2."))
+
+((~privmsg 10 "PRIVMSG NickServ :IDENTIFY changeme")
+ (0.00 ":NickServ!NickServ@services.int NOTICE tester :You are now identified 
for \2tester\2.")
+ (0.01 ":irc.foonet.net 900 tester tester!tester@10.0.2.100 tester :You are 
now logged in as tester"))
+
+((~join 10 "JOIN #chan")
+ (0.00 ":tester!tester@10.0.2.100 JOIN :#chan")
+ (0.04 ":irc.foonet.net 353 tester = #chan :@alice bob tester")
+ (0.00 ":irc.foonet.net 366 tester #chan :End of /NAMES list."))
+
+((mode-b 10 "MODE #chan")
+ (0.03 ":irc.foonet.net 324 tester #chan :+nt")
+ (0.01 ":irc.foonet.net 329 tester #chan :1670229160")
+ (0.00 ":alice!alice@0::1 PRIVMSG #chan :tester, welcome!")
+ (0.00 ":bob!bob@0::1 PRIVMSG #chan :tester, welcome!")
+ (0.05 ":alice!alice@0::1 PRIVMSG #chan :bob: Thou art the cap of all the 
fools alive.")
+ (0.06 ":bob!bob@0::1 PRIVMSG #chan :alice: What, man! 'tis a night of revels; 
the gallants desire it."))
+
+((quit 10 "QUIT :\2ERC\2")
+ (0.1 ":tester!tester@10.0.2.100 QUIT :Client Quit"))
+
+((drop 1 DROP))
diff --git a/test/lisp/progmodes/eglot-tests.el 
b/test/lisp/progmodes/eglot-tests.el
index f6b53fd0c6..d8c9560f5b 100644
--- a/test/lisp/progmodes/eglot-tests.el
+++ b/test/lisp/progmodes/eglot-tests.el
@@ -88,7 +88,7 @@ then restored."
 
 (defun eglot--call-with-fixture (fixture fn)
   "Helper for `eglot--with-fixture'.  Run FN under FIXTURE."
-  (let* ((fixture-directory (make-temp-file "eglot--fixture" t))
+  (let* ((fixture-directory (make-nearby-temp-file "eglot--fixture" t))
          (default-directory fixture-directory)
          file-specs created-files
          syms-to-restore
@@ -311,7 +311,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
 
 ;;; Unit tests
 
-(ert-deftest eclipse-connect ()
+(ert-deftest eglot-test-eclipse-connect ()
   "Connect to eclipse.jdt.ls server."
   (skip-unless (executable-find "jdtls"))
   (eglot--with-fixture
@@ -343,12 +343,12 @@ Pass TIMEOUT to `eglot--with-timeout'."
          (eglot--find-file-noselect "anotherproject/cena.c")
        (should-error (eglot--current-server-or-lose))))))
 
-(ert-deftest auto-detect-running-server ()
+(ert-deftest eglot-test-auto-detect-running-server ()
   "Visit a file and \\[eglot], then visit a neighbor."
   (skip-unless (executable-find "clangd"))
   (eglot-tests--auto-detect-running-server-1))
 
-(ert-deftest auto-shutdown ()
+(ert-deftest eglot-test-auto-shutdown ()
   "Visit a file and \\[eglot], then kill buffer."
   (skip-unless (executable-find "clangd"))
   (let (server
@@ -367,7 +367,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
         (let ((eglot-autoshutdown t)) (kill-buffer buffer))
         (should (not (jsonrpc-running-p server)))))))
 
-(ert-deftest auto-reconnect ()
+(ert-deftest eglot-test-auto-reconnect ()
   "Start a server.  Kill it.  Watch it reconnect."
   (skip-unless (executable-find "clangd"))
   (let (server (eglot-autoreconnect 1))
@@ -390,7 +390,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
           (while (process-live-p proc) (accept-process-output nil 0.5)))
         (should (not (eglot-current-server)))))))
 
-(ert-deftest rust-analyzer-watches-files ()
+(ert-deftest eglot-test-rust-analyzer-watches-files ()
   "Start rust-analyzer.  Notify it when a critical file changes."
   (skip-unless (executable-find "rust-analyzer"))
   (skip-unless (executable-find "cargo"))
@@ -425,7 +425,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
                    (and (string= (eglot--path-to-uri "Cargo.toml") uri)
                         (= type 3))))))))))
 
-(ert-deftest basic-diagnostics ()
+(ert-deftest eglot-test-basic-diagnostics ()
   "Test basic diagnostics."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -443,7 +443,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
         (flymake-goto-next-error 1 '() t)
         (should (eq 'flymake-error (face-at-point)))))))
 
-(ert-deftest diagnostic-tags-unnecessary-code ()
+(ert-deftest eglot-test-diagnostic-tags-unnecessary-code ()
   "Test rendering of diagnostics tagged \"unnecessary\"."
   (skip-unless (executable-find "rust-analyzer"))
   (skip-unless (executable-find "cargo"))
@@ -486,7 +486,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
    do (sit-for 0.5)
    finally (error "eglot--tests-force-full-eldoc didn't deliver")))
 
-(ert-deftest rust-analyzer-hover-after-edit ()
+(ert-deftest eglot-test-rust-analyzer-hover-after-edit ()
   "Hover and highlightChanges."
   (skip-unless (executable-find "rust-analyzer"))
   (skip-unless (executable-find "cargo"))
@@ -519,7 +519,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
               (&key id &allow-other-keys)
             (eq id pending-id)))))))
 
-(ert-deftest rename-a-symbol ()
+(ert-deftest eglot-test-rename-a-symbol ()
   "Test basic symbol renaming."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -534,7 +534,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
       (should (equal (buffer-string)
                      "int bar() {return 42;} int main() {return bar();}")))))
 
-(ert-deftest basic-completions ()
+(ert-deftest eglot-test-basic-completions ()
   "Test basic autocompletion in a python LSP."
   (skip-unless (executable-find "pylsp"))
   (eglot--with-fixture
@@ -546,7 +546,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
       (completion-at-point)
       (should (looking-back "sys.exit")))))
 
-(ert-deftest non-unique-completions ()
+(ert-deftest eglot-test-non-unique-completions ()
   "Test completion resulting in 'Complete, but not unique'."
   (skip-unless (executable-find "pylsp"))
   (eglot--with-fixture
@@ -563,7 +563,7 @@ Pass TIMEOUT to `eglot--with-timeout'."
         (forward-line -1)
         (should (looking-at "Complete, but not unique"))))))
 
-(ert-deftest basic-xref ()
+(ert-deftest eglot-test-basic-xref ()
   "Test basic xref functionality in a python LSP."
   (skip-unless (executable-find "pylsp"))
   (eglot--with-fixture
@@ -583,7 +583,7 @@ def foobazquuz(d, e, f): pass
 
 (declare-function yas-minor-mode nil)
 
-(ert-deftest snippet-completions ()
+(ert-deftest eglot-test-snippet-completions ()
   "Test simple snippet completion in a python LSP."
   (skip-unless (and (executable-find "pylsp")
                     (functionp 'yas-minor-mode)))
@@ -605,7 +605,7 @@ def foobazquuz(d, e, f): pass
 (declare-function company-mode nil)
 (declare-function company-complete nil)
 
-(ert-deftest snippet-completions-with-company ()
+(ert-deftest eglot-test-snippet-completions-with-company ()
   "Test simple snippet completion in a python LSP."
   (skip-unless (and (executable-find "pylsp")
                     (functionp 'yas-minor-mode)
@@ -628,7 +628,7 @@ def foobazquuz(d, e, f): pass
       ;; pylsp will change the representation of this candidate
       (should (member "foobazquuz(d, e, f)" company-candidates)))))
 
-(ert-deftest eglot-eldoc-after-completions ()
+(ert-deftest eglot-test-eldoc-after-completions ()
   "Test documentation echo in a python LSP."
   (skip-unless (executable-find "pylsp"))
   (eglot--with-fixture
@@ -641,7 +641,7 @@ def foobazquuz(d, e, f): pass
       (should (looking-back "sys.exit"))
       (should (string-match "^exit" (eglot--tests-force-full-eldoc))))))
 
-(ert-deftest eglot-multiline-eldoc ()
+(ert-deftest eglot-test-multiline-eldoc ()
   "Test if suitable amount of lines of hover info are shown."
   (skip-unless (executable-find "pylsp"))
   (eglot--with-fixture
@@ -656,7 +656,7 @@ def foobazquuz(d, e, f): pass
         (should (string-match "datetim" captured-message))
         (should (cl-find ?\n captured-message))))))
 
-(ert-deftest eglot-single-line-eldoc ()
+(ert-deftest eglot-test-single-line-eldoc ()
   "Test if suitable amount of lines of hover info are shown."
   (skip-unless (executable-find "pylsp"))
   (eglot--with-fixture
@@ -671,7 +671,7 @@ def foobazquuz(d, e, f): pass
         (should (string-match "datetim" captured-message))
         (should (not (cl-find ?\n eldoc-last-message)))))))
 
-(ert-deftest python-autopep-formatting ()
+(ert-deftest eglot-test-python-autopep-formatting ()
   "Test formatting in the pylsp python LSP.
 pylsp prefers autopep over yafp, despite its README stating the contrary."
   ;; Beware, default autopep rules can change over time, which may
@@ -696,7 +696,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
       (should
        (string= (buffer-string) "def a(): pass\n\n\ndef b(): pass\n")))))
 
-(ert-deftest python-yapf-formatting ()
+(ert-deftest eglot-test-python-yapf-formatting ()
   "Test formatting in the pylsp python LSP."
   (skip-unless (and (executable-find "pylsp")
                     (not (executable-find "autopep8"))
@@ -718,7 +718,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
       (should
        (string= (buffer-string) "def a():\n    pass\n\n\ndef b():\n    
pass\n")))))
 
-(ert-deftest rust-on-type-formatting ()
+(ert-deftest eglot-test-rust-on-type-formatting ()
   "Test textDocument/onTypeFormatting against rust-analyzer."
   (skip-unless (executable-find "rust-analyzer"))
   (skip-unless (executable-find "cargo"))
@@ -738,7 +738,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
         (eglot--simulate-key-event ?.)
         (should (looking-back "^    \\."))))))
 
-(ert-deftest javascript-basic ()
+(ert-deftest eglot-test-javascript-basic ()
   "Test basic autocompletion in a JavaScript LSP."
   (skip-unless (and (executable-find "typescript-language-server")
                     (executable-find "tsserver")))
@@ -768,7 +768,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
                                  (= severity 1))
                                diagnostics)))))))))
 
-(ert-deftest project-wide-diagnostics-typescript ()
+(ert-deftest eglot-test-project-wide-diagnostics-typescript ()
   "Test diagnostics through multiple files in a TypeScript LSP."
   (skip-unless (and (executable-find "typescript-language-server")
                     (executable-find "tsserver")))
@@ -797,7 +797,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
               (string= method "textDocument/publishDiagnostics"))
             (should (= 4 (length (flymake--project-diagnostics))))))))))
 
-(ert-deftest project-wide-diagnostics-rust-analyzer ()
+(ert-deftest eglot-test-project-wide-diagnostics-rust-analyzer ()
   "Test diagnostics through multiple files in a TypeScript LSP."
   (skip-unless (executable-find "rust-analyzer"))
   (skip-unless (executable-find "cargo"))
@@ -826,7 +826,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
                      "main.rs"
                      (flymake-diagnostic-buffer (car diags))))))))))
 
-(ert-deftest json-basic ()
+(ert-deftest eglot-test-json-basic ()
   "Test basic autocompletion in vscode-json-languageserver."
   (skip-unless (executable-find "vscode-json-languageserver"))
   (eglot--with-fixture
@@ -870,12 +870,12 @@ pylsp prefers autopep over yafp, despite its README 
stating the contrary."
           (funcall eglot-move-to-column-function 71)
           (should (looking-at "p")))))))
 
-(ert-deftest eglot-tests-lsp-abiding-column ()
+(ert-deftest eglot-test-lsp-abiding-column ()
   "Test basic `eglot-lsp-abiding-column' and 
`eglot-move-to-lsp-abiding-column'."
   (skip-unless (executable-find "clangd"))
   (eglot-tests--lsp-abiding-column-1))
 
-(ert-deftest eglot-ensure ()
+(ert-deftest eglot-test-ensure ()
   "Test basic `eglot-ensure' functionality."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -897,7 +897,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
            '(find-file "project/bar.c"))
         (should (eq server (eglot-current-server)))))))
 
-(ert-deftest slow-sync-connection-wait ()
+(ert-deftest eglot-test-slow-sync-connection-wait ()
   "Connect with `eglot-sync-connect' set to t."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -909,7 +909,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
              `((c-mode . ("sh" "-c" "sleep 1 && clangd")))))
         (should (eglot--tests-connect 3))))))
 
-(ert-deftest slow-sync-connection-intime ()
+(ert-deftest eglot-test-slow-sync-connection-intime ()
   "Connect synchronously with `eglot-sync-connect' set to 2."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -921,7 +921,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
              `((c-mode . ("sh" "-c" "sleep 1 && clangd")))))
         (should (eglot--tests-connect 3))))))
 
-(ert-deftest slow-async-connection ()
+(ert-deftest eglot-test-slow-async-connection ()
   "Connect asynchronously with `eglot-sync-connect' set to 2."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -937,7 +937,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
             (accept-process-output nil 0.2))
           (should (eglot-current-server)))))))
 
-(ert-deftest slow-sync-timeout ()
+(ert-deftest eglot-test-slow-sync-timeout ()
   "Failed attempt at connection synchronously."
   (skip-unless (executable-find "clangd"))
   (eglot--with-fixture
@@ -950,7 +950,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
              `((c-mode . ("sh" "-c" "sleep 2 && clangd")))))
         (should-error (apply #'eglot--connect (eglot--guess-contact)))))))
 
-(ert-deftest eglot-capabilities ()
+(ert-deftest eglot-test-capabilities ()
   "Unit test for `eglot--server-capable'."
   (cl-letf (((symbol-function 'eglot--capabilities)
              (lambda (_dummy)
@@ -976,7 +976,7 @@ pylsp prefers autopep over yafp, despite its README stating 
the contrary."
   (let ((eglot-strict-mode nil))
     (macroexpand-all (macroexp-progn body) macroexpand-all-environment)))
 
-(ert-deftest eglot-strict-interfaces ()
+(ert-deftest eglot-test-strict-interfaces ()
   (let ((eglot--lsp-interface-alist
          `((FooObject . ((:foo :bar) (:baz))))))
     (eglot--without-interface-warnings
@@ -1018,7 +1018,7 @@ pylsp prefers autopep over yafp, despite its README 
stating the contrary."
         (eglot--dbind ((FooObject) foo bar) `(:foo "foo" :baz bargh)
           (cons foo bar)))))))
 
-(ert-deftest eglot-dcase ()
+(ert-deftest eglot-test-dcase ()
   (eglot--without-interface-warnings
    (let ((eglot--lsp-interface-alist
           `((FooObject . ((:foo :bar) (:baz)))
@@ -1049,7 +1049,7 @@ pylsp prefers autopep over yafp, despite its README 
stating the contrary."
          (((CodeAction) _title _edit _command)
           (ert-fail "Shouldn't have destructured this object as a 
CodeAction"))))))))
 
-(ert-deftest eglot-dcase-issue-452 ()
+(ert-deftest eglot-test-dcase-issue-452 ()
   (let ((eglot--lsp-interface-alist
          `((FooObject . ((:foo :bar) (:baz)))
            (CodeAction (:title) (:kind :diagnostics :edit :command))
@@ -1100,7 +1100,7 @@ macro will assume it exists."
                (eglot--guess-contact ,i-sym)
              ,@body))))))
 
-(ert-deftest eglot-server-programs-simple-executable ()
+(ert-deftest eglot-test-server-programs-simple-executable ()
   (let ((eglot-server-programs '((foo-mode "some-executable")))
         (major-mode 'foo-mode))
     (eglot--guessing-contact (_ prompt-args guessed-class guessed-contact)
@@ -1108,7 +1108,7 @@ macro will assume it exists."
       (should (equal guessed-class 'eglot-lsp-server))
       (should (equal guessed-contact '("some-executable"))))))
 
-(ert-deftest eglot-server-programs-simple-missing-executable ()
+(ert-deftest eglot-test-server-programs-simple-missing-executable ()
   (let ((eglot-server-programs '((foo-mode "a-missing-executable.exe")))
         (major-mode 'foo-mode))
     (eglot--guessing-contact (interactive-p prompt-args guessed-class 
guessed-contact)
@@ -1117,7 +1117,7 @@ macro will assume it exists."
       (should (or prompt-args
                   (equal guessed-contact '("a-missing-executable.exe")))))))
 
-(ert-deftest eglot-server-programs-executable-multiple-major-modes ()
+(ert-deftest eglot-test-server-programs-executable-multiple-major-modes ()
   (let ((eglot-server-programs '(((bar-mode foo-mode) "some-executable")))
         (major-mode 'foo-mode))
     (eglot--guessing-contact (_ prompt-args guessed-class guessed-contact)
@@ -1125,7 +1125,7 @@ macro will assume it exists."
       (should (equal guessed-class 'eglot-lsp-server))
       (should (equal guessed-contact '("some-executable"))))))
 
-(ert-deftest eglot-server-programs-executable-with-arg ()
+(ert-deftest eglot-test-server-programs-executable-with-arg ()
   (let ((eglot-server-programs '((foo-mode "some-executable" "arg1")))
         (major-mode 'foo-mode))
     (eglot--guessing-contact (_ prompt-args guessed-class guessed-contact)
@@ -1133,7 +1133,7 @@ macro will assume it exists."
       (should (equal guessed-class 'eglot-lsp-server))
       (should (equal guessed-contact '("some-executable" "arg1"))))))
 
-(ert-deftest eglot-server-programs-executable-with-args-and-autoport ()
+(ert-deftest eglot-test-server-programs-executable-with-args-and-autoport ()
   (let ((eglot-server-programs '((foo-mode "some-executable" "arg1"
                                            :autoport "arg2")))
         (major-mode 'foo-mode))
@@ -1143,7 +1143,7 @@ macro will assume it exists."
       (should (equal guessed-contact '("some-executable" "arg1"
                                        :autoport "arg2"))))))
 
-(ert-deftest eglot-server-programs-host-and-port ()
+(ert-deftest eglot-test-server-programs-host-and-port ()
   (let ((eglot-server-programs '((foo-mode "somehost.example.com" 7777)))
         (major-mode 'foo-mode))
     (eglot--guessing-contact (_ prompt-args guessed-class guessed-contact)
@@ -1151,7 +1151,7 @@ macro will assume it exists."
       (should (equal guessed-class 'eglot-lsp-server))
       (should (equal guessed-contact '("somehost.example.com" 7777))))))
 
-(ert-deftest eglot-server-programs-host-and-port-and-tcp-args ()
+(ert-deftest eglot-test-server-programs-host-and-port-and-tcp-args ()
   (let ((eglot-server-programs '((foo-mode "somehost.example.com" 7777
                                            :type network)))
         (major-mode 'foo-mode))
@@ -1161,7 +1161,7 @@ macro will assume it exists."
       (should (equal guessed-contact '("somehost.example.com" 7777
                                        :type network))))))
 
-(ert-deftest eglot-server-programs-class-name-and-plist ()
+(ert-deftest eglot-test-server-programs-class-name-and-plist ()
   (let ((eglot-server-programs '((foo-mode bar-class :init-key init-val)))
         (major-mode 'foo-mode))
     (eglot--guessing-contact (_ prompt-args guessed-class guessed-contact)
@@ -1169,7 +1169,7 @@ macro will assume it exists."
       (should (equal guessed-class 'bar-class))
       (should (equal guessed-contact '(:init-key init-val))))))
 
-(ert-deftest eglot-server-programs-class-name-and-contact-spec ()
+(ert-deftest eglot-test-server-programs-class-name-and-contact-spec ()
   (let ((eglot-server-programs '((foo-mode bar-class "some-executable" "arg1"
                                            :autoport "arg2")))
         (major-mode 'foo-mode))
@@ -1179,7 +1179,7 @@ macro will assume it exists."
       (should (equal guessed-contact '("some-executable" "arg1"
                                        :autoport "arg2"))))))
 
-(ert-deftest eglot-server-programs-function ()
+(ert-deftest eglot-test-server-programs-function ()
   (let ((eglot-server-programs '((foo-mode . (lambda (&optional _)
                                                '("some-executable")))))
         (major-mode 'foo-mode))
@@ -1188,7 +1188,7 @@ macro will assume it exists."
       (should (equal guessed-class 'eglot-lsp-server))
       (should (equal guessed-contact '("some-executable"))))))
 
-(ert-deftest eglot-server-programs-guess-lang ()
+(ert-deftest eglot-test-server-programs-guess-lang ()
   (let ((major-mode 'foo-mode))
     (let ((eglot-server-programs '((foo-mode . ("prog-executable")))))
       (eglot--guessing-contact (_ nil _ _ guessed-lang)
@@ -1205,7 +1205,7 @@ macro will assume it exists."
 (defun eglot--glob-match (glob str)
   (funcall (eglot--glob-compile glob t t) str))
 
-(ert-deftest eglot--glob-test ()
+(ert-deftest eglot-test-glob-test ()
   (should (eglot--glob-match "foo/**/baz" "foo/bar/baz"))
   (should (eglot--glob-match "foo/**/baz" "foo/baz"))
   (should-not (eglot--glob-match "foo/**/baz" "foo/bar"))
@@ -1260,31 +1260,34 @@ macro will assume it exists."
 (defun eglot--call-with-tramp-test (fn)
   ;; Set up a Tramp method that’s just a shell so the remote host is
   ;; really just the local host.
-  (let ((tramp-remote-path (cons 'tramp-own-remote-path tramp-remote-path))
-        (tramp-histfile-override t)
-        (temporary-file-directory ert-remote-temporary-file-directory))
+  (let* ((tramp-remote-path (cons 'tramp-own-remote-path tramp-remote-path))
+         (tramp-histfile-override t)
+         (tramp-verbose 1)
+         (temporary-file-directory ert-remote-temporary-file-directory)
+         (default-directory temporary-file-directory))
     ;; We must check the remote LSP server.  So far, just "clangd" is used.
-    (let ((default-directory temporary-file-directory))
-      (unless (executable-find "clangd" 'remote)
-        (ert-skip "Remote clangd not found")))
+    (unless (executable-find "clangd" 'remote)
+      (ert-skip "Remote clangd not found"))
     (funcall fn)))
 
-(ert-deftest eglot--tramp-test ()
+(ert-deftest eglot-test-tramp-test ()
   "Ensure LSP servers can be used over TRAMP."
+  :tags '(:expensive-test)
   (eglot--call-with-tramp-test #'eglot-tests--auto-detect-running-server-1))
 
-(ert-deftest eglot--tramp-test-2 ()
+(ert-deftest eglot-test-tramp-test-2 ()
   "Ensure LSP servers can be used over TRAMP."
+  :tags '(:expensive-test)
   (eglot--call-with-tramp-test #'eglot-tests--lsp-abiding-column-1))
 
-(ert-deftest eglot--path-to-uri-windows ()
+(ert-deftest eglot-test-path-to-uri-windows ()
   (skip-unless (eq system-type 'windows-nt))
   (should (string-prefix-p "file:///"
                              (eglot--path-to-uri "c:/Users/Foo/bar.lisp")))
   (should (string-suffix-p "c%3A/Users/Foo/bar.lisp"
                            (eglot--path-to-uri "c:/Users/Foo/bar.lisp"))))
 
-(ert-deftest eglot--same-server-multi-mode ()
+(ert-deftest eglot-test-same-server-multi-mode ()
   "Check single LSP instance manages multiple modes in same project."
   (skip-unless (executable-find "clangd"))
   (let (server)
diff --git a/test/lisp/progmodes/ruby-mode-tests.el 
b/test/lisp/progmodes/ruby-mode-tests.el
index 33fded5a59..e90a9e4075 100644
--- a/test/lisp/progmodes/ruby-mode-tests.el
+++ b/test/lisp/progmodes/ruby-mode-tests.el
@@ -578,6 +578,33 @@ VALUES-PLIST is a list with alternating index and value 
elements."
     (search-backward "_")
     (should (string= (ruby-add-log-current-method) "M::C#foo"))))
 
+(ert-deftest ruby-add-log-current-method-after-inner-class-outside-methods ()
+  (ruby-with-temp-buffer (ruby-test-string
+                          "module M
+                          |  class C
+                          |    class D
+                          |    end
+                          |
+                          |_
+                          |  end
+                          |end")
+    (search-backward "_")
+    (delete-char 1)
+    (should (string= (ruby-add-log-current-method) "M::C"))))
+
+(ert-deftest 
ruby-add-log-current-method-after-inner-class-outside-methods-with-text ()
+  (ruby-with-temp-buffer (ruby-test-string
+                          "module M
+                          |  class C
+                          |    class D
+                          |    end
+                          |
+                          |    FOO = 5
+                          |  end
+                          |end")
+    (search-backward "FOO")
+    (should (string= (ruby-add-log-current-method) "M::C"))))
+
 (defvar ruby-block-test-example
   (ruby-test-string
    "class C



reply via email to

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