1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-05-10 23:31:19 -07:00

Restrict Dired handling of newlines in file names

* lisp/dired.el (dired--ls-accept-b-switch-p): New function.
(dired-internal-noselect): Use it in the condition on displaying
warning about filenames with newlines.
(dired--set-auto-toggle-b-switch): Use it to conditionalize
calling 'dired--toggle-b-switch'.
(dired-auto-toggle-b-switch, dired--toggle-b-switch): Improve doc
string.

* test/lisp/dired-tests.el (dired-test-filename-with-newline-1)
(dired-test-filename-with-newline-2): Skip unless Dired uses an
'ls' that supports the '-b' switch.

* etc/NEWS: Adjust accordingly the announcements of the Dired
warning and the new user option for file names with newlines.
This commit is contained in:
Stephen Berman 2026-04-17 19:26:37 +02:00
parent c92354d190
commit abde2d1ed3
3 changed files with 29 additions and 17 deletions

View file

@ -2536,7 +2536,8 @@ names relative to the root directory of the current project.
+++
*** Warning when Dired displays a file name with a literal newline.
On visiting a directory that contains a file whose name has a newline,
If Dired uses an 'ls' implementation that supports the '-b' switch, then
on visiting a directory that contains a file whose name has a newline,
and Dired displays that character as a literal newline, Emacs now
automatically pops up a buffer warning that such a display can be
problematic for Dired and showing a way to change the display to use the
@ -2544,7 +2545,8 @@ unproblematic character '\n'.
+++
*** New user option 'dired-auto-toggle-b-switch'.
When this user option is non-nil and 'dired-listing-switches' does not
When this user option is non-nil and Dired uses an 'ls' implementation
that supports the '-b' switch and 'dired-listing-switches' does not
include the '-b' switch, then on visiting a directory containing a file
whose name has a newline, Emacs automatically adds the '-b' switch and
redisplays the directory in Dired to show '\n' in the file name instead

View file

@ -553,7 +553,8 @@ displayed instead."
(defcustom dired-auto-toggle-b-switch nil
"Whether to automatically add or remove the `b' switch.
If non-nil, the function `dired--toggle-b-switch' (which see) is added
to `post-command-hook' in Dired mode."
to `post-command-hook' in Dired mode, unless the `ls' used by Dired does
not accept the `b' switch."
:type 'boolean
:group 'dired
:initialize #'custom-initialize-default
@ -1472,15 +1473,16 @@ The return value is the target column for the file names."
(dired-initial-position dirname))
(when (consp dired-directory)
(dired--align-all-files))
;; Pop up a warning if the Dired listing displays a literal newline.
;; We do this here in order to get the warning not only when
;; interactively invoking `dired' on a directory, but also e.g. when
;; passing the directory name as a command line argument when
;; starting Emacs from the shell.
;; Pop up a warning if the Dired listing displays a literal newline
;; and `ls' can take the `b' switch. We do this here in order to
;; get the warning not only when interactively invoking `dired' on a
;; directory, but also e.g. when passing the directory name as a
;; command line argument when starting Emacs from the shell.
(unless (or dired-auto-toggle-b-switch
(dired-switches-escape-p dired-listing-switches)
(dired-switches-escape-p dired-actual-switches))
(when (dired--filename-with-newline-p)
(when (and (dired--filename-with-newline-p)
(dired--ls-accept-b-switch-p))
(dired--display-filename-with-newline-warning buffer)))
(set-buffer old-buf)
buffer))
@ -4054,6 +4056,10 @@ newline character (regardless of whether Dired displays the character as
a literal newline or as \"\\n\")."
(directory-files default-directory nil "\n"))
(defun dired--ls-accept-b-switch-p ()
"Return non-nil if the `ls' used by Dired accepts the `b' switch."
(eq 0 (call-process insert-directory-program nil nil nil "-b")))
(defun dired--remove-b-switch ()
"Remove all variants of the `b' switch from `dired-actual-switches'.
This removes not only all occurrences of the short form `-b' but also
@ -4071,8 +4077,9 @@ the long forms `--escape' and `--quoting-style=escape'."
"Add or remove `b' switch and redisplay Dired buffer.
When the current Dired buffer has a file name containing a newline, add
the `b' switch to the actual switches if it isn't already among them;
otherwise remove the `b' switch unless it is in `dired-listing-switches'.
Then redisplay the Dired buffer. This function is called from
otherwise remove the `b' switch unless it is in
`dired-listing-switches'. Then redisplay the Dired buffer. When
`dired-auto-toggle-b-switch' is non-nil, this function is called from
`post-command-hook' in Dired mode buffers."
(when (eq major-mode 'dired-mode)
(if (and (dired--filename-with-newline-p) dired-auto-toggle-b-switch)
@ -4087,12 +4094,13 @@ Then redisplay the Dired buffer. This function is called from
(defun dired--set-auto-toggle-b-switch (symbol value)
"The :set function for user option `dired-auto-toggle-b-switch'."
(custom-set-default symbol value)
(if value
(add-hook 'post-command-hook #'dired--toggle-b-switch nil t)
(remove-hook 'post-command-hook #'dired--toggle-b-switch t))
(dolist (b (buffer-list))
(with-current-buffer b
(dired--toggle-b-switch))))
(when (dired--ls-accept-b-switch-p)
(if value
(add-hook 'post-command-hook #'dired--toggle-b-switch nil t)
(remove-hook 'post-command-hook #'dired--toggle-b-switch t))
(dolist (b (buffer-list))
(with-current-buffer b
(dired--toggle-b-switch)))))
(defun dired--display-filename-with-newline-warning (dir)
"Display a warning if buffer DIR has a file name with a newline."

View file

@ -663,6 +663,7 @@ The current directory at call time should not affect the result (Bug#50630)."
;; File names with embedded newlines are not allowed on MS-Windows and
;; MS-DOS.
(skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (dired--ls-accept-b-switch-p))
(with-current-buffer "*Messages*"
(let ((inhibit-read-only t))
(erase-buffer)))
@ -698,6 +699,7 @@ The current directory at call time should not affect the result (Bug#50630)."
;; File names with embedded newlines are not allowed on MS-Windows and
;; MS-DOS.
(skip-when (memq system-type '(windows-nt ms-dos)))
(skip-unless (dired--ls-accept-b-switch-p))
(with-current-buffer "*Messages*"
(let ((inhibit-read-only t))
(erase-buffer)))