emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: find-file-read-args


From: Juri Linkov
Subject: Re: find-file-read-args
Date: Thu, 12 Nov 2009 11:56:35 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (x86_64-pc-linux-gnu)

> Thanks for working this out.  Looking at the patch I wonder if the
> "file-at-point" feature shouldn't be implemented in read-file-name rather
> than in find-file.

In the following patch I moved the code that sets `minibuffer-default'
from functions `find-file-read-args' and `dired-read-dir-and-switches'
to `read-file-name' where the list of default values gets filled
dynamically with the help of `minibuffer-default-add-function' that
tries to guess additional default values only when the user types M-n.

There is still one problem.  Due to the dynamical nature of M-n, it needs
to visit the original buffer to get file names at point at the time when
the current buffer if the minibuffer.  I tried to find the original buffer
with the help of `(with-current-buffer (window-buffer (next-window)) ...'
but it often finds the wrong buffer when there are more than one window on
the frame.  Could you suggest a method for finding the original buffer,
from which the minibuffer was activated.  Maybe we should add a new
variable to hold the value of the original buffer set during
minibuffer setup?

Index: lisp/files.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/files.el,v
retrieving revision 1.1098
diff -c -r1.1098 files.el
*** lisp/files.el       6 Nov 2009 05:16:27 -0000       1.1098
--- lisp/files.el       12 Nov 2009 09:54:28 -0000
***************
*** 1275,1283 ****
      ;;(make-frame-visible (window-frame old-window))
      ))
  
- (defvar find-file-default nil
-   "Used within `find-file-read-args'.")
- 
  (defmacro minibuffer-with-setup-hook (fun &rest body)
    "Add FUN to `minibuffer-setup-hook' while executing BODY.
  BODY should use the minibuffer at most once.
--- 1275,1280 ----
***************
*** 1298,1309 ****
         (remove-hook 'minibuffer-setup-hook ,hook)))))
  
  (defun find-file-read-args (prompt mustmatch)
!   (list (let ((find-file-default
!              (and buffer-file-name
!                   (abbreviate-file-name buffer-file-name))))
!         (minibuffer-with-setup-hook
!             (lambda () (setq minibuffer-default find-file-default))
!           (read-file-name prompt nil default-directory mustmatch)))
        t))
  
  (defun find-file (filename &optional wildcards)
--- 1295,1301 ----
         (remove-hook 'minibuffer-setup-hook ,hook)))))
  
  (defun find-file-read-args (prompt mustmatch)
!   (list (read-file-name prompt nil default-directory mustmatch)
        t))
  
  (defun find-file (filename &optional wildcards)

Index: lisp/dired.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/dired.el,v
retrieving revision 1.438
diff -c -r1.438 dired.el
*** lisp/dired.el       10 Nov 2009 08:11:51 -0000      1.438
--- lisp/dired.el       12 Nov 2009 09:52:56 -0000
***************
*** 598,609 ****
            (if (next-read-file-uses-dialog-p)
                (read-directory-name (format "Dired %s(directory): " str)
                                     nil default-directory nil)
!             (let ((default (and buffer-file-name
!                                 (abbreviate-file-name buffer-file-name))))
!               (minibuffer-with-setup-hook
!                   (lambda () (setq minibuffer-default default))
!                 (read-file-name (format "Dired %s(directory): " str)
!                                 nil default-directory nil)))))))
  
  ;; We want to switch to a more sophisticated version of
  ;; dired-read-dir-and-switches like the following, if there is a way
--- 598,605 ----
            (if (next-read-file-uses-dialog-p)
                (read-directory-name (format "Dired %s(directory): " str)
                                     nil default-directory nil)
!             (read-file-name (format "Dired %s(directory): " str)
!                             nil default-directory nil)))))
  
  ;; We want to switch to a more sophisticated version of
  ;; dired-read-dir-and-switches like the following, if there is a way

Index: lisp/minibuffer.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/minibuffer.el,v
retrieving revision 1.94
diff -c -r1.94 minibuffer.el
*** lisp/minibuffer.el  10 Nov 2009 00:54:48 -0000      1.94
--- lisp/minibuffer.el  12 Nov 2009 09:54:59 -0000
***************
*** 1258,1263 ****
--- 1258,1315 ----
  ;; 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 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))))))
+     ;; Delistify the default list containing only 1 element
+     (if (and (consp default) (null (cdr default)))
+       (car default)
+       default)))
  
  (defun read-file-name (prompt &optional dir default-filename mustmatch 
initial predicate)
    "Read file name, prompting with PROMPT and completing in directory DIR.
***************
*** 1342,1348 ****
                      (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)))
--- 1394,1411 ----
                      (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 ()
!                                    (with-current-buffer (window-buffer 
(next-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/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]