emacs-diffs
[Top][All Lists]
Advanced

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

feature/pgtk 78a3933: Merge remote-tracking branch 'origin/master' into


From: Po Lu
Subject: feature/pgtk 78a3933: Merge remote-tracking branch 'origin/master' into feature/pgtk
Date: Wed, 1 Dec 2021 20:21:26 -0500 (EST)

branch: feature/pgtk
commit 78a3933b62c1c83a6a4d54c9bc65faf069aa83dc
Merge: 6e5c2fb 01a6c0b
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Merge remote-tracking branch 'origin/master' into feature/pgtk
---
 doc/emacs/dired.texi                               |   8 ++
 doc/emacs/display.texi                             |  25 +++-
 doc/emacs/mule.texi                                |  13 ++
 doc/lispref/display.texi                           |   7 +
 etc/NEWS                                           |  18 +++
 lisp/dired.el                                      |  51 ++++++-
 lisp/emacs-lisp/cconv.el                           |  31 ++++-
 lisp/emacs-lisp/cl-macs.el                         |   2 +-
 lisp/emacs-lisp/comp-cstr.el                       |  64 ++++-----
 lisp/emacs-lisp/comp.el                            |  16 +--
 lisp/faces.el                                      |   9 ++
 lisp/files.el                                      |  33 ++---
 lisp/gnus/gnus-art.el                              |   2 +-
 lisp/international/characters.el                   |  55 +++-----
 lisp/ls-lisp.el                                    |  13 +-
 lisp/man.el                                        |  32 +++--
 lisp/net/shr.el                                    |   2 +-
 lisp/pixel-scroll.el                               |  39 +++---
 lisp/textmodes/glyphless-mode.el                   |  67 +++++++++
 lisp/textmodes/pixel-fill.el                       |  24 ++--
 lisp/textmodes/table.el                            | 102 +++++++-------
 src/w32term.c                                      |   4 +-
 .../insert-directory/test_dir/bar                  |   0
 .../insert-directory/test_dir/foo                  |   0
 .../insert-directory/test_dir_other/bar            |   0
 .../insert-directory/test_dir_other/foo            |   0
 test/lisp/dired-tests.el                           |  74 ++++++++++
 test/lisp/emacs-lisp/bytecomp-tests.el             |  43 ++++++
 test/lisp/emacs-lisp/cconv-tests.el                | 152 +++++++++++++++++++++
 test/lisp/files-tests.el                           |  74 ----------
 30 files changed, 665 insertions(+), 295 deletions(-)

diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi
index 704850e..0edd8bc 100644
--- a/doc/emacs/dired.texi
+++ b/doc/emacs/dired.texi
@@ -1567,6 +1567,14 @@ rotation is lossless, and uses an external utility called
 @node Misc Dired Features
 @section Other Dired Features
 
+@vindex dired-free-space
+  By default, Dired will display the available space on the disk in
+the first line.  This is the @code{first} value of the
+@code{dired-free-space} variable.  If you set this to
+@code{separate} instead, Dired will display this on a separate line
+(including the space the files in the current directory takes).  If
+you set this to @code{nil}, the free space isn't displayed at all.
+
 @kindex + @r{(Dired)}
 @findex dired-create-directory
   The command @kbd{+} (@code{dired-create-directory}) reads a
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index 90044b1..15cad88 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -642,24 +642,41 @@ apply them to specific text when you want the effects 
they produce.
 @item default
 This face is used for ordinary text that doesn't specify any face.
 Its background color is used as the frame's background color.
+
 @item bold
 This face uses a bold variant of the default font.
+
 @item italic
 This face uses an italic variant of the default font.
+
 @item bold-italic
 This face uses a bold italic variant of the default font.
+
 @item underline
 This face underlines text.
+
 @item fixed-pitch
 This face forces use of a fixed-width font.  It's reasonable to
 customize this face to use a different fixed-width font, if you like,
 but you should not make it a variable-width font.
+
 @item fixed-pitch-serif
 This face is like @code{fixed-pitch}, except the font has serifs and
 looks more like traditional typewriting.
+
 @cindex @code{variable-pitch} face
 @item variable-pitch
-This face forces use of a variable-width font.
+This face forces use of a variable-width (i.e., proportional) font.
+The font size picked for this face matches the font picked for the
+default (usually fixed-width) font.
+
+@item variable-pitch-text
+This is like the @code{variable-pitch} face (from which it inherits),
+but is slightly larger.  A proportional font of the same height as a
+monospace font usually appears visually smaller, and can therefore be
+harder to read.  When displaying longer texts, this face can be a good
+choice over the (slightly smaller) @code{variable-pitch} face.
+
 @cindex @code{shadow} face
 @item shadow
 This face is used for making the text less noticeable than the surrounding
@@ -1673,6 +1690,12 @@ characters more prominent on display.  @xref{Glyphless 
Chars,,
 Glyphless Character Display, elisp, The Emacs Lisp Reference Manual},
 for details.
 
+@findex glyphless-display-mode
+  The @code{glyphless-display-mode} minor mode can be used to toggle
+the display of glyphless characters in the current buffer.  The
+glyphless characters will be displayed as boxes with acronyms of their
+names inside.
+
 @cindex curly quotes, and terminal capabilities
 @cindex curved quotes, and terminal capabilities
 @cindex @code{homoglyph} face
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 83c775d..121d696 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -1992,3 +1992,16 @@ or right of the current screen position, moving to the 
next or
 previous screen line as appropriate.  Note that this might potentially
 move point many buffer positions away, depending on the surrounding
 bidirectional context.
+
+@cindex bidi formatting control characters
+  Bidirectional text sometimes uses special formatting characters to
+affect the reordering of text for display.  The @sc{lrm} and @sc{rlm}
+characters, mentioned above, are two such characters, but there are
+more of them.  They are by default displayed as thin space glyphs on
+GUI frames, and as simple spaces on text-mode frames.  If you want to
+be aware of these special control characters, so that their effect on
+display does not come as a surprise, you can turn on the
+@code{glyphless-display-mode} (@pxref{Text Display}).  This minor mode
+will cause these formatting characters to be displayed as acronyms
+inside a small box, so that they stand out on display, and make their
+effect easier to understand.
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index f37b351..275c15e 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -8193,7 +8193,14 @@ there is no available font (on a graphical display), and 
characters
 which cannot be encoded by the terminal's coding system (on a text
 terminal).
 
+@vindex glyphless-display-mode
+The @code{glyphless-display-mode} minor mode can be used to toggle
+displaying glyphless characters in a convenient manner in the current
+buffer.  If this mode is enabled, all the glyphless characters are
+displayed as boxes that display acronyms of their character names.
+
 @defvar glyphless-char-display
+For more fine-grained (and global) control, this variable can be used.
 The value of this variable is a char-table which defines glyphless
 characters and how they are displayed.  Each entry must be one of the
 following display methods:
diff --git a/etc/NEWS b/etc/NEWS
index 352d189..f1f1512 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -76,6 +76,13 @@ time.
 * Changes in Emacs 29.1
 
 +++
+** New face 'variable-pitch-text'.
+This face is like 'variable-pitch' (from which it inherits), but is
+slightly larger, which should help with the visual size differences
+between the default, non-proportional font and proportional fonts when
+mixed.
+
++++
 ** New face 'mode-line-active'.
 This inherits from the 'mode-line' face, but is the face actually used
 on the mode lines (along with 'mode-line-inactive').
@@ -295,6 +302,10 @@ received.
 
 * Changes in Specialized Modes and Packages in Emacs 29.1
 
+** New minor mode 'glyphless-display-mode'.
+This allows an easy way to toggle seeing all glyphless characters in
+the current buffer.
+
 ** Registers
 
 +++
@@ -578,6 +589,13 @@ updating the thumbnail file.
 
 ** Dired
 
