]> git.eshelyaron.com Git - emacs.git/commitdiff
Provide additional default values (directories at other Dired
authorJuri Linkov <juri@jurta.org>
Wed, 25 Nov 2009 17:15:19 +0000 (17:15 +0000)
committerJuri Linkov <juri@jurta.org>
Wed, 25 Nov 2009 17:15:19 +0000 (17:15 +0000)
windows) via M-n in the minibuffer of some Dired commands.

* dired-aux.el (dired-diff, dired-compare-directories)
(dired-do-create-files): Use `dired-dwim-target-defaults' to set
`minibuffer-default' in `minibuffer-with-setup-hook'.
(dired-dwim-target-directory): Find a window that displays Dired
buffer instead of failing when the next window is not Dired.
Use `get-window-with-predicate' to find for the next Dired window.
(dired-dwim-target-defaults): New function.

* ediff-util.el (ediff-read-file-name):
Use `dired-dwim-target-defaults' to set `minibuffer-default'
in `minibuffer-with-setup-hook'.

etc/NEWS
lisp/ChangeLog
lisp/dired-aux.el
lisp/ediff-util.el

index 58ff7c6705fe58337740972ba806ef4f05226e45..2f288cba0455a2db1a02e00527cafff12a3679c8 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -152,7 +152,9 @@ when the value of the new variable `completions-format' is `vertical'.
 
 ** M-n provides more default values in the minibuffer of commands that
 read a file and directory name: a file name at point (when ffap is loaded
-without ffap-bindings), a file name on the current line in the Dired buffer.
+without ffap-bindings), a file name on the current line in the Dired buffer,
+a directory name of adjacent Dired windows for Dired commands that can
+operate on several directories (copy, rename, diff).
 
 ** M-r is bound to the new `move-to-window-line-top-bottom'
 to mirror the new behavior of C-l in Emacs-23.1.
index 5c7d0a1e25d75d6197d01cecf3e65a4f39589939..4f1c86f61010e82b4da62f8b5af2289414a3d024 100644 (file)
@@ -1,3 +1,20 @@
+2009-11-25  Juri Linkov  <juri@jurta.org>
+
+       Provide additional default values (directories at other Dired
+       windows) via M-n in the minibuffer of some Dired commands.
+
+       * dired-aux.el (dired-diff, dired-compare-directories)
+       (dired-do-create-files): Use `dired-dwim-target-defaults' to set
+       `minibuffer-default' in `minibuffer-with-setup-hook'.
+       (dired-dwim-target-directory): Find a window that displays Dired
+       buffer instead of failing when the next window is not Dired.
+       Use `get-window-with-predicate' to find for the next Dired window.
+       (dired-dwim-target-defaults): New function.
+
+       * ediff-util.el (ediff-read-file-name):
+       Use `dired-dwim-target-defaults' to set `minibuffer-default'
+       in `minibuffer-with-setup-hook'.
+
 2009-11-25  Juri Linkov  <juri@jurta.org>
 
        Provide additional default values (file name at point or at the
index b45b625b1ba1f9ef2e62cc6a496f38976c331fdd..4976d2cd68391f690c32c2d893ab870c181d92e1 100644 (file)
@@ -59,30 +59,27 @@ The prompted-for file is the first file given to `diff'.
 With prefix arg, prompt for second argument SWITCHES,
 which is options for `diff'."
   (interactive
-   (let ((current (dired-get-filename t))
-        (default (if (mark t)
-                     (save-excursion (goto-char (mark t))
-                                     (dired-get-filename t t)))))
-     (if (or (equal default current)
-            (and (not (equal (dired-dwim-target-directory)
-                             (dired-current-directory)))
-                 (not mark-active)))
-        (setq default nil))
+   (let* ((current (dired-get-filename t))
+         (target-dir (dired-dwim-target-directory))
+         (marked (and (mark t) (save-excursion
+                                 (goto-char (mark t))
+                                 (dired-get-filename nil t))))
+         (defaults
+           (append (dired-dwim-target-defaults nil target-dir)
+                   ;; Additional file with the mark.
+                   (and marked (list marked)))))
      (require 'diff)
-     (list (read-file-name (format "Diff %s with%s: "
-                                  current
-                                  (if default
-                                      (concat " (default " default ")")
-                                    ""))
-                          (if default
-                              (dired-current-directory)
-                            (dired-dwim-target-directory))
-                          default t)
-          (if current-prefix-arg
-              (read-string "Options for diff: "
-                           (if (stringp diff-switches)
-                               diff-switches
-                             (mapconcat 'identity diff-switches " ")))))))
+     (list
+      (minibuffer-with-setup-hook
+         (lambda ()
+           (set (make-local-variable 'minibuffer-default-add-function) nil)
+           (setq minibuffer-default defaults))
+       (read-file-name (format "Diff %s with: " current) target-dir nil t))
+      (if current-prefix-arg
+         (read-string "Options for diff: "
+                      (if (stringp diff-switches)
+                          diff-switches
+                        (mapconcat 'identity diff-switches " ")))))))
   (diff file (dired-get-filename t) switches))
 
 ;;;###autoload
@@ -128,11 +125,17 @@ Examples of PREDICATE:
     (not (and (= (nth 2 fa1) (nth 2 fa2))   - mark files with different UID
               (= (nth 3 fa1) (nth 3 fa2))))   and GID."
   (interactive
-   (list (read-directory-name (format "Compare %s with: "
-                                     (dired-current-directory))
-                             (dired-dwim-target-directory)
-                             (dired-dwim-target-directory))
-         (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil")))
+   (list
+    (let* ((target-dir (dired-dwim-target-directory))
+          (defaults (dired-dwim-target-defaults nil target-dir)))
+      (minibuffer-with-setup-hook
+         (lambda ()
+           (set (make-local-variable 'minibuffer-default-add-function) nil)
+           (setq minibuffer-default defaults))
+       (read-directory-name (format "Compare %s with: "
+                                    (dired-current-directory))
+                            target-dir target-dir t)))
+    (read-from-minibuffer "Mark if (lisp expr or RET): " nil nil t nil "nil")))
   (let* ((dir1 (dired-current-directory))
          (file-alist1 (dired-files-attributes dir1))
          (file-alist2 (dired-files-attributes dir2))
@@ -1463,10 +1466,15 @@ Optional arg HOW-TO determiness how to treat the target.
         (default (and dired-one-file
                       (expand-file-name (file-name-nondirectory (car fn-list))
                                         target-dir)))
+        (defaults (dired-dwim-target-defaults fn-list target-dir))
         (target (expand-file-name ; fluid variable inside dired-create-files
-                  (dired-mark-read-file-name
-                   (concat (if dired-one-file op1 operation) " %s to: ")
-                   target-dir op-symbol arg rfn-list default)))
+                 (minibuffer-with-setup-hook
+                     (lambda ()
+                       (set (make-local-variable 'minibuffer-default-add-function) nil)
+                       (setq minibuffer-default defaults))
+                   (dired-mark-read-file-name
+                    (concat (if dired-one-file op1 operation) " %s to: ")
+                    target-dir op-symbol arg rfn-list default))))
         (into-dir (cond ((null how-to)
                          ;; Allow DOS/Windows users to change the letter
                          ;; case of a directory.  If we don't test these
@@ -1523,18 +1531,69 @@ Optional arg HOW-TO determiness how to treat the target.
 
 (defun dired-dwim-target-directory ()
   ;; Try to guess which target directory the user may want.
-  ;; If there is a dired buffer displayed in the next window, use
-  ;; its current subdir, else use current subdir of this dired buffer.
+  ;; If there is a dired buffer displayed in one of the next windows,
+  ;; use its current subdir, else use current subdir of this dired buffer.
   (let ((this-dir (and (eq major-mode 'dired-mode)
                       (dired-current-directory))))
     ;; non-dired buffer may want to profit from this function, e.g. vm-uudecode
     (if dired-dwim-target
-       (let* ((other-buf (window-buffer (next-window)))
-              (other-dir (with-current-buffer other-buf
-                           (and (eq major-mode 'dired-mode)
-                                (dired-current-directory)))))
+       (let* ((other-win (get-window-with-predicate
+                          (lambda (window)
+                            (with-current-buffer (window-buffer window)
+                              (eq major-mode 'dired-mode)))))
+              (other-dir (and other-win
+                              (with-current-buffer (window-buffer other-win)
+                                (and (eq major-mode 'dired-mode)
+                                     (dired-current-directory))))))
          (or other-dir this-dir))
       this-dir)))
+
+(defun dired-dwim-target-defaults (fn-list target-dir)
+  ;; Return a list of default values for file-reading functions in Dired.
+  ;; This list may contain directories from Dired buffers in other windows.
+  ;; `fn-list' is a list of file names used to build a list of defaults.
+  ;; When nil or more than one element, a list of defaults will
+  ;; contain only directory names.  `target-dir' is a directory name
+  ;; to exclude from the returned list, for the case when this
+  ;; directory name is already presented in initial input.
+  ;; For Dired operations that support `dired-dwim-target',
+  ;; the argument `target-dir' should have the value returned
+  ;; from `dired-dwim-target-directory'.
+  (let ((dired-one-file
+        (and (consp fn-list) (null (cdr fn-list)) (car fn-list)))
+       (current-dir (and (eq major-mode 'dired-mode)
+                         (dired-current-directory)))
+       dired-dirs)
+    ;; Get a list of directories of visible buffers in dired-mode.
+    (walk-windows (lambda (w)
+                   (with-current-buffer (window-buffer w)
+                     (and (eq major-mode 'dired-mode)
+                          (push (dired-current-directory) dired-dirs)))))
+    ;; Force the current dir to be the first in the list.
+    (setq dired-dirs
+         (delete-dups (delq nil (cons current-dir (nreverse dired-dirs)))))
+    ;; Remove the target dir (if specified) or the current dir from
+    ;; default values, because it should be already in initial input.
+    (setq dired-dirs (delete (or target-dir current-dir) dired-dirs))
+    ;; Return a list of default values.
+    (if dired-one-file
+       ;; For one file operation, provide a list that contains
+       ;; other directories, other directories with the appended filename
+       ;; and the current directory with the appended filename, e.g.
+       ;; 1. /TARGET-DIR/
+       ;; 2. /TARGET-DIR/FILENAME
+       ;; 3. /CURRENT-DIR/FILENAME
+       (append dired-dirs
+               (mapcar (lambda (dir)
+                         (expand-file-name
+                          (file-name-nondirectory (car fn-list)) dir))
+                       (reverse dired-dirs))
+               (list (expand-file-name
+                      (file-name-nondirectory (car fn-list))
+                      (or target-dir current-dir))))
+      ;; For multi-file operation, return only a list of other directories.
+      dired-dirs)))
+
 \f
 ;;;###autoload
 (defun dired-create-directory (directory)
index ea12ef7532aa6c48477a5a9a9a4a086f5c86c339..e8a171bf5172f824384c0aa32b7d47f7a783e786 100644 (file)
@@ -3113,21 +3113,25 @@ Hit \\[ediff-recenter] to reset the windows afterward."
   (if (string= default-file "")
       (setq default-file nil))
 
-  (let (f)
-    (setq f (expand-file-name
-            (read-file-name
-             (format "%s%s "
-                     prompt
-                     (cond (default-file
-                             (concat " (default " default-file "):"))
-                           (t (concat " (default " default-dir "):"))))
-             default-dir
-             (or default-file default-dir)
-             t  ; must match, no-confirm
-             (if default-file (file-name-directory default-file))
-             )
-            default-dir
-            ))
+  (let ((defaults (and (fboundp 'dired-dwim-target-defaults)
+                      (dired-dwim-target-defaults
+                       (and default-file (list default-file))
+                       default-dir)))
+       f)
+    (setq f (minibuffer-with-setup-hook
+               (lambda () (when defaults
+                            (setq minibuffer-default defaults)))
+             (read-file-name
+              (format "%s%s "
+                      prompt
+                      (cond (default-file
+                              (concat " (default " default-file "):"))
+                            (t (concat " (default " default-dir "):"))))
+              default-dir
+              (or default-file default-dir)
+              t                        ; must match, no-confirm
+              (if default-file (file-name-directory default-file)))))
+    (setq f (expand-file-name f default-dir))
     ;; If user entered a directory name, expand the default file in that
     ;; directory.  This allows the user to enter a directory name for the
     ;; B-file and diff against the default-file in that directory instead