\f
;;; Code:
-;; LOAD.
-
;; This is a no-op if dired-x is being loaded via `dired-load-hook',
;; but maybe not if a dired-x function is being autoloaded.
(require 'dired)
-;; We will redefine some functions and also need some macros.
-(require 'dired-aux)
-
;;; User-defined variables.
(defgroup dired-x nil
(other :tag "non-writable only" if-file-read-only))
:group 'dired-x)
+(defcustom dired-omit-size-limit 30000
+ "Maximum size for the \"omitting\" feature.
+If nil, there is no maximum size."
+ :type '(choice (const :tag "no maximum" nil) integer)
+ :group 'dired-x)
+
(define-minor-mode dired-omit-mode
- "Toggle Dired-Omit mode.
-With numeric ARG, enable Dired-Omit mode if ARG is positive, disable
-otherwise. Enabling and disabling is buffer-local.
-If enabled, \"uninteresting\" files are not listed.
-Uninteresting files are those whose filenames match regexp `dired-omit-files',
-plus those ending with extensions in `dired-omit-extensions'.
+ "Toggle omission of uninteresting files in Dired (Dired-Omit mode).
+With a prefix argument ARG, enable Dired-Omit mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil.
+
+Dired-Omit mode is a buffer-local minor mode. When enabled in a
+Dired buffer, Dired does not list files whose filenames match
+regexp `dired-omit-files', nor files ending with extensions in
+`dired-omit-extensions'.
-To enable omitting in every Dired buffer, you can put in your ~/.emacs
+To enable omitting in every Dired buffer, you can put this in
+your init file:
- (add-hook 'dired-mode-hook (lambda () (dired-omit-mode 1)))
+ (add-hook 'dired-mode-hook (lambda () (dired-omit-mode)))
See Info node `(dired-x) Omitting Variables' for more information."
:group 'dired-x
(let ((dired-omit-size-limit nil)) (dired-omit-expunge))
(revert-buffer)))
+(put 'dired-omit-mode 'safe-local-variable 'booleanp)
+
;; For backward compatibility
(define-obsolete-variable-alias 'dired-omit-files-p 'dired-omit-mode "22.1")
:type 'boolean
:group 'dired-x)
-(defcustom dired-omit-size-limit 30000
- "Maximum size for the \"omitting\" feature.
-If nil, there is no maximum size."
- :type '(choice (const :tag "no maximum" nil) integer)
- :group 'dired-x)
-
(defcustom dired-enable-local-variables t
"Control use of local-variables lists in Dired.
-The value can be t, nil or something else.
-A value of t means local-variables lists are obeyed;
-nil means they are ignored; anything else means query.
-
This temporarily overrides the value of `enable-local-variables' when
listing a directory. See also `dired-local-variables-file'."
- :type 'boolean
+ :risky t
+ :type '(choice (const :tag "Query Unsafe" t)
+ (const :tag "Safe Only" :safe)
+ (const :tag "Do all" :all)
+ (const :tag "Ignore" nil)
+ (other :tag "Query" other))
:group 'dired-x)
+(make-obsolete-variable 'dired-enable-local-variables
+ "use a standard `dir-locals-file' instead." "24.1")
+
(defcustom dired-guess-shell-gnutar
(catch 'found
(dolist (exe '("tar" "gtar"))
(dired-omit-mode)
(dired-goto-file file)))))))
+;;;###autoload
(defun dired-jump-other-window (&optional file-name)
"Like \\[dired-jump] (`dired-jump') but in other window."
(interactive
;; Returns t if any work was done, nil otherwise.
(defun dired-mark-unmarked-files (regexp msg &optional unflag-p localp)
"Mark unmarked files matching REGEXP, displaying MSG.
-REGEXP is matched against the entire file name.
-Does not re-mark files which already have a mark.
+REGEXP is matched against the entire file name. When called
+interactively, prompt for REGEXP.
With prefix argument, unflag all those files.
Optional fourth argument LOCALP is as in `dired-get-filename'."
- (interactive "P")
+ (interactive
+ (list (dired-read-regexp
+ "Mark unmarked files matching regexp (default all): ")
+ nil current-prefix-arg nil))
(let ((dired-marker-char (if unflag-p ?\s dired-marker-char)))
(dired-mark-if
(and
nil))))
-(defun dired-virtual-revert (&optional arg noconfirm)
+(defun dired-virtual-revert (&optional _arg _noconfirm)
(if (not
(y-or-n-p "Cannot revert a Virtual Dired buffer - switch to Real Dired mode? "))
(error "Cannot revert a Virtual Dired buffer")
(dired-current-directory)
default-directory)))
"Alist of major modes and their opinion on `default-directory'.
-This is given as a Lisp expression to evaluate. A resulting value of
-nil is ignored in favor of `default-directory'.")
+Each element has the form (MAJOR . EXPRESSION).
+The function `dired-default-directory' evaluates EXPRESSION to
+determine a default directory.")
+
+(put 'dired-default-directory-alist 'risky-local-variable t) ; gets eval'd
+(make-obsolete-variable 'dired-default-directory-alist
+ "this feature is due to be removed." "24.1")
(defun dired-default-directory ()
- "Usage like variable `default-directory'.
-Knows about the special cases in variable `dired-default-directory-alist'."
+ "Return the `dired-default-directory-alist' entry for the current major-mode.
+If none, return `default-directory'."
(or (eval (cdr (assq major-mode dired-default-directory-alist)))
default-directory))
+;; It looks like this was intended to be something of a "general" feature,
+;; but it only ever seems to have been used in dired-smart-shell-command,
+;; and does not seem worth keeping around (?).
+(make-obsolete 'dired-default-directory
+ "this feature is due to be removed." "24.1")
+
(defun dired-smart-shell-command (command &optional output-buffer error-buffer)
"Like function `shell-command', but in the current Virtual Dired directory."
(interactive
((eq major-mode 'dired-mode) (dired-get-filename t t))))
current-prefix-arg
shell-command-default-error-buffer))
- (let ((default-directory (dired-default-directory)))
+ (let ((default-directory (or (and (eq major-mode 'dired-mode)
+ (dired-current-directory))
+ default-directory)))
(shell-command command output-buffer error-buffer)))
\f
;;; LOCAL VARIABLES FOR DIRED BUFFERS.
-;; Brief Description:
-;;;
+;; Brief Description (This feature is obsolete as of Emacs 24.1)
+;;
;; * `dired-extra-startup' is part of the `dired-mode-hook'.
-;;;
+;;
;; * `dired-extra-startup' calls `dired-hack-local-variables'
-;;;
+;;
;; * `dired-hack-local-variables' checks the value of
-;;; `dired-local-variables-file'
-;;;
+;; `dired-local-variables-file'
+;;
;; * Check if `dired-local-variables-file' is a non-nil string and is a
-;;; filename found in the directory of the Dired Buffer being created.
-;;;
+;; filename found in the directory of the Dired Buffer being created.
+;;
;; * If `dired-local-variables-file' satisfies the above, then temporarily
-;;; include it in the Dired Buffer at the bottom.
-;;;
+;; include it in the Dired Buffer at the bottom.
+;;
;; * Set `enable-local-variables' temporarily to the user variable
-;;; `dired-enable-local-variables' and run `hack-local-variables' on the
-;;; Dired Buffer.
+;; `dired-enable-local-variables' and run `hack-local-variables' on the
+;; Dired Buffer.
-;; FIXME do standard dir-locals obsolete this?
(defcustom dired-local-variables-file (convert-standard-filename ".dired")
"Filename, as string, containing local dired buffer variables to be hacked.
If this file found in current directory, then it will be inserted into dired
:type 'file
:group 'dired)
+(make-obsolete-variable 'dired-local-variables-file 'dir-locals-file "24.1")
+
(defun dired-hack-local-variables ()
"Evaluate local variables in `dired-local-variables-file' for dired buffer."
(and (stringp dired-local-variables-file)
(insert "\^L\n")
(insert-file-contents dired-local-variables-file))
;; Hack 'em.
- (let ((buffer-file-name dired-local-variables-file))
- (hack-local-variables))
+ (unwind-protect
+ (let ((buffer-file-name dired-local-variables-file))
+ (hack-local-variables))
+ ;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
+ (delete-region opoint (point-max)))
;; Make sure that the modeline shows the proper information.
- (dired-sort-set-modeline)
- ;; Delete this stuff: `eobp' is used to find last subdir by dired.el.
- (delete-region opoint (point-max)))))
+ (dired-sort-set-modeline))))
+(make-obsolete 'dired-hack-local-variables
+ 'hack-dir-local-variables-non-file-buffer "24.1")
+
+;; Does not seem worth a dedicated command.
+;; See the more general features in files-x.el.
(defun dired-omit-here-always ()
- "Create `dired-local-variables-file' for omitting and reverts directory.
-Sets `dired-omit-mode' to t in a local variables file that is readable by
-dired."
+ "Create `dir-locals-file' setting `dired-omit-mode' to t in `dired-mode'.
+If in a Dired buffer, reverts it."
(interactive)
(if (file-exists-p dired-local-variables-file)
- (message "File `./%s' already exists." dired-local-variables-file)
- ;; Create `dired-local-variables-file'.
- (with-current-buffer (get-buffer-create " *dot-dired*")
- (erase-buffer)
- (insert "Local Variables:\ndired-omit-mode: t\nEnd:\n")
- (write-file dired-local-variables-file)
- (kill-buffer))
+ (error "Old-style dired-local-variables-file `./%s' found;
+replace it with a dir-locals-file `./%s'"
+ dired-local-variables-file
+ dir-locals-file))
+ (if (file-exists-p dir-locals-file)
+ (message "File `./%s' already exists." dir-locals-file)
+ (with-temp-buffer
+ (insert "\
+\((dired-mode . ((subdirs . nil)
+ (dired-omit-mode . t))))\n")
+ (write-file dir-locals-file))
;; Run extra-hooks and revert directory.
- (dired-extra-startup)
- (dired-revert)))
+ (when (derived-mode-p 'dired-mode)
+ (hack-dir-local-variables-non-file-buffer)
+ (dired-extra-startup)
+ (dired-revert))))
+
+(make-obsolete 'dired-omit-here-always 'add-dir-local-variable "24.1")
\f
;;; GUESS SHELL COMMAND.
;; NOTE: Use `gunzip -c' instead of `zcat' on `.gz' files. Some do not
;; install GNU zip's version of zcat.
-(declare-function Man-support-local-filenames "man" ())
+(autoload 'Man-support-local-filenames "man")
(defvar dired-guess-shell-alist-default
(list
- (list "\\.tar$"
+ (list "\\.tar\\'"
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " xvf")
"tar xvf")
;; REGEXPS for compressed archives must come before the .Z rule to
;; be recognized:
- (list "\\.tar\\.Z$"
+ (list "\\.tar\\.Z\\'"
;; Untar it.
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " zxvf")
" " dired-guess-shell-znew-switches))
;; gzip'ed archives
- (list "\\.t\\(ar\\.\\)?gz$"
+ (list "\\.t\\(ar\\.\\)?gz\\'"
'(if dired-guess-shell-gnutar
(concat dired-guess-shell-gnutar " zxvf")
(concat "gunzip -qc * | tar xvf -"))
(concat "gunzip -qc * | tar tvf -")))
;; bzip2'ed archives
- (list "\\.t\\(ar\\.bz2\\|bz\\)$"
+ (list "\\.t\\(ar\\.bz2\\|bz\\)\\'"
"bunzip2 -c * | tar xvf -"
;; Extract files into a separate subdirectory
'(concat "mkdir " (file-name-sans-extension file)
"bunzip2")
;; xz'ed archives
- (list "\\.t\\(ar\\.\\)?xz$"
+ (list "\\.t\\(ar\\.\\)?xz\\'"
"unxz -c * | tar xvf -"
;; Extract files into a separate subdirectory
'(concat "mkdir " (file-name-sans-extension file)
;; Optional decompression.
"unxz")
- '("\\.shar\\.Z$" "zcat * | unshar")
- '("\\.shar\\.g?z$" "gunzip -qc * | unshar")
+ '("\\.shar\\.Z\\'" "zcat * | unshar")
+ '("\\.shar\\.g?z\\'" "gunzip -qc * | unshar")
- '("\\.e?ps$" "ghostview" "xloadimage" "lpr")
- (list "\\.e?ps\\.g?z$" "gunzip -qc * | ghostview -"
+ '("\\.e?ps\\'" "ghostview" "xloadimage" "lpr")
+ (list "\\.e?ps\\.g?z\\'" "gunzip -qc * | ghostview -"
;; Optional decompression.
'(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.e?ps\\.Z$" "zcat * | ghostview -"
+ (list "\\.e?ps\\.Z\\'" "zcat * | ghostview -"
;; Optional conversion to gzip format.
'(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
" " dired-guess-shell-znew-switches))
- '("\\.patch$" "cat * | patch")
- (list "\\.patch\\.g?z$" "gunzip -qc * | patch"
+ '("\\.patch\\'" "cat * | patch")
+ (list "\\.patch\\.g?z\\'" "gunzip -qc * | patch"
;; Optional decompression.
'(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.patch\\.Z$" "zcat * | patch"
+ (list "\\.patch\\.Z\\'" "zcat * | patch"
;; Optional conversion to gzip format.
'(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
" " dired-guess-shell-znew-switches))
;; The following four extensions are useful with dired-man ("N" key)
- (list "\\.\\(?:[0-9]\\|man\\)$" '(progn (require 'man)
- (if (Man-support-local-filenames)
- "man -l"
- "cat * | tbl | nroff -man -h")))
- (list "\\.\\(?:[0-9]\\|man\\)\\.g?z$" '(progn (require 'man)
- (if (Man-support-local-filenames)
- "man -l"
- "gunzip -qc * | tbl | nroff -man -h"))
+ ;; FIXME "man ./" does not work with dired-do-shell-command,
+ ;; because there seems to be no way for us to modify the filename,
+ ;; only the command. Hmph. `dired-man' works though.
+ (list "\\.\\(?:[0-9]\\|man\\)\\'" '(let ((loc (Man-support-local-filenames)))
+ (cond ((eq loc 'man-db) "man -l")
+ ((eq loc 'man) "man ./")
+ (t
+ "cat * | tbl | nroff -man -h"))))
+ (list "\\.\\(?:[0-9]\\|man\\)\\.g?z\\'"
+ '(let ((loc (Man-support-local-filenames)))
+ (cond ((eq loc 'man-db)
+ "man -l")
+ ((eq loc 'man)
+ "man ./")
+ (t "gunzip -qc * | tbl | nroff -man -h")))
;; Optional decompression.
'(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.[0-9]\\.Z$" '(progn (require 'man)
- (if (Man-support-local-filenames)
- "man -l"
- "zcat * | tbl | nroff -man -h"))
+ (list "\\.[0-9]\\.Z\\'" '(let ((loc (Man-support-local-filenames)))
+ (cond ((eq loc 'man-db) "man -l")
+ ((eq loc 'man) "man ./")
+ (t "zcat * | tbl | nroff -man -h")))
;; Optional conversion to gzip format.
'(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
" " dired-guess-shell-znew-switches))
- '("\\.pod$" "perldoc" "pod2man * | nroff -man")
-
- '("\\.dvi$" "xdvi" "dvips") ; preview and printing
- '("\\.au$" "play") ; play Sun audiofiles
- '("\\.mpe?g$\\|\\.avi$" "xine -p")
- '("\\.ogg$" "ogg123")
- '("\\.mp3$" "mpg123")
- '("\\.wav$" "play")
- '("\\.uu$" "uudecode") ; for uudecoded files
- '("\\.hqx$" "mcvert")
- '("\\.sh$" "sh") ; execute shell scripts
- '("\\.xbm$" "bitmap") ; view X11 bitmaps
- '("\\.gp$" "gnuplot")
- '("\\.p[bgpn]m$" "xloadimage")
- '("\\.gif$" "xloadimage") ; view gif pictures
- '("\\.tif$" "xloadimage")
- '("\\.png$" "display") ; xloadimage 4.1 doesn't grok PNG
- '("\\.jpe?g$" "xloadimage")
- '("\\.fig$" "xfig") ; edit fig pictures
- '("\\.out$" "xgraph") ; for plotting purposes.
- '("\\.tex$" "latex" "tex")
- '("\\.texi\\(nfo\\)?$" "makeinfo" "texi2dvi")
- '("\\.pdf$" "xpdf")
- '("\\.doc$" "antiword" "strings")
- '("\\.rpm$" "rpm -qilp" "rpm -ivh")
- '("\\.dia$" "dia")
- '("\\.mgp$" "mgp")
+ '("\\.pod\\'" "perldoc" "pod2man * | nroff -man")
+
+ '("\\.dvi\\'" "xdvi" "dvips") ; preview and printing
+ '("\\.au\\'" "play") ; play Sun audiofiles
+ '("\\.mpe?g\\'\\|\\.avi\\'" "xine -p")
+ '("\\.ogg\\'" "ogg123")
+ '("\\.mp3\\'" "mpg123")
+ '("\\.wav\\'" "play")
+ '("\\.uu\\'" "uudecode") ; for uudecoded files
+ '("\\.hqx\\'" "mcvert")
+ '("\\.sh\\'" "sh") ; execute shell scripts
+ '("\\.xbm\\'" "bitmap") ; view X11 bitmaps
+ '("\\.gp\\'" "gnuplot")
+ '("\\.p[bgpn]m\\'" "xloadimage")
+ '("\\.gif\\'" "xloadimage") ; view gif pictures
+ '("\\.tif\\'" "xloadimage")
+ '("\\.png\\'" "display") ; xloadimage 4.1 doesn't grok PNG
+ '("\\.jpe?g\\'" "xloadimage")
+ '("\\.fig\\'" "xfig") ; edit fig pictures
+ '("\\.out\\'" "xgraph") ; for plotting purposes.
+ '("\\.tex\\'" "latex" "tex")
+ '("\\.texi\\(nfo\\)?\\'" "makeinfo" "texi2dvi")
+ '("\\.pdf\\'" "xpdf")
+ '("\\.doc\\'" "antiword" "strings")
+ '("\\.rpm\\'" "rpm -qilp" "rpm -ivh")
+ '("\\.dia\\'" "dia")
+ '("\\.mgp\\'" "mgp")
;; Some other popular archivers.
- (list "\\.zip$" "unzip" "unzip -l"
+ (list "\\.zip\\'" "unzip" "unzip -l"
;; Extract files into a separate subdirectory
'(concat "unzip" (if dired-guess-shell-gzip-quiet " -q")
" -d " (file-name-sans-extension file)))
- '("\\.zoo$" "zoo x//")
- '("\\.lzh$" "lharc x")
- '("\\.arc$" "arc x")
- '("\\.shar$" "unshar")
+ '("\\.zoo\\'" "zoo x//")
+ '("\\.lzh\\'" "lharc x")
+ '("\\.arc\\'" "arc x")
+ '("\\.shar\\'" "unshar")
+ '("\\.rar\\'" "unrar x")
+ '("\\.7z\\'" "7z x")
;; Compression.
- (list "\\.g?z$" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
- (list "\\.dz$" "dictunzip")
- (list "\\.bz2$" "bunzip2")
- (list "\\.xz$" "unxz")
- (list "\\.Z$" "uncompress"
+ (list "\\.g?z\\'" '(concat "gunzip" (if dired-guess-shell-gzip-quiet " -q")))
+ (list "\\.dz\\'" "dictunzip")
+ (list "\\.bz2\\'" "bunzip2")
+ (list "\\.xz\\'" "unxz")
+ (list "\\.Z\\'" "uncompress"
;; Optional conversion to gzip format.
'(concat "znew" (if dired-guess-shell-gzip-quiet " -q")
" " dired-guess-shell-znew-switches))
- '("\\.sign?$" "gpg --verify"))
+ '("\\.sign?\\'" "gpg --verify"))
"Default alist used for shell command guessing.
See `dired-guess-shell-alist-user'.")
`.foo' and `.bar' files, write
\(setq dired-guess-shell-alist-user
- (list (list \"\\\\.foo\\\\'\" \"FOO-COMMAND\");; fixed rule
- ;; possibly more rules ...
- (list \"\\\\.bar\\\\'\";; rule with condition test
- '(if condition
- \"BAR-COMMAND-1\"
- \"BAR-COMMAND-2\")))\)"
+ '((\"\\\\.foo\\\\'\" \"FOO-COMMAND\")
+ (\"\\\\.bar\\\\'\"
+ (if condition
+ \"BAR-COMMAND-1\"
+ \"BAR-COMMAND-2\"))))"
:group 'dired-x
:type '(alist :key-type regexp :value-type (repeat sexp)))
:type 'boolean)
(defun dired-guess-default (files)
- "Guess a shell commands for FILES. Return command or list of commands.
+ "Return a shell command, or a list of commands, appropriate for FILES.
See `dired-guess-shell-alist-user'."
(let* ((case-fold-search dired-guess-shell-case-fold-search)
;; Return commands or nil if flist is still non-nil.
;; Evaluate the commands in order that any logical testing will be done.
(if (cdr cmds)
- (mapcar #'eval cmds)
- (eval (car cmds))))) ; single command
+ (delete-dups (mapcar #'eval cmds))
+ (eval (car cmds))))) ; single command
(defun dired-guess-shell-command (prompt files)
"Ask user with PROMPT for a shell command, guessing a default from FILES."
(setq count (1+ count)
start (1+ start)))
;; ... and prepend a "../" for each slash found:
- (dotimes (n count)
+ (dotimes (_n count)
(setq name1 (concat "../" name1)))))
(make-symbolic-link
(directory-file-name name1) ; must not link to foo/
; (trailing slash!)
name2 ok-if-already-exists)))
+(autoload 'dired-do-create-files "dired-aux")
+
;;;###autoload
(defun dired-do-relsymlink (&optional arg)
"Relative symlink all marked (or next ARG) files into a directory.
(dired-do-create-files 'relsymlink #'dired-make-relative-symlink
"RelSymLink" arg dired-keep-marker-relsymlink))
+(autoload 'dired-mark-read-regexp "dired-aux")
+(autoload 'dired-do-create-files-regexp "dired-aux")
+
(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name)
"RelSymlink all marked files containing REGEXP to NEWNAME.
See functions `dired-do-rename-regexp' and `dired-do-relsymlink'
displayed this way is restricted by the height of the current window and
`window-min-height'.
-To keep dired buffer displayed, type \\[split-window-vertically] first.
+To keep dired buffer displayed, type \\[split-window-below] first.
To display just marked files, type \\[delete-other-windows] first."
(interactive "P")
(dired-simultaneous-find-file (dired-get-marked-files) noselect))
(declare-function Man-getpage-in-background "man" (topic))
+(defvar manual-program) ; from man.el
+
(defun dired-man ()
"Run `man' on this file."
;; Used also to say: "Display old buffer if buffer name matches filename."
\f
;; Does anyone use this? - lrd 6/29/93.
;; Apparently people do use it. - lrd 12/22/97.
+
+(with-no-warnings
+ ;; Warnings are suppresed to avoid "global/dynamic var `X' lacks a prefix".
+ ;; This is unbearably ugly, but not more than having global variables
+ ;; named size, time, name or s, however practical it can be while writing
+ ;; `dired-mark-sexp' predicates.
+ (defvar inode)
+ (defvar s)
+ (defvar mode)
+ (defvar nlink)
+ (defvar uid)
+ (defvar gid)
+ (defvar size)
+ (defvar time)
+ (defvar name)
+ (defvar sym))
+
(defun dired-mark-sexp (predicate &optional unflag-p)
"Mark files for which PREDICATE returns non-nil.
-With a prefix arg, unflag those files instead.
+With a prefix arg, unmark or unflag those files instead.
PREDICATE is a lisp expression that can refer to the following symbols:
is loaded then call \\[dired-x-bind-find-file]."
:type 'boolean
:initialize 'custom-initialize-default
- :set (lambda (sym val)
- (set sym val)
+ :set (lambda (symbol value)
+ (set symbol value)
(dired-x-bind-find-file))
:group 'dired-x)