+*** New user option 'dired-free-space'.
+Dired will now, by default, include the free space in the first line
+instead of having it on a separate line.  To get the previous
+behaviour back, say:
+
+    (setq dired-free-space 'separate)
+
 ---
 *** New user option 'dired-make-directory-clickable'.
 If non-nil (which is the default), hitting 'RET' or 'mouse-1' on
diff --git a/lisp/dired.el b/lisp/dired.el
index 9280c08..c8add87 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -209,6 +209,17 @@ If a character, new links are unconditionally marked with 
that character."
                 (character :tag "Mark"))
   :group 'dired-mark)
 
+(defcustom dired-free-space 'first
+  "Whether to display free disk space in dired buffers.
+If nil, don't display.
+If `separate', display on a separate line (along with used count).
+If `first', display the free disk space on the first line."
+  :type '(choice (const :tag "On a separate line" separate)
+                 (const :tag "On the first line" first)
+                 (const :tag "Don't display" nil))
+  :version "29.1"
+  :group 'dired)
+
 (defcustom dired-dwim-target nil
   "If non-nil, Dired tries to guess a default target directory.
 This means: if there is a Dired buffer displayed in some window,
@@ -1614,15 +1625,51 @@ see `dired-use-ls-dired' for more details.")
          ;; by its expansion, so it does not matter whether what we insert
          ;; here is fully expanded, but it should be absolute.
          (insert "  " (or (car-safe (insert-directory-wildcard-in-dir-p dir))
-                           (directory-file-name (file-name-directory dir))) 
":\n")
+                           (directory-file-name (file-name-directory dir)))
+                  ":\n")
          (setq content-point (point)))
        (when wildcard
          ;; Insert "wildcard" line where "total" line would be for a full dir.
          (insert "  wildcard " (or (cdr-safe 
(insert-directory-wildcard-in-dir-p dir))
                                     (file-name-nondirectory dir))
-                  "\n")))
+                  "\n"))
+        (setq content-point (dired--insert-disk-space opoint dir)))
       (dired-insert-set-properties content-point (point)))))
 
+(defun dired--insert-disk-space (beg file)
+  ;; Try to insert the amount of free space.
+  (save-excursion
+    (goto-char beg)
+    ;; First find the line to put it on.
+    (if (not (re-search-forward "^ *\\(total\\)" nil t))
+        beg
+      (if (or (not dired-free-space)
+              (eq dired-free-space 'first))
+          (delete-region (match-beginning 0) (line-beginning-position 2))
+        ;; Replace "total" with "total used in directory" to
+        ;; avoid confusion.
+        (replace-match "total used in directory" nil nil nil 1))
+      (when-let ((available (get-free-disk-space file)))
+        (cond
+         ((eq dired-free-space 'separate)
+         (end-of-line)
+         (insert " available " available)
+          (forward-line 1)
+          (point))
+         ((eq dired-free-space 'first)
+          (goto-char beg)
+          (when (and (looking-at " */")
+                     (progn
+                       (end-of-line)
+                       (eq (char-after (1- (point))) ?:)))
+            (put-text-property (1- (point)) (point)
+                               'display
+                               (concat ": (" available " available)")))
+          (forward-line 1)
+          (point))
+         (t
+          beg))))))
+
 (defun dired-insert-set-properties (beg end)
   "Add various text properties to the lines in the region, from BEG to END."
   (save-excursion
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index 03e109f..7cec91b 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -304,6 +304,25 @@ of converted forms."
             `(,@(nreverse special-forms) ,@(macroexp-unprogn body))))
       funcbody)))
 
+(defun cconv--lifted-arg (var env)
+  "The argument to use for VAR in λ-lifted calls according to ENV.
+This is used when VAR is being shadowed; we may still need its value for
+such calls."
+  (let ((mapping (cdr (assq var env))))
+    (pcase-exhaustive mapping
+      (`(internal-get-closed-var . ,_)
+       ;; The variable is captured.
+       mapping)
+      (`(car-safe ,exp)
+       ;; The variable is mutably captured; skip
+       ;; the indirection step because the variable is
+       ;; passed "by reference" to the λ-lifted function.
+       exp)
+      (_
+       ;; The variable is not captured; use the (shadowed) variable value.
+       ;; (If the mapping is `(car-safe SYMBOL)', SYMBOL is always VAR.
+       var))))
+
 (defun cconv-convert (form env extend)
   ;; This function actually rewrites the tree.
   "Return FORM with all its lambdas changed so they are closed.
@@ -428,10 +447,11 @@ places where they originally did not directly appear."
                  ;; One of the lambda-lifted vars is shadowed, so add
                  ;; a reference to the outside binding and arrange to use
                  ;; that reference.
-                 (let ((closedsym (make-symbol (format "closed-%s" var))))
+                 (let ((var-def (cconv--lifted-arg var env))
+                       (closedsym (make-symbol (format "closed-%s" var))))
                    (setq new-env (cconv--remap-llv new-env var closedsym))
                    (setq new-extend (cons closedsym (remq var new-extend)))
-                   (push `(,closedsym ,var) binders-new)))
+                   (push `(,closedsym ,var-def) binders-new)))
 
                ;; We push the element after redefined free variables are
                ;; processed.  This is important to avoid the bug when free
@@ -449,14 +469,13 @@ places where they originally did not directly appear."
          ;; before we know that the var will be in `new-extend' (bug#24171).
          (dolist (binder binders-new)
            (when (memq (car-safe binder) new-extend)
-             ;; One of the lambda-lifted vars is shadowed, so add
-             ;; a reference to the outside binding and arrange to use
-             ;; that reference.
+             ;; One of the lambda-lifted vars is shadowed.
              (let* ((var (car-safe binder))
+                    (var-def (cconv--lifted-arg var env))
                     (closedsym (make-symbol (format "closed-%s" var))))
                (setq new-env (cconv--remap-llv new-env var closedsym))
                (setq new-extend (cons closedsym (remq var new-extend)))
-               (push `(,closedsym ,var) binders-new)))))
+               (push `(,closedsym ,var-def) binders-new)))))
 
        `(,letsym ,(nreverse binders-new)
                  . ,(mapcar (lambda (form)
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 1852471..9c9a778 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -3050,7 +3050,7 @@ To see the documentation for a defined struct type, use
                             `(,predicate cl-x))))
     (when pred-form
       (push `(,defsym ,predicate (cl-x)
-               (declare (side-effect-free error-free))
+               (declare (side-effect-free error-free) (pure t))
                ,(if (eq (car pred-form) 'and)
                     (append pred-form '(t))
                   `(and ,pred-form t)))
diff --git a/lisp/emacs-lisp/comp-cstr.el b/lisp/emacs-lisp/comp-cstr.el
index 5518cdb..3e81619 100644
--- a/lisp/emacs-lisp/comp-cstr.el
+++ b/lisp/emacs-lisp/comp-cstr.el
@@ -70,7 +70,7 @@
                                        (irange &aux
                                                (range (list irange))
                                                (typeset ())))
-                         (:copier comp-cstr-shallow-copy))
+                         (:copier nil))
   "Internal representation of a type/value constraint."
   (typeset '(t) :type list
            :documentation "List of possible types the mvar can assume.
@@ -133,6 +133,14 @@ Integer values are handled in the `range' slot.")
                     :range (copy-tree (range cstr))
                     :neg (neg cstr))))
 
+(defsubst comp-cstr-shallow-copy (dst src)
+  "Copy the content of SRC into DST."
+  (with-comp-cstr-accessors
+    (setf (range dst) (range src)
+          (valset dst) (valset src)
+          (typeset dst) (typeset src)
+          (neg dst) (neg src))))
+
 (defsubst comp-cstr-empty-p (cstr)
   "Return t if CSTR is equivalent to the nil type specifier or nil otherwise."
   (with-comp-cstr-accessors
@@ -438,10 +446,7 @@ Return them as multiple value."
                                                        ext-range)
                             ext-range)
               (neg dst) nil)
-      (setf (typeset dst) (typeset old-dst)
-            (valset dst) (valset old-dst)
-            (range dst) (range old-dst)
-            (neg dst) (neg old-dst)))))
+      (comp-cstr-shallow-copy dst old-dst))))
 
 (defmacro comp-cstr-set-range-for-arithm (dst src1 src2 &rest range-body)
   ;; Prevent some code duplication for `comp-cstr-add-2'
@@ -581,10 +586,8 @@ DST is returned."
                                                     (when (range pos)
                                                       '(integer)))))
                                  (typeset neg)))
