unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@jurta.org>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org
Subject: dired-dwim-target (was: FFAP)
Date: Sun, 15 Nov 2009 17:12:32 +0200	[thread overview]
Message-ID: <87iqdbx2kv.fsf_-_@mail.jurta.org> (raw)
In-Reply-To: <87bpjfiark.fsf@mail.jurta.org> (Juri Linkov's message of "Fri, 06 Nov 2009 23:19:45 +0200")

The first thing I have to do when using Dired in pristine Emacs without
.emacs is to type `M-x set-variable RET dired-dwim-target RET t RET'
because without dired-dwim-target = t Dired is helpless to me.

By default Dired operations provide the following minibuffer
default values (0. means initial input, and 1. - minibuffer's
contents after one M-n):

0. current directory name
1. file name from the current Dired line

However, when there is another Dired window on the same frame, there is
no easy way to copy/rename a file to it.  When `dired-dwim-target' is t,
then the default values are:

0. other directory name
1. file name from the other directory

This is better for copying/renaming to another directory, but still
inconvenient for copying/renaming in the current directory.  This
requires deleting all other Dired windows to force it showing the
default with the current directory name.

The solution is simple: provide both the current and other
directory names as default values.  The following patch keeps
the old behavior when there is one Dired window:

0. current directory name
1. file name from the current Dired line

but with more Dired windows it provides more default values:

0. current directory name
1. other directory name
2. file name from the other directory
3. file name from the current Dired line

When there are more than one marked file:

0. current directory name
1. other directory name

When `dired-dwim-target' is t (whose only purpose now will be
to show the other directory name as initial input, but with
`dired-dwim-target' = nil the same will be easily achievable via M-n):

0. other directory name
1. current directory name
2. file name from the current Dired line
3. file name from the other directory

When there are more than one marked file:

0. other directory name
1. current directory name

Actually in the following patch after reaching the end of the
aforementioned lists prepared in `dired-do-create-files-defaults',
the function `read-file-name-defaults' starts adding more items
guessed from the content of the Dired buffer.  But perhaps this
is not too useful.  If so, this can be easily disabled by
setting `minibuffer-default-add-function' to nil in
`dired-do-create-files' (currently commented out).

Index: lisp/dired-aux.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/dired-aux.el,v
retrieving revision 1.197
diff -c -r1.197 dired-aux.el
*** lisp/dired-aux.el	13 Nov 2009 22:19:50 -0000	1.197
--- lisp/dired-aux.el	15 Nov 2009 15:12:05 -0000
***************
*** 1463,1471 ****
  		       (expand-file-name (file-name-nondirectory (car 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)))
  	 (into-dir (cond ((null how-to)
  			  ;; Allow DOS/Windows users to change the letter
  			  ;; case of a directory.  If we don't test these
--- 1463,1477 ----
  		       (expand-file-name (file-name-nondirectory (car fn-list))
  					 target-dir)))
  	 (target (expand-file-name ; fluid variable inside dired-create-files
! 		  (minibuffer-with-setup-hook
! 		      (lambda ()
! 			;; (set (make-local-variable 'minibuffer-default-add-function) nil)
! 			(setq minibuffer-default
! 			      (dired-do-create-files-defaults
! 			       fn-list target-dir)))
! 		    (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
***************
*** 1520,1525 ****
--- 1526,1568 ----
     (function read-file-name)
     (format prompt (dired-mark-prompt arg files)) dir default))
  
+ (defun dired-do-create-files-defaults (fn-list target-dir)
+   ;; Return a list of default values for `dired-do-create-files-defaults'.
+   (let (target-dirs)
+     ;; Get a list of directories of visible buffers in dired-mode.
+     (walk-windows (lambda (w)
+ 		    (with-current-buffer (window-buffer w)
+ 		      (when (eq major-mode 'dired-mode)
+ 			(push default-directory target-dirs)))))
+     ;; Return default values.
+     (cond
+      (dired-dwim-target
+       (setq target-dirs (delete target-dir target-dirs))
+       (if dired-one-file
+ 	  (append target-dirs
+ 		  (mapcar (lambda (dir)
+ 			    (expand-file-name
+ 			     (file-name-nondirectory (car fn-list))
+ 			     dir))
+ 			  (reverse target-dirs))
+ 		  (list (expand-file-name
+ 			 (file-name-nondirectory (car fn-list))
+ 			 dir)))
+ 	target-dirs))
+      (t
+       (setq target-dirs (delete default-directory target-dirs))
+       (if dired-one-file
+ 	  (append target-dirs
+ 		  (mapcar (lambda (dir)
+ 			    (expand-file-name
+ 			     (file-name-nondirectory (car fn-list))
+ 			     dir))
+ 			  (reverse target-dirs))
+ 		  (list (expand-file-name
+ 			 (file-name-nondirectory (car fn-list))
+ 			 target-dir)))
+ 	target-dirs)))))
+ 
  (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

Index: lisp/minibuffer.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/minibuffer.el,v
retrieving revision 1.96
diff -c -r1.96 minibuffer.el
*** lisp/minibuffer.el	12 Nov 2009 23:10:06 -0000	1.96
--- lisp/minibuffer.el	15 Nov 2009 15:11:14 -0000
***************
*** 1253,1258 ****
--- 1253,1310 ----
  ;; Not always defined, but only called if next-read-file-uses-dialog-p says so.
  (declare-function x-file-dialog "xfns.c"
                    (prompt dir &optional default-filename mustmatch only-dir-p))
+ (declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
+ 
+ (defun read-file-name-defaults (&optional dir initial)
+   (let ((default
+ 	  (cond
+ 	   ;; With non-nil `initial', use `dir' as the first default.
+ 	   ;; Essentially, this mean reversing the normal order of the
+ 	   ;; current directory name and the current file name, i.e.
+ 	   ;; 1. with normal file reading:
+ 	   ;; 1.1. initial input is the current directory
+ 	   ;; 1.2. the first default is the current file name
+ 	   ;; 2. with non-nil `initial' (for `find-alternate-file'):
+ 	   ;; 2.2. initial input is the current file name
+ 	   ;; 2.1. the first default is the current directory
+ 	   (initial (abbreviate-file-name dir))
+ 	   ;; In file buffers, try to get the current file name
+ 	   (buffer-file-name
+ 	    (abbreviate-file-name buffer-file-name))
+ 	   ;; In Dired, get file name from the current line.
+ 	   ((eq major-mode 'dired-mode)
+ 	    (let ((filename (dired-get-filename nil t)))
+ 	      (when filename
+ 		(if (file-directory-p filename)
+ 		    (file-name-as-directory (abbreviate-file-name filename))
+ 		  (abbreviate-file-name filename)))))))
+ 	(filename-at-point
+ 	 (cond
+ 	  ((fboundp 'ffap-guesser)
+ 	   ;; Logic from `ffap-read-file-or-url' and `dired-at-point-prompter'
+ 	   (let ((guess (ffap-guesser)))
+ 	     (setq guess
+ 		   (if (or (not guess)
+ 			   (and (fboundp 'ffap-url-p)
+ 				(ffap-url-p guess))
+ 			   (and (fboundp 'ffap-file-remote-p)
+ 				(ffap-file-remote-p guess)))
+ 		       guess
+ 		     (abbreviate-file-name (expand-file-name guess))))
+ 	     (when guess
+ 	       (if (file-directory-p guess)
+ 		   (file-name-as-directory guess)
+ 		 guess))))
+ 	  ;; ((fboundp 'thing-at-point)
+ 	  ;;  (thing-at-point 'filename))
+ 	  )))
+     (when filename-at-point
+       (setq default (delete-dups
+ 		     (delete "" (delq nil (list filename-at-point default))))))
+     ;; Append new default values to the end of existing `minibuffer-default'
+     (append
+      (if (listp minibuffer-default) minibuffer-default (list minibuffer-default))
+      (if (listp default) default (list default)))))
  
  (defun read-file-name (prompt &optional dir default-filename mustmatch initial predicate)
    "Read file name, prompting with PROMPT and completing in directory DIR.
***************
*** 1337,1343 ****
                      (lexical-let ((dir (file-name-as-directory
                                          (expand-file-name dir))))
                        (minibuffer-with-setup-hook
!                           (lambda () (setq default-directory dir))
                          (completing-read prompt 'read-file-name-internal
                                           pred mustmatch insdef
                                           'file-name-history default-filename)))
--- 1389,1409 ----
                      (lexical-let ((dir (file-name-as-directory
                                          (expand-file-name dir))))
                        (minibuffer-with-setup-hook
!                           (lambda ()
! 			    (setq default-directory dir)
! 			    ;; Unless a list of default values is provided,
! 			    ;; reset `minibuffer-default' to nil and on the
! 			    ;; first request on `M-n' fill it with a list of
! 			    ;; default values relevant for file-name reading.
! 			    (unless (consp default-filename)
! 			      (setq minibuffer-default nil)
! 			      (set (make-local-variable 'minibuffer-default-add-function)
! 				   (lambda ()
! 				     (message "Original buffer: %S"
! 					      (window-buffer (minibuffer-selected-window)))
! 				     (with-current-buffer
! 					 (window-buffer (minibuffer-selected-window))
! 				       (read-file-name-defaults dir initial))))))
                          (completing-read prompt 'read-file-name-internal
                                           pred mustmatch insdef
                                           'file-name-history default-filename)))

-- 
Juri Linkov
http://www.jurta.org/emacs/




  parent reply	other threads:[~2009-11-15 15:12 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-06  0:13 find-file-literally-at-point Edward O'Connor
2009-11-06  1:45 ` find-file-literally-at-point Juri Linkov
2009-11-06  4:20   ` FFAP (was: find-file-literally-at-point) Stefan Monnier
2009-11-06  4:41     ` FFAP Miles Bader
2009-11-06 15:20       ` FFAP Stefan Monnier
2009-11-06  4:45     ` FFAP Juri Linkov
2009-11-06  8:50       ` FFAP Eli Zaretskii
2009-11-06 10:37         ` FFAP Juri Linkov
2009-11-06 15:18       ` FFAP Stefan Monnier
2009-11-06 21:19         ` FFAP Juri Linkov
2009-11-07  1:32           ` FFAP Stefan Monnier
2009-11-09  0:52             ` FFAP Juri Linkov
2009-11-09  6:33               ` FFAP Stefan Monnier
2009-11-09 10:09           ` find-file-read-args (was: FFAP) Juri Linkov
2009-11-09 14:28             ` find-file-read-args Stefan Monnier
2009-11-10  0:57               ` find-file-read-args Juri Linkov
2009-11-12  9:56               ` find-file-read-args Juri Linkov
2009-11-12 10:45                 ` find-file-read-args martin rudalics
2009-11-12 10:51                   ` find-file-read-args Juri Linkov
2009-11-15 15:09                     ` find-file-read-args Juri Linkov
2009-11-15 17:28                       ` find-file-read-args martin rudalics
2009-11-16  1:23                         ` find-file-read-args Stefan Monnier
2009-11-17  7:43                           ` find-file-read-args martin rudalics
2009-11-17  9:59                             ` find-file-read-args Juri Linkov
2009-11-17 17:42                               ` dired-dwim-target-directory (was: find-file-read-args) Juri Linkov
2009-11-17 17:43                               ` Juri Linkov
2009-11-23  4:19                               ` find-file-read-args Stefan Monnier
2009-11-23  9:59                                 ` find-file-read-args Juri Linkov
2009-11-23 20:17                                   ` find-file-read-args Stefan Monnier
2009-11-23 21:17                                     ` find-file-read-args Juri Linkov
2009-11-24  2:33                                       ` find-file-read-args Stefan Monnier
2009-11-24 17:08                                         ` find-file-read-args Juri Linkov
2009-11-24 19:40                                           ` find-file-read-args Stefan Monnier
2009-11-23 21:17                                 ` find-file-literally (was: find-file-read-args) Juri Linkov
2009-11-25  2:10                                   ` find-file-literally Stefan Monnier
2009-11-09 10:14           ` read-file-name (was: FFAP) Juri Linkov
2009-11-09 14:31             ` read-file-name Stefan Monnier
2009-11-10  0:55               ` read-file-name Juri Linkov
2009-11-10 17:25                 ` read-file-name Stefan Monnier
2009-11-09 10:30           ` dired-read-dir-and-switches (was: FFAP) Juri Linkov
2009-11-09 10:36           ` M-! M-n should fetch filename (Re: FFAP) Juri Linkov
2009-11-09 14:35             ` Stefan Monnier
2009-11-10  0:59               ` Juri Linkov
2009-11-10 17:29                 ` Stefan Monnier
2009-11-11  0:12                   ` Juri Linkov
2009-11-15 15:12           ` Juri Linkov [this message]
2009-11-23 21:12             ` dired-dwim-target-defaults (was: dired-dwim-target) Juri Linkov
2009-11-09  0:44   ` find-file-literally-at-point Juri Linkov
2009-11-09  2:00     ` find-file-literally-at-point Miles Bader
2009-11-09  2:11       ` find-file-literally-at-point Juri Linkov
2009-11-10  0:49         ` find-file-literally-at-point Juri Linkov
2009-11-09 10:01   ` utf-8-with-signature (was: find-file-literally-at-point) Juri Linkov
2009-11-06 10:20 ` find-file-literally-at-point Eduard Wiebe
2009-11-09  0:55   ` find-file-literally-at-point Juri Linkov
2009-11-09 19:49     ` find-file-literally-at-point Eduard Wiebe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87iqdbx2kv.fsf_-_@mail.jurta.org \
    --to=juri@jurta.org \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).