emacs-diffs
[Top][All Lists]
Advanced

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

master 08bd066149: Merge from origin/emacs-29


From: Stefan Kangas
Subject: master 08bd066149: Merge from origin/emacs-29
Date: Sat, 11 Feb 2023 21:43:55 -0500 (EST)

branch: master
commit 08bd066149faee95fe6660d5002306a1dbc4b91b
Merge: 14c97db736 4da398d8b5
Author: Stefan Kangas <stefankangas@gmail.com>
Commit: Stefan Kangas <stefankangas@gmail.com>

    Merge from origin/emacs-29
    
    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...
    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
    
    # Conflicts:
    #       lisp/transient.el
---
 ChangeLog.2                                        |   2 +-
 ChangeLog.3                                        |   2 +-
 .../html-manual/Multiple-Languages.html            |   6 +-
 admin/notes/tree-sitter/starter-guide              |   4 +-
 doc/lispref/files.texi                             |  11 ++
 doc/lispref/parsing.texi                           |  29 +--
 doc/lispref/text.texi                              |  47 ++++-
 doc/misc/transient.texi                            |  30 +--
 lisp/emacs-lisp/lisp-mode.el                       |   3 +
 lisp/image/exif.el                                 |  47 +++--
 lisp/image/image-converter.el                      |  71 ++++---
 lisp/image/image-crop.el                           |  48 ++---
 lisp/image/image-dired-dired.el                    |  56 +++---
 lisp/image/image-dired-external.el                 |  52 +++--
 lisp/image/image-dired-tags.el                     |  20 +-
 lisp/image/image-dired-util.el                     |   8 +-
 lisp/image/image-dired.el                          |  84 ++++----
 lisp/image/wallpaper.el                            |   8 +-
 lisp/mail/rmailsum.el                              |   6 +-
 lisp/progmodes/bug-reference.el                    |   2 +-
 lisp/progmodes/eglot.el                            |   3 +-
 lisp/subr.el                                       |   4 +-
 lisp/transient.el                                  | 217 +++++++++------------
 src/fns.c                                          |  17 +-
 src/treesit.c                                      |  46 +++--
 test/src/treesit-tests.el                          |  14 +-
 26 files changed, 437 insertions(+), 400 deletions(-)

diff --git a/ChangeLog.2 b/ChangeLog.2
index cde9e63df8..11e6049b0b 100644
--- a/ChangeLog.2
+++ b/ChangeLog.2
@@ -111,7 +111,7 @@
 
 2017-03-21  Noam Postavsky  <npostavs@gmail.com>
 
-       Narrow scope of modification hook renabling in org-src fontification
+       Narrow scope of modification hook re-enabling in org-src fontification
 
        Modification hooks should be enabled while modifying text in the
        org-src temp buffer, but in 2017-01-29 "Call modification hooks in
diff --git a/ChangeLog.3 b/ChangeLog.3
index 3d733804e3..c254f595e8 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -204741,7 +204741,7 @@
 
 2017-03-21  Noam Postavsky  <npostavs@gmail.com>
 
-       Narrow scope of modification hook renabling in org-src fontification
+       Narrow scope of modification hook re-enabling in org-src fontification
 
        Modification hooks should be enabled while modifying text in the
        org-src temp buffer, but in 2017-01-29 "Call modification hooks in
diff --git a/admin/notes/tree-sitter/html-manual/Multiple-Languages.html 
b/admin/notes/tree-sitter/html-manual/Multiple-Languages.html
index 65507687d5..390d908259 100644
--- a/admin/notes/tree-sitter/html-manual/Multiple-Languages.html
+++ b/admin/notes/tree-sitter/html-manual/Multiple-Languages.html
@@ -223,9 +223,9 @@ ranges for <acronym>CSS</acronym> and JavaScript parsers:
 </p>
 <div class="example">
 <pre class="example">;; Create parsers.