-              (setf (typeset dst) (typeset pos)
-                    (valset dst) (valset pos)
-                    (range dst) (range pos)
-                    (neg dst) nil)
+              (comp-cstr-shallow-copy dst pos)
+              (setf (neg dst) nil)
               (cl-return-from comp-cstr-union-1-no-mem dst))
 
             ;; Verify disjoint condition between positive types and
@@ -631,15 +634,9 @@ DST is returned."
                         (comp-range-negation (range neg))
                         (range pos))))))
 
-            (if (comp-cstr-empty-p neg)
-                (setf (typeset dst) (typeset pos)
-                      (valset dst) (valset pos)
-                      (range dst) (range pos)
-                      (neg dst) nil)
-              (setf (typeset dst) (typeset neg)
-                    (valset dst) (valset neg)
-                    (range dst) (range neg)
-                    (neg dst) (neg neg)))))
+            (comp-cstr-shallow-copy dst (if (comp-cstr-empty-p neg)
+                                            pos
+                                          neg))))
 
         ;; (not null) => t
         (when (and (neg dst)
@@ -663,10 +660,7 @@ DST is returned."
                      (mapcar #'comp-cstr-copy srcs)
                      (apply #'comp-cstr-union-1-no-mem range srcs)
                      mem-h))))
-      (setf (typeset dst) (typeset res)
-            (valset dst) (valset res)
-            (range dst) (range res)
-            (neg dst) (neg res))
+      (comp-cstr-shallow-copy dst res)
       res)))
 
 (cl-defun comp-cstr-intersection-homogeneous (dst &rest srcs)
@@ -753,10 +747,8 @@ Non memoized version of `comp-cstr-intersection-no-mem'."
             ;; In case pos is not relevant return directly the content
             ;; of neg.
             (when (equal (typeset pos) '(t))
-              (setf (typeset dst) (typeset neg)
-                    (valset dst) (valset neg)
-                    (range dst) (range neg)
-                    (neg dst) t)
+              (comp-cstr-shallow-copy dst neg)
+              (setf (neg dst) t)
 
               ;; (not t) => nil
               (when (and (null (valset dst))
@@ -800,10 +792,8 @@ Non memoized version of `comp-cstr-intersection-no-mem'."
                   (cl-set-difference (valset pos) (valset neg)))
 
             ;; Return a non negated form.
-            (setf (typeset dst) (typeset pos)
-                  (valset dst) (valset pos)
-                  (range dst) (range pos)
-                  (neg dst) nil)))
+            (comp-cstr-shallow-copy dst pos)
+            (setf (neg dst) nil)))
         dst))))
 
 
@@ -883,7 +873,7 @@ Non memoized version of `comp-cstr-intersection-no-mem'."
   "Constraint OP1 being = OP2 setting the result into DST."
   (with-comp-cstr-accessors
     (cl-flet ((relax-cstr (cstr)
-                (setf cstr (comp-cstr-shallow-copy cstr))
+                (setf cstr (copy-sequence cstr))
                 ;; If can be any float extend it to all integers.
                 (when (memq 'float (typeset cstr))
                   (setf (range cstr) '((- . +))))
@@ -1008,10 +998,7 @@ DST is returned."
                      (mapcar #'comp-cstr-copy srcs)
                      (apply #'comp-cstr-intersection-no-mem srcs)
                      mem-h))))
-      (setf (typeset dst) (typeset res)
-            (valset dst) (valset res)
-            (range dst) (range res)
-            (neg dst) (neg res))
+      (comp-cstr-shallow-copy dst res)
       res)))
 
 (defun comp-cstr-intersection-no-hashcons (dst &rest srcs)
@@ -1067,10 +1054,9 @@ DST is returned."
             (valset dst) ()
             (range dst) nil
             (neg dst) nil))
-     (t (setf (typeset dst) (typeset src)
-              (valset dst) (valset src)
-              (range dst) (range src)
-              (neg dst) (not (neg src)))))
+     (t
+      (comp-cstr-shallow-copy dst src)
+      (setf (neg dst) (not (neg src)))))
     dst))
 
 (defun comp-cstr-value-negation (dst src)
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index 0a10505..b512240 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -3086,13 +3086,6 @@ Forward propagate immediate involed in assignments." ; 
FIXME: Typo.  Involved or
             (`(setimm ,lval ,v)
              (setf (comp-cstr-imm lval) v))))))
 
