emacs-diffs
[Top][All Lists]
Advanced

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

master 142f5683c1 1/2: Merge from origin/emacs-29


From: Stefan Kangas
Subject: master 142f5683c1 1/2: Merge from origin/emacs-29
Date: Wed, 15 Feb 2023 09:13:02 -0500 (EST)

branch: master
commit 142f5683c1042a5344abd51b97fe8e0d0c8cc5f5
Merge: 571558e460 7678b7e46f
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Merge from origin/emacs-29
    
    7678b7e46f2 Eglot: check server capability before sending didSave (bu...
    a3a1ef7bd5e Fix rust-ts-mode type and module highlighting (Bug#61302)
    477aa047ee7 rust-ts-mode: Highlight variable reassignments
    5206a551c16 Improve backward compatibility of save-restriction
    accd88d5545 Don't indent template_string contents (bug#61503)
    d97a3839967 csharp-ts-mode: fontify compiler directives (bug#61512)
    420d2cae846 Update to Transient v0.3.7-209-gdab1dfa
    a3751b5d0c1 ; Raise an error if a VC package checkout is empty
    6a32ba8b69c ; Fix the installation of dependencies for VC packages
    4eac80fcc39 ; Prepare to update ERC version to 5.5
    4f099a72173 ; Remove failing erc-reuse-buffers test
    4bb27a5ca93 ; Minor docs copyedits
    13bcff3da5c Merge branch 'emacs-29' of git.savannah.gnu.org:/srv/git/...
    3d572ae0d50 Rename with/without-narrowing to with/without-restriction
    d806b0e33cf * lisp/repeat.el: Rename internal function and variable (...
    dd8b720ee74 ; * etc/NEWS: Fix typos.
    909bd04cf5f ; * lisp/calendar/lunar.el: Add comments. (bug#61460)
    10f2aedea9a ; * lisp/progmodes/c-ts-mode.el (c-ts-base-mode): delete ...
    865758130a1 ; * admin/git-bisect-start: Update failing commits
    b948d0d7efe Merge branch 'scratch/fix-locked-narrowing'
    dcb2379a463 Minor improvements to labeled narrowing
    cc30422825a Fix spurious display of eclipses in Calendar
    f2114e8d89f Fix indentation for closing bracket in c-ts-mode (bug#61398)
    f49caaa8925 ; * src/pdumper.c (dump_buffer): Update hash.
    fe2ea5ddd8d Update to Org 9.6.1-31-gaf1bb1
    8280d721d7c * src/.gdbinit (nextcons): Amend $.u.cdr to $.u.s.u.cdr (...
    eb2b0931cf1 Add lambda_expression to c-ts-common-indent-type-regexp-a...
    2da05876edb ; Use the right name when specifying VC packages
    d4fc7012978 Tolerate missing elpa-packages.eld files
    8bc1b7d0b27 Avoid warning about 'load-path' in non-interactive sessions
    3d17aee13d9 ; Fix installation of dependencies for VC packages
    86ca7df6a34 ; Mention Hunspell private-dictionary misfeature in doc s...
    7287b7b53a1 Support webkit2gtk-4.1
    048a2dabfc4 ; Fix typo
    8f3091defb3 ; Fix typo in buffer.h
    4da398d8b57 ; Fix typos
    074008ee2d2 ; Fix doc strings in lisp/image/ directory
    2d1e43436da ; Improve documentation of hash functions.
    900f7e07275 ; Remove extraneous local variables from image-dired-*.el...
    4297039bd13 Save and restore the absence of narrowing locks
    4f053afe8e7 bug-reference: prevent match-data clobbering (bug#61395)
    10af9fbcad1 ; * admin/notes/tree-sitter/starter-guide: Typos.
    9ac242ce93d ; Fix recent changes in treesit docs
    f5789aefc2e Rename LIMIT to DEPTH in tree-sitter functions (bug#61231)
    b39821fdcef ; Fix incorrect function name in treesit manual
    51901736965 Add 'live' property to treesit-node-check (bug#61235)
    56960a6558b Update to Transient v0.3.7-205-gb8ad0da
    68a6b364d1c Fix 'rmail-summary-output'
    67c6ec25590 lisp-mode: add docstring recognition for more common lisp...
    417a8ed8b05 ; Improve discoverability of empty file names handling
    e47cf6ca15a Update to Transient v0.3.7-204-gecff8c2
    b04cce02ff4 Fix Scala entry in Eglot's DB of LSP servers
    973c1d24c6a ruby-ts-mode: Also don't reindent 'identifier' when insid...
    a5651c0c403 ruby-ts-mode: Fix indentation inside empty if/unless/case...
    2956e54b1dd Add an extensive test for labeled (locked) narrowing
    79ce185ad13 Update the documentation about labeled (locked) narrowing
    a6cd4553d48 Rename two long line optimizations variables
    0d73e4aa261 Add specific symbols for narrowings
    d8438e2bb44 Add 'without-narrowing' macro
    97314447e60 Make 'narrowing-lock' and 'narrowing-unlock' internal
    a4aa32bdfff Fix 'save-restriction' for narrowing locks
    
    # Conflicts:
    #       etc/NEWS
---
 admin/git-bisect-start                            |  35 ++-
 doc/lispref/commands.texi                         |   6 +
 doc/lispref/display.texi                          |  10 +-
 doc/lispref/positions.texi                        |  88 +++++++-
 doc/misc/erc.texi                                 |  12 +-
 etc/ERC-NEWS                                      |  20 +-
 etc/NEWS.29                                       |  25 ++-
 lisp/calendar/lunar.el                            |  11 +-
 lisp/emacs-lisp/package-vc.el                     |  26 ++-
 lisp/erc/erc-backend.el                           |   6 +-
 lisp/erc/erc-button.el                            |   2 +-
 lisp/erc/erc-match.el                             |   2 +-
 lisp/erc/erc-sasl.el                              |  39 ++--
 lisp/erc/erc-services.el                          |   6 +-
 lisp/erc/erc.el                                   |  44 ++--
 lisp/progmodes/c-ts-mode.el                       |   3 +-
 lisp/progmodes/csharp-mode.el                     |  27 ++-
 lisp/progmodes/eglot.el                           |  15 +-
 lisp/progmodes/js.el                              |   1 +
 lisp/progmodes/rust-ts-mode.el                    | 107 +++++++--
 lisp/progmodes/typescript-ts-mode.el              |   1 +
 lisp/repeat.el                                    |  18 +-
 lisp/subr.el                                      |  53 +++--
 lisp/transient.el                                 | 250 ++++++++++------------
 src/buffer.c                                      |  47 ++--
 src/editfns.c                                     | 118 +++++-----
 src/keyboard.c                                    |  31 ++-
 src/xdisp.c                                       |  27 +--
 test/lisp/calendar/lunar-tests.el                 |  27 +--
 test/lisp/erc/erc-scenarios-base-reuse-buffers.el |  36 ----
 test/src/buffer-tests.el                          | 106 +++++++++
 31 files changed, 759 insertions(+), 440 deletions(-)

diff --git a/admin/git-bisect-start b/admin/git-bisect-start
index a439ee7fe1..65bfffc0ad 100755
--- a/admin/git-bisect-start
+++ b/admin/git-bisect-start
@@ -82,7 +82,7 @@ done
 # SKIP-BRANCH 58cc931e92ece70c3e64131ee12a799d65409100
 
 ## The list below is the exhaustive list of all commits between Dec 1
-## 2016 and Dec 31 2022 on which building Emacs with the default
+## 2016 and Jan 31 2023 on which building Emacs with the default
 ## options, on a GNU/Linux computer and with GCC, fails.  It is
 ## possible (though unlikely) that building Emacs with non-default
 ## options, with other compilers, or on other platforms, would succeed
@@ -1674,3 +1674,36 @@ $REAL_GIT bisect skip $(cat $0 | grep '^# SKIP-SINGLE ' 
| sed 's/^# SKIP-SINGLE
 # SKIP-SINGLE 8c13e8497821881b5197a1717e9e53b9991859d0
 # SKIP-SINGLE a6db8464e150c49724c71c5969b97f205ee2dec5
 # SKIP-SINGLE cfbfd393b450d4eb7ac0b7922b44208688553c9e
+# SKIP-SINGLE 382e018856a884a96a94ad551dbc1d7b0317b2e5
+# SKIP-SINGLE 8360e12f0ea3a3ccf0305adab3c7ea7e38af36c1
+# SKIP-SINGLE 56e8607dc99b90c43f82001cbf073e58a4698298
+# SKIP-SINGLE 956889d8ff1c79db45ca9b1711f406961e71c272
+# SKIP-SINGLE e2e937300f5a68ce1e2a349a583859a29394ac5f
+# SKIP-SINGLE 176830fe2bb1c80ee128e515f6223cddc8b0a2ca
+# SKIP-SINGLE 3f069bd796b0024033640051b5f74ba9834985f8
+# SKIP-SINGLE 435ba92ccc4c46914c261de57f71ac6d92c20178
+# SKIP-SINGLE ad6d8f7df180a9563d3f064f29c6366f114b8de0
+# SKIP-SINGLE 8d7ad65665833ae99b7e7119dae37afa438968a4
+# SKIP-SINGLE 10032f424ccf611783f5b92742e91e70595587c4
+# SKIP-SINGLE 4b1714571c8c6cf7ae2ee2602c66b7c903c45a4a
+# SKIP-SINGLE f27a330b99eebbe7f4690163358b4cacbd4e17a1
+# SKIP-SINGLE b73539832d9c4e802925cb8f261a13473da383b3
+# SKIP-SINGLE f50cb7d7c4b37cd8e4bb1ffa5d3f9273c7e19e10
+# SKIP-SINGLE 96015c9c8cc1720e8ee7cd9cea4de48126dd9122
+# SKIP-SINGLE 2bd0b9475384adfb4dd2cc794bbe1d8621546717
+# SKIP-SINGLE d9a2673ee95cf7172a622dc0229ddf72aec8e8c1
+# SKIP-SINGLE 0116e27b26cb4a98f2de8dca12d8e9d90d222992
+# SKIP-SINGLE 96601cd90ba1b8a650d0e41dad2a58cb9e270f1b
+# SKIP-SINGLE 99e40959f4036debe099f144ed2664a38e23563d
+# SKIP-SINGLE 207a0d9408cb97b9ae78469e2487e3075ade03f8
+# SKIP-SINGLE 64fee21d5f85db465198970a4d636cb17d500f26
+# SKIP-SINGLE 48bd17923a98f49a30bdce2f3a52e03fe45d63f0
+# SKIP-SINGLE 9058601308db4892fbc3e599b83fe4326fef9886
+# SKIP-SINGLE a3003492ace0571e5179500b42bbe44cb9763dbb
+# SKIP-SINGLE 197f994384cb37ae4ae7a771815bbe565d4ae242
+# SKIP-SINGLE 1970726e26a979243925fabe32686ba2ee757c6b
+# SKIP-SINGLE 1de6ebf2878485a0ef6b778df7d6a14d5b22a01c
+# SKIP-SINGLE 013ab7e2a83afa7fb577c356ae686439a2906f34
+# SKIP-SINGLE 1c3ca3bb649b7e812a84b4a559463462d4357080
+# SKIP-SINGLE 48ed4228a75907ae1bb7a2d4314ffb3277c75e3a
+# SKIP-SINGLE b9025c507a3a7dae4de19b18cafaa09b18183832
diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index dc78adc452..6fd9377e1d 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -99,6 +99,12 @@ is removed from the hook.
 emacs, The GNU Emacs Manual}) runs these two hooks just as a keyboard
 command does.
 
+  Note that, when the buffer text includes very long lines, these two
+hooks are called as if they were in a @code{with-restriction} form
+(@pxref{Narrowing}), with a
+@code{long-line-optimizations-in-command-hooks} label and with the
+buffer narrowed to a portion around point.
+
 @node Defining Commands
 @section Defining Commands
 @cindex defining commands
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index c5374e1481..a8311f5c9a 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -3501,11 +3501,11 @@ function finishes are the ones that really matter.
 For efficiency, we recommend writing these functions so that they
 usually assign faces to around 400 to 600 characters at each call.
 
-When the buffer text includes very long lines, these functions are
-called with the buffer narrowed to a relatively small region around
-@var{pos}, and with narrowing locked, so the functions cannot use
-@code{widen} to gain access to the rest of the buffer.
-@xref{Narrowing}.
+Note that, when the buffer text includes very long lines, these
+functions are called as if they were in a @code{with-restriction} form
+(@pxref{Narrowing}), with a
+@code{long-line-optimizations-in-fontification-functions} label and
+with the buffer narrowed to a portion around @var{pos}.
 @end defvar
 
 @node Basic Faces
diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi
index 838877b628..edc7c86533 100644
--- a/doc/lispref/positions.texi
+++ b/doc/lispref/positions.texi
@@ -1071,11 +1071,13 @@ positions.
 In an interactive call, @var{start} and @var{end} are set to the bounds
 of the current region (point and the mark, with the smallest first).
 
-Note that, in rare circumstances, Emacs may decide to leave, for
-performance reasons, the accessible portion of the buffer unchanged
-after a call to @code{narrow-to-region}.  This can happen when a Lisp
-program is called via low-level hooks, such as
-@code{jit-lock-functions}, @code{post-command-hook}, etc.
+However, when the narrowing has been set by @code{with-restriction} with
+a label argument (see below), @code{narrow-to-region} can be used only
+within the limits of that narrowing.  If @var{start} or @var{end} are
+outside these limits, the corresponding limit set by
+@code{with-restriction} is used instead.  To gain access to other
+portions of the buffer, use @code{without-restriction} with the same
+label.
 @end deffn
 
 @deffn Command narrow-to-page &optional move-count
@@ -1099,13 +1101,13 @@ It is equivalent to the following expression:
 @example
 (narrow-to-region 1 (1+ (buffer-size)))
 @end example
-@end deffn
 
-Note that, in rare circumstances, Emacs may decide to leave, for
-performance reasons, the accessible portion of the buffer unchanged
-after a call to @code{widen}.  This can happen when a Lisp program is
-called via low-level hooks, such as @code{jit-lock-functions},
-@code{post-command-hook}, etc.
+However, when a narrowing has been set by @code{with-restriction} with a
+label argument (see below), the limits set by @code{with-restriction}
+are restored, instead of canceling the narrowing.  To gain access to
+other portions of the buffer, use @code{without-restriction} with the
+same label.
+@end deffn
 
 @defun buffer-narrowed-p
 This function returns non-@code{nil} if the buffer is narrowed, and
@@ -1120,6 +1122,9 @@ in effect.  The state of narrowing is restored even in 
the event of an
 abnormal exit via @code{throw} or error (@pxref{Nonlocal Exits}).
 Therefore, this construct is a clean way to narrow a buffer temporarily.
 
+This construct also saves and restores the narrowings that were set by
+@code{with-restriction} with a label argument (see below).
+
 The value returned by @code{save-restriction} is that returned by the
 last form in @var{body}, or @code{nil} if no body forms were given.
 
@@ -1169,3 +1174,64 @@ This is the contents of foo@point{}
 @end group
 @end example
 @end defspec
+
+@defspec with-restriction start end [:label label] body
+This special form saves the current bounds of the accessible portion
+of the buffer, sets the accessible portion to start at @var{start} and
+end at @var{end}, evaluates the @var{body} forms, and restores the
+saved bounds.  In that case it is equivalent to
+
+@example
+(save-restriction
+  (narrow-to-region start end)
+  body)
+@end example
+
+@cindex labeled narrowing
+When the optional argument @var{label}, a symbol, is present, the
+narrowing is @dfn{labeled}.  A labeled narrowing differs from a
+non-labeled one in several ways:
+
+@itemize @bullet
+@item
+During the evaluation of the @var{body} form, @code{narrow-to-region}
+and @code{widen} can be used only within the @var{start} and @var{end}
+limits.
+
+@item
+To lift the restriction introduced by @code{with-restriction} and gain
+access to other portions of the buffer, use @code{without-restriction}
+with the same @var{label} argument.  (Another way to gain access to
+other portions of the buffer is to use an indirect buffer
+(@pxref{Indirect Buffers}).)
+
+@item
+Labeled narrowings can be nested.
+
+@item
+Labeled narrowings can only be used in Lisp programs: they are never
+visible on display, and never interfere with narrowings set by the
+user.
+@end itemize
+
+If you use @code{with-restriction} with the optional @var{label}
+argument, we recommend documenting the @var{label} in the doc strings
+of the functions which use it, so that other Lisp programs your code
+calls could lift the labeled narrowing if and when it needs.
+@end defspec
+
+@defspec without-restriction [:label label] body
+This special form saves the current bounds of the accessible portion
+of the buffer, widens the buffer, evaluates the @var{body} forms, and
+restores the saved bounds.  In that case it is equivalent to
+
+@example
+(save-restriction
+  (widen)
+  body)
+@end example
+
+When the optional argument @var{label} is present, the narrowing set
+by @code{with-restriction} with the same @var{label} argument is
+lifted.
+@end defspec
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi
index 8030dfa4bb..d5ec0f48e1 100644
--- a/doc/misc/erc.texi
+++ b/doc/misc/erc.texi
@@ -90,7 +90,8 @@ Advanced Usage
 @chapter Introduction
 
 ERC is a powerful, modular, and extensible IRC client for Emacs.
-It is distributed with Emacs since version 22.1.
+It has been included in Emacs since 2006 (@pxref{History}) and is also
+available on GNU ELPA.
 
 IRC is short for Internet Relay Chat.  When using IRC, you can
 communicate with other users on the same IRC network.  There are many
@@ -1463,6 +1464,7 @@ or if you have bugs to report, there are several places 
you can go.
 @item
 @uref{https://www.emacswiki.org/emacs/ERC} is the
 emacswiki.org page for ERC@.  Anyone may add tips, hints, etc.@: to it.
+If you do so, please help keep it up to date.
 
 @item
 You can ask questions about using ERC on the Emacs mailing list,
@@ -1471,7 +1473,13 @@ You can ask questions about using ERC on the Emacs 
mailing list,
 @item
 You can visit the IRC Libera.Chat channel @samp{#emacs}.  Many of the
 contributors are frequently around and willing to answer your
-questions.
+questions.  You can also try the relatively quiet @samp{#erc}, on the
+same network, for more involved questions.
+
+@item
+You can check GNU ELPA between Emacs releases to see if a newer
+version is available that might contain a fix for your issue:
+@uref{https://elpa.gnu.org/packages/erc.html}.
 
 @item
 To report a bug in ERC, use @kbd{M-x erc-bug}.
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 9d09172401..d5e256d9d3 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -47,18 +47,18 @@ From now on, only the most essential operations will be 
officially
 supported in its absence, and users will see a warning upon
 entry-point invocation when it's not present.
 
-** Tighter auth-source integration with bigger changes on the horizon.
+** Tighter auth-source integration.
 The days of hit-and-miss auth-source queries are hopefully behind us.
 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 section titled "auth-source" in
-the Integrations chapter of ERC's manual.
+nonstandard server passwords.  See the section entitled "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
-section in the manual for details.
+A new module, 'erc-sasl', now ships with ERC.  See Info node "(erc)
+SASL" in the manual for details.
 
 ** Username argument for entry-point commands.
 Commands 'erc' and 'erc-tls' now accept a ':user' keyword argument,
@@ -88,8 +88,8 @@ off by default, new users are encouraged to enable them.
 Clicking on 'irc://' and 'ircs://' links elsewhere in Emacs now does
 the right thing most of the time.  However, for security reasons,
 users are now prompted to confirm connection parameters prior to lift
-off.  See the new '(erc) Integrations' section in the Info manual to
-override this.
+off.  See the new '(erc) Integrations' section in the Info manual for
+details.
 
 ** Miscellaneous behavioral changes impacting the user experience.
 A bug has been fixed that saw prompts being mangled, doubled, or
@@ -117,6 +117,12 @@ file called erc-common.el.  This was done to further 
lessen the
 various complications arising from the mutual dependency between 'erc'
 and 'erc-backend'.
 
+ERC now relies on the Compat library from GNU ELPA to supply forward
+compatibility shims for users running older versions of Emacs.  The
+required Compat version resides atop ERC's main library file, in the
+'Package-Requires' header.  Third-party ERC modules will benefit
+automatically from this adoption.
+
 The function 'erc-network' always returns non-nil in server and target
 buffers belonging to a successfully established IRC connection, even
 after that connection has been closed.  (Also see the note in the
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 2d15e39036..35063678f5 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -570,7 +570,7 @@ documented from day one; it just didn't behave according to
 documentation.  It turns out some Lisp programs were using this
 coding-system on the wrong assumption that the "auto" part means some
 automagic handling of the end-of-line (EOL) format conversion; those
-program will now start to fail, because BOM signature in UTF-8 encoded
+programs will now start to fail, because BOM signature in UTF-8 encoded
 text is rarely expected.  That is the reason we mention this bugfix
 here.
 
@@ -615,8 +615,19 @@ with 'C-x x t', or try disabling all known slow minor 
modes with
 and the major mode with 'M-x so-long-mode', or visit the file with
 'M-x find-file-literally' instead of the usual 'C-x C-f'.
 
-Note that the display optimizations in these cases may cause the
-buffer to be occasionally mis-fontified.
+In buffers in which these display optimizations are in effect, the
+'fontification-functions', 'pre-command-hook' and 'post-command-hook'
+hooks are executed on a narrowed portion of the buffer, whose size is
+controlled by the variables 'long-line-optimizations-region-size' and
+'long-line-optimizations-bol-search-limit', as if they were in a
+'with-restriction' form.  This may, in particular, cause occasional
+mis-fontifications in these buffers.  Modes which are affected by
+these optimizations and by the fact that the buffer is narrowed,
+should adapt and either modify their algorithm so as not to expect the
+entire buffer to be accessible, or, if accessing outside of the
+narrowed region doesn't hurt performance, use the
+'without-restriction' form to temporarily lift the restriction and
+access portions of the buffer outside of the narrowed region.
 
 The new function 'long-line-optimizations-p' returns non-nil when
 these optimizations are in effect in the current buffer.
@@ -3814,6 +3825,14 @@ TIMEOUT is the idle time after which to deactivate the 
transient map.
 The default timeout value can be defined by the new variable
 'set-transient-map-timeout'.
 
++++
+** New forms 'with-restriction' and 'without-restriction'.
+These forms can be used as enhanced alternatives to the
+'save-restriction' form combined with, respectively,
+'narrow-to-region' and 'widen'.  They also accept an optional label
+argument, with which labeled narrowings can be created and lifted.
+See the "(elisp) Narrowing" node for details.
+
 ** Connection Local Variables
 
 +++
diff --git a/lisp/calendar/lunar.el b/lisp/calendar/lunar.el
index 0db811417a..8ced414410 100644
--- a/lisp/calendar/lunar.el
+++ b/lisp/calendar/lunar.el
@@ -85,6 +85,9 @@ remainder mod 4 gives the phase: 0 new moon, 1 first quarter, 
2 full moon,
                            (* 0.0107306 time time)
                            (* 0.00001236 time time time))
                         360.0))
+         ;; moon-lat is the argument of latitude, which is the angle
+         ;; of the moon measured from the ascending node of its orbit
+         ;; (i.e. argument of perigee + true anomaly).
          (moon-lat (mod
                     (+ 21.2964
                        (* 390.67050646 index)
@@ -153,15 +156,19 @@ remainder mod 4 gives the phase: 0 new moon, 1 first 
quarter, 2 full moon,
 ;; Line 7000 Peter Duffett-Smith Cambridge University Press 1990
 (defun eclipse-check (moon-lat phase)
   (let* ((moon-lat (* (/ float-pi 180) moon-lat))
+         ;; For positions near the ascending or descending node,
+         ;; calculate the absolute angular distance from that node.
          (moon-lat (abs (- moon-lat (* (floor (/ moon-lat float-pi))
                                        float-pi))))
-         (moon-lat (if (> moon-lat 0.37)
+         (moon-lat (if (> moon-lat 0.37) ; FIXME (* 0.5 float-pi)
                        (- float-pi moon-lat)
                      moon-lat))
          (phase-name (cond ((= phase 0) "Solar")
                            ((= phase 2) "Lunar")
                            (t ""))))
-    (cond ((< moon-lat 2.42600766e-1)
+    (cond ((string= phase-name "")
+          "")
+         ((< moon-lat 2.42600766e-1)
           (concat "** " phase-name " Eclipse **"))
          ((< moon-lat 0.37)
           (concat "** " phase-name " Eclipse possible **"))
diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el
index bf49f274bf..bad59aa6c0 100644
--- a/lisp/emacs-lisp/package-vc.el
+++ b/lisp/emacs-lisp/package-vc.el
@@ -435,24 +435,29 @@ version of that package."
                         (push pkg missing))))))
                 (version-order (a b)
                   "Predicate to sort packages in order."
-                  (version-list-< (cadr b) (cadr a)))
+                  (version-list-<
+                   (package-desc-version b)
+                   (package-desc-version a)))
                 (duplicate-p (a b)
                   "Are A and B the same package?"
-                  (eq (car a) (car b)))
+                  (equal a (car b)))
                 (depends-on-p (target package)
                   "Does PACKAGE depend on TARGET?"
                   (or (eq target package)
                       (let* ((pac package-archive-contents)
                              (desc (cadr (assoc package pac))))
-                        (seq-some
-                         (apply-partially #'depends-on-p target)
-                         (package-desc-reqs desc)))))
+                        (and desc (seq-some
+                                   (apply-partially #'depends-on-p target)
+                                   (package-desc-reqs desc))))))
                 (dependent-order (a b)
-                  (or (not (depends-on-p (car b) (car a)))
-                      (depends-on-p (car a) (car b)))))
+                  (let ((desc-a (package-desc-name a))
+                        (desc-b (package-desc-name b)))
+                    (or (not desc-a) (not desc-b)
+                        (not (depends-on-p desc-b desc-a))
+                        (depends-on-p desc-a desc-b)))))
       (mapc #'search requirements)
       (cl-callf sort to-install #'version-order)
-      (cl-callf seq-uniq to-install #'duplicate-p)
+      (cl-callf seq-uniq to-install)
       (cl-callf sort to-install #'dependent-order))
     (mapc #'package-install-from-archive to-install)
     missing))
@@ -606,7 +611,7 @@ checkout.  This overrides the `:branch' attribute in 
PKG-SPEC."
   (pcase-let* (((map :lisp-dir) pkg-spec)
                (name (package-desc-name pkg-desc))
                (dirname (package-desc-full-name pkg-desc))
-               (pkg-dir (expand-file-name dirname package-user-dir)))
+               (pkg-dir (file-name-as-directory (expand-file-name dirname 
package-user-dir))))
     (when (string-empty-p name)
       (user-error "Empty package name"))
     (setf (package-desc-dir pkg-desc) pkg-dir)
@@ -615,6 +620,9 @@ checkout.  This overrides the `:branch' attribute in 
PKG-SPEC."
           (package--delete-directory pkg-dir)
         (error "There already exists a checkout for %s" name)))
     (package-vc--clone pkg-desc pkg-spec pkg-dir rev)
+    (when (directory-empty-p pkg-dir)
+      (delete-directory pkg-dir)
+      (error "Empty checkout for %s" name))
 
     ;; When nothing is specified about a `lisp-dir', then should
     ;; heuristically check if there is a sub-directory with lisp
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 1da701aebc..cf0b734bd2 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -425,7 +425,7 @@ Called with a server buffer as its only argument.  
Potential uses
 include exponential backoff and probing for connectivity prior to
 dialing.  Use `erc-schedule-reconnect' to instead try again later
 and optionally alter the attempts tally."
-  :package-version '(ERC . "5.4.1") ; FIXME on next release
+  :package-version '(ERC . "5.5")
   :type '(choice (function-item erc-server-delayed-reconnect)
                  function))
 
@@ -1167,7 +1167,7 @@ Note that future bundled modules providing IRCv3 
functionality
 will not be compatible with the legacy format.  User code should
 eventually transition to expecting this \"5.5+ variant\" and set
 this option to nil."
-  :package-version '(ERC . "5.4.1") ; FIXME increment on next release
+  :package-version '(ERC . "5.5")
   :type '(choice (const nil)
                  (const legacy)
                  (const overridable)))
@@ -1201,7 +1201,7 @@ instead, leave them as a single string."
                 (get 'erc-parse-tags 'erc-v3-warned-p))
       (put 'erc-parse-tags 'erc-v3-warned-p t)
       (display-warning
-       'ERC
+       'erc
        (concat
         "Legacy ERC tags behavior is currently in effect, but other modules,"
         " including those bundled with ERC, may override this in future"
diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el
index 1be47c3e66..c28dddefa0 100644
--- a/lisp/erc/erc-button.el
+++ b/lisp/erc/erc-button.el
@@ -176,7 +176,7 @@ PAR is a number of a regexp grouping whose text will be 
passed to
   CALLBACK.  There can be several PAR arguments.  If REGEXP is
   `nicknames', these are ignored, and CALLBACK will be called with
   the nickname matched as the argument."
-  :version "29.1"
+  :package-version '(ERC . "5.5")
   :type '(repeat
           (list :tag "Button"
                 (choice :tag "Matches"
diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el
index 499bcaf572..52ee5c855f 100644
--- a/lisp/erc/erc-match.el
+++ b/lisp/erc/erc-match.el
@@ -244,7 +244,7 @@ server and other miscellaneous functions."
   "Whether to `regexp-quote' when adding to a match list interactively.
 When the value is a boolean, the opposite behavior will be made
 available via universal argument."
-  :package-version '(ERC . "5.4.1") ; FIXME increment on next release
+  :package-version '(ERC . "5.5")
   :type '(choice (const ask)
                  (const t)
                  (const nil)))
diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el
index 97c7c54a51..ed91f41225 100644
--- a/lisp/erc/erc-sasl.el
+++ b/lisp/erc/erc-sasl.el
@@ -24,13 +24,13 @@
 ;;
 ;; https://lists.gnu.org/archive/html/erc-discuss/2012-02/msg00001.html
 ;;
-;; See options and Info manual for usage.
+;; See M-x customize-group RET erc-sasl RET and (info "(erc) SASL")
+;; for usage.
 ;;
 ;; TODO:
 ;;
-;; - Find a way to obfuscate the password in memory (via something
-;;   like `auth-source--obfuscate'); it's currently visible in
-;;   backtraces.
+;; - Obfuscate non-auth-source passwords in memory.  They're currently
+;;   visible in backtraces.
 ;;
 ;; - Implement a proxy mechanism that chooses the strongest available
 ;;   mechanism for you.  Requires CAP 3.2 (see bug#49860).
@@ -52,7 +52,7 @@
 (defgroup erc-sasl nil
   "SASL for ERC."
   :group 'erc
-  :package-version '(ERC . "5.4.1")) ; FIXME increment on next release
+  :package-version '(ERC . "5.5"))
 
 (defcustom erc-sasl-mechanism 'plain
   "SASL mechanism to connect with.
@@ -76,19 +76,19 @@ commands, `erc' and `erc-tls'."
 
 (defcustom erc-sasl-password :password
   "Optional account password to send when authenticating.
-When `erc-sasl-auth-source-function' is a function, ERC will
-attempt an auth-source query and prompt for input if it fails.
-Otherwise, when the value is a nonempty string, ERC will use it
-unconditionally for most mechanisms.  Likewise with `:password',
-except ERC will instead use the \"session password\" on file, if
-any, which often originates from the entry-point commands `erc'
-or `erc-tls'.  As with auth-source, ERC will prompt for input as
-a fallback.
-
-Note that, with `:password', ERC will forgo sending a traditional
+When `erc-sasl-auth-source-function' is a function, ERC attempts
+an auth-source query and prompts for input if it fails.
+Otherwise, when the value of this option is a nonempty string,
+ERC uses it unconditionally for most mechanisms.  Likewise with a
+value of `:password', except ERC instead uses the \"session
+password\" on file, if any, which often originates from the
+entry-point commands `erc' or `erc-tls'.  As with auth-source,
+ERC prompts for input as a fallback.
+
+Note that, with `:password', ERC forgoes sending a traditional
 server password via the IRC \"PASS\" command.  Also, when
-`erc-sasl-mechanism' is set to `ecdsa-nist256p-challenge', this
-option should hold the file name of the key."
+`erc-sasl-mechanism' is set to `ecdsa-nist256p-challenge', ERC
+expects this option to hold the file name of the key."
   :type '(choice (const nil) (const :password) string symbol))
 
 (defcustom erc-sasl-auth-source-function nil
@@ -100,9 +100,8 @@ though ERC itself only specifies `:user' paired with a
 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) auth-source' for details on ERC's auth-source
-integration."
+nil, in which case, ERC prompts for input.  See Info 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)
                  (const nil)
diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el
index 1c2fc2fcdc..2e6959cc3f 100644
--- a/lisp/erc/erc-services.el
+++ b/lisp/erc/erc-services.el
@@ -180,9 +180,9 @@ 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) auth-source' for details."
-  :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
-  :type '(choice (const erc-auth-source-search)
+prompting.  See Info node `(erc) auth-source' for details."
+  :package-version '(ERC . "5.5")
+  :type '(choice (function-item erc-auth-source-search)
                  (const nil)
                  function))
 
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index ff1820cfaf..d35907a167 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -217,8 +217,8 @@ 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) auth-source'.")
+functionality should consider auth-source instead.  See Info
+node `(auth) Top' and Info node `(erc) auth-source'.")
 
 (make-obsolete-variable 'erc-password "use auth-source instead" "29.1")
 
@@ -250,19 +250,19 @@ node `(auth) Top' and info node `(erc) auth-source'.")
 Issue an error when the number of input lines submitted for
 sending exceeds this value.  The value t means disallow more
 than 1 line of input."
-  :package-version '(ERC . "5.4.1") ; FIXME match to next release
+  :package-version '(ERC . "5.5")
   :group 'erc
   :type '(choice integer boolean))
 
 (defcustom erc-ask-about-multiline-input nil
   "Whether to ask to ignore `erc-inhibit-multiline-input' when tripped."
-  :package-version '(ERC . "5.4.1") ; FIXME match to next release
+  :package-version '(ERC . "5.5")
   :group 'erc
   :type 'boolean)
 
 (defcustom erc-prompt-hidden ">"
   "Text to show in lieu of the prompt when hidden."
-  :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
+  :package-version '(ERC . "5.5")
   :group 'erc-display
   :type 'string)
 
@@ -272,7 +272,7 @@ To unhide, type something in the input area.  Once 
revealed, a
 prompt remains unhidden until the next disconnection.  Channel
 prompts are unhidden upon rejoining.  See
 `erc-unhide-query-prompt' for behavior concerning query prompts."
-  :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
+  :package-version '(ERC . "5.5")
   :group 'erc-display
   :type '(choice (const :tag "Always hide prompt" t)
                  (set (const server)
@@ -284,7 +284,7 @@ prompts are unhidden upon rejoining.  See
 Otherwise, prompts in a connection's query buffers remain hidden
 until the user types in the input area or a new message arrives
 from the target."
-  :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release
+  :package-version '(ERC . "5.5")
   :group 'erc-display
   ;; Extensions may one day offer a way to discover whether a target
   ;; is online.  When that happens, this can be expanded accordingly.
@@ -1479,7 +1479,7 @@ The available choices are:
   `bury'            - bury it in a new buffer,
   `buffer'          - in place of the current buffer,
   any other value  - in place of the current buffer."
-  :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
+  :package-version '(ERC . "5.5")
   :group 'erc-buffers
   :type '(choice (const :tag "Split window and select" window)
                  (const :tag "Split window, don't select" window-noselect)
@@ -1495,7 +1495,7 @@ This only affects automatic reconnections and is ignored 
when
 issuing a /reconnect command or reinvoking `erc-tls' with the
 same args (assuming success, of course).  See `erc-join-buffer'
 for a description of possible values."
-  :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
+  :package-version '(ERC . "5.5")
   :group 'erc-buffers
   :type '(choice (const :tag "Use value of `erc-join-buffer'" nil)
                  (const :tag "Split window and select" window)
@@ -2319,7 +2319,7 @@ Example usage:
 
 When present, ID should be a symbol or a string to use for naming
 the server buffer and identifying the connection unequivocally.
-See info node `(erc) Network Identifier' for details.  Like USER
+See Info node `(erc) Network Identifier' for details.  Like USER
 and CLIENT-CERTIFICATE, this parameter cannot be specified
 interactively."
   (interactive (let ((erc-default-port erc-default-port-tls))
@@ -3258,10 +3258,10 @@ 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) auth-source' for details."
-  :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
+nil.  See Info node `(erc) auth-source' for details."
+  :package-version '(ERC . "5.5")
   :group 'erc
-  :type '(choice (const erc-auth-source-search)
+  :type '(choice (function-item erc-auth-source-search)
                  (const nil)
                  function))
 
@@ -3272,11 +3272,11 @@ Called with a subset of keyword arguments known to
 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
+auth-source for channel keys.  For more information, see Info
 node `(erc) auth-source'."
-  :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA
+  :package-version '(ERC . "5.5")
   :group 'erc
-  :type '(choice (const erc-auth-source-search)
+  :type '(choice (function-item erc-auth-source-search)
                  (const nil)
                  function))
 
@@ -6837,8 +6837,8 @@ shortened server name instead."
 
 ;; erc-goodies is required at end of this file.
 
-;; FIXME when 29.1 is cut and `format-spec' is added to ELPA Compat,
-;; remove the function invocations from the spec form below.
+;; TODO when ERC drops Emacs 28, replace the expressions in the format
+;; spec below with functions.
 (defun erc-update-mode-line-buffer (buffer)
   "Update the mode line in a single ERC buffer BUFFER."
   (with-current-buffer buffer
@@ -7213,7 +7213,7 @@ See also `format-spec'."
 (defcustom erc-kill-server-hook '(erc-kill-server
                                   erc-networks-shrink-ids-and-buffer-names)
   "Invoked whenever a live server buffer is killed via `kill-buffer'."
-  :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
+  :package-version '(ERC . "5.5")
   :group 'erc-hooks
   :type 'hook)
 
@@ -7222,7 +7222,7 @@ See also `format-spec'."
     erc-networks-shrink-ids-and-buffer-names
     erc-networks-rename-surviving-target-buffer)
   "Invoked whenever a channel-buffer is killed via `kill-buffer'."
-  :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
+  :package-version '(ERC . "5.5")
   :group 'erc-hooks
   :type 'hook)
 
@@ -7232,7 +7232,7 @@ See also `format-spec'."
   "Hook run whenever a query buffer is killed.
 
 See also `kill-buffer'."
-  :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA
+  :package-version '(ERC . "5.5")
   :group 'erc-hooks
   :type 'hook)
 
@@ -7311,7 +7311,7 @@ Called with a string meant to represent a URL scheme, like
 \"ircs\", followed by any number of keyword arguments recognized
 by `erc' and `erc-tls'."
   :group 'erc
-  :package-version '(ERC . "5.4.1") ; FIXME increment on release
+  :package-version '(ERC . "5.5")
   :type '(choice (const nil) function))
 
 (defun erc--url-default-connect-function (scheme &rest plist)
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 6db28459c3..40b258bddf 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -803,8 +803,7 @@ the semicolon.  This function skips the semicolon."
               `((block . ,(rx (or "compound_statement"
                                   "field_declaration_list"
                                   "enumerator_list"
-                                  "initializer_list"
-                                  "field_declaration_list")))
+                                  "initializer_list")))
                 (if . "if_statement")
                 (else . ("if_statement" . "alternative"))
                 (do . "do_statement")
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el
index 063cfffe1d..07ec25a477 100644
--- a/lisp/progmodes/csharp-mode.el
+++ b/lisp/progmodes/csharp-mode.el
@@ -862,7 +862,30 @@ compilation and evaluation time conflicts."
    :language 'c-sharp
    :feature 'escape-sequence
    :override t
-   '((escape_sequence) @font-lock-escape-face)))
+   '((escape_sequence) @font-lock-escape-face)
+
+   :language 'c-sharp
+   :feature 'directives
+   :override t
+   '((if_directive
+      "if" @font-lock-preprocessor-face
+      (identifier) @font-lock-variable-name-face)
+     (elif_directive
+      "elif" @font-lock-preprocessor-face
+      (identifier) @font-lock-variable-name-face)
+     (else_directive) @font-lock-preprocessor-face
+     (endif_directive) @font-lock-preprocessor-face
+     (define_directive
+      "define" @font-lock-preprocessor-face
+      (identifier) @font-lock-variable-name-face)
+     (nullable_directive) @font-lock-preprocessor-face
+     (pragma_directive) @font-lock-preprocessor-face
+     (region_directive) @font-lock-preprocessor-face
+     (endregion_directive) @font-lock-preprocessor-face
+     (region_directive
+      (preproc_message) @font-lock-variable-name-face)
+     (endregion_directive
+      (preproc_message) @font-lock-variable-name-face))))
 
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode))
@@ -930,7 +953,7 @@ Key bindings:
   (setq-local treesit-font-lock-settings csharp-ts-mode--font-lock-settings)
   (setq-local treesit-font-lock-feature-list
               '(( comment definition)
-                ( keyword string type)
+                ( keyword string type directives)
                 ( constant escape-sequence expression literal property)
                 ( function bracket delimiter error)))
 
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 8ecdefd490..267a7a5ea2 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -2496,13 +2496,14 @@ When called interactively, use the currently active 
server"
 (defun eglot--signal-textDocument/didSave ()
   "Send textDocument/didSave to server."
   (eglot--signal-textDocument/didChange)
-  (jsonrpc-notify
-   (eglot--current-server-or-lose)
-   :textDocument/didSave
-   (list
-    ;; TODO: Handle TextDocumentSaveRegistrationOptions to control this.
-    :text (buffer-substring-no-properties (point-min) (point-max))
-    :textDocument (eglot--TextDocumentIdentifier))))
+  (when (eglot--server-capable :textDocumentSync :save)
+    (jsonrpc-notify
+     (eglot--current-server-or-lose)
+     :textDocument/didSave
+     (list
+      ;; TODO: Handle TextDocumentSaveRegistrationOptions to control this.
+      :text (buffer-substring-no-properties (point-min) (point-max))
+      :textDocument (eglot--TextDocumentIdentifier)))))
 
 (defun eglot-flymake-backend (report-fn &rest _more)
   "A Flymake backend for Eglot.
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 6ae325c065..90813c8de3 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3442,6 +3442,7 @@ This function is intended for use in 
`after-change-functions'."
        ((parent-is "arguments") parent-bol js-indent-level)
        ((parent-is "array") parent-bol js-indent-level)
        ((parent-is "formal_parameters") parent-bol js-indent-level)
+       ((parent-is "template_string") no-indent) ; Don't indent the string 
contents.
        ((parent-is "template_substitution") parent-bol js-indent-level)
        ((parent-is "object_pattern") parent-bol js-indent-level)
        ((parent-is "object") parent-bol js-indent-level)
diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el
index 5c71a8ad46..f510b7bb6c 100644
--- a/lisp/progmodes/rust-ts-mode.el
+++ b/lisp/progmodes/rust-ts-mode.el
@@ -124,8 +124,8 @@
   (treesit-font-lock-rules
    :language 'rust
    :feature 'attribute
-   '((attribute_item) @font-lock-constant-face
-     (inner_attribute_item) @font-lock-constant-face)
+   '((attribute_item) @font-lock-preprocessor-face
+     (inner_attribute_item) @font-lock-preprocessor-face)
 
    :language 'rust
    :feature 'bracket
@@ -147,12 +147,6 @@
    :feature 'comment
    '(([(block_comment) (line_comment)]) @font-lock-comment-face)
 
-   :language 'rust
-   :feature 'constant
-   `((boolean_literal) @font-lock-constant-face
-     ((identifier) @font-lock-constant-face
-      (:match "^[A-Z][A-Z\\d_]*$" @font-lock-constant-face)))
-
    :language 'rust
    :feature 'delimiter
    '((["," "." ";" ":" "::"]) @font-lock-delimiter-face)
@@ -163,11 +157,16 @@
      (macro_definition "macro_rules!" @font-lock-constant-face)
      (macro_definition (identifier) @font-lock-preprocessor-face)
      (field_declaration name: (field_identifier) @font-lock-property-face)
-     (parameter) @rust-ts-mode--fontify-pattern
-     (let_declaration) @rust-ts-mode--fontify-pattern
-     (for_expression) @rust-ts-mode--fontify-pattern
-     (let_condition) @rust-ts-mode--fontify-pattern
-     (match_arm) @rust-ts-mode--fontify-pattern)
+     (parameter pattern: (_) @rust-ts-mode--fontify-pattern)
+     (let_declaration pattern: (_) @rust-ts-mode--fontify-pattern)
+     (for_expression pattern: (_) @rust-ts-mode--fontify-pattern)
+     (let_condition pattern: (_) @rust-ts-mode--fontify-pattern)
+     (match_arm pattern: (_) @rust-ts-mode--fontify-pattern))
+
+   :language 'rust
+   :feature 'assignment
+   '((assignment_expression left: (_) @rust-ts-mode--fontify-pattern)
+     (compound_assignment_expr left: (_) @rust-ts-mode--fontify-pattern))
 
    :language 'rust
    :feature 'function
@@ -206,7 +205,54 @@
 
    :language 'rust
    :feature 'type
-   `((enum_variant name: (identifier) @font-lock-type-face)
+   `((scoped_use_list path: (identifier) @font-lock-constant-face)
+     (scoped_use_list path: (scoped_identifier
+                             name: (identifier) @font-lock-constant-face))
+
+     ((use_as_clause alias: (identifier) @font-lock-type-face)
+      (:match "^[A-Z]" @font-lock-type-face))
+     ((use_as_clause path: (identifier) @font-lock-type-face)
+      (:match "^[A-Z]" @font-lock-type-face))
+     ((use_as_clause path:
+                     (scoped_identifier path: (_)
+                                        name: (identifier) 
@font-lock-type-face))
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_as_clause path: (scoped_identifier name: (identifier) @default))
+
+     ((use_declaration
+       argument: (scoped_identifier
+                  path: (_) @font-lock-constant-face
+                  name: (identifier) @font-lock-type-face))
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_declaration
+      argument: (scoped_identifier
+                 name: (identifier) @default))
+
+     (use_declaration
+      argument: (scoped_identifier
+                 path: (scoped_identifier
+                        path: (_) @font-lock-constant-face
+                        name: (identifier) @font-lock-constant-face)
+                 name: (identifier) @default))
+
+     (use_declaration
+      argument: (scoped_use_list
+                 path: (scoped_identifier
+                        path: (_) @font-lock-constant-face
+                        name: (identifier) @font-lock-constant-face)))
+
+     ((use_list (identifier) @font-lock-type-face)
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_list (identifier) @default)
+     ((use_list (scoped_identifier path: (_)
+                                   name: (identifier) @font-lock-type-face))
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_list (scoped_identifier path: (_)
+                                  name: (identifier) @default))
+     (use_wildcard (scoped_identifier
+                    name: (identifier) @font-lock-constant-face))
+
+     (enum_variant name: (identifier) @font-lock-type-face)
      (match_arm
       pattern: (match_pattern (_ type: (identifier) @font-lock-type-face)))
      (match_arm
@@ -220,25 +266,40 @@
       (:match "^[A-Z]" @font-lock-type-face))
      ((scoped_identifier path: (identifier) @font-lock-type-face)
       (:match "^[A-Z]" @font-lock-type-face))
-     ((scoped_identifier
-        (scoped_identifier
-         path: (identifier) @font-lock-type-face))
-      (:match "^[A-Z]" @font-lock-type-face))
      ((scoped_identifier
        path: [(identifier) @font-lock-type-face
               (scoped_identifier
                name: (identifier) @font-lock-type-face)])
       (:match "^[A-Z]" @font-lock-type-face))
-     (scoped_type_identifier path: (identifier) @font-lock-type-face)
+     ((scoped_identifier path: (identifier) @font-lock-type-face)
+      (:match
+       
"^\\(u8\\|u16\\|u32\\|u64\\|u128\\|usize\\|i8\\|i16\\|i32\\|i64\\|i128\\|isize\\|char\\|str\\)$"
+       @font-lock-type-face))
+     (scoped_identifier path: (_) @font-lock-constant-face
+                        name: (identifier) @font-lock-type-face)
+     (scoped_identifier path: (scoped_identifier
+                               name: (identifier) @font-lock-constant-face))
+     (scoped_type_identifier path: (_) @font-lock-constant-face)
+     (scoped_type_identifier
+      path: (scoped_identifier
+             path: (_) @font-lock-constant-face
+             name: (identifier) @font-lock-constant-face))
      (type_identifier) @font-lock-type-face
-     (use_as_clause alias: (identifier) @font-lock-type-face)
-     (use_list (identifier) @font-lock-type-face))
+     ;; Ensure function calls aren't highlighted as types.
+     (call_expression function: (scoped_identifier name: (identifier) 
@default)))
 
    :language 'rust
    :feature 'property
    '((field_identifier) @font-lock-property-face
      (shorthand_field_initializer (identifier) @font-lock-property-face))
 
+   ;; Must be under type, otherwise some imports can be highlighted as 
consants.
+   :language 'rust
+   :feature 'constant
+   `((boolean_literal) @font-lock-constant-face
+     ((identifier) @font-lock-constant-face
+      (:match "^[A-Z][A-Z\\d_]*$" @font-lock-constant-face)))
+
    :language 'rust
    :feature 'variable
    '((identifier) @font-lock-variable-name-face
@@ -261,7 +322,7 @@
    (treesit-available-p)
    `(lambda (node override start end &rest _)
       (let ((captures (treesit-query-capture
-                       (treesit-node-child-by-field-name node "pattern")
+                       node
                        ,(treesit-query-compile 'rust '((identifier) @id
                                                        
(shorthand_field_identifier) @id)))))
         (pcase-dolist (`(_name . ,id) captures)
@@ -342,7 +403,7 @@ delimiters < and >'s."
     (setq-local treesit-font-lock-feature-list
                 '(( comment definition)
                   ( keyword string)
-                  ( attribute builtin constant escape-sequence
+                  ( assignment attribute builtin constant escape-sequence
                     number type)
                   ( bracket delimiter error function operator property 
variable)))
 
diff --git a/lisp/progmodes/typescript-ts-mode.el 
b/lisp/progmodes/typescript-ts-mode.el
index 3437ea4350..afc8ff47db 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -86,6 +86,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
      ((parent-is "arguments") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "array") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "formal_parameters") parent-bol 
typescript-ts-mode-indent-offset)
+     ((parent-is "template_string") no-indent) ; Don't indent the string 
contents.
      ((parent-is "template_substitution") parent-bol 
typescript-ts-mode-indent-offset)
      ((parent-is "object_pattern") parent-bol typescript-ts-mode-indent-offset)
      ((parent-is "object") parent-bol typescript-ts-mode-indent-offset)
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 37d4aaec98..2fcac4d2ce 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -359,8 +359,8 @@ This property can override the value of this variable."
   :group 'repeat
   :version "28.1")
 
-(defvar repeat-exit-function nil
-  "Function that exits the repeating sequence.")
+(defvar repeat--transient-exitfun nil
+  "Function returned by `set-transient-map'.")
 
 (defvar repeat-exit-timer nil
   "Timer activated after the last key typed in the repeating key sequence.")
@@ -517,9 +517,9 @@ See `describe-repeat-maps' for a list of all repeatable 
commands."
                       'ignore))
 
         (setq repeat-in-progress t)
-        (repeat--exit)
+        (repeat--clear-prev)
         (let ((exitfun (set-transient-map map)))
-          (setq repeat-exit-function exitfun)
+          (setq repeat--transient-exitfun exitfun)
 
           (let* ((prop (repeat--command-property 'repeat-exit-timeout))
                  (timeout (unless (eq prop 'no) (or prop 
repeat-exit-timeout))))
@@ -538,17 +538,17 @@ See `describe-repeat-maps' for a list of all repeatable 
commands."
 This function can be used to force exit of repetition while it's active."
   (interactive)
   (setq repeat-in-progress nil)
-  (repeat--exit)
+  (repeat--clear-prev)
   (funcall repeat-echo-function nil))
 
-(defun repeat--exit ()
+(defun repeat--clear-prev ()
   "Internal function to clean up previously set exit function and timer."
   (when repeat-exit-timer
     (cancel-timer repeat-exit-timer)
     (setq repeat-exit-timer nil))
-  (when repeat-exit-function
-    (funcall repeat-exit-function)
-    (setq repeat-exit-function nil)))
+  (when repeat--transient-exitfun
+    (funcall repeat--transient-exitfun)
+    (setq repeat--transient-exitfun nil)))
 
 (defun repeat-echo-message-string (keymap)
   "Return a string with the list of repeating keys in KEYMAP."
diff --git a/lisp/subr.el b/lisp/subr.el
index a5fc566cc7..a1397fa678 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -3963,30 +3963,51 @@ See also `locate-user-emacs-file'.")
   "Return non-nil if the current buffer is narrowed."
   (/= (- (point-max) (point-min)) (buffer-size)))
 
-(defmacro with-narrowing (start end &rest rest)
+(defmacro with-restriction (start end &rest rest)
   "Execute BODY with restrictions set to START and END.
 
 The current restrictions, if any, are restored upon return.
 
-With the optional :locked TAG argument, inside BODY,
-`narrow-to-region' and `widen' can be used only within the START
-and END limits, unless the restrictions are unlocked by calling
-`narrowing-unlock' with TAG.  See `narrowing-lock' for a more
-detailed description.
+When the optional :label LABEL argument is present, in which
+LABEL is a symbol, inside BODY, `narrow-to-region' and `widen'
+can be used only within the START and END limits.  To gain access
+to other portions of the buffer, use `without-restriction' with the
+same LABEL argument.
 
-\(fn START END [:locked TAG] BODY)"
-  (if (eq (car rest) :locked)
-      `(internal--with-narrowing ,start ,end (lambda () ,@(cddr rest))
+\(fn START END [:label LABEL] BODY)"
+  (if (eq (car rest) :label)
+      `(internal--with-restriction ,start ,end (lambda () ,@(cddr rest))
                                  ,(cadr rest))
-    `(internal--with-narrowing ,start ,end (lambda () ,@rest))))
+    `(internal--with-restriction ,start ,end (lambda () ,@rest))))
 
-(defun internal--with-narrowing (start end body &optional tag)
-  "Helper function for `with-narrowing', which see."
+(defun internal--with-restriction (start end body &optional label)
+  "Helper function for `with-restriction', which see."
   (save-restriction
-    (progn
-      (narrow-to-region start end)
-      (if tag (narrowing-lock tag))
-      (funcall body))))
+    (narrow-to-region start end)
+    (if label (internal--lock-narrowing label))
+    (funcall body)))
+
+(defmacro without-restriction (&rest rest)
+  "Execute BODY without restrictions.
+
+The current restrictions, if any, are restored upon return.
+
+When the optional :label LABEL argument is present, the
+restrictions set by `with-restriction' with the same LABEL argument
+are lifted.
+
+\(fn [:label LABEL] BODY)"
+  (if (eq (car rest) :label)
+      `(internal--without-restriction (lambda () ,@(cddr rest))
+                                    ,(cadr rest))
+    `(internal--without-restriction (lambda () ,@rest))))
+
+(defun internal--without-restriction (body &optional label)
+  "Helper function for `without-restriction', which see."
+  (save-restriction
+    (if label (internal--unlock-narrowing label))
+    (widen)
+    (funcall body)))
 
 (defun find-tag-default-bounds ()
   "Determine the boundaries of the default tag, based on text at point.
diff --git a/lisp/transient.el b/lisp/transient.el
index 73ea6fa940..c0ecd2950d 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -965,7 +965,7 @@ keyword.
 
 Only use this alias to define an infix command that actually
 sets an infix argument.  To define a infix command that, for
-example, sets a variable use `transient-define-infix' instead.
+example, sets a variable, use `transient-define-infix' instead.
 
 \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)")
 
@@ -1509,18 +1509,8 @@ then just return it.  Otherwise return the symbol whose
 
 ;;; Keymaps
 
-(defvar transient-base-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "ESC ESC ESC") #'transient-quit-all)
-    (define-key map (kbd "C-g")   #'transient-quit-one)
-    (define-key map (kbd "C-q")   #'transient-quit-all)
-    (define-key map (kbd "C-z")   #'transient-suspend)
-    (define-key map (kbd "C-v")   #'transient-scroll-up)
-    (define-key map (kbd "C-M-v") #'transient-scroll-down)
-    (define-key map [next]        #'transient-scroll-up)
-    (define-key map [prior]       #'transient-scroll-down)
-    map)
-  "Parent of other keymaps used by Transient.
+(defvar-keymap transient-base-map
+  :doc "Parent of other keymaps used by Transient.
 
 This is the parent keymap of all the keymaps that are used in
 all transients: `transient-map' (which in turn is the parent
@@ -1533,40 +1523,42 @@ the latter isn't a proper transient prefix command, it 
can be
 edited using the same functions as used for transients.
 
 If you add a new command here, then you must also add a binding
-to `transient-predicate-map'.")
-
-(defvar transient-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map transient-base-map)
-    (define-key map (kbd "C-u")   #'universal-argument)
-    (define-key map (kbd "C--")   #'negative-argument)
-    (define-key map (kbd "C-t")   #'transient-show)
-    (define-key map (kbd "?")     #'transient-help)
-    (define-key map (kbd "C-h")   #'transient-help)
-    ;; Also bound to "C-x p" and "C-x n" in transient-common-commands.
-    (define-key map (kbd "C-M-p") #'transient-history-prev)
-    (define-key map (kbd "C-M-n") #'transient-history-next)
-    map)
-  "Top-level keymap used by all transients.
+to `transient-predicate-map'."
+  "ESC ESC ESC" #'transient-quit-all
+  "C-g"     #'transient-quit-one
+  "C-q"     #'transient-quit-all
+  "C-z"     #'transient-suspend
+  "C-v"     #'transient-scroll-up
+  "C-M-v"   #'transient-scroll-down
+  "<next>"  #'transient-scroll-up
+  "<prior>" #'transient-scroll-down)
+
+(defvar-keymap transient-map
+  :doc "Top-level keymap used by all transients.
 
 If you add a new command here, then you must also add a binding
-to `transient-predicate-map'.  Also see `transient-base-map'.")
-
-(defvar transient-edit-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map transient-base-map)
-    (define-key map (kbd "?")     #'transient-help)
-    (define-key map (kbd "C-h")   #'transient-help)
-    (define-key map (kbd "C-x l") #'transient-set-level)
-    map)
-  "Keymap that is active while a transient in is in \"edit mode\".")
-
-(defvar transient-sticky-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map transient-base-map)
-    (define-key map (kbd "C-g") #'transient-quit-seq)
-    map)
-  "Keymap that is active while an incomplete key sequence is active.")
+to `transient-predicate-map'.  Also see `transient-base-map'."
+  :parent transient-base-map
+  "C-u"   #'universal-argument
+  "C--"   #'negative-argument
+  "C-t"   #'transient-show
+  "?"     #'transient-help
+  "C-h"   #'transient-help
+  ;; Also bound to "C-x p" and "C-x n" in transient-common-commands.
+  "C-M-p" #'transient-history-prev
+  "C-M-n" #'transient-history-next)
+
+(defvar-keymap transient-edit-map
+  :doc "Keymap that is active while a transient in is in \"edit mode\"."
+  :parent transient-base-map
+  "?"     #'transient-help
+  "C-h"   #'transient-help
+  "C-x l" #'transient-set-level)
+
+(defvar-keymap transient-sticky-map
+  :doc "Keymap that is active while an incomplete key sequence is active."
+  :parent transient-base-map
+  "C-g" #'transient-quit-seq)
 
 (defvar transient--common-command-prefixes '(?\C-x))
 
@@ -1606,70 +1598,28 @@ to `transient-predicate-map'.  Also see 
`transient-base-map'.")
                          "Show common permanently")))
                (list "C-x l" "Show/hide suffixes" #'transient-set-level))))))))
 
-(defvar transient-popup-navigation-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "<down-mouse-1>") #'transient-noop)
-    (define-key map (kbd "<up>")   #'transient-backward-button)
-    (define-key map (kbd "<down>") #'transient-forward-button)
-    (define-key map (kbd "C-r")    #'transient-isearch-backward)
-    (define-key map (kbd "C-s")    #'transient-isearch-forward)
-    (define-key map (kbd "M-RET")  #'transient-push-button)
-    map)
-  "One of the keymaps used when popup navigation is enabled.
-See `transient-enable-popup-navigation'.")
-
-(defvar transient-button-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "<mouse-1>") #'transient-push-button)
-    (define-key map (kbd "<mouse-2>") #'transient-push-button)
-    map)
-  "One of the keymaps used when popup navigation is enabled.
-See `transient-enable-popup-navigation'.")
-
-(defvar transient-predicate-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [transient-suspend]       #'transient--do-suspend)
-    (define-key map [transient-help]          #'transient--do-stay)
-    (define-key map [transient-set-level]     #'transient--do-stay)
-    (define-key map [transient-history-prev]  #'transient--do-stay)
-    (define-key map [transient-history-next]  #'transient--do-stay)
-    (define-key map [universal-argument]      #'transient--do-stay)
-    (define-key map [negative-argument]       #'transient--do-minus)
-    (define-key map [digit-argument]          #'transient--do-stay)
-    (define-key map [top-level]               #'transient--do-quit-all)
-    (define-key map [transient-quit-all]      #'transient--do-quit-all)
-    (define-key map [transient-quit-one]      #'transient--do-quit-one)
-    (define-key map [transient-quit-seq]      #'transient--do-stay)
-    (define-key map [transient-show]          #'transient--do-stay)
-    (define-key map [transient-update]        #'transient--do-stay)
-    (define-key map [transient-toggle-common] #'transient--do-stay)
-    (define-key map [transient-set]           #'transient--do-call)
-    (define-key map [transient-save]          #'transient--do-call)
-    (define-key map [transient-reset]         #'transient--do-call)
-    (define-key map [describe-key-briefly]    #'transient--do-stay)
-    (define-key map [describe-key]            #'transient--do-stay)
-    (define-key map [transient-scroll-up]     #'transient--do-stay)
-    (define-key map [transient-scroll-down]   #'transient--do-stay)
-    (define-key map [mwheel-scroll]           #'transient--do-stay)
-    (define-key map [scroll-bar-toolkit-scroll]   #'transient--do-stay)
-    (define-key map [transient-noop]              #'transient--do-noop)
-    (define-key map [transient-mouse-push-button] #'transient--do-move)
-    (define-key map [transient-push-button]       #'transient--do-push-button)
-    (define-key map [transient-backward-button]   #'transient--do-move)
-    (define-key map [transient-forward-button]    #'transient--do-move)
-    (define-key map [transient-isearch-backward]  #'transient--do-move)
-    (define-key map [transient-isearch-forward]   #'transient--do-move)
-    ;; If a valid but incomplete prefix sequence is followed by
-    ;; an unbound key, then Emacs calls the `undefined' command
-    ;; but does not set `this-command', `this-original-command'
-    ;; or `real-this-command' accordingly.  Instead they are nil.
-    (define-key map [nil] #'transient--do-warn)
-    map)
-  "Base keymap used to map common commands to their transient behavior.
+(defvar-keymap transient-popup-navigation-map
+  :doc "One of the keymaps used when popup navigation is enabled.
+See `transient-enable-popup-navigation'."
+  "<down-mouse-1>" #'transient-noop
+  "<up>"   #'transient-backward-button
+  "<down>" #'transient-forward-button
+  "C-r"    #'transient-isearch-backward
+  "C-s"    #'transient-isearch-forward
+  "M-RET"  #'transient-push-button)
+
+(defvar-keymap transient-button-map
+  :doc "One of the keymaps used when popup navigation is enabled.
+See `transient-enable-popup-navigation'."
+  "<mouse-1>" #'transient-push-button
+  "<mouse-2>" #'transient-push-button)
+
+(defvar-keymap transient-predicate-map
+  :doc "Base keymap used to map common commands to their transient behavior.
 
 The \"transient behavior\" of a command controls, among other
 things, whether invoking the command causes the transient to be
-exited or not and whether infix arguments are exported before
+exited or not, and whether infix arguments are exported before
 doing so.
 
 Each \"key\" is a command that is common to all transients and
@@ -1681,7 +1631,43 @@ transient behavior of the respective command.
 
 For transient commands that are bound in individual transients,
 the transient behavior is specified using the `:transient' slot
-of the corresponding object.")
+of the corresponding object."
+  "<transient-suspend>"           #'transient--do-suspend
+  "<transient-help>"              #'transient--do-stay
+  "<transient-set-level>"         #'transient--do-stay
+  "<transient-history-prev>"      #'transient--do-stay
+  "<transient-history-next>"      #'transient--do-stay
+  "<universal-argument>"          #'transient--do-stay
+  "<negative-argument>"           #'transient--do-minus
+  "<digit-argument>"              #'transient--do-stay
+  "<top-level>"                   #'transient--do-quit-all
+  "<transient-quit-all>"          #'transient--do-quit-all
+  "<transient-quit-one>"          #'transient--do-quit-one
+  "<transient-quit-seq>"          #'transient--do-stay
+  "<transient-show>"              #'transient--do-stay
+  "<transient-update>"            #'transient--do-stay
+  "<transient-toggle-common>"     #'transient--do-stay
+  "<transient-set>"               #'transient--do-call
+  "<transient-save>"              #'transient--do-call
+  "<transient-reset>"             #'transient--do-call
+  "<describe-key-briefly>"        #'transient--do-stay
+  "<describe-key>"                #'transient--do-stay
+  "<transient-scroll-up>"         #'transient--do-stay
+  "<transient-scroll-down>"       #'transient--do-stay
+  "<mwheel-scroll>"               #'transient--do-stay
+  "<scroll-bar-toolkit-scroll>"   #'transient--do-stay
+  "<transient-noop>"              #'transient--do-noop
+  "<transient-mouse-push-button>" #'transient--do-move
+  "<transient-push-button>"       #'transient--do-push-button
+  "<transient-backward-button>"   #'transient--do-move
+  "<transient-forward-button>"    #'transient--do-move
+  "<transient-isearch-backward>"  #'transient--do-move
+  "<transient-isearch-forward>"   #'transient--do-move
+  ;; If a valid but incomplete prefix sequence is followed by
+  ;; an unbound key, then Emacs calls the `undefined' command
+  ;; but does not set `this-command', `this-original-command'
+  ;; or `real-this-command' accordingly.  Instead they are nil.
+  "<nil>"                         #'transient--do-warn)
 
 (defvar transient--transient-map nil)
 (defvar transient--predicate-map nil)
@@ -1725,9 +1711,9 @@ of the corresponding object.")
                      (string-trim key)
                      cmd conflict)))
           (define-key map kbd cmd))))
-    (when-let ((b (lookup-key map "-"))) (define-key map [kp-subtract] b))
-    (when-let ((b (lookup-key map "="))) (define-key map [kp-equal] b))
-    (when-let ((b (lookup-key map "+"))) (define-key map [kp-add] b))
+    (when-let ((b (keymap-lookup map "-"))) (keymap-set map "<kp-subtract>" b))
+    (when-let ((b (keymap-lookup map "="))) (keymap-set map "<kp-equal>" b))
+    (when-let ((b (keymap-lookup map "+"))) (keymap-set map "<kp-add>" b))
     (when transient-enable-popup-navigation
       ;; `transient--make-redisplay-map' maps only over bindings that are
       ;; directly in the base keymap, so that cannot be a composed keymap.
@@ -1742,7 +1728,7 @@ of the corresponding object.")
     (set-keymap-parent map transient-predicate-map)
     (when (memq (oref transient--prefix transient-non-suffix)
                 '(nil transient--do-warn transient--do-noop))
-      (define-key map [handle-switch-frame] #'transient--do-suspend))
+      (keymap-set map "<handle-switch-frame>" #'transient--do-suspend))
     (dolist (obj transient--suffixes)
       (let* ((cmd (oref obj command))
              (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t))
@@ -1810,8 +1796,8 @@ of the corresponding object.")
 
 This function is called by transient prefix commands to setup the
 transient.  In that case NAME is mandatory, LAYOUT and EDIT must
-be nil and PARAMS may be (but usually is not) used to set e.g. the
-\"scope\" of the transient (see `transient-define-prefix').
+be nil and PARAMS may be (but usually is not) used to set, e.g.,
+the \"scope\" of the transient (see `transient-define-prefix').
 
 This function is also called internally in which case LAYOUT and
 EDIT may be non-nil."
@@ -2587,10 +2573,10 @@ transient is active."
 
 (defvar transient-resume-mode)
 
-(defun transient-help ()
-  "Show help for the active transient or one of its suffixes."
-  (interactive)
-  (if (called-interactively-p 'any)
+(defun transient-help (&optional interactive)
+  "Show help for the active transient or one of its suffixes.\n\n(fn)"
+  (interactive (list t))
+  (if interactive
       (setq transient--helpp t)
     (with-demoted-errors "transient-help: %S"
       (when (lookup-key transient--transient-map
@@ -3831,17 +3817,15 @@ Suffixes on levels %s and %s are unavailable.\n"
                (propertize (format ">=%s" (1+ level))
                            'face 'transient-disabled-suffix))))))
 
-(defvar transient-resume-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [remap Man-quit]    #'transient-resume)
-    (define-key map [remap Info-exit]   #'transient-resume)
-    (define-key map [remap quit-window] #'transient-resume)
-    map)
-  "Keymap for `transient-resume-mode'.
+(defvar-keymap transient-resume-mode-map
+  :doc "Keymap for `transient-resume-mode'.
 
 This keymap remaps every command that would usually just quit the
 documentation buffer to `transient-resume', which additionally
-resumes the suspended transient.")
+resumes the suspended transient."
+  "<remap> <Man-quit>"    #'transient-resume
+  "<remap> <Info-exit>"   #'transient-resume
+  "<remap> <quit-window>" #'transient-resume)
 
 (define-minor-mode transient-resume-mode
   "Auxiliary minor-mode used to resume a transient after viewing help.")
@@ -3901,13 +3885,11 @@ See `forward-button' for information about N."
 ;;; Compatibility
 ;;;; Popup Isearch
 
-(defvar transient--isearch-mode-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map isearch-mode-map)
-    (define-key map [remap isearch-exit]   #'transient-isearch-exit)
-    (define-key map [remap isearch-cancel] #'transient-isearch-cancel)
-    (define-key map [remap isearch-abort]  #'transient-isearch-abort)
-    map))
+(defvar-keymap transient--isearch-mode-map
+  :parent isearch-mode-map
+  "<remap> <isearch-exit>"   #'transient-isearch-exit
+  "<remap> <isearch-cancel>" #'transient-isearch-cancel
+  "<remap> <isearch-abort>"  #'transient-isearch-abort)
 
 (defun transient-isearch-backward (&optional regexp-p)
   "Do incremental search backward.
@@ -4034,8 +4016,8 @@ that does that.  Of course \"Q\" may already be bound to 
something
 else, so that function binds \"M-q\" to that command instead.
 Of course \"M-q\" may already be bound to something else, but
 we stop there."
-  (define-key transient-base-map   "q" #'transient-quit-one)
-  (define-key transient-sticky-map "q" #'transient-quit-seq)
+  (keymap-set transient-base-map   "q" #'transient-quit-one)
+  (keymap-set transient-sticky-map "q" #'transient-quit-seq)
   (setq transient-substitute-key-function
         #'transient-rebind-quit-commands))
 
diff --git a/src/buffer.c b/src/buffer.c
index 38648519ba..df1f520666 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5916,40 +5916,41 @@ If nil, these display shortcuts will always remain 
disabled.
 There is no reason to change that value except for debugging purposes.  */);
   XSETFASTINT (Vlong_line_threshold, 50000);
 
-  DEFVAR_INT ("long-line-locked-narrowing-region-size",
-             long_line_locked_narrowing_region_size,
-             doc: /* Region size for locked narrowing in buffers with long 
lines.
+  DEFVAR_INT ("long-line-optimizations-region-size",
+             long_line_optimizations_region_size,
+             doc: /* Region size for narrowing in buffers with long lines.
 
-This variable has effect only in buffers which contain one or more
-lines whose length is above `long-line-threshold', which see.  For
-performance reasons, in such buffers, low-level hooks such as
-`fontification-functions' or `post-command-hook' are executed on a
-narrowed buffer, with a narrowing locked with `narrowing-lock'.  This
-variable specifies the size of the narrowed region around point.
+This variable has effect only in buffers in which
+`long-line-optimizations-p' is non-nil.  For performance reasons, in
+such buffers, the `fontification-functions', `pre-command-hook' and
+`post-command-hook' hooks are executed on a narrowed buffer around
+point, as if they were called in a `with-restriction' form with a label.
+This variable specifies the size of the narrowed region around point.
 
 To disable that narrowing, set this variable to 0.
 
-See also `long-line-locked-narrowing-bol-search-limit'.
+See also `long-line-optimizations-bol-search-limit'.
 
 There is no reason to change that value except for debugging purposes.  */);
-  long_line_locked_narrowing_region_size = 500000;
+  long_line_optimizations_region_size = 500000;
 
-  DEFVAR_INT ("long-line-locked-narrowing-bol-search-limit",
-             long_line_locked_narrowing_bol_search_limit,
+  DEFVAR_INT ("long-line-optimizations-bol-search-limit",
+             long_line_optimizations_bol_search_limit,
              doc: /* Limit for beginning of line search in buffers with long 
lines.
 
-This variable has effect only in buffers which contain one or more
-lines whose length is above `long-line-threshold', which see.  For
-performance reasons, in such buffers, low-level hooks such as
-`fontification-functions' or `post-command-hook' are executed on a
-narrowed buffer, with a narrowing locked with `narrowing-lock'.  The
-variable `long-line-locked-narrowing-region-size' specifies the size
-of the narrowed region around point.  This variable, which should be a
-small integer, specifies the number of characters by which that region
-can be extended backwards to make it start at the beginning of a line.
+This variable has effect only in buffers in which
+`long-line-optimizations-p' is non-nil.  For performance reasons, in
+such buffers, the `fontification-functions', `pre-command-hook' and
+`post-command-hook' hooks are executed on a narrowed buffer around
+point, as if they were called in a `with-restriction' form with a label.
+The variable `long-line-optimizations-region-size' specifies the
+size of the narrowed region around point.  This variable, which should
+be a small integer, specifies the number of characters by which that
+region can be extended backwards to make it start at the beginning of
+a line.
 
 There is no reason to change that value except for debugging purposes.  */);
-  long_line_locked_narrowing_bol_search_limit = 128;
+  long_line_optimizations_bol_search_limit = 128;
 
   DEFVAR_INT ("large-hscroll-threshold", large_hscroll_threshold,
     doc: /* Horizontal scroll of truncated lines above which to use redisplay 
shortcuts.
diff --git a/src/editfns.c b/src/editfns.c
index 78d2c73ecb..f83c5c7259 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2659,7 +2659,11 @@ DEFUN ("delete-and-extract-region", 
Fdelete_and_extract_region,
    the (uninterned) Qoutermost_narrowing tag and records the narrowing
    bounds that were set by the user and that are visible on display.
    This alist is used internally by narrow-to-region, widen,
-   narrowing-lock, narrowing-unlock and save-restriction.  */
+   internal--lock-narrowing, internal--unlock-narrowing and
+   save-restriction.  For efficiency reasons, an alist is used instead
+   of a buffer-local variable: otherwise reset_outermost_narrowings,
+   which is called during each redisplay cycle, would have to loop
+   through all live buffers.  */
 static Lisp_Object narrowing_locks;
 
 /* Add BUF with its LOCKS in the narrowing_locks alist.  */
@@ -2763,7 +2767,10 @@ unwind_reset_outermost_narrowing (Lisp_Object buf)
    In particular, this function is called when redisplay starts, so
    that if a Lisp function executed during redisplay calls (redisplay)
    while a locked narrowing is in effect, the locked narrowing will
-   not be visible on display.  */
+   not be visible on display.
+   See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#140 and
+   https://debbugs.gnu.org/cgi/bugreport.cgi?bug=57207#254 for example
+   recipes that demonstrate why this is necessary.  */
 void
 reset_outermost_narrowings (void)
 {
@@ -2792,27 +2799,25 @@ narrowing_locks_save (void)
 {
   Lisp_Object buf = Fcurrent_buffer ();
   Lisp_Object locks = assq_no_quit (buf, narrowing_locks);
-  if (NILP (locks))
-    return Qnil;
-  locks = XCAR (XCDR (locks));
+  if (!NILP (locks))
+    locks = XCAR (XCDR (locks));
   return Fcons (buf, Fcopy_sequence (locks));
 }
 
 static void
 narrowing_locks_restore (Lisp_Object buf_and_saved_locks)
 {
-  if (NILP (buf_and_saved_locks))
-    return;
   Lisp_Object buf = XCAR (buf_and_saved_locks);
   Lisp_Object saved_locks = XCDR (buf_and_saved_locks);
   narrowing_locks_remove (buf);
-  narrowing_locks_add (buf, saved_locks);
+  if (!NILP (saved_locks))
+    narrowing_locks_add (buf, saved_locks);
 }
 
 static void
 unwind_narrow_to_region_locked (Lisp_Object tag)
 {
-  Fnarrowing_unlock (tag);
+  Finternal__unlock_narrowing (tag);
   Fwiden ();
 }
 
@@ -2821,7 +2826,7 @@ void
 narrow_to_region_locked (Lisp_Object begv, Lisp_Object zv, Lisp_Object tag)
 {
   Fnarrow_to_region (begv, zv);
-  Fnarrowing_lock (tag);
+  Finternal__lock_narrowing (tag);
   record_unwind_protect (restore_point_unwind, Fpoint_marker ());
   record_unwind_protect (unwind_narrow_to_region_locked, tag);
 }
@@ -2829,10 +2834,12 @@ narrow_to_region_locked (Lisp_Object begv, Lisp_Object 
zv, Lisp_Object tag)
 DEFUN ("widen", Fwiden, Swiden, 0, 0, "",
        doc: /* Remove restrictions (narrowing) from current buffer.
 
-This allows the buffer's full text to be seen and edited, unless
-restrictions have been locked with `narrowing-lock', which see, in
-which case the narrowing that was current when `narrowing-lock' was
-called is restored.  */)
+This allows the buffer's full text to be seen and edited.
+
+However, when restrictions have been set by `with-restriction' with a
+label, `widen' restores the narrowing limits set by `with-restriction'.
+To gain access to other portions of the buffer, use
+`without-restriction' with the same label.  */)
   (void)
 {
   Fset (Qoutermost_narrowing, Qnil);
@@ -2879,11 +2886,12 @@ When calling from Lisp, pass two arguments START and 
END:
 positions (integers or markers) bounding the text that should
 remain visible.
 
-When restrictions have been locked with `narrowing-lock', which see,
-`narrow-to-region' can be used only within the limits of the
-restrictions that were current when `narrowing-lock' was called.  If
-the START or END arguments are outside these limits, the corresponding
-limit of the locked restriction is used instead of the argument.  */)
+However, when restrictions have been set by `with-restriction' with a
+label, `narrow-to-region' can be used only within the limits of these
+restrictions.  If the START or END arguments are outside these limits,
+the corresponding limit set by `with-restriction' is used instead of the
+argument.  To gain access to other portions of the buffer, use
+`without-restriction' with the same label.  */)
   (Lisp_Object start, Lisp_Object end)
 {
   EMACS_INT s = fix_position (start), e = fix_position (end);
@@ -2912,7 +2920,7 @@ limit of the locked restriction is used instead of the 
argument.  */)
 
   /* Record the accessible range of the buffer when narrow-to-region
      is called, that is, before applying the narrowing.  It is used
-     only by narrowing-lock.  */
+     only by internal--lock-narrowing.  */
   Fset (Qoutermost_narrowing, list3 (Qoutermost_narrowing,
                                     Fpoint_min_marker (),
                                     Fpoint_max_marker ()));
@@ -2932,31 +2940,18 @@ limit of the locked restriction is used instead of the 
argument.  */)
   return Qnil;
 }
 
-DEFUN ("narrowing-lock", Fnarrowing_lock, Snarrowing_lock, 1, 1, 0,
-       doc: /* Lock the current narrowing with TAG.
+DEFUN ("internal--lock-narrowing", Finternal__lock_narrowing,
+       Sinternal__lock_narrowing, 1, 1, 0,
+       doc: /* Lock the current narrowing with LABEL.
 
-When restrictions are locked, `narrow-to-region' and `widen' can be
-used only within the limits of the restrictions that were current when
-`narrowing-lock' was called, unless the lock is removed by calling
-`narrowing-unlock' with TAG.
-
-Locking restrictions should be used sparingly, after carefully
-considering the potential adverse effects on the code that will be
-executed within locked restrictions.  It is typically meant to be used
-around portions of code that would become too slow, and make Emacs
-unresponsive, if they were executed in a large buffer.  For example,
-restrictions are locked by Emacs around low-level hooks such as
-`fontification-functions' or `post-command-hook'.
-
-Locked restrictions are never visible on display, and can therefore
-not be used as a stronger variant of normal restrictions.  */)
+This is an internal function used by `with-restriction'.  */)
   (Lisp_Object tag)
 {
   Lisp_Object buf = Fcurrent_buffer ();
   Lisp_Object outermost_narrowing
     = buffer_local_value (Qoutermost_narrowing, buf);
-  /* If narrowing-lock is called without being preceded by
-     narrow-to-region, do nothing.  */
+  /* If internal--lock-narrowing is ever called without being preceded
+     by narrow-to-region, do nothing.  */
   if (NILP (outermost_narrowing))
     return Qnil;
   if (NILP (narrowing_lock_peek_tag (buf)))
@@ -2967,16 +2962,11 @@ not be used as a stronger variant of normal 
restrictions.  */)
   return Qnil;
 }
 
-DEFUN ("narrowing-unlock", Fnarrowing_unlock, Snarrowing_unlock, 1, 1, 0,
-       doc: /* Unlock a narrowing locked with (narrowing-lock TAG).
+DEFUN ("internal--unlock-narrowing", Finternal__unlock_narrowing,
+       Sinternal__unlock_narrowing, 1, 1, 0,
+       doc: /* Unlock a narrowing locked with LABEL.
 
-Unlocking restrictions locked with `narrowing-lock' should be used
-sparingly, after carefully considering the reasons why restrictions
-were locked.  Restrictions are typically locked around portions of
-code that would become too slow, and make Emacs unresponsive, if they
-were executed in a large buffer.  For example, restrictions are locked
-by Emacs around low-level hooks such as `fontification-functions' or
-`post-command-hook'.  */)
+This is an internal function used by `without-restriction'.  */)
   (Lisp_Object tag)
 {
   Lisp_Object buf = Fcurrent_buffer ();
@@ -2985,8 +2975,8 @@ by Emacs around low-level hooks such as 
`fontification-functions' or
   return Qnil;
 }
 
-Lisp_Object
-save_restriction_save (void)
+static Lisp_Object
+save_restriction_save_1 (void)
 {
   if (BEGV == BEG && ZV == Z)
     /* The common case that the buffer isn't narrowed.
@@ -3009,8 +2999,8 @@ save_restriction_save (void)
     }
 }
 
-void
-save_restriction_restore (Lisp_Object data)
+static void
+save_restriction_restore_1 (Lisp_Object data)
 {
   struct buffer *cur = NULL;
   struct buffer *buf = (CONSP (data)
@@ -3078,13 +3068,28 @@ save_restriction_restore (Lisp_Object data)
     set_buffer_internal (cur);
 }
 
+Lisp_Object
+save_restriction_save (void)
+{
+  Lisp_Object restr = save_restriction_save_1 ();
+  Lisp_Object locks = narrowing_locks_save ();
+  return Fcons (restr, locks);
+}
+
+void
+save_restriction_restore (Lisp_Object data)
+{
+  narrowing_locks_restore (XCDR (data));
+  save_restriction_restore_1 (XCAR (data));
+}
+
 DEFUN ("save-restriction", Fsave_restriction, Ssave_restriction, 0, UNEVALLED, 
0,
        doc: /* Execute BODY, saving and restoring current buffer's 
restrictions.
 The buffer's restrictions make parts of the beginning and end invisible.
 \(They are set up with `narrow-to-region' and eliminated with `widen'.)
 This special form, `save-restriction', saves the current buffer's
-restrictions, as well as their locks if they have been locked with
-`narrowing-lock', when it is entered, and restores them when it is exited.
+restrictions, including those that were set by `with-restriction' with a
+label argument, when it is entered, and restores them when it is exited.
 So any `narrow-to-region' within BODY lasts only until the end of the form.
 The old restrictions settings are restored even in case of abnormal exit
 \(throw or error).
@@ -3102,7 +3107,6 @@ usage: (save-restriction &rest BODY)  */)
   specpdl_ref count = SPECPDL_INDEX ();
 
   record_unwind_protect (save_restriction_restore, save_restriction_save ());
-  record_unwind_protect (narrowing_locks_restore, narrowing_locks_save ());
   val = Fprogn (body);
   return unbind_to (count, val);
 }
@@ -4903,8 +4907,8 @@ it to be non-nil.  */);
   defsubr (&Sdelete_and_extract_region);
   defsubr (&Swiden);
   defsubr (&Snarrow_to_region);
-  defsubr (&Snarrowing_lock);
-  defsubr (&Snarrowing_unlock);
+  defsubr (&Sinternal__lock_narrowing);
+  defsubr (&Sinternal__unlock_narrowing);
   defsubr (&Ssave_restriction);
   defsubr (&Stranspose_regions);
 }
diff --git a/src/keyboard.c b/src/keyboard.c
index 6f0f075e54..b2816f8270 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1910,12 +1910,13 @@ safe_run_hooks_maybe_narrowed (Lisp_Object hook, struct 
window *w)
   specbind (Qinhibit_quit, Qt);
 
   if (current_buffer->long_line_optimizations_p
-      && long_line_locked_narrowing_region_size > 0)
+      && long_line_optimizations_region_size > 0)
     {
       ptrdiff_t begv = get_locked_narrowing_begv (PT);
       ptrdiff_t zv = get_locked_narrowing_zv (PT);
       if (begv != BEG || zv != Z)
-       narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv), hook);
+       narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
+                                Qlong_line_optimizations_in_command_hooks);
     }
 
   run_hook_with_args (2, ((Lisp_Object []) {hook, hook}),
@@ -12168,6 +12169,8 @@ syms_of_keyboard (void)
   /* Hooks to run before and after each command.  */
   DEFSYM (Qpre_command_hook, "pre-command-hook");
   DEFSYM (Qpost_command_hook, "post-command-hook");
+  DEFSYM (Qlong_line_optimizations_in_command_hooks,
+         "long-line-optimizations-in-command-hooks");
 
   /* Hook run after the region is selected.  */
   DEFSYM (Qpost_select_region_hook, "post-select-region-hook");
@@ -12728,13 +12731,11 @@ If an unhandled error happens in running this hook, 
the function in
 which the error occurred is unconditionally removed, since otherwise
 the error might happen repeatedly and make Emacs nonfunctional.
 
-Note that, when the current buffer contains one or more lines whose
-length is above `long-line-threshold', these hook functions are called
-with the buffer narrowed to a small portion around point (whose size
-is specified by `long-line-locked-narrowing-region-size'), and the
-narrowing is locked (see `narrowing-lock'), so that these hook
-functions cannot use `widen' to gain access to other portions of
-buffer text.
+Note that, when `long-line-optimizations-p' is non-nil in the buffer,
+these functions are called as if they were in a `with-restriction' form,
+with a `long-line-optimizations-in-command-hooks' label and with the
+buffer narrowed to a portion around point whose size is specified by
+`long-line-optimizations-region-size'.
 
 See also `post-command-hook'.  */);
   Vpre_command_hook = Qnil;
@@ -12750,13 +12751,11 @@ It is a bad idea to use this hook for expensive 
processing.  If
 unavoidable, wrap your code in `(while-no-input (redisplay) CODE)' to
 avoid making Emacs unresponsive while the user types.
 
-Note that, when the current buffer contains one or more lines whose
-length is above `long-line-threshold', these hook functions are called
-with the buffer narrowed to a small portion around point (whose size
-is specified by `long-line-locked-narrowing-region-size'), and the
-narrowing is locked (see `narrowing-lock'), so that these hook
-functions cannot use `widen' to gain access to other portions of
-buffer text.
+Note that, when `long-line-optimizations-p' is non-nil in the buffer,
+these functions are called as if they were in a `with-restriction' form,
+with a `long-line-optimizations-in-command-hooks' label and with the
+buffer narrowed to a portion around point whose size is specified by
+`long-line-optimizations-region-size'.
 
 See also `pre-command-hook'.  */);
   Vpost_command_hook = Qnil;
diff --git a/src/xdisp.c b/src/xdisp.c
index 66c2d5e47f..1cc83cf946 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3536,11 +3536,11 @@ get_closer_narrowed_begv (struct window *w, ptrdiff_t 
pos)
 ptrdiff_t
 get_locked_narrowing_begv (ptrdiff_t pos)
 {
-  if (long_line_locked_narrowing_region_size <= 0)
+  if (long_line_optimizations_region_size <= 0)
     return BEGV;
-  int len = long_line_locked_narrowing_region_size / 2;
+  int len = long_line_optimizations_region_size / 2;
   int begv = max (pos - len, BEGV);
-  int limit = long_line_locked_narrowing_bol_search_limit;
+  int limit = long_line_optimizations_bol_search_limit;
   while (limit > 0)
     {
       if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
@@ -3554,9 +3554,9 @@ get_locked_narrowing_begv (ptrdiff_t pos)
 ptrdiff_t
 get_locked_narrowing_zv (ptrdiff_t pos)
 {
-  if (long_line_locked_narrowing_region_size <= 0)
+  if (long_line_optimizations_region_size <= 0)
     return ZV;
-  int len = long_line_locked_narrowing_region_size / 2;
+  int len = long_line_optimizations_region_size / 2;
   return min (pos + len, ZV);
 }
 
@@ -4394,7 +4394,7 @@ handle_fontified_prop (struct it *it)
       eassert (it->end_charpos == ZV);
 
       if (current_buffer->long_line_optimizations_p
-         && long_line_locked_narrowing_region_size > 0)
+         && long_line_optimizations_region_size > 0)
        {
          ptrdiff_t begv = it->locked_narrowing_begv;
          ptrdiff_t zv = it->locked_narrowing_zv;
@@ -4406,7 +4406,7 @@ handle_fontified_prop (struct it *it)
            }
          if (begv != BEG || zv != Z)
            narrow_to_region_locked (make_fixnum (begv), make_fixnum (zv),
-                                    Qfontification_functions);
+                                    
Qlong_line_optimizations_in_fontification_functions);
        }
 
       /* Don't allow Lisp that runs from 'fontification-functions'
@@ -36313,6 +36313,8 @@ be let-bound around code that needs to disable messages 
temporarily. */);
   DEFSYM (QCfile, ":file");
   DEFSYM (Qfontified, "fontified");
   DEFSYM (Qfontification_functions, "fontification-functions");
+  DEFSYM (Qlong_line_optimizations_in_fontification_functions,
+         "long-line-optimizations-in-fontification-functions");
 
   /* Name of the symbol which disables Lisp evaluation in 'display'
      properties.  This is used by enriched.el.  */
@@ -36822,12 +36824,11 @@ Each function is called with one argument POS.  
Functions must
 fontify a region starting at POS in the current buffer, and give
 fontified regions the property `fontified' with a non-nil value.
 
-Note that, when the buffer contains one or more lines whose length is
-above `long-line-threshold', these functions are called with the
-buffer narrowed to a small portion around POS (whose size is specified
-by `long-line-locked-narrowing-region-size'), and the narrowing is
-locked (see `narrowing-lock'), so that these functions cannot use
-`widen' to gain access to other portions of buffer text.  */);
+Note that, when `long-line-optimizations-p' is non-nil in the buffer,
+these functions are called as if they were in a `with-restriction' form,
+with a `long-line-optimizations-in-fontification-functions' label and
+with the buffer narrowed to a portion around POS whose size is
+specified by `long-line-optimizations-region-size'.  */);
   Vfontification_functions = Qnil;
   Fmake_variable_buffer_local (Qfontification_functions);
 
diff --git a/test/lisp/calendar/lunar-tests.el 
b/test/lisp/calendar/lunar-tests.el
index 0d66403e3b..baae928262 100644
--- a/test/lisp/calendar/lunar-tests.el
+++ b/test/lisp/calendar/lunar-tests.el
@@ -43,21 +43,24 @@
 
 (ert-deftest lunar-test-eclipse-check ()
   (with-lunar-test
-   (should (equal (eclipse-check 1 1) "**  Eclipse **"))))
+   (should (equal (eclipse-check 10.0 1) ""))
+   (should (equal (eclipse-check 10.0 2) "** Lunar Eclipse **"))))
 
 (ert-deftest lunar-test-phase-list ()
   (with-lunar-test
-   (should (equal  (lunar-phase-list 3 1871)
-                   '(((3 21 1871) "04:03" 0 "")
-                     ((3 29 1871) "06:46" 1 "**  Eclipse **")
-                     ((4 5 1871) "14:20" 2 "")
-                     ((4 12 1871) "05:57" 3 "**  Eclipse possible **")
-                     ((4 19 1871) "19:06" 0 "")
-                     ((4 27 1871) "23:49" 1 "")
-                     ((5 4 1871) "22:57" 2 "")
-                     ((5 11 1871) "14:29" 3 "")
-                     ((5 19 1871) "10:46" 0 "")
-                     ((5 27 1871) "13:02" 1 ""))))))
+   (should (equal (lunar-phase-list 9 2023)
+                  '(((9 6 2023) "22:27" 3 "")
+                    ((9 15 2023) "01:40" 0 "")
+                    ((9 22 2023) "19:33" 1 "")
+                    ((9 29 2023) "09:54" 2 "** Lunar Eclipse possible **")
+                    ((10 6 2023) "13:53" 3 "")
+                    ((10 14 2023) "17:55" 0 "** Solar Eclipse **")
+                    ((10 22 2023) "03:30" 1 "")
+                    ((10 28 2023) "20:20" 2 "** Lunar Eclipse **")
+                    ((11 5 2023) "08:42" 3 "")
+                    ((11 13 2023) "09:27" 0 "")
+                    ((11 20 2023) "10:51" 1 "")
+                    ((11 27 2023) "09:13" 2 ""))))))
 
 (ert-deftest lunar-test-new-moon-time ()
   (with-lunar-test
diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el 
b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
index d23a0b3590..71027a0c13 100644
--- a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
+++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el
@@ -63,42 +63,6 @@ collisions involving bouncers in ERC.  Run EXTRA."
       (should (cdr (erc-scenarios-common-buflist "127.0.0.1"))))
     (when more (funcall more port))))
 
-;; XXX maybe remove: already covered many times over by other scenarios
-(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--enabled ()
-  :tags '(:expensive-test)
-  (with-suppressed-warnings ((obsolete erc-reuse-buffers))
-    (should erc-reuse-buffers))
-  (let ((erc-scenarios-common-dialog "base/reuse-buffers/server"))
-    (erc-scenarios-common-with-cleanup
-        ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet))
-         (port (process-contact dumb-server :service))
-         erc-autojoin-channels-alist)
-
-      (ert-info ("Connect to foonet")
-        (with-current-buffer (erc :server "127.0.0.1"
-                                  :port port
-                                  :nick "tester"
-                                  :password "foonet:changeme"
-                                  :full-name "tester")
-          (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
-          (erc-d-t-search-for 12 "marked as being away")))
-
-      (ert-info ("Connect to barnet")
-        (with-current-buffer (erc :server "127.0.0.1"
-                                  :port port
-                                  :nick "tester"
-                                  :password "barnet:changeme"
-                                  :full-name "tester")
-          (should (string= (buffer-name) (format "127.0.0.1:%d" port)))
-          (erc-d-t-search-for 45 "marked as being away")))
-
-      (erc-d-t-wait-for 2 (get-buffer "foonet"))
-      (erc-d-t-wait-for 2 (get-buffer "barnet"))
-
-      (ert-info ("Server buffers are unique, no IP-based names")
-        (should-not (eq (get-buffer "foonet") (get-buffer "barnet")))
-        (should-not (erc-scenarios-common-buflist "127.0.0.1"))))))
-
 ;; FIXME no sense in running this twice (JOIN variant includes this)
 (ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--disabled ()
   :tags '(:expensive-test)
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 9d4bbf3e04..45914b2b6b 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -8539,4 +8539,110 @@ Finally, kill the buffer and its temporary file."
       (if f2 (delete-file f2))
       )))
 
+(ert-deftest test-labeled-narrowing ()
+  "Test `with-restriction' and `without-restriction'."
+  (with-current-buffer (generate-new-buffer " foo" t)
+    (insert (make-string 5000 ?a))
+    (should (= (point-min) 1))
+    (should (= (point-max) 5001))
+    (with-restriction
+     100 500 :label 'foo
+     (should (= (point-min) 100))
+     (should (= (point-max) 500))
+     (widen)
+     (should (= (point-min) 100))
+     (should (= (point-max) 500))
+     (narrow-to-region 1 5000)
+     (should (= (point-min) 100))
+     (should (= (point-max) 500))
+     (narrow-to-region 50 150)
+     (should (= (point-min) 100))
+     (should (= (point-max) 150))
+     (widen)
+     (should (= (point-min) 100))
+     (should (= (point-max) 500))
+     (narrow-to-region 400 1000)
+     (should (= (point-min) 400))
+     (should (= (point-max) 500))
+     (without-restriction
+      :label 'bar
+      (should (= (point-min) 100))
+      (should (= (point-max) 500)))
+     (without-restriction
+      :label 'foo
+      (should (= (point-min) 1))
+      (should (= (point-max) 5001)))
+     (should (= (point-min) 400))
+     (should (= (point-max) 500))
+     (widen)
+     (should (= (point-min) 100))
+     (should (= (point-max) 500))
+     (with-restriction
+      50 250 :label 'bar
+      (should (= (point-min) 100))
+      (should (= (point-max) 250))
+      (widen)
+      (should (= (point-min) 100))
+      (should (= (point-max) 250))
+      (without-restriction
+       :label 'bar
+       (should (= (point-min) 100))
+       (should (= (point-max) 500))
+       (without-restriction
+        :label 'foo
+        (should (= (point-min) 1))
+        (should (= (point-max) 5001)))
+       (should (= (point-min) 100))
+       (should (= (point-max) 500)))
+      (should (= (point-min) 100))
+      (should (= (point-max) 250)))
+     (should (= (point-min) 100))
+     (should (= (point-max) 500))
+     (with-restriction
+      50 250 :label 'bar
+      (should (= (point-min) 100))
+      (should (= (point-max) 250))
+      (with-restriction
+       150 500 :label 'baz
+       (should (= (point-min) 150))
+       (should (= (point-max) 250))
+       (without-restriction
+        :label 'bar
+        (should (= (point-min) 150))
+        (should (= (point-max) 250)))
+       (without-restriction
+        :label 'foo
+        (should (= (point-min) 150))
+        (should (= (point-max) 250)))
+       (without-restriction
+        :label 'baz
+        (should (= (point-min) 100))
+        (should (= (point-max) 250))
+        (without-restriction
+         :label 'foo
+         (should (= (point-min) 100))
+         (should (= (point-max) 250)))
+        (without-restriction
+         :label 'bar
+         (should (= (point-min) 100))
+         (should (= (point-max) 500))
+         (without-restriction
+          :label 'foobar
+          (should (= (point-min) 100))
+          (should (= (point-max) 500)))
+         (without-restriction
+          :label 'foo
+          (should (= (point-min) 1))
+          (should (= (point-max) 5001)))
+         (should (= (point-min) 100))
+         (should (= (point-max) 500)))
+        (should (= (point-min) 100))
+        (should (= (point-max) 250)))
+       (should (= (point-min) 150))
+       (should (= (point-max) 250)))
+      (should (= (point-min) 100))
+      (should (= (point-max) 250))))
+    (should (= (point-min) 1))
+    (should (= (point-max) 5001))))
+
 ;;; buffer-tests.el ends here



reply via email to

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