-(setq html (treesit-get-parser-create 'html))
-(setq css (treesit-get-parser-create 'css))
-(setq js (treesit-get-parser-create 'javascript))
+(setq html (treesit-parser-create 'html))
+(setq css (treesit-parser-create 'css))
+(setq js (treesit-parser-create 'javascript))
 </pre><pre class="example">
 
 </pre><pre class="example">;; Set CSS ranges.
diff --git a/admin/notes/tree-sitter/starter-guide 
b/admin/notes/tree-sitter/starter-guide
index 606f7891df..b8910aab5c 100644
--- a/admin/notes/tree-sitter/starter-guide
+++ b/admin/notes/tree-sitter/starter-guide
@@ -45,7 +45,7 @@ You can use this script that I put together here:
 You can also find them under this directory in /build-modules.
 
 This script automatically pulls and builds language definitions for C,
-C++, Rust, JSON, Go, HTML, Javascript, CSS, Python, Typescript,
+C++, Rust, JSON, Go, HTML, JavaScript, CSS, Python, Typescript,
 and C#. Better yet, I pre-built these language definitions for
 GNU/Linux and macOS, they can be downloaded here:
 
@@ -271,7 +271,7 @@ Matchers and anchors are functions that takes (NODE PARENT 
BOL &rest
 _). Matches return nil/non-nil for no match/match, and anchors return
 the anchor point. Below are some convenient builtin matchers and anchors.
 
-For MATHCER we have
+For MATCHER we have
 
     (parent-is TYPE) => matches if PARENT’s type matches TYPE as regexp
     (node-is TYPE) => matches NODE’s type
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index ad01e0f288..70785c8100 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -893,6 +893,12 @@ permissions of the file itself.)
 If the file does not exist, or if there was trouble determining
 whether the file exists, this function returns @code{nil}.
 
+@cindex empty file name, and @code{file-exists-p}
+Since a file name that is an empty string is interpreted relative to
+the current buffer's default directory (@pxref{Relative File Names}),
+calling @code{file-exists-p} with an argument that is an empty string
+will report about the buffer's default directory.
+
 @cindex dangling symlinks, testing for existence
 Directories are files, so @code{file-exists-p} can return @code{t}
 when given a directory.  However, because @code{file-exists-p} follows
@@ -2352,6 +2358,10 @@ form.
 @end example
 @end defun
 
+@cindex empty file name
+  A file name that is an empty string stands for the current buffer's
+default directory.
+
 @node Directory Names
 @subsection Directory Names
 @cindex directory name
@@ -2541,6 +2551,7 @@ This is for the sake of filesystems that have the concept 
of a
 superroot above the root directory @file{/}.  On other filesystems,
 @file{/../} is interpreted exactly the same as @file{/}.
 
+@cindex empty file names, and @code{expand-file-name}
 Expanding @file{.} or the empty string returns the default directory:
 
 @example
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index cebb59b650..fd65fa3e75 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -734,7 +734,7 @@ is non-@code{nil}, it looks for smallest named child.
 
 @heading Searching for node
 
-@defun treesit-search-subtree node predicate &optional backward all limit
+@defun treesit-search-subtree node predicate &optional backward all depth
 This function traverses the subtree of @var{node} (including
 @var{node} itself), looking for a node for which @var{predicate}
 returns non-@code{nil}.  @var{predicate} is a regexp that is matched
@@ -745,9 +745,9 @@ the first node that matches, or @code{nil} if none does.
 By default, this function only traverses named nodes, but if @var{all}
 is non-@code{nil}, it traverses all the nodes.  If @var{backward} is
 non-@code{nil}, it traverses backwards (i.e., it visits the last child
-first when traversing down the tree).  If @var{limit} is
+first when traversing down the tree).  If @var{depth} is
 non-@code{nil}, it must be a number that limits the tree traversal to
-that many levels down the tree.  If @var{limit} is @code{nil}, it
+that many levels down the tree.  If @var{depth} is @code{nil}, it
 defaults to 1000.
 @end defun
 
@@ -805,7 +805,7 @@ Arguments @var{predicate}, @var{backward} and @var{all} are 
the same
 as in @code{treesit-search-forward}.
 @end defun
 
-@defun treesit-induce-sparse-tree root predicate &optional process-fn limit
+@defun treesit-induce-sparse-tree root predicate &optional process-fn depth
 This function creates a sparse tree from @var{root}'s subtree.
 
 It takes the subtree under @var{root}, and combs it so only the nodes
@@ -836,8 +836,8 @@ b   1   2         b   |   |      b   c   d
 
 If @var{process-fn} is non-@code{nil}, instead of returning the
 matched nodes, this function passes each node to @var{process-fn} and
-uses the returned value instead.  If non-@code{nil}, @var{limit} is
-the number of levels to go down from @var{root}.  If @var{limit} is
+uses the returned value instead.  If non-@code{nil}, @var{depth} is
+the number of levels to go down from @var{root}.  If @var{depth} is
 @code{nil}, it defaults to 1000.
 
 Each node in the returned tree looks like
@@ -970,10 +970,15 @@ A node ``has error'' if the text it spans contains a 
syntax error.  It
 can be that the node itself has an error, or one of its descendants
 has an error.
 
+@cindex tree-sitter, live parsing node
+@cindex live node, tree-sitter
+A node is considered @dfn{live} if its parser is not deleted, and the
+buffer to which it belongs to is a live buffer (@pxref{Killing Buffers}).
+
 @defun treesit-node-check node property
-This function checks if @var{node} has the specified @var{property}.
-@var{property} can be @code{named}, @code{missing}, @code{extra},
-@code{outdated}, or @code{has-error}.
+This function returns non-@code{nil} if @var{node} has the specified
+@var{property}.  @var{property} can be @code{named}, @code{missing},
+@code{extra}, @code{outdated}, @code{has-error}, or @code{live}.
 @end defun
 
 @defun treesit-node-type node
@@ -1584,9 +1589,9 @@ ranges for @acronym{CSS} and JavaScript parsers:
 @example
 @group
 ;; Create parsers.
-(setq html (treesit-get-parser-create 'html))
-(setq css (treesit-get-parser-create 'css))
-(setq js (treesit-get-parser-create 'javascript))
+(setq html (treesit-parser-create 'html))
+(setq css (treesit-parser-create 'css))
+(setq js (treesit-parser-create 'javascript))
 @end group
 
 @group
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 326c111cac..0a48beab8b 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -4947,16 +4947,38 @@ computed for the whole of @var{object}.
 If the argument @var{binary} is omitted or @code{nil}, the function
 returns the @dfn{text form} of the hash, as an ordinary Lisp string.
 If @var{binary} is non-@code{nil}, it returns the hash in @dfn{binary
-form}, as a sequence of bytes stored in a unibyte string.
+form}, as a sequence of bytes stored in a unibyte string.  The length
+of the returned string depends on @var{algorithm}:
+
+@itemize
+@item
+For @code{md5}: 32 characters (32 bytes if @var{binary} is
+non-@code{nil}).
+@item
+For @code{sha1}: 40 characters (40 bytes if @var{binary} is
+non-@code{nil}).
+@item
+For @code{sha224}: 56 characters (56 bytes if @var{binary} is
+non-@code{nil}).
+@item
+For @code{sha256}: 64 characters (64 bytes if @var{binary} is
+non-@code{nil}).
+@item
+For @code{sha384}: 96 characters (96 bytes if @var{binary} is
+non-@code{nil}).
+@item
+For @code{sha512}: 128 characters (128 bytes if @var{binary} is
+non-@code{nil}).
+@end itemize
 
 This function does not compute the hash directly from the internal
 representation of @var{object}'s text (@pxref{Text Representations}).
 Instead, it encodes the text using a coding system (@pxref{Coding
 Systems}), and computes the hash from that encoded text.  If
 @var{object} is a buffer, the coding system used is the one which
-would be chosen by default for writing the text into a file.  If
-@var{object} is a string, the user's preferred coding system is used
-(@pxref{Recognize Coding,,, emacs, GNU Emacs Manual}).
+would be chosen by default for writing the text of that buffer into a
+file.  If @var{object} is a string, the user's preferred coding system
+is used (@pxref{Recognize Coding,,, emacs, GNU Emacs Manual}).
 @end defun
 
 @defun md5 object &optional start end coding-system noerror
@@ -4964,7 +4986,7 @@ This function returns an MD5 hash.  It is semi-obsolete, 
since for
 most purposes it is equivalent to calling @code{secure-hash} with
 @code{md5} as the @var{algorithm} argument.  The @var{object},
 @var{start} and @var{end} arguments have the same meanings as in
-@code{secure-hash}.
+@code{secure-hash}.  The function returns a 32-character string.
 
 If @var{coding-system} is non-@code{nil}, it specifies a coding system
 to use to encode the text; if omitted or @code{nil}, the default
@@ -4987,7 +5009,20 @@ It should be somewhat more efficient on larger buffers 
than
 @code{secure-hash} is, and should not allocate more memory.
 @c Note that we do not document what hashing function we're using, or
 @c even whether it's a cryptographic hash, since that may change
-@c according to what we find useful.
+@c according to what we find useful.  We also don't document the
+@c length of the hash string it returns, since that can be used to
+@c guess the hashing function being used.
+@end defun
+
+@defun sha1 object &optional start end binary
+This function is equivalent to calling @code{secure-hash} like this:
+
+@lisp
+(secure-hash 'sha1 object start end binary)
+@end lisp
+
+It returns a 40-character string if @var{binary} is @code{nil}, or a
+40-byte unibyte string otherwise.
 @end defun
 
 @node Suspicious Text
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index 8ac5df9904..7be8b63041 100644
--- a/doc/misc/transient.texi
+++ b/doc/misc/transient.texi
@@ -1061,18 +1061,6 @@ For example, the scope of the 
@code{magit-branch-configure} transient is
 the branch whose variables are being configured.
 @end defmac
 
-It is possible to define one or more groups independently of a prefix
-definition, which is useful when those groups are to be used by more
-than just one prefix command.
-
-@defmac transient-define-groups name group...
-This macro defines one or more groups of infix and suffix commands
-and stores them in a property of the symbol @var{NAME}.  @var{GROUP} has the
-same form as for @code{transient-define-prefix}.  Subsequently @var{NAME} can
-be used in a @var{GROUP} of @code{transient-define-prefix}, as described in the
-next section.
-@end defmac
-
 @node Binding Suffix and Infix Commands
 @section Binding Suffix and Infix Commands
 
@@ -1199,22 +1187,8 @@ a table.
 
 Inside group specifications, including inside contained suffix
 specifications, nothing has to be quoted and quoting anyway is
-invalid.
-
-How symbols are treated, depends on context.  Inside suffix
-specifications they often name functions.  However if they appear in
-a place where a group is expected, then they are treated as indirect
-group specifications. Such a symbol must have an associated group
-specification, created using @code{transient-define-groups}.
-
-Likewise a symbol can appear in a place where a suffix specification
-is expected.  The value of the @code{transient--layout} property of that
-symbol must be a single suffix specification or a list of such
-specifications.  Currently no macro exist that would create such a
-symbol, and this feature should usually not be used.
-
-The value following a keyword, can be explicitly unquoted using @code{,}.
-This feature is experimental and should be avoided as well.
+invalid.  The value following a keyword, can be explicitly unquoted
+using @code{,}.  This feature is experimental and should be avoided.
 
 The form of suffix specifications is documented in the next node.
 
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 367f59e878..d44c9d6e23 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -181,8 +181,11 @@ to a package-local <package>-loaddefs.el file.")
 (put 'define-category 'doc-string-elt 2)
 ;; CL
 (put 'defconstant 'doc-string-elt 3)
+(put 'define-compiler-macro 'doc-string-elt 3)
+(put 'define-setf-expander 'doc-string-elt 3)
 (put 'defparameter 'doc-string-elt 3)
 (put 'defstruct 'doc-string-elt 2)
+(put 'deftype 'doc-string-elt 3)
 
 (defvar lisp-doc-string-elt-property 'doc-string-elt
   "The symbol property that holds the docstring position info.")
diff --git a/lisp/image/exif.el b/lisp/image/exif.el
index 50428c3a31..4807df0fbb 100644
--- a/lisp/image/exif.el
+++ b/lisp/image/exif.el
@@ -110,7 +110,7 @@ from the return value of this function."
     (exif-parse-buffer)))
 
 (defun exif-parse-buffer (&optional buffer)
-  "Parse BUFFER (which should be a JPEG file) and return the Exif data, if any.
+  "Parse BUFFER (which should visit a JPEG file) and return Exif data, if any.
 The return value is a list of Exif items.
 
 If the data is invalid, an `exif-error' is signaled.
@@ -134,17 +134,17 @@ from the return value of this function."
           (exif--parse-exif-chunk app1))))))
 
 (defun exif-field (field data)
-  "Return raw FIELD from EXIF.
+  "Return raw FIELD from Exif DATA.
 If FIELD is not present in the data, return nil.
 FIELD is a symbol in the cdr of `exif-tag-alist'.
-DATA is the result of calling `exif-parse-file'."
+DATA is the result of calling `exif-parse-file' or `exif-parse-buffer'."
   (plist-get (seq-find (lambda (e)
                          (eq field (plist-get e :tag-name)))
                        data)
              :value))
 
 (defun exif-orientation (exif)
-  "Return the orientation (in degrees) in EXIF.
+  "Return the orientation (in degrees) in EXIF data.
 If the orientation isn't present in the data, return nil."
   (let ((code (exif-field 'orientation exif)))
     (cadr (assq code exif--orientation))))
@@ -255,21 +255,24 @@ If the orientation isn't present in the data, return nil."
         ;; We've reached the end of the directories.
         dir))))
 
-(defun exif--direct-ascii-value (value bytes le)
-  "Make VALUE into a zero-terminated string.
-VALUE is an integer representing BYTES characters."
+(defun exif--direct-ascii-value (value nbytes le)
+  "Make a string representing VALUE with NBYTES bytes according to LE 
endianness.
+VALUE is an integer value of NBYTES bytes.
+The return value is a null-terminated unibyte string whose length is
+NBYTES+1 bytes.  If LE is non-nil, the returned string representation of
+VALUE is little-endian, otherwise it is big-endian."
   (with-temp-buffer
     (set-buffer-multibyte nil)
     (if le
-        (dotimes (i bytes)
+        (dotimes (i nbytes)
           (insert (logand (ash value (* i -8)) 255)))
-      (dotimes (i bytes)
-        (insert (logand (ash value (* (- (1- bytes) i) -8)) 255))))
+      (dotimes (i nbytes)
+        (insert (logand (ash value (* (- (1- nbytes) i) -8)) 255))))
     (insert 0)
     (buffer-string)))
 
 (defun exif--process-value (value type le)
-  "Do type-based post-processing of the value."
+  "Do type-based post-processing of the VALUE whose endianness is per LE."
   (cl-case type
     ;; Chop off trailing zero byte.
     (ascii (substring value 0 (1- (length value))))
@@ -282,7 +285,8 @@ VALUE is an integer representing BYTES characters."
     (otherwise value)))
 
 (defun exif--read-chunk (bytes)
-  "Return BYTES octets from the buffer and advance point that much."
+  "Return BYTES octets from the current buffer and advance point that much.
+This function assumes that the current buffer is unibyte."
   (when (> (+ (point) bytes) (point-max))
     (signal 'exif-error '("Premature end of file")))
   (prog1
@@ -290,8 +294,9 @@ VALUE is an integer representing BYTES characters."
     (forward-char bytes)))
 
 (defun exif--read-number-be (bytes)
-  "Read BYTES octets from the buffer as a chunk of big-endian bytes.
-Advance point to after the read bytes."
+  "Read BYTES octets from the current buffer as a chunk of big-endian bytes.
+Advance point to after the read bytes.
+This function assumes that the current buffer is unibyte."
   (when (> (+ (point) bytes) (point-max))
     (signal 'exif-error '("Premature end of file")))
   (let ((sum 0))
@@ -301,8 +306,9 @@ Advance point to after the read bytes."
     sum))
 
 (defun exif--read-number-le (bytes)
-  "Read BYTES octets from the buffer as a chunk of low-endian bytes.
-Advance point to after the read bytes."
+  "Read BYTES octets from the current buffer as a chunk of little-endian bytes.
+Advance point to after the read bytes.
+This function assumes that the current buffer is unibyte."
   (when (> (+ (point) bytes) (point-max))
     (signal 'exif-error '("Premature end of file")))
   (let ((sum 0))
@@ -311,10 +317,11 @@ Advance point to after the read bytes."
       (forward-char 1))
     sum))
 
-(defun exif--read-number (bytes lower-endian)
-  "Read BYTES octets from the buffer with endianness determined by 
LOWER-ENDIAN.
-Advance point to after the read bytes."
-  (if lower-endian
+(defun exif--read-number (bytes little-endian)
+  "Read BYTES octets from current buffer with endianness given by 
LITTLE-ENDIAN.
+Advance point to after the read bytes.
+This function assumes that the current buffer is unibyte."
+  (if little-endian
       (exif--read-number-le bytes)
     (exif--read-number-be bytes)))
 
diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el
index 596e623357..ff9d4ad0d8 100644
--- a/lisp/image/image-converter.el
+++ b/lisp/image/image-converter.el
@@ -38,9 +38,9 @@ If nil, Emacs will try to find one of the supported converters
 installed on the system.
 
 The actual range of image formats that will be converted depends
-on what image formats the chosen converter reports being able to
-handle.  `auto-mode-alist' is then used to further filter what
-formats that are to be supported: Only the suffixes that map to
+on the image formats which the chosen converter is able to
+handle.  `auto-mode-alist' is then used to further filter the
+formats that are to be supported: only the suffixes that map to
 `image-mode' will be handled."
   :group 'image
   :type 'symbol
@@ -48,16 +48,16 @@ formats that are to be supported: Only the suffixes that 
map to
 
 (defcustom image-convert-to-format "png"
   "The image format to convert to.
-This should be a string like \"png\" or \"ppm\" or some
+This should be a string like \"png\" or \"ppm\", or some
 other (preferably lossless) format that Emacs understands
-natively.  The converter chosen has to support the format, and if
-not, conversion will fail."
+natively.  The converter chosen has to support this format; if
+not, the conversion will fail."
   :group 'image
   :version "29.1"
   :type 'string)
 
 (defvar image-converter-regexp nil
-  "A regexp that matches the file name suffixes that can be converted.")
+  "A regexp that matches the file name suffixes which can be converted.")
 
 (defvar image-converter-file-name-extensions nil
   "A list of file name suffixes that can be converted.")
@@ -66,7 +66,7 @@ not, conversion will fail."
   '((graphicsmagick :command ("gm" "convert") :probe ("-list" "format"))
     (ffmpeg :command "ffmpeg" :probe "-decoders")
     (imagemagick :command "convert" :probe ("-list" "format")))
-  "List of supported image converters to try.")
+  "List of supported image converters to try and required command-line 
switches.")
 
 (defvar image-converter--extra-converters (make-hash-table :test #'equal))
 
@@ -80,8 +80,8 @@ This also determines which external formats we can parse."
   "Return `image-convert' if SOURCE is an image that can be converted.
 SOURCE can either be a file name or a string containing image
 data.  In the latter case, DATA-P should be non-nil.  If DATA-P
-is a string, it should be a MIME format string like
-\"image/gif\"."
+is a string, it should be a MIME format string specifying the image type,
+like \"image/gif\"."
   (image-converter-initialize)
   ;; When image-converter was customized
   (when (and image-converter (not image-converter-regexp))
@@ -101,22 +101,21 @@ is a string, it should be a MIME format string like
        'image-convert))
 
 (defun image-convert (image &optional image-format)
-  "Convert IMAGE file to an image format Emacs understands.
-This will usually be \"png\", but this is controlled by the
-`image-convert-to-format' user option.
+  "Convert IMAGE to an image format which Emacs understands.
+This will usually be \"png\", but is controlled by the value
+of the `image-convert-to-format' user option.
 
-IMAGE can either be a file name or image data.
-
-To pass in image data, IMAGE should a string containing the image
-data, and IMAGE-FORMAT should be a symbol with a MIME format name
-like \"image/webp\".  For instance:
+IMAGE can either be a file name, an image object returned
+by `create-image', or a string with image data.  In the latter
+case, IMAGE-FORMAT should be a symbol whose name is a MIME
+specification of image format, such as \"image/webp\".
+For instance:
 
   (image-convert data-string \\='image/bmp)
 
-IMAGE can also be an image object as returned by `create-image'.
-
-This function converts the image the preferred format, and the
-converted image data is returned as a string."
+This function converts the image to the preferred format, per
+the value of `image-convert-to-format', and returns the
+converted image data as a string."
   (image-converter-initialize)
   (unless image-converter
     (error "No external image converters available"))
@@ -152,14 +151,14 @@ converted image data is returned as a string."
       (buffer-string))))
 
 (defun image-converter--value (type elem)
-  "Return the value of ELEM of image converter TYPE."
+  "Return the value of property ELEM for image converter TYPE."
   (let ((value (plist-get (cdr (assq type image-converter--converters)) elem)))
     (if (stringp value)
         (list value)
       value)))
 
 (cl-defmethod image-converter--probe ((type (eql 'graphicsmagick)))
-  "Check whether the system has GraphicsMagick installed."
+  "Check whether the system has GraphicsMagick installed that's usable 
converter."
   (with-temp-buffer
     (let ((command (image-converter--value type :command))
           formats)
@@ -177,7 +176,7 @@ converted image data is returned as a string."
         (nreverse formats)))))
 
 (cl-defmethod image-converter--probe ((type (eql 'imagemagick)))
-  "Check whether the system has ImageMagick installed."
+  "Check whether the system has ImageMagick installed that's a usable 
converter."
   (with-temp-buffer
     (let ((command (image-converter--value type :command))
           formats)
@@ -197,7 +196,7 @@ converted image data is returned as a string."
       (nreverse formats))))
 
 (cl-defmethod image-converter--probe ((type (eql 'ffmpeg)))
-  "Check whether the system has ffmpeg installed."
+  "Check whether the system has ffmpeg installed that's a usable converter."
   (with-temp-buffer
     (let ((command (image-converter--value type :command))
           formats)
@@ -215,7 +214,7 @@ converted image data is returned as a string."
         (nreverse formats)))))
 
 (defun image-converter--find-converter ()
-  "Find an installed image converter."
+  "Find an installed image converter Emacs can use."
   (catch 'done
     (dolist (elem image-converter--converters)
       (when-let ((formats (image-converter--filter-formats
@@ -239,12 +238,12 @@ Only suffixes that map to `image-mode' are returned."
 
 (cl-defmethod image-converter--convert ((type (eql 'graphicsmagick)) source
                                         image-format)
-  "Convert using GraphicsMagick."
+  "Convert image in SOURCE using GraphicsMagick."
   (image-converter--convert-magick type source image-format))
 
 (cl-defmethod image-converter--convert ((type (eql 'imagemagick)) source
                                         image-format)
-  "Convert using ImageMagick."
+  "Convert image in SOURCE using ImageMagick."
   (image-converter--convert-magick type source image-format))
 
 (defun image-converter--mime-type (image-format)
@@ -281,7 +280,7 @@ Only suffixes that map to `image-mode' are returned."
 
 (cl-defmethod image-converter--convert ((type (eql 'ffmpeg)) source
                                         image-format)
-  "Convert using ffmpeg."
+  "Convert image in SOURCE using ffmpeg."
   (let ((command (image-converter--value type :command))
         (coding-system-for-read 'no-conversion))
     (unless (zerop (if image-format
@@ -308,12 +307,12 @@ Only suffixes that map to `image-mode' are returned."
 
 ;;;###autoload
 (defun image-converter-add-handler (suffix converter)
-  "Make Emacs use CONVERTER to parse image files that end with SUFFIX.
-CONVERTER is a function with two parameters, where the first is
-the file name or a string with the image data, and the second is
-non-nil if the first parameter is image data.  The converter
-should output the image in the current buffer, converted to
-`image-convert-to-format'."
+  "Make Emacs use CONVERTER to parse image files whose names end with SUFFIX.
+CONVERTER is a function with two arguments, the file name or a string
+with the image data, and a non-nil value if the first argument is image data.
+The converter should produce the image in the current buffer, converted to
+the format given by `image-convert-to-format'.
+SUFFIX should not include the leading dot."
   (cl-pushnew suffix image-converter-file-name-extensions :test #'equal)
   (setq image-converter-file-name-extensions
         (sort image-converter-file-name-extensions #'string<))
diff --git a/lisp/image/image-crop.el b/lisp/image/image-crop.el
index e6e5abf53d..be6e22bc60 100644
--- a/lisp/image/image-crop.el
+++ b/lisp/image/image-crop.el
@@ -41,71 +41,71 @@
   :group 'image)
 
 (defvar image-crop-exif-rotate nil
-  "If non-nil, rotate images by updating exif data.
+  "If non-nil, rotate images by updating Exif data.
 If nil, rotate the images \"physically\".")
 
 (defcustom image-crop-resize-command '("convert" "-resize" "%wx" "-" "%f:-")
-  "Command to resize an image.
-The following `format-spec' elements are allowed:
+  "List of command and command-line arguments to resize an image.
+The following `format-spec' elements are allowed in the value:
 
 %w: Width.
-%f: Result file type."
+%f: File type to produce."
   :type '(repeat string)
   :version "29.1")
 
 (defcustom image-crop-cut-command '("convert" "-draw" "rectangle %l,%t %r,%b"
                                     "-fill" "%c"
                                     "-" "%f:-")
-  "Command to cut a rectangle out of an image.
+  "List of command and its command-line arguments to cut a rectangle out of 
image.
 
-The following `format-spec' elements are allowed:
+The following `format-spec' elements are allowed in the value:
 %l: Left.
 %t: Top.
 %r: Right.
 %b: Bottom.
 %c: Color.
-%f: Result file type."
+%f: File type to produce."
   :type '(repeat string)
   :version "29.1")
 
 (defcustom image-crop-crop-command '("convert" "+repage" "-crop" "%wx%h+%l+%t"
                                     "-" "%f:-")
-  "Command to crop an image.
+  "List of command and its command-line arguments to crop an image.
 
-The following `format-spec' elements are allowed:
+The following `format-spec' elements are allowed in the value:
 %l: Left.
 %t: Top.
 %w: Width.
 %h: Height.
-%f: Result file type."
+%f: File type to produce."
   :type '(repeat string)
   :version "29.1")
 
 (defcustom image-crop-rotate-command '("convert" "-rotate" "%r" "-" "%f:-")
-  "Command to rotate an image.
+  "List of command and its command-line arguments to rotate an image.
 
-The following `format-spec' elements are allowed:
+The following `format-spec' elements are allowed in the value:
 %r: Rotation (in degrees).
-%f: Result file type."
+%f: File type to produce."
   :type '(repeat string)
   :version "29.1")
 
 (defvar image-crop-buffer-text-function #'image-crop--default-buffer-text
-  "Function to return the buffer text for the cropped image.
-After cropping an image, the displayed image will be updated to
-show the cropped image in the buffer.  Different modes will have
-different ways to represent this image data in a buffer.  For
-instance, an HTML-based mode might want to represent the image
-with <img src=\"data:...base64...\">, but that's up to the mode.
+  "Function to return the buffer text corresponding to the cropped image.
+After cropping an image, the displayed image in the buffer will be updated
+to show the cropped image.  Different modes will have different ways to
+represent this image data in a buffer, but that's up to the mode.  For
+instance, an HTML-based mode might want to represent the image with
+<img src=\"data:...base64...\">.
 
-The default action is to not alter the buffer text at all.
+The default action is to not alter the image's text in the buffer, and
+just return it.
 
-The function is called with two arguments: The first is the
-original buffer text, and the second parameter is the cropped
-image data.")
+The function is called with two arguments: the original buffer text,
+and the cropped image data.")
 
 (defcustom image-cut-color "black"
-  "Color to use for the rectangle cut from the image."
+  "Color to use for the rectangle that was cut from the image."
   :type 'string
   :version "29.1")
 
diff --git a/lisp/image/image-dired-dired.el b/lisp/image/image-dired-dired.el
index 85bdd537c2..6b932601df 100644
--- a/lisp/image/image-dired-dired.el
+++ b/lisp/image/image-dired-dired.el
@@ -57,11 +57,12 @@ Dired and you might want to turn it off."
 
 ;;;###autoload
 (defun image-dired-dired-toggle-marked-thumbs (&optional arg)
-  "Toggle thumbnails in front of file names in the Dired buffer.
-If no marked file could be found, insert or hide thumbnails on the
-current line.  ARG, if non-nil, specifies the files to use instead
-of the marked files.  If ARG is an integer, use the next ARG (or
-previous -ARG, if ARG<0) files."
+  "Toggle thumbnails in front of marked file names in the Dired buffer.
+If no file is marked, toggle display of thumbnail on the current file's line.
+ARG, if non-nil (interactively, the prefix argument), specifies the files
+whose thumbnail display to toggle instead of the marked files: if ARG is an
+integer, use the next ARG (or previous -ARG, if ARG<0) files; any other
+value of ARG means toggle thumbnail display of the current line's file."
   (interactive "P" dired-mode)
   (setq image-dired--generate-thumbs-start  (current-time))
   (dired-map-over-marks
@@ -91,8 +92,8 @@ previous -ARG, if ARG<0) files."
 
 (defun image-dired-dired-after-readin-hook ()
   "Relocate existing thumbnail overlays in Dired buffer after reverting.
-Move them to their corresponding files if they still exist.
-Otherwise, delete overlays.
+Move each overlay to its corresponding file if it still exists.
+Otherwise, delete the overlay.
 Used by `image-dired-dired-toggle-marked-thumbs'."
   (mapc (lambda (overlay)
           (when (overlay-get overlay 'put-image)
@@ -104,7 +105,7 @@ Used by `image-dired-dired-toggle-marked-thumbs'."
         (overlays-in (point-min) (point-max))))
 
 (defun image-dired-next-line-and-display ()
-  "Move to next Dired line and display thumbnail image."
+  "Move to next Dired line and display its thumbnail image."
   (interactive nil dired-mode)
   (dired-next-line 1)
   (image-dired-display-thumbs t image-dired-dired-append-when-browsing t)
@@ -112,7 +113,7 @@ Used by `image-dired-dired-toggle-marked-thumbs'."
       (image-dired-dired-display-properties)))
 
 (defun image-dired-previous-line-and-display ()
-  "Move to previous Dired line and display thumbnail image."
+  "Move to previous Dired line and display its thumbnail image."
   (interactive nil dired-mode)
   (dired-previous-line 1)
   (image-dired-display-thumbs t image-dired-dired-append-when-browsing t)
@@ -130,7 +131,7 @@ Used by `image-dired-dired-toggle-marked-thumbs'."
              "off")))
 
 (defun image-dired-mark-and-display-next ()
-  "Mark current file in Dired and display next thumbnail image."
+  "Mark current file in Dired and display the next thumbnail image."
   (interactive nil dired-mode)
   (dired-mark 1)
   (image-dired-display-thumbs t image-dired-dired-append-when-browsing t)
@@ -148,7 +149,7 @@ Used by `image-dired-dired-toggle-marked-thumbs'."
              "off")))
 
 (defun image-dired-track-thumbnail ()
-  "Track current Dired file's thumb in `image-dired-thumbnail-buffer'.
+  "Move to thumbnail of the current Dired file in 
`image-dired-thumbnail-buffer'.
 This is almost the same as what `image-dired-track-original-file' does,
 but the other way around."
   (let ((file (dired-get-filename))
@@ -170,18 +171,18 @@ but the other way around."
           (image-dired--update-header-line))))))
 
 (defun image-dired-dired-next-line (&optional arg)
-  "Call `dired-next-line', then track thumbnail.
+  "Call `dired-next-line', while tracking the file's thumbnail.
 This can safely replace `dired-next-line'.
-With prefix argument, move ARG lines."
+With prefix argument ARG, move that many lines."
   (interactive "P" dired-mode)
   (dired-next-line (or arg 1))
   (if image-dired-track-movement
       (image-dired-track-thumbnail)))
 
 (defun image-dired-dired-previous-line (&optional arg)
-  "Call `dired-previous-line', then track thumbnail.
+  "Call `dired-previous-line', while tracking the file's thumbnail.
 This can safely replace `dired-previous-line'.
-With prefix argument, move ARG lines."
+With prefix argument ARG, move that many lines."
   (interactive "P" dired-mode)
   (dired-previous-line (or arg 1))
   (if image-dired-track-movement
@@ -307,7 +308,8 @@ With prefix argument ARG, create thumbnails even if they 
already exist
 
 ;;;###autoload
 (defun image-dired-dired-display-external ()
-  "Display file at point using an external viewer."
+  "Display file at point using an external viewer.
+The viewer is specified by the value of `image-dired-external-viewer'."
   (interactive nil dired-mode)
   (let ((file (dired-get-filename)))
     (start-process "image-dired-external" nil
@@ -323,15 +325,15 @@ See documentation for `image-dired-display-image' for 
more information."
 
 (defun image-dired-copy-with-exif-file-name ()
   "Copy file with unique name to main image directory.
-Copy current or all marked files in Dired to a new file in your
-main image directory, using a file name generated by
+Copy current or all files marked in Dired to new file(s) in your
+main image directory, using file name(s) generated by
 `image-dired-get-exif-file-name'.  A typical usage for this if when
 copying images from a digital camera into the image directory.
 
- Typically, you would open up the folder with the incoming
+Typically, you would open up the folder with the incoming
 digital images, mark the files to be copied, and execute this
-function.  The result is a couple of new files in
-`image-dired-main-image-directory' called
+command.  The result is one or more new files in
+`image-dired-main-image-directory', named like
 2005_05_08_12_52_00_dscn0319.jpg,
 2005_05_08_14_27_45_dscn0320.jpg etc."
   (interactive nil dired-mode)
@@ -350,11 +352,11 @@ function.  The result is a couple of new files in
 
 ;;;###autoload
 (defun image-dired-mark-tagged-files (regexp)
-  "Use REGEXP to mark files with matching tag.
+  "Mark files whose tag matches REGEXP.
 A `tag' is a keyword, a piece of meta data, associated with an
 image file and stored in image-dired's database file.  This command
-lets you input a regexp and this will be matched against all tags
-on all image files in the database file.  The files that have a
+prompts for a regexp, and then matches it against all the tags
+of all the image files in the database file.  The files that have a
 matching tag will be marked in the Dired buffer."
   (interactive "sMark tagged files (regexp): " dired-mode)
   (image-dired-sane-db-file)
@@ -386,7 +388,7 @@ matching tag will be marked in the Dired buffer."
     (message "%d files with matching tag marked" hits)))
 
 (defun image-dired-dired-display-properties ()
-  "Display properties for Dired file in the echo area."
+  "Show in the echo area the image-related properties of a file in Dired 
buffer."
   (interactive nil dired-mode)
   (let* ((file-name (dired-get-filename))
          (dired-buf (buffer-name (current-buffer)))
@@ -405,8 +407,4 @@ matching tag will be marked in the Dired buffer."
 
 (provide 'image-dired-dired)
 
-;; Local Variables:
-;; nameless-current-name: "image-dired"
-;; End:
-
 ;;; image-dired-dired.el ends here
diff --git a/lisp/image/image-dired-external.el 
b/lisp/image/image-dired-external.el
index b3ee4b36ad..9f35e17a7e 100644
--- a/lisp/image/image-dired-external.el
+++ b/lisp/image/image-dired-external.el
@@ -86,15 +86,15 @@ using the NeuQuant algorithm."
   (if (executable-find "pngquant")
       '("--ext" "-nq8.png" "%t") ; same extension as "pngnq"
     '("-f" "%t"))
-  "Arguments to pass `image-dired-cmd-pngnq-program'.
-Available format specifiers are the same as in
+  "Arguments to pass to `image-dired-cmd-pngnq-program'.
+Value can use the same format specifiers as in
 `image-dired-cmd-create-thumbnail-options'."
   :type '(repeat (string :tag "Argument"))
   :version "29.1")
 
 (defcustom image-dired-cmd-pngcrush-program (executable-find "pngcrush")
   "The file name of the `pngcrush' program.
-It optimizes the compression of PNG images.  Also it adds PNG textual chunks
+It optimizes the compression of PNG images.  It also adds PNG textual chunks
 with the information required by the Thumbnail Managing Standard."
   :type '(choice (const :tag "Not Set" nil) file))
 
@@ -110,7 +110,7 @@ with the information required by the Thumbnail Managing 
Standard."
     "-text" "b" "Thumb::URI" "file://%f"
     "%q" "%t")
   "Arguments for `image-dired-cmd-pngcrush-program'.
-The available %-format specifiers are the same as in
+The value can use the same %-format specifiers as in
 `image-dired-cmd-create-thumbnail-options', with \"%q\" for a
 temporary file name (typically generated by pnqnq)."
   :version "26.1"
@@ -123,7 +123,7 @@ temporary file name (typically generated by pnqnq)."
 
 (defcustom image-dired-cmd-optipng-options '("-o5" "%t")
   "Arguments passed to `image-dired-cmd-optipng-program'.
-Available format specifiers are described in
+The value can use format specifiers described in
 `image-dired-cmd-create-thumbnail-options'."
   :version "26.1"
   :type '(repeat (string :tag "Argument"))
@@ -139,14 +139,14 @@ Available format specifiers are described in
                "-thumbnail" "%wx%h>" "png:%t")))
     (if (executable-find "gm") (cons "convert" opts) opts))
   "Options for creating thumbnails according to the Thumbnail Managing 
Standard.
-The available %-format specifiers are the same as in
+The value can use the same %-format specifiers as in
 `image-dired-cmd-create-thumbnail-options', with \"%m\" for file
 modification time."
   :type '(repeat (string :tag "Argument"))
   :version "29.1")
 
 (defcustom image-dired-cmd-rotate-original-program "jpegtran"
-  "Executable used to rotate original image.
+  "Executable program used to rotate original image.
 Used together with `image-dired-cmd-rotate-original-options'."
   :type 'file)
 
@@ -154,11 +154,11 @@ Used together with 
`image-dired-cmd-rotate-original-options'."
   '("-rotate" "%d" "-copy" "all" "-outfile" "%t" "%o")
   "Arguments of command used to rotate original image.
 Used with `image-dired-cmd-rotate-original-program'.
-Available format specifiers are: %d which is replaced by the
-number of (positive) degrees to rotate the image, normally 90 or
-270 \(for 90 degrees right and left), %o which is replaced by the
-original image file name and %t which is replaced by
-`image-dired-temp-image-file'."
+The value can use the following format specifiers:
+%d which is replaced by the number of (positive) degrees
+to rotate the image, normally 90 or 270 (for 90 degrees right and left),
+%o which is replaced by the original image file name
+and %t which is replaced by `image-dired-temp-image-file'."
   :version "26.1"
   :type '(repeat (string :tag "Argument")))
 
@@ -176,9 +176,10 @@ Used together with 
`image-dired-cmd-write-exif-data-options'."
 (defcustom image-dired-cmd-write-exif-data-options '("-%t=%v" "%f")
   "Arguments of command used to write EXIF data.
 Used with `image-dired-cmd-write-exif-data-program'.
-Available format specifiers are: %f which is replaced by
-the image file name, %t which is replaced by the tag name and %v
-which is replaced by the tag value."
+The value can use the following format specifiers are:
+%f which is replaced by the image file name,
+%t which is replaced by the tag name
+and %v which is replaced by the tag value."
   :version "26.1"
   :type '(repeat (string :tag "Argument")))
 
@@ -206,7 +207,7 @@ which is replaced by the tag value."
   "Time when `display-thumbs' was called.")
 
 (defvar image-dired-queue nil
-  "List of items in the queue.
+  "List of items in the Image-Dired queue.
 Each item has the form (ORIGINAL-FILE TARGET-FILE).")
 
 (defvar image-dired-queue-active-jobs 0
@@ -214,13 +215,13 @@ Each item has the form (ORIGINAL-FILE TARGET-FILE).")
 
 (defvar image-dired-queue-active-limit (min 4 (max 2 (/ (num-processors) 2)))
   "Maximum number of concurrent jobs permitted for generating images.
-Increase at own risk.  If you want to experiment with this,
+Increase at your own risk.  If you want to experiment with this,
 consider setting `image-dired-debug' to a non-nil value to see
 the time spent on generating thumbnails.  Run `clear-image-cache'
 and remove the cached thumbnail files between each trial run.")
 
 (defun image-dired-pngnq-thumb (spec)
-  "Quantize thumbnail described by format SPEC with pngnq(1)."
+  "Quantize thumbnail described by format SPEC with command `pngnq'."
   (let ((process
          (apply #'start-process "image-dired-pngnq" nil
                 image-dired-cmd-pngnq-program
@@ -243,7 +244,7 @@ and remove the cached thumbnail files between each trial 
run.")
     process))
 
 (defun image-dired-pngcrush-thumb (spec)
-  "Optimize thumbnail described by format SPEC with pngcrush(1)."
+  "Optimize thumbnail described by format SPEC with command `pngcrush'."
   ;; If pngnq wasn't run, then the THUMB-nq8.png file does not exist.
   ;; pngcrush needs an infile and outfile, so we just copy THUMB to
   ;; THUMB-nq8.png and use the latter as a temp file.
@@ -268,7 +269,7 @@ and remove the cached thumbnail files between each trial 
run.")
     process))
 
 (defun image-dired-optipng-thumb (spec)
-  "Optimize thumbnail described by format SPEC with optipng(1)."
+  "Optimize thumbnail described by format SPEC with command `optipng'."
   (let ((process
          (apply #'start-process "image-dired-optipng" nil
                 image-dired-cmd-optipng-program
@@ -354,7 +355,8 @@ and remove the cached thumbnail files between each trial 
run.")
 
 (defun image-dired-thumb-queue-run ()
   "Run a queued job if one exists and not too many jobs are running.
-Queued items live in `image-dired-queue'."
+Queued items live in `image-dired-queue'.
+Number of simultaneous jobs is limited by `image-dired-queue-active-limit'."
   (while (and image-dired-queue
               (< image-dired-queue-active-jobs
                  image-dired-queue-active-limit))
@@ -414,7 +416,7 @@ The new file will be named THUMBNAIL-FILE."
 The file name should be unique as long as you do not take more than
 one picture per second.  The original file name is suffixed at the end
 for traceability.  The format of the returned file name is
-YYYY_MM_DD_HH_MM_DD_ORIG_FILE_NAME.jpg.  Used from
+YYYY_MM_DD_HH_MM_ss_ORIG_FILE_NAME.jpg.  Used from
 `image-dired-copy-with-exif-file-name'."
   (let (data no-exif-data-found)
     (if (not (eq 'jpeg (image-type (expand-file-name file))))
@@ -434,7 +436,7 @@ YYYY_MM_DD_HH_MM_DD_ORIG_FILE_NAME.jpg.  Used from
             (file-name-nondirectory file))))
 
 (defun image-dired-thumbnail-set-image-description ()
-  "Set the ImageDescription EXIF tag for the original image.
+  "Set the ImageDescription EXIF tag for the original image at point.
 If the image already has a value for this tag, it is used as the
 default value at the prompt."
   (interactive nil image-dired-thumbnail-mode)
@@ -466,8 +468,4 @@ default value at the prompt."
 
 (provide 'image-dired-external)
 
-;; Local Variables:
-;; nameless-current-name: "image-dired"
-;; End:
-
 ;;; image-dired-external.el ends here
diff --git a/lisp/image/image-dired-tags.el b/lisp/image/image-dired-tags.el
index 039a7a6617..b9c1a81185 100644
--- a/lisp/image/image-dired-tags.el
+++ b/lisp/image/image-dired-tags.el
@@ -39,7 +39,7 @@
 
 (defmacro image-dired--with-db-file (&rest body)
   "Run BODY in a temp buffer containing `image-dired-tags-db-file'.
-Return the last form in BODY."
+Return the value of last form in BODY."
   (declare (indent 0) (debug t))
   `(with-temp-buffer
      (if (file-exists-p image-dired-tags-db-file)
@@ -91,7 +91,8 @@ FILE-TAGS is an alist in the following form:
       (save-buffer))))
 
 (defun image-dired-remove-tag (files tag)
-  "For all FILES, remove TAG from the image database."
+  "For each file in FILES, remove TAG from the image database.
+FILES can be a name of a single file (a string) or a list of file names."
   (image-dired-sane-db-file)
   (image-dired--with-db-file
     (setq buffer-file-name image-dired-tags-db-file)
@@ -119,7 +120,8 @@ FILE-TAGS is an alist in the following form:
     (save-buffer)))
 
 (defun image-dired-list-tags (file)
-  "Read all tags for image FILE from the image database."
+  "Read all tags for image FILE from the image database.
+Value is a list of all tags for FILE."
   (image-dired-sane-db-file)
   (image-dired--with-db-file
     (let (end (tags ""))
@@ -136,7 +138,8 @@ FILE-TAGS is an alist in the following form:
 
 ;;;###autoload
 (defun image-dired-tag-files (arg)
-  "Tag marked file(s) in Dired.  With prefix ARG, tag file at point."
+  "Tag file(s) which are marked in a Dired buffer.
+With prefix ARG, tag the file at point."
   (interactive "P" dired-mode)
   (let ((tag (completing-read
               "Tags to add (separate tags with a semicolon): "
@@ -187,8 +190,7 @@ With prefix argument ARG, remove tag from file at point."
       'tags (image-dired-list-tags (image-dired-original-file-name))))))
 
 (defun image-dired-write-comments (file-comments)
-  "Write file comments to database.
-Write file comments to one or more files.
+  "Write file comments specified by FILE-COMMENTS comments to database.
 FILE-COMMENTS is an alist on the following form:
  ((FILE . COMMENT) ... )"
   (image-dired-sane-db-file)
@@ -224,7 +226,7 @@ FILE-COMMENTS is an alist on the following form:
       (save-buffer))))
 
 (defun image-dired-update-property (prop value)
-  "Update text property PROP with value VALUE at point."
+  "Set text property PROP of text at point to have the given VALUE."
   (let ((inhibit-read-only t))
     (put-text-property
      (point) (1+ (point))
@@ -378,8 +380,4 @@ tags to their respective image file.  Internal function 
used by
 
 (provide 'image-dired-tags)
 
-;; Local Variables:
-;; nameless-current-name: "image-dired"
-;; End:
-
 ;;; image-dired-tags.el ends here
diff --git a/lisp/image/image-dired-util.el b/lisp/image/image-dired-util.el
index c03f9d2e3d..a80b3afc0f 100644
--- a/lisp/image/image-dired-util.el
+++ b/lisp/image/image-dired-util.el
@@ -110,11 +110,11 @@ See also `image-dired-thumbnail-storage'."
     (abbreviate-file-name f)))
 
 (defun image-dired-associated-dired-buffer ()
-  "Get associated Dired buffer at point."
+  "Get associated Dired buffer for thumbnail at point."
   (get-text-property (point) 'associated-dired-buffer))
 
 (defmacro image-dired--with-dired-buffer (&rest body)
-  "Run BODY in associated Dired buffer.
+  "Run BODY in the Dired buffer associated with thumbnail at point.
 Should be used by commands in `image-dired-thumbnail-mode'."
   (declare (indent defun) (debug t))
   (let ((file (make-symbol "file"))
@@ -179,8 +179,4 @@ Should be used by commands in `image-dired-thumbnail-mode'."
 
 (provide 'image-dired-util)
 
-;; Local Variables:
-;; nameless-current-name: "image-dired"
-;; End:
-
 ;;; image-dired-util.el ends here
diff --git a/lisp/image/image-dired.el b/lisp/image/image-dired.el
index 0c6fd74392..49b8d9f03c 100644
--- a/lisp/image/image-dired.el
+++ b/lisp/image/image-dired.el
@@ -171,7 +171,7 @@ thumbnails:
     sharing of thumbnails across different programs.  Thumbnails
     will be stored in \"$XDG_CACHE_HOME/thumbnails/\"
 
-    Set this user option to one of the following values:
+    To use this way, set this user option to one of the following values:
 
     - `standard' means use thumbnails sized 128x128.
     - `standard-large' means use thumbnails sized 256x256.
@@ -181,20 +181,20 @@ thumbnails:
  2. In the Image-Dired specific directory indicated by
     `image-dired-dir'.
 
-    Set this user option to `image-dired' to use it (or
-    `use-image-dired-dir', which means the same thing for
-    backwards-compatibility reasons).
+    To use this way, set this user option to `image-dired' (or
+    to `use-image-dired-dir', which means the same thing for
+    backward-compatibility reasons).
 
  3. In a subdirectory \".image-dired\" in the same directory
     where the image files are.
 
-    Set this user option to `per-directory' to use it.
+    To use this way, set this user option to `per-directory'.
 
-To change the default size of thumbnails with (2) and (3) above,
-customize `image-dired-thumb-size'.
+To control the default size of thumbnails for alternatives (2)
+and (3) above, customize the value of `image-dired-thumb-size'.
 
 With Thumbnail Managing Standard, save thumbnails in the PNG
-format, as mandated by that standard, and otherwise as JPEG.
+format, as mandated by that standard; otherwise save them as JPEG.
 
 For more information on the Thumbnail Managing Standard, see:
 
https://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html";
@@ -216,13 +216,13 @@ 
https://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html
   'image-dired-tags-db-file "29.1")
 (defcustom image-dired-tags-db-file
   (expand-file-name ".image-dired_db" image-dired-dir)
-  "Database file where file names and their associated tags are stored."
+  "Database file where image-dired file names and associated tags are stored."
   :type 'file)
 
 (defcustom image-dired-rotate-original-ask-before-overwrite t
-  "Confirm overwrite of original file after rotate operation.
+  "Confirm overwriting of original file after image-rotate operation.
 If non-nil, ask user for confirmation before overwriting the
-original file with `image-dired-temp-rotate-image-file'."
+original image file by `image-dired-temp-rotate-image-file'."
   :type 'boolean)
 
 (defcustom image-dired-thumb-size
@@ -261,11 +261,12 @@ deletion."
 
 (defcustom image-dired-line-up-method 'dynamic
   "Default method for line-up of thumbnails in thumbnail buffer.
-Used by `image-dired-display-thumbs' and other functions that needs
-to line-up thumbnails.  Dynamic means to use the available width of
-the window containing the thumbnail buffer, Fixed means to use
-`image-dired-thumbs-per-row', Interactive is for asking the user,
-and No line-up means that no automatic line-up will be done."
+Used by `image-dired-display-thumbs' and other functions that need
+to line-up thumbnails.  The value `dynamic' means to use the
+available width of the window containing the thumbnail buffer,
+the value `fixed' means to use `image-dired-thumbs-per-row',
+the value `interactive' means ask the user, and the
+value `none' means that no automatic line-up will be done."
   :type '(choice :tag "Default line-up method"
                  (const :tag "Dynamic" dynamic)
                  (const :tag "Fixed" fixed)
@@ -277,8 +278,8 @@ and No line-up means that no automatic line-up will be 
done."
   :type 'natnum)
 
 (defcustom image-dired-track-movement t
-  "The current state of the tracking and mirroring.
-For more information, see the documentation for
+  "The current state of the Image-Dired tracking and mirroring of thumbnails.
+For more information, see the documentation of
 `image-dired-toggle-movement-tracking'."
   :type 'boolean)
 
@@ -286,14 +287,14 @@ For more information, see the documentation for
   "Display format for thumbnail properties.
 This is used for the header line in the Image-Dired buffer.
 
-The following %-specs are replaced by `format-spec' before
+The following %-specs in the value are replaced by `format-spec' before
 displaying:
 
   \"%f\"  The file name (without a directory) of the
           original image file.
   \"%n\"  The number of this image out of the total (e.g. 1/10).
   \"%b\"  The associated Dired buffer name.
-  \"%d\"  The name of the directory that the file is in.
+  \"%d\"  The name of the file's directory.
   \"%s\"  The image file size.
   \"%t\"  The list of tags (from the Image-Dired database).
   \"%c\"  The comment (from the Image-Dired database)."
@@ -310,9 +311,9 @@ displaying:
         ((executable-find "xli") "xli")
         ((executable-find "qiv") "qiv -t")
         ((executable-find "xloadimage") "xloadimage"))
-  "Name of external viewer.
-Including parameters.  Used when displaying original image from
-`image-dired-thumbnail-mode'."
+  "Shell command to invoke the external image viewer program.
+Should include command-line arguments if needed.  Used when displaying
+original image from `image-dired-thumbnail-mode'."
   :version "29.1"
   :type '(choice string
                  (const :tag "Not Set" nil)))
@@ -325,14 +326,14 @@ Used by `image-dired-copy-with-exif-file-name'."
   :version "29.1")
 
 (defcustom image-dired-show-all-from-dir-max-files 1000
-  "Maximum number of files in directory before prompting.
+  "Maximum number of files in directory to show before prompting.
 
-If there are more image files than this in a selected directory,
+If there are more image files in a selected directory than this number,
 the `image-dired-show-all-from-dir' command will ask for
 confirmation before creating the thumbnail buffer.  If this
-variable is nil, it will never ask."
+variable is nil, never ask."
   :type '(choice integer
-                 (const :tag "Disable warning" nil))
+                 (const :tag "Don't ask for confirmation" nil))
   :version "29.1")
 
 (defcustom image-dired-marking-shows-next t
@@ -401,7 +402,7 @@ This affects the following commands:
     (image-file-name-regexp)))
 
 (defun image-dired-insert-image (file type relief margin)
-  "Insert image FILE of image TYPE, using RELIEF and MARGIN, at point."
+  "Insert at point image FILE of image TYPE, using RELIEF and MARGIN."
   (let ((i `(image :type ,type
                    :file ,file
                    :relief ,relief
@@ -495,9 +496,9 @@ by exactly one space or one newline character."
 
 Convenience command that:
 
- - Opens Dired in folder DIR
- - Splits windows in most useful (?) way
- - Sets `truncate-lines' to t
+ - opens Dired in folder DIR;
+ - splits windows in most useful (?) way; and
+ - sets `truncate-lines' to t
 
 After the command has finished, you would typically mark some
 image files in Dired and type
@@ -525,7 +526,7 @@ calling `image-dired-restore-window-configuration'."
         (other-window -2)))))
 
 (defun image-dired-restore-window-configuration ()
-  "Restore window configuration.
+  "Restore window configuration altered by Image-Dired.
 Restore any changes to the window configuration made by calling
 `image-dired-dired-with-window-configuration'."
   (interactive nil image-dired-thumbnail-mode)
@@ -632,7 +633,7 @@ never ask for confirmation."
 ;;; Movement tracking
 
 (defun image-dired-track-original-file ()
-  "Track the original file in the associated Dired buffer.
+  "Track in the associated Dired buffer the file that corresponds to thumbnail.
 See `image-dired-toggle-movement-tracking'.  Interactive use is
 only useful if `image-dired-track-movement' is nil."
   (interactive nil image-dired-thumbnail-mode image-dired-image-mode)
@@ -646,8 +647,8 @@ only useful if `image-dired-track-movement' is nil."
 (defun image-dired-toggle-movement-tracking ()
   "Turn on and off `image-dired-track-movement'.
 Tracking of the movements between thumbnail and Dired buffer so that
-they are \"mirrored\" in the dired buffer.  When this is on, moving
-around in the thumbnail or dired buffer will find the matching
+the movements are \"mirrored\" in the Dired buffer.  When this is on,
+moving around in the thumbnail or Dired buffer will move to the matching
 position in the other buffer."
   (interactive nil image-dired-thumbnail-mode image-dired-image-mode)
   (setq image-dired-track-movement (not image-dired-track-movement))
@@ -751,7 +752,9 @@ On reaching end or beginning of buffer, stop and show a 
message."
 ;;; Header line
 
 (defun image-dired-format-properties-string (buf file image-count props 
comment)
-  "Format display properties.
+  "Format display properties for Image-Dired.
+The properties are formatted according to specification
+in `image-dired-display-properties-format', which see.
 BUF is the associated Dired buffer, FILE is the original image
 file name, IMAGE-COUNT is a string like \"N/M\" where N is the
 number of this image and M is the total number of images, PROPS
@@ -816,7 +819,7 @@ for.  The default is to look for `dired-marker-char'."
   (image-dired-dired-file-marked-p dired-del-marker))
 
 (defmacro image-dired--on-file-in-dired-buffer (&rest body)
-  "Run BODY with point on file at point in Dired buffer.
+  "Run BODY in associated Dired buffer with point on current file's line.
 Should be called from commands in `image-dired-thumbnail-mode'."
   (declare (indent defun) (debug t))
   `(if-let ((file-name (image-dired-original-file-name)))
@@ -1192,7 +1195,8 @@ Ask user how many thumbnails should be displayed per row."
 ;;; Display image from thumbnail buffer
 
 (defun image-dired-thumbnail-display-external ()
-  "Display original image for thumbnail at point using external viewer."
+  "Display original image for thumbnail at point using external viewer.
+The viewer command is specified by `image-dired-external-viewer'."
   (interactive nil image-dired-thumbnail-mode)
   (let ((file (image-dired-original-file-name)))
     (if (not (image-dired-image-at-point-p))
@@ -1205,7 +1209,7 @@ Ask user how many thumbnails should be displayed per row."
 
 (defun image-dired-display-image (file &optional _ignored)
   "Display image FILE in the image buffer window.
-If it is an image, the window will use `image-dired-image-mode'
+If FILE is an image, the window will use `image-dired-image-mode'
 which is based on `image-mode'."
   (declare (advertised-calling-convention (file) "29.1"))
   (setq file (expand-file-name file))
@@ -1293,7 +1297,7 @@ overwritten.  This confirmation can be turned off using
 
 (defun image-dired-copy-filename-as-kill (&optional arg)
   "Copy names of marked (or next ARG) files into the kill ring.
-This works as `dired-copy-filename-as-kill' (which see)."
+This works like `dired-copy-filename-as-kill' (which see)."
   (interactive "P" image-dired-thumbnail-mode)
   (image-dired--with-dired-buffer
     (dired-copy-filename-as-kill arg)))
diff --git a/lisp/image/wallpaper.el b/lisp/image/wallpaper.el
index c497e1f429..a2f175e462 100644
--- a/lisp/image/wallpaper.el
+++ b/lisp/image/wallpaper.el
@@ -109,7 +109,7 @@ COMMAND is the executable to run to set the wallpaper.
 ARGS is the default list of command line arguments for COMMAND.
 
 PREDICATE is a function that will be called without any arguments
-and returns non-nil if this setter should be used.
+and should return non-nil if this setter should be used.
 
 INIT-ACTION is a function that will be called without any
 arguments before trying to set the wallpaper.
@@ -304,7 +304,7 @@ order in which they appear.")
                     (throw 'found setter))))))))
 
 (defun wallpaper--find-command ()
-  "Return a valid command to set the wallpaper in this environment."
+  "Return the appropriate command to set the wallpaper."
   (when-let ((setter (wallpaper--find-setter)))
     (wallpaper-setter-command setter)))
 
@@ -437,7 +437,7 @@ See also `wallpaper-default-width'.")
 On a graphical display, try using the same monitor as the current
 frame.
 On a non-graphical display, try to get the name by connecting to
-the display server directly, and run \"xrandr\" if that doesn't
+the display server directly, or run \"xrandr\" if that doesn't
 work.  Prompt for the monitor name if neither method works.
 
 This function is meaningful only on X and is used only there."
@@ -469,7 +469,7 @@ This function is meaningful only on X and is used only 
there."
       (read-string (format-prompt "Monitor name" nil)))))
 
 (defun wallpaper--format-arg (format file)
-  "Format a `wallpaper-command-args' argument ARG.
+  "Format a `wallpaper-command-args' argument ARG using FORMAT.
 FILE is the image file name."
   (format-spec
    format
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
index ba58090765..21dec2bbeb 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/mail/rmailsum.el
@@ -1931,7 +1931,7 @@ even if the header display is currently pruned."
    (progn (require 'rmailout)
          (list (rmail-output-read-file-name)
                (prefix-numeric-value current-prefix-arg))))
-  (let ((i 0) prev-msg)
+  (let ((i 0) prev-msg curmsg)
     (while
        (and (< i n)
             (progn (rmail-summary-goto-msg)
@@ -1942,7 +1942,11 @@ even if the header display is currently pruned."
       (setq i (1+ i))
       (with-current-buffer rmail-buffer
        (let ((rmail-delete-after-output nil))
+          (setq curmsg rmail-current-message)
          (rmail-output file-name 1)))
+      ;; rmail-output sometimes moves to the next message; undo that.
+      (or (= curmsg (rmail-summary-msg-number))
+          (rmail-summary-goto-msg curmsg))
       (if rmail-delete-after-output
          (rmail-summary-delete-forward nil)
        (if (< i n)
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index 9f1439e6a0..bc28028458 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -174,7 +174,7 @@ subexpression 10."
                   (re-search-forward bug-reference-bug-regexp end-line 'move))
         (when (or (not bug-reference-prog-mode)
                   ;; This tests for both comment and string syntax.
-                  (nth 8 (syntax-ppss)))
+                  (nth 8 (save-match-data (syntax-ppss))))
           (let* ((bounds (bug-reference--overlay-bounds))
                  (overlay (or
                            (let ((ov (pop overlays)))
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 6caf5894ed..8ecdefd490 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -221,7 +221,8 @@ chosen (interactively or automatically)."
                                               "--client-id" 
"emacs.eglot-dart"))
                                 (elixir-mode . ("language_server.sh"))
                                 (ada-mode . ("ada_language_server"))
-                                (scala-mode . ("metals-emacs"))
+                                (scala-mode . ,(eglot-alternatives
+                                                '("metals" "metals-emacs")))
                                 (racket-mode . ("racket" "-l" 
"racket-langserver"))
                                 ((tex-mode context-mode texinfo-mode 
bibtex-mode)
                                  . ,(eglot-alternatives '("digestif" 
"texlab")))
diff --git a/lisp/subr.el b/lisp/subr.el
index f749c9e6d2..898ecb6e35 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -4182,8 +4182,8 @@ or byte-code."
   "Return the SHA-1 (Secure Hash Algorithm) of an OBJECT.
 OBJECT is either a string or a buffer.  Optional arguments START and
 END are character positions specifying which portion of OBJECT for
-computing the hash.  If BINARY is non-nil, return a string in binary
-form.
+computing the hash.  If BINARY is non-nil, return a 40-byte unibyte
+string; otherwise returna 40-character string.
 
 Note that SHA-1 is not collision resistant and should not be used
 for anything security-related.  See `secure-hash' for
diff --git a/lisp/transient.el b/lisp/transient.el
index 0b41bc44ad..73ea6fa940 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -632,7 +632,8 @@ If `transient-save-history' is nil, then do nothing."
    (transient-non-suffix :initarg :transient-non-suffix :initform nil)
    (incompatible         :initarg :incompatible         :initform nil)
    (suffix-description   :initarg :suffix-description)
-   (variable-pitch       :initarg :variable-pitch       :initform nil))
+   (variable-pitch       :initarg :variable-pitch       :initform nil)
+   (unwind-suffix        :documentation "Internal use." :initform nil))
   "Transient prefix command.
 
 Each transient prefix command consists of a command, which is
@@ -876,18 +877,6 @@ to the setup function:
             (list ,@(cl-mapcan (lambda (s) (transient--parse-child name s))
                                suffixes))))))
 
-(defmacro transient-define-groups (name &rest groups)
-  "Define one or more GROUPS and store them in symbol NAME.
-GROUPS, defined using this macro, can be used inside the
-definition of transient prefix commands, by using the symbol
-NAME where a group vector is expected.  GROUPS has the same
-form as for `transient-define-prefix'."
-  (declare (debug (&define name [&rest vectorp]))
-           (indent defun))
-  `(put ',name 'transient--layout
-        (list ,@(cl-mapcan (lambda (group) (transient--parse-child name group))
-                           groups))))
-
 (defmacro transient-define-suffix (name arglist &rest args)
   "Define NAME as a transient suffix command.
 
@@ -1411,17 +1400,6 @@ Usually it remains current while the transient is 
active.")
 
 (defvar transient--history nil)
 
-(defvar transient--abort-commands
-  '(abort-minibuffers                   ; (minibuffer-quit-recursive-edit)
-    abort-recursive-edit                ; (throw 'exit t)
-    exit-recursive-edit                 ; (throw 'exit nil)
-    keyboard-escape-quit                ; dwim
-    keyboard-quit                       ; (signal 'quit nil)
-    minibuffer-keyboard-quit            ; (abort-minibuffers)
-    minibuffer-quit-recursive-edit      ; (throw 'exit (lambda ()
-                                        ;      (signal 'minibuffer-quit nil)))
-    top-level))                         ; (throw 'top-level nil)
-
 (defvar transient--scroll-commands
   '(transient-scroll-up
     transient-scroll-down
@@ -1476,10 +1454,11 @@ probably use this instead:
               (lambda (obj)
                 (eq (transient--suffix-command obj)
                     (or command
-                        ;; When `this-command' is `transient-set-level',
-                        ;; its reader needs to know what command is being
-                        ;; configured.
-                        this-original-command)))
+                        (if (eq this-command 'transient-set-level)
+                            ;; This is how it can look up for which
+                            ;; command it is setting the level.
+                            this-original-command
+                          this-command))))
               (or transient--suffixes
                   transient-current-suffixes))))
         (or (and (cdr suffixes)
@@ -1657,6 +1636,7 @@ See `transient-enable-popup-navigation'.")
     (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)
@@ -1717,8 +1697,8 @@ of the corresponding object.")
 
 (defun transient--pop-keymap (var)
   (let ((map (symbol-value var)))
-    (transient--debug "     pop  %s%s" var (if map "" " VOID"))
     (when map
+      (transient--debug "     pop  %s" var)
       (with-demoted-errors "transient--pop-keymap: %S"
         (internal-pop-keymap map 'overriding-terminal-local-map)))))
 
@@ -2042,6 +2022,7 @@ value.  Otherwise return CHILDREN as is."
   (transient--push-keymap 'transient--redisplay-map)
   (add-hook 'pre-command-hook  #'transient--pre-command)
   (add-hook 'post-command-hook #'transient--post-command)
+  (advice-add 'recursive-edit :around #'transient--recursive-edit)
   (when transient--exitp
     ;; This prefix command was invoked as the suffix of another.
     ;; Prevent `transient--post-command' from removing the hooks
@@ -2077,11 +2058,14 @@ value.  Otherwise return CHILDREN as is."
            (not (memq this-command '(transient-quit-one
                                      transient-quit-all
                                      transient-help))))
-      (setq this-command 'transient-set-level))
+      (setq this-command 'transient-set-level)
+      (transient--wrap-command))
      (t
       (setq transient--exitp nil)
-      (when (eq (transient--do-pre-command) transient--exit)
-        (transient--pre-exit))))))
+      (let ((exitp (eq (transient--do-pre-command) transient--exit)))
+        (transient--wrap-command)
+        (when exitp
+          (transient--pre-exit)))))))
 
 (defun transient--do-pre-command ()
   (if-let ((fn (transient--get-predicate-for this-command)))
@@ -2163,7 +2147,7 @@ value.  Otherwise return CHILDREN as is."
   (remove-hook 'pre-command-hook  #'transient--pre-command)
   (remove-hook 'post-command-hook #'transient--post-command))
 
-(defun transient--resume-override ()
+(defun transient--resume-override (&optional _ignore)
   (transient--debug 'resume-override)
   (when (and transient--showp transient-hide-during-minibuffer-read)
     (transient--show))
@@ -2172,6 +2156,19 @@ value.  Otherwise return CHILDREN as is."
   (add-hook 'pre-command-hook  #'transient--pre-command)
   (add-hook 'post-command-hook #'transient--post-command))
 
+(defun transient--recursive-edit (fn)
+  (transient--debug 'recursive-edit)
+  (if (not transient--prefix)
+      (funcall fn)
+    (transient--suspend-override (bound-and-true-p edebug-active))
+    (funcall fn) ; Already unwind protected.
+    (cond ((memq this-command '(top-level abort-recursive-edit))
+           (setq transient--exitp t)
+           (transient--post-exit)
+           (transient--delete-window))
+          (transient--prefix
+           (transient--resume-override)))))
+
 (defmacro transient--with-suspended-override (&rest body)
   (let ((depth (make-symbol "depth"))
         (setup (make-symbol "setup"))
@@ -2199,76 +2196,69 @@ value.  Otherwise return CHILDREN as is."
              (remove-hook 'minibuffer-exit-hook ,exit)))
        ,@body)))
 
-(defun transient--post-command-hook ()
-  (run-hooks 'transient--post-command-hook))
-
-(add-hook 'post-command-hook #'transient--post-command-hook)
-
-(defun transient--delay-post-command (&optional abort-only)
-  (transient--debug 'delay-post-command)
-  (let ((depth (minibuffer-depth))
-        (command this-command)
-        (delayed (if transient--exitp
-                     (apply-partially #'transient--post-exit this-command)
-                   #'transient--resume-override))
-        outside-interactive post-command abort-minibuffer)
-    (unless abort-only
-      (setq post-command
-            (lambda () "@transient--delay-post-command"
-              (let ((act (and (not (equal (this-command-keys-vector) []))
-                              (or (eq this-command command)
-                                  ;; `execute-extended-command' was
-                                  ;; used to call another command
-                                  ;; that also uses the minibuffer.
-                                  (equal
-                                   (ignore-errors
-                                     (string-to-multibyte (this-command-keys)))
-                                   (format "\M-x%s\r" this-command))
-                                  ;; Minibuffer used outside `interactive'.
-                                  (and outside-interactive 'post-cmd)))))
-                (transient--debug 'post-command-hook "act: %s" act)
-                (when act
-                  (remove-hook 'transient--post-command-hook post-command)
-                  (remove-hook 'minibuffer-exit-hook abort-minibuffer)
-                  (funcall delayed)))))
-      (add-hook 'transient--post-command-hook post-command))
-    (setq abort-minibuffer
-          (lambda () "@transient--delay-post-command"
-            (let ((act (and (= (minibuffer-depth) depth)
-                            (or (memq this-command transient--abort-commands)
-                                (equal (this-command-keys) "")
-                                (prog1 nil
-                                  (setq outside-interactive t))))))
-              (transient--debug
-               'abort-minibuffer
-               "mini: %s|%s, act: %s" (minibuffer-depth) depth
-               (or act (and outside-interactive '->post-cmd)))
-              (when act
-                (remove-hook 'transient--post-command-hook post-command)
-                (remove-hook 'minibuffer-exit-hook abort-minibuffer)
-                (funcall delayed)))))
-    (add-hook 'minibuffer-exit-hook abort-minibuffer)))
+(defun transient--wrap-command ()
+  (let* ((prefix transient--prefix)
+         (suffix this-command)
+         (advice nil)
+         (advice-interactive
+          (lambda (spec)
+            (let ((abort t))
+              (unwind-protect
+                 (prog1 (advice-eval-interactive-spec spec)
+                   (setq abort nil))
+               (when abort
+                  (when-let ((unwind (oref prefix unwind-suffix)))
+                    (transient--debug 'unwind-interactive)
+                    (funcall unwind suffix))
+                  (if (symbolp suffix)
+                      (advice-remove suffix advice)
+                    (remove-function suffix advice))
+                  (oset prefix unwind-suffix nil))))))
+         (advice-body
+          (lambda (fn &rest args)
+            (unwind-protect
+                (apply fn args)
+              (when-let ((unwind (oref prefix unwind-suffix)))
+                (transient--debug 'unwind-command)
+                (funcall unwind suffix))
+              (if (symbolp suffix)
+                  (advice-remove suffix advice)
+                (remove-function suffix advice))
+              (oset prefix unwind-suffix nil)))))
+    (setq advice `(lambda (fn &rest args)
+                    (interactive ,advice-interactive)
+                    (apply ',advice-body fn args)))
+    (if (symbolp suffix)
+        (advice-add suffix :around advice '((depth . -99)))
+      (add-function :around (var suffix) advice '((depth . -99))))))
+
+(defun transient--premature-post-command ()
+  (and (equal (this-command-keys-vector) [])
+       (= (minibuffer-depth)
+          (1+ transient--minibuffer-depth))
+       (progn
+         (transient--debug 'premature-post-command)
+         (transient--suspend-override)
+         (oset (or transient--prefix transient-current-prefix)
+               unwind-suffix
+               (if transient--exitp
+                   #'transient--post-exit
+                 #'transient--resume-override))
+         t)))
 
 (defun transient--post-command ()
-  (transient--debug 'post-command)
-  (transient--with-emergency-exit
-    (cond
-     ((and (equal (this-command-keys-vector) [])
-           (= (minibuffer-depth)
-              (1+ transient--minibuffer-depth)))
-      (transient--suspend-override)
-      (transient--delay-post-command (eq transient--exitp 'replace)))
-     (transient--exitp
-      (transient--post-exit))
-     ((eq this-command (oref transient--prefix command)))
-     (t
-      (let ((old transient--redisplay-map)
-            (new (transient--make-redisplay-map)))
-        (unless (equal old new)
-          (transient--pop-keymap 'transient--redisplay-map)
-          (setq transient--redisplay-map new)
-          (transient--push-keymap 'transient--redisplay-map)))
-      (transient--redisplay)))))
+  (unless (transient--premature-post-command)
+    (transient--debug 'post-command)
+    (transient--with-emergency-exit
+      (cond (transient--exitp (transient--post-exit))
+            ((eq this-command (oref transient--prefix command)))
+            ((let ((old transient--redisplay-map)
+                   (new (transient--make-redisplay-map)))
+               (unless (equal old new)
+                 (transient--pop-keymap 'transient--redisplay-map)
+                 (setq transient--redisplay-map new)
+                 (transient--push-keymap 'transient--redisplay-map))
+               (transient--redisplay)))))))
 
 (defun transient--post-exit (&optional command)
   (transient--debug 'post-exit)
@@ -2289,7 +2279,8 @@ value.  Otherwise return CHILDREN as is."
                          (setq transient--exitp nil)
                        (transient--stack-zap)))))
     (remove-hook 'pre-command-hook  #'transient--pre-command)
-    (remove-hook 'post-command-hook #'transient--post-command))
+    (remove-hook 'post-command-hook #'transient--post-command)
+    (advice-remove 'recursive-edit #'transient--recursive-edit))
   (setq transient-current-prefix nil)
   (setq transient-current-command nil)
   (setq transient-current-suffixes nil)
@@ -2358,7 +2349,7 @@ value.  Otherwise return CHILDREN as is."
   (when transient--debug
     (let ((inhibit-message (not (eq transient--debug 'message))))
       (if (symbolp arg)
-          (message "-- %-18s (cmd: %s, event: %S, exit: %s%s)"
+          (message "-- %-22s (cmd: %s, event: %S, exit: %s%s)"
                    arg
                    (or (ignore-errors (transient--suffix-symbol this-command))
                        (if (byte-code-function-p this-command)
@@ -3994,23 +3985,6 @@ search instead."
 
 ;;;; Edebug
 
-(defun transient--edebug--recursive-edit (fn arg-mode)
-  (transient--debug 'edebug--recursive-edit)
-  (if (not transient--prefix)
-      (funcall fn arg-mode)
-    (transient--suspend-override t)
-    (funcall fn arg-mode)
-    (transient--resume-override)))
-
-(advice-add 'edebug--recursive-edit :around 
#'transient--edebug--recursive-edit)
-
-(defun transient--abort-edebug ()
-  (when (bound-and-true-p edebug-active)
-    (transient--emergency-exit)))
-
-(advice-add 'abort-recursive-edit :before #'transient--abort-edebug)
-(advice-add 'top-level :before #'transient--abort-edebug)
-
 (defun transient--edebug-command-p ()
   (and (bound-and-true-p edebug-active)
        (or (memq this-command '(top-level abort-recursive-edit))
@@ -4105,7 +4079,8 @@ we stop there."
                 (regexp-opt (list "transient-define-prefix"
                                   "transient-define-infix"
                                   "transient-define-argument"
-                                  "transient-define-suffix")
+                                  "transient-define-suffix"
+                                  "transient-define-groups")
                             t)
                 "\\_>[ \t'(]*"
                 "\\(\\(?:\\sw\\|\\s_\\)+\\)?")
diff --git a/src/fns.c b/src/fns.c
index 59d5b5c085..0af9b725c7 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -5809,8 +5809,9 @@ secure_hash (Lisp_Object algorithm, Lisp_Object object, 
Lisp_Object start,
 DEFUN ("md5", Fmd5, Smd5, 1, 5, 0,
        doc: /* Return MD5 message digest of OBJECT, a buffer or string.
 
-A message digest is a cryptographic checksum of a document, and the
-algorithm to calculate it is defined in RFC 1321.
+A message digest is the string representation of the cryptographic checksum
+of a document, and the algorithm to calculate it is defined in RFC 1321.
+The MD5 digest is 32-character long.
 
 The two optional arguments START and END are character positions
 specifying for which part of OBJECT the message digest should be
@@ -5844,12 +5845,12 @@ anything security-related.  See `secure-hash' for 
alternatives.  */)
 DEFUN ("secure-hash", Fsecure_hash, Ssecure_hash, 2, 5, 0,
        doc: /* Return the secure hash of OBJECT, a buffer or string.
 ALGORITHM is a symbol specifying the hash to use:
-- md5    corresponds to MD5
-- sha1   corresponds to SHA-1
-- sha224 corresponds to SHA-2 (SHA-224)
-- sha256 corresponds to SHA-2 (SHA-256)
-- sha384 corresponds to SHA-2 (SHA-384)
-- sha512 corresponds to SHA-2 (SHA-512)
+- md5    corresponds to MD5, produces a 32-character signature
+- sha1   corresponds to SHA-1, produces a 40-character signature
+- sha224 corresponds to SHA-2 (SHA-224), produces a 56-character signature
+- sha256 corresponds to SHA-2 (SHA-256), produces a 64-character signature
+- sha384 corresponds to SHA-2 (SHA-384), produces a 96-character signature
+- sha512 corresponds to SHA-2 (SHA-512), produces a 128-character signature
 
 The two optional arguments START and END are positions specifying for
 which part of OBJECT to compute the hash.  If nil or omitted, uses the
diff --git a/src/treesit.c b/src/treesit.c
index cfa3721b5e..cab2f0d535 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1475,6 +1475,15 @@ This symbol is the one used to create the parser.  */)
   return XTS_PARSER (parser)->language_symbol;
 }
 
+/* Return true if PARSER is not deleted and its buffer is live.  */
+static bool
+treesit_parser_live_p (Lisp_Object parser)
+{
+  CHECK_TS_PARSER (parser);
+  return ((!XTS_PARSER (parser)->deleted) &&
+         (!NILP (Fbuffer_live_p (XTS_PARSER (parser)->buffer))));
+}
+
 /*** Parser API */
 
 DEFUN ("treesit-parser-root-node",
@@ -1908,7 +1917,8 @@ DEFUN ("treesit-node-check",
        Ftreesit_node_check, Streesit_node_check, 2, 2, 0,
        doc: /* Return non-nil if NODE has PROPERTY, nil otherwise.
 
-PROPERTY could be `named', `missing', `extra', `outdated', or `has-error'.
+PROPERTY could be `named', `missing', `extra', `outdated',
+`has-error', or `live'.
 
 Named nodes correspond to named rules in the language definition,
 whereas "anonymous" nodes correspond to string literals in the
@@ -1924,7 +1934,10 @@ A node is "outdated" if the parser has reparsed at least 
once after
 the node was created.
 
 A node "has error" if itself is a syntax error or contains any syntax
-errors.  */)
+errors.
+
+A node is "live" if its parser is not deleted and its buffer is
+live.  */)
   (Lisp_Object node, Lisp_Object property)
 {
   if (NILP (node)) return Qnil;
@@ -1947,9 +1960,11 @@ errors.  */)
     result = ts_node_is_extra (treesit_node);
   else if (EQ (property, Qhas_error))
     result = ts_node_has_error (treesit_node);
+  else if (EQ (property, Qlive))
+    result = treesit_parser_live_p (XTS_NODE (node)->parser);
   else
     signal_error ("Expecting `named', `missing', `extra', "
-                 "`outdated', or `has-error', but got",
+                  "`outdated', `has-error', or `live', but got",
                  property);
   return result ? Qt : Qnil;
 }
@@ -3135,13 +3150,13 @@ the way.  PREDICATE is a regexp string that matches 
against each
 node's type, or a function that takes a node and returns nil/non-nil.
 
 By default, only traverse named nodes, but if ALL is non-nil, traverse
-all nodes.  If BACKWARD is non-nil, traverse backwards.  If LIMIT is
+all nodes.  If BACKWARD is non-nil, traverse backwards.  If DEPTH is
 non-nil, only traverse nodes up to that number of levels down in the
-tree.  If LIMIT is nil, default to 1000.
+tree.  If DEPTH is nil, default to 1000.
 
 Return the first matched node, or nil if none matches.  */)
   (Lisp_Object node, Lisp_Object predicate, Lisp_Object backward,
-   Lisp_Object all, Lisp_Object limit)
+   Lisp_Object all, Lisp_Object depth)
 {
   CHECK_TS_NODE (node);
   CHECK_TYPE (STRINGP (predicate) || FUNCTIONP (predicate),
@@ -3152,10 +3167,10 @@ Return the first matched node, or nil if none matches.  
*/)
   /* We use a default limit of 1000.  See bug#59426 for the
      discussion.  */
   ptrdiff_t the_limit = treesit_recursion_limit;
-  if (!NILP (limit))
+  if (!NILP (depth))
     {
-      CHECK_FIXNUM (limit);
-      the_limit = XFIXNUM (limit);
+      CHECK_FIXNUM (depth);
+      the_limit = XFIXNUM (depth);
     }
 
   treesit_initialize ();
@@ -3307,8 +3322,8 @@ If PROCESS-FN is non-nil, it should be a function of one 
argument.  In
 that case, instead of returning the matched nodes, pass each node to
 PROCESS-FN, and use its return value instead.
 
-If non-nil, LIMIT is the number of levels to go down the tree from
-ROOT.  If LIMIT is nil or omitted, it defaults to 1000.
+If non-nil, DEPTH is the number of levels to go down the tree from
+ROOT.  If DEPTH is nil or omitted, it defaults to 1000.
 
 Each node in the returned tree looks like (NODE . (CHILD ...)).  The
 root of this tree might be nil, if ROOT doesn't match PREDICATE.
@@ -3319,7 +3334,7 @@ PREDICATE can also be a function that takes a node and 
returns
 nil/non-nil, but it is slower and more memory consuming than using
 a regexp.  */)
   (Lisp_Object root, Lisp_Object predicate, Lisp_Object process_fn,
-   Lisp_Object limit)
+   Lisp_Object depth)
 {
   CHECK_TS_NODE (root);
   CHECK_TYPE (STRINGP (predicate) || FUNCTIONP (predicate),
@@ -3331,10 +3346,10 @@ a regexp.  */)
   /* We use a default limit of 1000.  See bug#59426 for the
      discussion.  */
   ptrdiff_t the_limit = treesit_recursion_limit;
-  if (!NILP (limit))
+  if (!NILP (depth))
     {
-      CHECK_FIXNUM (limit);
-      the_limit = XFIXNUM (limit);
+      CHECK_FIXNUM (depth);
+      the_limit = XFIXNUM (depth);
     }
 
   treesit_initialize ();
@@ -3448,6 +3463,7 @@ syms_of_treesit (void)
   DEFSYM (Qextra, "extra");
   DEFSYM (Qoutdated, "outdated");
   DEFSYM (Qhas_error, "has-error");
+  DEFSYM (Qlive, "live");
 
   DEFSYM (QCanchor, ":anchor");
   DEFSYM (QCequal, ":equal");
diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el
index a2ab3be7cd..5aa12e8aa0 100644
--- a/test/src/treesit-tests.el
+++ b/test/src/treesit-tests.el
@@ -100,6 +100,7 @@
       (should (eq nil (treesit-node-check root-node 'missing)))
       (should (eq nil (treesit-node-check root-node 'extra)))
       (should (eq nil (treesit-node-check root-node 'has-error)))
+      (should (eq t (treesit-node-check root-node 'live)))
       ;; `treesit-node-child'.
       (setq doc-node (treesit-node-child root-node 0))
       (should (equal "array" (treesit-node-type doc-node)))
@@ -160,7 +161,18 @@
                     :type 'args-out-of-range)
       ;; `treesit-node-eq'.
       (should (treesit-node-eq root-node root-node))
-      (should (not (treesit-node-eq root-node doc-node))))))
+      (should (not (treesit-node-eq root-node doc-node)))
+
+      ;; Further test for `treesit-node-check'.
+      (treesit-parser-delete parser)
+      (should (equal nil (treesit-node-check root-node 'live)))
+      ;; Recreate parser.
+      (setq parser (treesit-parser-create 'json))
+      (setq root-node (treesit-parser-root-node
+                       parser))
+      (should (equal t (treesit-node-check root-node 'live)))
+      (kill-buffer)
+      (should (equal nil (treesit-node-check root-node 'live))))))
 
 ;;; Indirect buffer
 



reply via email to

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