-(defun comp-mvar-propagate (lval rval)
-  "Propagate into LVAL properties of RVAL."
-  (setf (comp-mvar-typeset lval) (comp-mvar-typeset rval)
-        (comp-mvar-valset lval) (comp-mvar-valset rval)
-        (comp-mvar-range lval) (comp-mvar-range rval)
-        (comp-mvar-neg lval) (comp-mvar-neg rval)))
-
 (defun comp-function-foldable-p (f args)
   "Given function F called with ARGS, return non-nil when optimizable."
   (and (comp-function-pure-p f)
@@ -3142,10 +3135,7 @@ Fold the call in case."
         (when (comp-cstr-empty-p cstr)
           ;; Store it to be rewritten as non local exit.
           (setf (comp-block-lap-non-ret-insn comp-block) insn))
-        (setf (comp-mvar-range lval) (comp-cstr-range cstr)
-              (comp-mvar-valset lval) (comp-cstr-valset cstr)
-              (comp-mvar-typeset lval) (comp-cstr-typeset cstr)
-              (comp-mvar-neg lval) (comp-cstr-neg cstr))))
+        (comp-cstr-shallow-copy lval cstr)))
     (cl-case f
       (+ (comp-cstr-add lval args))
       (- (comp-cstr-sub lval args))
@@ -3163,9 +3153,9 @@ Fold the call in case."
         (let ((f (comp-func-name (gethash f (comp-ctxt-funcs-h comp-ctxt)))))
           (comp-fwprop-call insn lval f args)))
        (_
-        (comp-mvar-propagate lval rval))))
+        (comp-cstr-shallow-copy lval rval))))
     (`(assume ,lval ,(and (pred comp-mvar-p) rval))
-     (comp-mvar-propagate lval rval))
+     (comp-cstr-shallow-copy lval rval))
     (`(assume ,lval (,kind . ,operands))
      (cl-case kind
        (and
diff --git a/lisp/faces.el b/lisp/faces.el
index 535fa44..9757987 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2381,6 +2381,15 @@ If you set `term-file-prefix' to nil, this function does 
nothing."
   "The basic variable-pitch face."
   :group 'basic-faces)
 
+(defface variable-pitch-text
+  '((t :inherit variable-pitch
+       :height 1.1))
+  "The proportional face used for longer texts.
+This is like the `variable-pitch' face, but is slightly bigger by
+default."
+  :version "29.1"
+  :group 'basic-faces)
+
 (defface shadow
   '((((class color grayscale) (min-colors 88) (background light))
      :foreground "grey50")
diff --git a/lisp/files.el b/lisp/files.el
index f72723a..07279c4 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7211,11 +7211,18 @@ DIRNAME is globbed by the shell if necessary.
 Prefix arg (second arg if noninteractive) means supply -l switch to `ls'.
 Actions controlled by variables `list-directory-brief-switches'
 and `list-directory-verbose-switches'."
-  (interactive (let ((pfx current-prefix-arg))
-                (list (read-directory-name (if pfx "List directory (verbose): "
-                                        "List directory (brief): ")
-                                      nil default-directory nil)
-                      pfx)))
+  (interactive
+   (let ((pfx current-prefix-arg))
+     (list (read-file-name
+            (if pfx "List directory (verbose): "
+             "List directory (brief): ")
+           nil default-directory t
+            nil
+            (lambda (file)
+              (or (file-directory-p file)
+                  (insert-directory-wildcard-in-dir-p
+                   (expand-file-name file)))))
+           pfx)))
   (let ((switches (if verbose list-directory-verbose-switches
                    list-directory-brief-switches))
        buffer)
@@ -7666,21 +7673,7 @@ normally equivalent short `-D' option is just passed on 
to
                                            (if val coding-no-eol coding))
                      (if val
                          (put-text-property pos (point)
-                                            'dired-filename t)))))))
-
-         (if full-directory-p
-             ;; Try to insert the amount of free space.
-             (save-excursion
-               (goto-char beg)
-               ;; First find the line to put it on.
-               (when (re-search-forward "^ *\\(total\\)" nil t)
-                 ;; Replace "total" with "total used in directory" to
-                 ;; avoid confusion.
-                 (replace-match "total used in directory" nil nil nil 1)
-                 (let ((available (get-free-disk-space file)))
-                   (when available
-                     (end-of-line)
-                     (insert " available " available))))))))))
+                                            'dired-filename t)))))))))))
 
 (defun insert-directory-adj-pos (pos error-lines)
   "Convert `ls --dired' file name position value POS to a buffer position.
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index 554381e..07cb686 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -769,7 +769,7 @@ Obsolete; use the face `gnus-signature' for customizations 
instead."
   :group 'gnus-article-signature)
 
 (defface gnus-header
-  '((t :inherit variable-pitch))
+  '((t :inherit variable-pitch-text))
   "Base face used for all Gnus header faces.
 All the other `gnus-header-' faces inherit from this face."
   :version "29.1"
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index 3a8e968..3b8924f 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -1522,7 +1522,7 @@ Setup `char-width-table' appropriate for non-CJK language 
environment."
 This function updates the char-table `glyphless-char-display',
 and is intended to be used in the `:set' attribute of the
 option `glyphless-char-display'."
-  (when value
+  (when variable
     (set-default variable value))
   (dolist (elt value)
     (let ((target (car elt))
@@ -1576,6 +1576,19 @@ option `glyphless-char-display'."
     (set-char-table-range chartable (cons from to) method)))
 
 ;;; Control of displaying glyphless characters.
+(define-widget 'glyphless-char-display-method 'lazy
+  "Display method for glyphless characters."
+  :group 'mule
+  :format "%v"
+  :value 'thin-space
+  :type
+  '(choice
+    (const :tag "Don't display" zero-width)
+    (const :tag "Display as thin space" thin-space)
+    (const :tag "Display as empty box" empty-box)
+    (const :tag "Display acronym" acronym)
+    (const :tag "Display hex code in a box" hex-code)))
+
 (defcustom glyphless-char-display-control
   '((format-control . thin-space)
     (variation-selectors . thin-space)
@@ -1619,41 +1632,11 @@ function (`update-glyphless-char-display'), which 
updates
   :version "28.1"
   :type '(alist :key-type (symbol :tag "Character Group")
                :value-type (symbol :tag "Display Method"))
-  :options '((c0-control
-             (choice :value thin-space
-                      (const :tag "Don't display" zero-width)
-                     (const :tag "Display as thin space" thin-space)
-                     (const :tag "Display as empty box" empty-box)
-                     (const :tag "Display acronym" acronym)
-                     (const :tag "Display hex code in a box" hex-code)))
-            (c1-control
-             (choice :value thin-space
-                      (const :tag "Don't display" zero-width)
-                     (const :tag "Display as thin space" thin-space)
-                     (const :tag "Display as empty box" empty-box)
-                     (const :tag "Display acronym" acronym)
-                     (const :tag "Display hex code in a box" hex-code)))
-            (format-control
-             (choice :value thin-space
-                      (const :tag "Don't display" zero-width)
-                     (const :tag "Display as thin space" thin-space)
-                     (const :tag "Display as empty box" empty-box)
-                     (const :tag "Display acronym" acronym)
-                     (const :tag "Display hex code in a box" hex-code)))
-            (variation-selectors
-             (choice :value thin-space
-                      (const :tag "Don't display" zero-width)
-                     (const :tag "Display as thin space" thin-space)
-                     (const :tag "Display as empty box" empty-box)
-                     (const :tag "Display acronym" acronym)
-                     (const :tag "Display hex code in a box" hex-code)))
-            (no-font
-             (choice :value hex-code
-                      (const :tag "Don't display" zero-width)
-                     (const :tag "Display as thin space" thin-space)
-                     (const :tag "Display as empty box" empty-box)
-                     (const :tag "Display acronym" acronym)
-                     (const :tag "Display hex code in a box" hex-code))))
+  :options '((c0-control glyphless-char-display-method)
+            (c1-control glyphless-char-display-method)
+            (format-control glyphless-char-display-method)
+            (variation-selectors glyphless-char-display-method)
+            (no-font (glyphless-char-display-method :value hex-code)))
   :set 'update-glyphless-char-display
   :group 'display)
 
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el
index eea8089..25d1963 100644
--- a/lisp/ls-lisp.el
+++ b/lisp/ls-lisp.el
@@ -337,18 +337,7 @@ are also supported; unsupported long options are silently 
ignored."
                 (ls-lisp-insert-directory
                  file switches (ls-lisp-time-index switches)
                  nil full-directory-p))
