diff lisp/minibuffer.el @ 106239:0ac473df1bd1

Provide additional default values (file name at point or at the current Dired line) via M-n for file reading minibuffers. (Bug#5010) * minibuffer.el (read-file-name-defaults): New function. (read-file-name): Reset `minibuffer-default' to nil when it duplicates initial input `insdef'. Bind `minibuffer-default-add-function' to lambda that calls `read-file-name-defaults' in `minibuffer-selected-window'. (minibuffer-insert-file-name-at-point): New command. * files.el (file-name-at-point-functions): New defcustom. (find-file-default): Remove defvar. (find-file-read-args): Don't use `find-file-default'. Move `minibuffer-with-setup-hook' that sets `minibuffer-default' to `read-file-name'. (find-file-literally): Use `read-file-name' with `confirm-nonexistent-file-or-buffer'. * ffap.el (ffap-guess-file-name-at-point): New autoloaded function. * dired.el (dired-read-dir-and-switches): Move `minibuffer-with-setup-hook' that sets `minibuffer-default' to `read-file-name'. (dired-file-name-at-point): New function. (dired-mode): Add hook `dired-file-name-at-point' to `file-name-at-point-functions'.
author Juri Linkov <juri@jurta.org>
date Wed, 25 Nov 2009 17:11:29 +0000
parents 57f23ca20a76
children ab53cadac0b6
line wrap: on
line diff
--- a/lisp/minibuffer.el	Wed Nov 25 16:36:04 2009 +0000
+++ b/lisp/minibuffer.el	Wed Nov 25 17:11:29 2009 +0000
@@ -1321,6 +1321,32 @@
 (declare-function x-file-dialog "xfns.c"
                   (prompt dir &optional default-filename mustmatch only-dir-p))
 
+(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' (e.g. 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))))
+	(file-name-at-point
+	 (run-hook-with-args-until-success 'file-name-at-point-functions)))
+    (when file-name-at-point
+      (setq default (delete-dups
+		     (delete "" (delq nil (list file-name-at-point default))))))
+    ;; Append new defaults 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.
 Value is not expanded---you must call `expand-file-name' yourself.
@@ -1404,7 +1430,24 @@
                     (lexical-let ((dir (file-name-as-directory
                                         (expand-file-name dir))))
                       (minibuffer-with-setup-hook
-                          (lambda () (setq default-directory dir))
+                          (lambda ()
+			    (setq default-directory dir)
+			    ;; When the first default in `minibuffer-default'
+			    ;; duplicates initial input `insdef',
+			    ;; reset `minibuffer-default' to nil.
+			    (when (equal (or (car-safe insdef) insdef)
+					 (or (car-safe minibuffer-default)
+					     minibuffer-default))
+			      (setq minibuffer-default
+				    (cdr-safe minibuffer-default)))
+			    ;; On the first request on `M-n' fill
+			    ;; `minibuffer-default' with a list of defaults
+			    ;; relevant for file-name reading.
+			    (set (make-local-variable 'minibuffer-default-add-function)
+				 (lambda ()
+				   (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)))
@@ -1997,6 +2040,17 @@
     (when newstr
       (completion-pcm-try-completion newstr table pred (length newstr)))))
 
+
+;; Miscellaneous
+
+(defun minibuffer-insert-file-name-at-point ()
+  "Get a file name at point in original buffer and insert it to minibuffer."
+  (interactive)
+  (let ((file-name-at-point
+	 (with-current-buffer (window-buffer (minibuffer-selected-window))
+	   (run-hook-with-args-until-success 'file-name-at-point-functions))))
+    (when file-name-at-point
+      (insert file-name-at-point))))
 
 (provide 'minibuffer)