-            (signal (car err) (cdr err)))))
-       ;; Try to insert the amount of free space.
-       (save-excursion
-         (goto-char (point-min))
-         ;; First find the line to put it on.
-         (when (re-search-forward "^total" nil t)
-           (let ((available (get-free-disk-space orig-file)))
-             (when available
-               ;; Replace "total" with "total used", to avoid confusion.
-               (replace-match "total used in directory")
-               (end-of-line)
-               (insert " available " available)))))))))
+            (signal (car err) (cdr err)))))))))
 (advice-add 'insert-directory :around #'ls-lisp--insert-directory)
 
 (defun ls-lisp-insert-directory
diff --git a/lisp/man.el b/lisp/man.el
index 2bde1fc..fff31ba 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1334,7 +1334,7 @@ default type, `Man-xref-man-page' is used for the 
buttons."
 
 (defun Man-highlight-references0 (start-section regexp button-pos target type)
   ;; Based on `Man-build-references-alist'
-  (when (or (null start-section)        ;; Search regardless of sections.
+  (when (or (null start-section) ;; Search regardless of sections.
             ;; Section header is in this chunk.
             (Man-find-section start-section))
     (let ((end (if start-section
@@ -1347,18 +1347,24 @@ default type, `Man-xref-man-page' is used for the 
buttons."
                 (goto-char (point-min))
                 nil)))
       (while (re-search-forward regexp end t)
-       ;; An overlay button is preferable because the underlying text
-       ;; may have text property highlights (Bug#7881).
-       (make-button
-        (match-beginning button-pos)
-        (match-end button-pos)
-        'type type
-        'Man-target-string (cond
-                            ((numberp target)
-                             (match-string target))
-                            ((functionp target)
-                             target)
-                            (t nil)))))))
+        (let ((b (match-beginning button-pos))
+              (e (match-end button-pos))
+              (match (match-string button-pos)))
+          ;; Some lists of references end with ", and ...".  Chop the
+          ;; "and" bit off before making a button.
+          (when (string-match "\\`and +" match)
+            (setq b (+ b (- (match-end 0) (match-beginning 0)))))
+         ;; An overlay button is preferable because the underlying text
+         ;; may have text property highlights (Bug#7881).
+         (make-button
+          b e
+          'type type
+          'Man-target-string (cond
+                              ((numberp target)
+                               (match-string target))
+                              ((functionp target)
+                               target)
+                              (t nil))))))))
 
 (defun Man-cleanup-manpage (&optional interactive)
   "Remove overstriking and underlining from the current buffer.
diff --git a/lisp/net/shr.el b/lisp/net/shr.el
index d4c7aaf..ee0e824 100644
--- a/lisp/net/shr.el
+++ b/lisp/net/shr.el
@@ -163,7 +163,7 @@ cid: URL as the argument.")
 (defvar shr-put-image-function #'shr-put-image
   "Function called to put image and alt string.")
 
-(defface shr-text '((t :inherit variable-pitch))
+(defface shr-text '((t :inherit variable-pitch-text))
   "Face used for rendering text."
   :version "29.1")
 
diff --git a/lisp/pixel-scroll.el b/lisp/pixel-scroll.el
index 6567153..9cd2352 100644
--- a/lisp/pixel-scroll.el
+++ b/lisp/pixel-scroll.el
@@ -91,7 +91,7 @@ is always with pixel resolution.")
 (defvar pixel-last-scroll-time 0
   "Time when the last scrolling was made, in second since the epoch.")
 
-(defvar x-coalesce-scroll-events)
+(defvar mwheel-coalesce-scroll-events)
 
 (defvar pixel-scroll-precision-mode-map
   (let ((map (make-sparse-keymap)))
@@ -412,22 +412,25 @@ the height of the current window."
   (let* ((edges (window-edges nil t nil t))
          (max-y (- (nth 3 edges)
                    (nth 1 edges)))
-         (usable-height max-y))
-    (when-let* ((posn (posn-at-point))
-               (current-y (+ (cdr (posn-x-y posn))
-                             (line-pixel-height))))
-      (while (and (<= (- max-y current-y) delta)
-                  (<= (cdr (posn-object-width-height posn))
-                     usable-height))
-        (vertical-motion -1)
-        (setq current-y (- current-y (line-pixel-height))))
-      (when (and (>= (cdr (posn-object-width-height posn))
-                     usable-height)
-                 (let ((prev-line-height (save-excursion
-                                           (vertical-motion -1)
-                                           (line-pixel-height))))
-                   (<= 0 (- (cdr (posn-x-y posn)) prev-line-height))))
-        (vertical-motion -1)))
+         (usable-height max-y)
+         (posn (posn-at-x-y 0 (+ (window-tab-line-height)
+                                 (window-header-line-height)
+                                 (- max-y delta))))
+         (point (posn-point posn))
+         (up-point (save-excursion
+                     (goto-char point)
+                     (vertical-motion -1)
+                     (point))))
+    (when (> (point) up-point)
+      (when (let ((pos-visible (pos-visible-in-window-p up-point nil t)))
+              (or (eq (length pos-visible) 2)
+                  (when-let* ((posn (posn-at-point up-point))
+                              (edges (window-edges nil t))
+                              (usable-height (- (nth 3 edges)
+                                                (nth 1 edges))))
+                    (> (cdr (posn-object-width-height posn))
+                       usable-height))))
+        (goto-char up-point)))
     (let ((current-vscroll (window-vscroll nil t)))
       (if (<= delta current-vscroll)
           (set-window-vscroll nil (- current-vscroll delta) t)
@@ -490,7 +493,7 @@ precisely, according to the turning of the mouse wheel."
   :global t
   :group 'mouse
   :keymap pixel-scroll-precision-mode-map
-  (setq x-coalesce-scroll-events
+  (setq mwheel-coalesce-scroll-events
         (not pixel-scroll-precision-mode)))
 
 (provide 'pixel-scroll)
diff --git a/lisp/textmodes/glyphless-mode.el b/lisp/textmodes/glyphless-mode.el
new file mode 100644
index 0000000..3aeb360
--- /dev/null
+++ b/lisp/textmodes/glyphless-mode.el
@@ -0,0 +1,67 @@
+;;; glyphless-mode.el --- minor mode for displaying glyphless characters  -*- 
lexical-binding: t; -*-
+
+;; Copyright (C) 2021 Free Software Foundation, Inc.
+
+;; Maintainer: emacs-devel@gnu.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(defcustom glyphless-mode-types '(all)
+  "Which glyphless characters to display.
+The value can be any of the groups supported by
+`glyphless-char-display-control' (which see), and in addition
+`all', for all glyphless characters."
+  :version "29.1"
+  :type '(repeat (choice (const :tag "All" all)
+                         (const :tag "No font" no-font)
+                         (const :tag "C0 Control" c0-control)
+                         (const :tag "C1 Control" c1-control)
+                         (const :tag "Format Control" format-control)
+                         (const :tag "Variation Selectors" variation-selectors)
+                         (const :tag "No Font" no-font)))
+  :group 'display)
+
+;;;###autoload
+(define-minor-mode glyphless-display-mode
+  "Minor mode for displaying glyphless characters in the current buffer.
+If enabled, all glyphless characters will be displayed as boxes
+that display their acronyms."
+  :lighter " Glyphless"
+  (if glyphless-display-mode
+      (progn
+        (setq-local glyphless-char-display
+                    (let ((table (make-display-table)))
+                      (set-char-table-parent table glyphless-char-display)
+                      table))
+        (glyphless-mode--setup))
+    (kill-local-variable 'glyphless-char-display)))
+
+(defun glyphless-mode--setup ()
+  (let ((types (if (memq 'all glyphless-mode-types)
+                   '(c0-control c1-control format-control
+                                variation-selectors no-font)
+                 glyphless-mode-types)))
+    (when types
+      (update-glyphless-char-display
+       nil (mapcar (lambda (e) (cons e 'acronym)) types)))))
+
+(provide 'glyphless-mode)
+
+;;; glyphless-mode.el ends here
diff --git a/lisp/textmodes/pixel-fill.el b/lisp/textmodes/pixel-fill.el
index 1115ba3..f69696e 100644
--- a/lisp/textmodes/pixel-fill.el
+++ b/lisp/textmodes/pixel-fill.el
@@ -90,10 +90,17 @@ prefix on subsequent lines."
         (goto-char (point-min))
         ;; First replace all whitespace with space.
         (while (re-search-forward "[ \t\n]+" nil t)
-          (if (or (= (match-beginning 0) start)
-                  (= (match-end 0) end))
-              (delete-region (match-beginning 0) (match-end 0))
-            (replace-match " ")))
+          (cond
+           ((or (= (match-beginning 0) start)
+                (= (match-end 0) end))
+            (delete-region (match-beginning 0) (match-end 0)))
+           ;; If there's just a single space here, don't replace.
+           ((not (and (= (- (match-end 0) (match-beginning 0)) 1)
+                      (= (char-after (match-beginning 0)) ?\s)))
+            (replace-match
+             ;; We need to use a space that has an appropriate width.
+             (propertize " " 'face
+                         (get-text-property (match-beginning 0) 'face))))))
         (goto-char start)
         (pixel-fill--fill-line pixel-width indentation)
         (goto-char (point-max))
@@ -120,10 +127,11 @@ prefix on subsequent lines."
       ;; Success; continue.
       (when (= (preceding-char) ?\s)
        (delete-char -1))
-      (insert ?\n)
-      (when (> indentation 0)
-        (insert (propertize " " 'display
-                            (list 'space :align-to (list indentation)))))
+      (unless (eobp)
+        (insert ?\n)
+        (when (> indentation 0)
+          (insert (propertize " " 'display
+                              (list 'space :align-to (list indentation))))))
       (setq start (point))
       (pixel-fill--goto-pixel width))))
 
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index fef5ad2..ca99d56 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -1195,6 +1195,21 @@ executing body forms.")
 (easy-menu-add-item (current-global-map)
                     '("menu-bar" "tools") table-global-menu-map)
 
+;;;###autoload
+(define-minor-mode table-fixed-width-mode
+  "Cell width is fixed when this is non-nil.
+Normally it should be nil for allowing automatic cell width expansion
+that widens a cell when it is necessary.  When non-nil, typing in a
+cell does not automatically expand the cell width.  A word that is too
+long to fit in a cell is chopped into multiple lines.  The chopped
+location is indicated by `table-word-continuation-char'.  This
+variable's value can be toggled by \\[table-fixed-width-mode] at
+run-time."
+  :tag "Fix Cell Width"
+  :group 'table
+  (table--finish-delayed-tasks)
+  (table--update-cell-face))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; Macros
@@ -1219,43 +1234,49 @@ original buffer's point is moved to the location that 
corresponds to
 the last cache point coordinate."
   (declare (debug (body)) (indent 0))
   (let ((height-expansion (make-symbol "height-expansion-var-symbol"))
-       (width-expansion (make-symbol "width-expansion-var-symbol")))
-    `(let (,height-expansion ,width-expansion)
+       (width-expansion (make-symbol "width-expansion-var-symbol"))
+        (fixed-width (make-symbol "fixed-width")))
+    `(let ((,fixed-width table-fixed-width-mode)
+           ,height-expansion ,width-expansion)
        ;; make sure cache has valid data unless it is explicitly inhibited.
        (unless table-inhibit-update
         (table-recognize-cell))
        (with-current-buffer (get-buffer-create table-cache-buffer-name)
-        ;; goto the cell coordinate based on 
`table-cell-cache-point-coordinate'.
-        (set-mark (table--goto-coordinate table-cell-cache-mark-coordinate))
-        (table--goto-coordinate table-cell-cache-point-coordinate)
-        (table--untabify-line)
-        ;; always reset before executing body forms because auto-fill behavior 
is the default.
-        (setq table-inhibit-auto-fill-paragraph nil)
-        ;; do the body
-        ,@body
-        ;; fill paragraph unless the body does not want to by setting 
`table-inhibit-auto-fill-paragraph'.
-        (unless table-inhibit-auto-fill-paragraph
-          (if (and table-cell-info-justify
-                   (not (eq table-cell-info-justify 'left)))
-              (table--fill-region (point-min) (point-max))
-            (table--fill-region
-             (save-excursion (forward-paragraph -1) (point))
-             (save-excursion (forward-paragraph 1) (point)))))
-        ;; keep the updated cell coordinate.
-        (setq table-cell-cache-point-coordinate (table--get-coordinate))
-        ;; determine the cell width expansion.
-        (setq ,width-expansion (table--measure-max-width))
-        (if (<= ,width-expansion table-cell-info-width) nil
-          (table--fill-region (point-min) (point-max) ,width-expansion)
-          ;; keep the updated cell coordinate.
-          (setq table-cell-cache-point-coordinate (table--get-coordinate)))
-        (setq ,width-expansion (- ,width-expansion table-cell-info-width))
-        ;; determine the cell height expansion.
-        (if (looking-at "\\s *\\'") nil
-          (goto-char (point-min))
-          (if (re-search-forward "\\(\\s *\\)\\'" nil t)
-              (goto-char (match-beginning 1))))
-        (setq ,height-expansion (- (cdr (table--get-coordinate)) (1- 
table-cell-info-height))))
+         (let ((table-fixed-width-mode ,fixed-width))
+          ;; Go to the cell coordinate based on
+          ;; `table-cell-cache-point-coordinate'.
+          (set-mark (table--goto-coordinate table-cell-cache-mark-coordinate))
+          (table--goto-coordinate table-cell-cache-point-coordinate)
+          (table--untabify-line)
+          ;; Always reset before executing body forms because
+          ;; auto-fill behavior is the default.
+          (setq table-inhibit-auto-fill-paragraph nil)
+          ;; Do the body
+          ,@body
+          ;; Fill paragraph unless the body does not want to by
+          ;; setting `table-inhibit-auto-fill-paragraph'.
+          (unless table-inhibit-auto-fill-paragraph
+            (if (and table-cell-info-justify
+                     (not (eq table-cell-info-justify 'left)))
+                (table--fill-region (point-min) (point-max))
+              (table--fill-region
+               (save-excursion (forward-paragraph -1) (point))
+               (save-excursion (forward-paragraph 1) (point)))))
+          ;; Keep the updated cell coordinate.
+          (setq table-cell-cache-point-coordinate (table--get-coordinate))
+          ;; Determine the cell width expansion.
+          (setq ,width-expansion (table--measure-max-width))
+          (if (<= ,width-expansion table-cell-info-width) nil
+            (table--fill-region (point-min) (point-max) ,width-expansion)
+            ;; Keep the updated cell coordinate.
+            (setq table-cell-cache-point-coordinate (table--get-coordinate)))
+          (setq ,width-expansion (- ,width-expansion table-cell-info-width))
+          ;; Determine the cell height expansion.
+          (if (looking-at "\\s *\\'") nil
+            (goto-char (point-min))
+            (if (re-search-forward "\\(\\s *\\)\\'" nil t)
+                (goto-char (match-beginning 1))))
+          (setq ,height-expansion (- (cdr (table--get-coordinate)) (1- 
table-cell-info-height)))))
        ;; now back to the table buffer.
        ;; expand the cell width in the table buffer if necessary.
        (if (> ,width-expansion 0)
@@ -2823,21 +2844,6 @@ or `top', `middle', `bottom' or `none' for vertical."
          (table--justify-cell-contents justify))))))
 
 ;;;###autoload
-(define-minor-mode table-fixed-width-mode
-  "Cell width is fixed when this is non-nil.
-Normally it should be nil for allowing automatic cell width expansion
-that widens a cell when it is necessary.  When non-nil, typing in a
-cell does not automatically expand the cell width.  A word that is too
-long to fit in a cell is chopped into multiple lines.  The chopped
-location is indicated by `table-word-continuation-char'.  This
-variable's value can be toggled by \\[table-fixed-width-mode] at
-run-time."
-  :tag "Fix Cell Width"
-  :group 'table
-  (table--finish-delayed-tasks)
-  (table--update-cell-face))
-
-;;;###autoload
 (defun table-query-dimension (&optional where)
   "Return the dimension of the current cell and the current table.
 The result is a list (cw ch tw th c r cells) where cw is the cell
diff --git a/src/w32term.c b/src/w32term.c
index 6b7cbbe..5c6a9fe 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -3251,10 +3251,10 @@ w32_construct_mouse_wheel (struct input_event *result, 
W32Msg *msg,
       int scroll_unit = max (w32_wheel_scroll_lines, 1), nlines;
       double value_to_report;
 
-      /* w32_wheel_scroll_lines == INT_MAX means the user asked for
+      /* w32_wheel_scroll_lines == UINT_MAX means the user asked for
         "entire page" to be the scroll unit.  We interpret that as
         the height of the window under the mouse pointer.  */
-      if (w32_wheel_scroll_lines == INT_MAX)
+      if (w32_wheel_scroll_lines == UINT_MAX)
        {
          Lisp_Object window = window_from_coordinates (f, p.x, p.y, NULL,
                                                        false, false);
diff --git a/test/lisp/files-resources/insert-directory/test_dir/bar 
b/test/lisp/dired-resources/insert-directory/test_dir/bar
similarity index 100%
rename from test/lisp/files-resources/insert-directory/test_dir/bar
rename to test/lisp/dired-resources/insert-directory/test_dir/bar
diff --git a/test/lisp/files-resources/insert-directory/test_dir/foo 
b/test/lisp/dired-resources/insert-directory/test_dir/foo
similarity index 100%
rename from test/lisp/files-resources/insert-directory/test_dir/foo
rename to test/lisp/dired-resources/insert-directory/test_dir/foo
diff --git a/test/lisp/files-resources/insert-directory/test_dir_other/bar 
b/test/lisp/dired-resources/insert-directory/test_dir_other/bar
similarity index 100%
rename from test/lisp/files-resources/insert-directory/test_dir_other/bar
rename to test/lisp/dired-resources/insert-directory/test_dir_other/bar
diff --git a/test/lisp/files-resources/insert-directory/test_dir_other/foo 
b/test/lisp/dired-resources/insert-directory/test_dir_other/foo
similarity index 100%
rename from test/lisp/files-resources/insert-directory/test_dir_other/foo
rename to test/lisp/dired-resources/insert-directory/test_dir_other/foo
diff --git a/test/lisp/dired-tests.el b/test/lisp/dired-tests.el
index ad1bca9..4379111 100644
--- a/test/lisp/dired-tests.el
+++ b/test/lisp/dired-tests.el
@@ -511,5 +511,79 @@
       (when (file-directory-p testdir)
         (delete-directory testdir t)))))
 
+;; `dired-insert-directory' output tests.
+(let* ((data-dir "insert-directory")
+       (test-dir (file-name-as-directory
+                  (ert-resource-file
+                   (concat data-dir "/test_dir"))))
+       (test-dir-other (file-name-as-directory
+                        (ert-resource-file
+                         (concat data-dir "/test_dir_other"))))
+       (test-files `(,test-dir "foo" "bar")) ;expected files to be found
+       ;; Free space test data for `insert-directory'.
+       ;; Meaning: (path free-space-bytes-to-stub expected-free-space-string)
+       (free-data `((,test-dir 10 "available 10 B")
+                    (,test-dir-other 100 "available 100 B")
+                    (:default 999 "available 999 B"))))
+
+  (defun files-tests--look-up-free-data (path)
+    "Look up free space test data, with a default for unspecified paths."
+    (let ((path (file-name-as-directory path)))
+      (cdr (or (assoc path free-data)
+               (assoc :default free-data)))))
+
+  (defun files-tests--make-file-system-info-stub (&optional static-path)
+    "Return a stub for `file-system-info' using dynamic or static test data.
+If that data should be static, pass STATIC-PATH to choose which
+path's data to use."
+    (lambda (path)
+      (let* ((path (cond (static-path)
+                         ;; file-system-info knows how to handle ".", so we
+                         ;; do the same thing
+                         ((equal "." path) default-directory)
+                         (path)))
+             (return-size
+              (car (files-tests--look-up-free-data path))))
+        (list return-size return-size return-size))))
+
+  (defun files-tests--insert-directory-output (dir &optional verbose)
+    "Run `insert-directory' and return its output."
+    (with-current-buffer-window "files-tests--insert-directory" nil nil
+      (let ((dired-free-space 'separate))
+        (dired-insert-directory dir "-l" nil nil t))
+      (buffer-substring-no-properties (point-min) (point-max))))
+
+  (ert-deftest files-tests-insert-directory-shows-files ()
+    "Verify `insert-directory' reports the files in the directory."
+    (let* ((test-dir (car test-files))
+           (files (cdr test-files))
+           (output (files-tests--insert-directory-output test-dir)))
+      (dolist (file files)
+        (should (string-match-p file output)))))
+
+  (defun files-tests--insert-directory-shows-given-free (dir &optional
+                                                             info-func)
+    "Run `insert-directory' and verify it reports the correct available space.
+Stub `file-system-info' to ensure the available space is consistent,
+either with the given stub function or a default one using test data."
+    (cl-letf (((symbol-function 'file-system-info)
+               (or info-func
+                   (files-tests--make-file-system-info-stub))))
+      (should (string-match-p (cadr
+                               (files-tests--look-up-free-data dir))
+                              (files-tests--insert-directory-output dir t)))))
+
+  (ert-deftest files-tests-insert-directory-shows-free ()
+    "Test that verbose `insert-directory' shows the correct available space."
+    (files-tests--insert-directory-shows-given-free
+     test-dir
+     (files-tests--make-file-system-info-stub test-dir)))
+
+  (ert-deftest files-tests-bug-50630 ()
+    "Verify verbose `insert-directory' shows free space of the target 
directory.
+The current directory at call time should not affect the result (Bug#50630)."
+    (let ((default-directory test-dir-other))
+      (files-tests--insert-directory-shows-given-free test-dir))))
+
 (provide 'dired-tests)
 ;;; dired-tests.el ends here
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index 816f14a..b82afd3 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -643,6 +643,49 @@ inner loops respectively."
 
     (cond)
     (mapcar (lambda (x) (cond ((= x 0)))) '(0 1))
+
+    ;; These expressions give different results in lexbind and dynbind modes,
+    ;; but in each the compiler and interpreter should agree!
+    ;; (They look much the same but come in pairs exercising both the
+    ;; `let' and `let*' paths.)
+    (let ((f (lambda (x)
+               (lambda ()
+                 (let ((g (lambda () x)))
+                   (let ((x 'a))
+                     (list x (funcall g))))))))
+      (funcall (funcall f 'b)))
+    (let ((f (lambda (x)
+               (lambda ()
+                 (let ((g (lambda () x)))
+                   (let* ((x 'a))
+                     (list x (funcall g))))))))
+      (funcall (funcall f 'b)))
+    (let ((f (lambda (x)
+               (lambda ()
+                 (let ((g (lambda () x)))
+                   (setq x (list x x))
+                   (let ((x 'a))
+                     (list x (funcall g))))))))
+      (funcall (funcall f 'b)))
+    (let ((f (lambda (x)
+               (lambda ()
+                 (let ((g (lambda () x)))
+                   (setq x (list x x))
+                   (let* ((x 'a))
+                     (list x (funcall g))))))))
+      (funcall (funcall f 'b)))
+    (let ((f (lambda (x)
+               (let ((g (lambda () x))
+                     (h (lambda () (setq x (list x x)))))
+                 (let ((x 'a))
+                   (list x (funcall g) (funcall h)))))))
+      (funcall (funcall f 'b)))
+    (let ((f (lambda (x)
+               (let ((g (lambda () x))
+                     (h (lambda () (setq x (list x x)))))
+                 (let* ((x 'a))
+                   (list x (funcall g) (funcall h)))))))
+      (funcall (funcall f 'b)))
     )
   "List of expressions for cross-testing interpreted and compiled code.")
 
diff --git a/test/lisp/emacs-lisp/cconv-tests.el 
b/test/lisp/emacs-lisp/cconv-tests.el
index 4290571..0701892 100644
--- a/test/lisp/emacs-lisp/cconv-tests.el
+++ b/test/lisp/emacs-lisp/cconv-tests.el
@@ -205,5 +205,157 @@
            nil 99)
           42)))
 
+(defun cconv-tests--intern-all (x)
+  "Intern all symbols in X."
+  (cond ((symbolp x) (intern (symbol-name x)))
+        ((consp x) (cons (cconv-tests--intern-all (car x))
+                         (cconv-tests--intern-all (cdr x))))
+        ;; Assume we don't need to deal with vectors etc.
+        (t x)))
+
+(ert-deftest cconv-closure-convert-remap-var ()
+  ;; Verify that we correctly remap shadowed lambda-lifted variables.
+
+  ;; We intern all symbols for ease of comparison; this works because
+  ;; the `cconv-closure-convert' result should contain no pair of
+  ;; distinct symbols having the same name.
+
+  ;; Sanity check: captured variable, no lambda-lifting or shadowing:
+  (should (equal (cconv-tests--intern-all
+           (cconv-closure-convert
+            '#'(lambda (x)
+                 #'(lambda () x))))
+           '#'(lambda (x)
+                (internal-make-closure
+                 nil (x) nil
+                 (internal-get-closed-var 0)))))
+
+  ;; Basic case:
+  (should (equal (cconv-tests--intern-all
+                  (cconv-closure-convert
+                   '#'(lambda (x)
+                        (let ((f #'(lambda () x)))
+                          (let ((x 'b))
+                            (list x (funcall f)))))))
+                 '#'(lambda (x)
+                      (let ((f #'(lambda (x) x)))
+                        (let ((x 'b)
+                              (closed-x x))
+                          (list x (funcall f closed-x)))))))
+  (should (equal (cconv-tests--intern-all
+                  (cconv-closure-convert
+                   '#'(lambda (x)
+                        (let ((f #'(lambda () x)))
+                          (let* ((x 'b))
+                            (list x (funcall f)))))))
+                 '#'(lambda (x)
+                      (let ((f #'(lambda (x) x)))
+                        (let* ((closed-x x)
+                               (x 'b))
+                          (list x (funcall f closed-x)))))))
+
+  ;; With the lambda-lifted shadowed variable also being captured:
+  (should (equal
+           (cconv-tests--intern-all
+            (cconv-closure-convert
+             '#'(lambda (x)
+                  #'(lambda ()
+                      (let ((f #'(lambda () x)))
+                        (let ((x 'a))
+                          (list x (funcall f))))))))
+           '#'(lambda (x)
+                (internal-make-closure
+                 nil (x) nil
+                 (let ((f #'(lambda (x) x)))
+                   (let ((x 'a)
+                         (closed-x (internal-get-closed-var 0)))
+                     (list x (funcall f closed-x))))))))
+  (should (equal
+           (cconv-tests--intern-all
+            (cconv-closure-convert
+             '#'(lambda (x)
+                  #'(lambda ()
+                      (let ((f #'(lambda () x)))
+                        (let* ((x 'a))
+                          (list x (funcall f))))))))
+           '#'(lambda (x)
+                (internal-make-closure
+                 nil (x) nil
+                 (let ((f #'(lambda (x) x)))
+                   (let* ((closed-x (internal-get-closed-var 0))
+                          (x 'a))
+                     (list x (funcall f closed-x))))))))
+  ;; With lambda-lifted shadowed variable also being mutably captured:
+  (should (equal
+           (cconv-tests--intern-all
+            (cconv-closure-convert
+             '#'(lambda (x)
+                  #'(lambda ()
+                      (let ((f #'(lambda () x)))
+                        (setq x x)
+                        (let ((x 'a))
+                          (list x (funcall f))))))))
+           '#'(lambda (x)
+                (let ((x (list x)))
+                  (internal-make-closure
+                   nil (x) nil
+                   (let ((f #'(lambda (x) (car-safe x))))
+                     (setcar (internal-get-closed-var 0)
+                             (car-safe (internal-get-closed-var 0)))
+                     (let ((x 'a)
+                           (closed-x (internal-get-closed-var 0)))
+                       (list x (funcall f closed-x)))))))))
+  (should (equal
+           (cconv-tests--intern-all
+            (cconv-closure-convert
+             '#'(lambda (x)
+                  #'(lambda ()
+                      (let ((f #'(lambda () x)))
+                        (setq x x)
+                        (let* ((x 'a))
+                          (list x (funcall f))))))))
+           '#'(lambda (x)
+                (let ((x (list x)))
+                  (internal-make-closure
+                   nil (x) nil
+                   (let ((f #'(lambda (x) (car-safe x))))
+                     (setcar (internal-get-closed-var 0)
+                             (car-safe (internal-get-closed-var 0)))
+                     (let* ((closed-x (internal-get-closed-var 0))
+                            (x 'a))
+                       (list x (funcall f closed-x)))))))))
+  ;; Lambda-lifted variable that isn't actually captured where it is shadowed:
+  (should (equal
+           (cconv-tests--intern-all
+            (cconv-closure-convert
+             '#'(lambda (x)
+                  (let ((g #'(lambda () x))
+                        (h #'(lambda () (setq x x))))
+                    (let ((x 'b))
+                      (list x (funcall g) (funcall h)))))))
+           '#'(lambda (x)
+                (let ((x (list x)))
+                  (let ((g #'(lambda (x) (car-safe x)))
+                        (h #'(lambda (x) (setcar x (car-safe x)))))
+                    (let ((x 'b)
+                          (closed-x x))
+                      (list x (funcall g closed-x) (funcall h closed-x))))))))
+  (should (equal
+           (cconv-tests--intern-all
+            (cconv-closure-convert
+             '#'(lambda (x)
+                  (let ((g #'(lambda () x))
+                        (h #'(lambda () (setq x x))))
+                    (let* ((x 'b))
+                      (list x (funcall g) (funcall h)))))))
+           '#'(lambda (x)
+                (let ((x (list x)))
+                  (let ((g #'(lambda (x) (car-safe x)))
+                        (h #'(lambda (x) (setcar x (car-safe x)))))
+                    (let* ((closed-x x)
+                           (x 'b))
+                      (list x (funcall g closed-x) (funcall h closed-x))))))))
+  )
+
 (provide 'cconv-tests)
 ;;; cconv-tests.el ends here
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index d3d58aa..4620488 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1822,79 +1822,5 @@ Prompt users for any modified buffer with 
`buffer-offer-save' non-nil."
   (should (equal (file-name-split "/foo/bar/") '("" "foo" "bar" "")))
   (should (equal (file-name-split "foo/bar/") '("foo" "bar" ""))))
 
-;; `insert-directory' output tests.
-(let* ((data-dir "insert-directory")
-       (test-dir (file-name-as-directory
-                  (ert-resource-file
-                   (concat data-dir "/test_dir"))))
-       (test-dir-other (file-name-as-directory
-                        (ert-resource-file
-                         (concat data-dir "/test_dir_other"))))
-       (test-files `(,test-dir "foo" "bar")) ;expected files to be found
-       ;; Free space test data for `insert-directory'.
-       ;; Meaning: (path free-space-bytes-to-stub expected-free-space-string)
-       (free-data `((,test-dir 10 "available 10 B")
-                    (,test-dir-other 100 "available 100 B")
-                    (:default 999 "available 999 B"))))
-
-
-  (defun files-tests--look-up-free-data (path)
-    "Look up free space test data, with a default for unspecified paths."
-    (let ((path (file-name-as-directory path)))
-      (cdr (or (assoc path free-data)
-               (assoc :default free-data)))))
-
-  (defun files-tests--make-file-system-info-stub (&optional static-path)
-    "Return a stub for `file-system-info' using dynamic or static test data.
-If that data should be static, pass STATIC-PATH to choose which
-path's data to use."
-    (lambda (path)
-      (let* ((path (cond (static-path)
-                         ;; file-system-info knows how to handle ".", so we
-                         ;; do the same thing
-                         ((equal "." path) default-directory)
-                         (path)))
-             (return-size
-              (car (files-tests--look-up-free-data path))))
-        (list return-size return-size return-size))))
-
-  (defun files-tests--insert-directory-output (dir &optional verbose)
-    "Run `insert-directory' and return its output."
-    (with-current-buffer-window "files-tests--insert-directory" nil nil
-      (insert-directory dir "-l" nil t)
-      (buffer-substring-no-properties (point-min) (point-max))))
-
-  (ert-deftest files-tests-insert-directory-shows-files ()
-    "Verify `insert-directory' reports the files in the directory."
-    (let* ((test-dir (car test-files))
-           (files (cdr test-files))
-           (output (files-tests--insert-directory-output test-dir)))
-      (dolist (file files)
-        (should (string-match-p file output)))))
-
-  (defun files-tests--insert-directory-shows-given-free (dir &optional
-                                                             info-func)
-    "Run `insert-directory' and verify it reports the correct available space.
-Stub `file-system-info' to ensure the available space is consistent,
-either with the given stub function or a default one using test data."
-    (cl-letf (((symbol-function 'file-system-info)
-               (or info-func
-                   (files-tests--make-file-system-info-stub))))
-      (should (string-match-p (cadr
-                               (files-tests--look-up-free-data dir))
-                              (files-tests--insert-directory-output dir t)))))
-
-  (ert-deftest files-tests-insert-directory-shows-free ()
-    "Test that verbose `insert-directory' shows the correct available space."
-    (files-tests--insert-directory-shows-given-free
-     test-dir
-     (files-tests--make-file-system-info-stub test-dir)))
-
-  (ert-deftest files-tests-bug-50630 ()
-    "Verify verbose `insert-directory' shows free space of the target 
directory.
-The current directory at call time should not affect the result (Bug#50630)."
-    (let ((default-directory test-dir-other))
-      (files-tests--insert-directory-shows-given-free test-dir))))
-
 (provide 'files-tests)
 ;;; files-tests.el ends here



reply via email to

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