Mercurial > emacs
changeset 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 | 8cb41d65f821 |
children | 16d3ef458ae1 |
files | etc/NEWS lisp/ChangeLog lisp/dired.el lisp/ffap.el lisp/files.el lisp/minibuffer.el |
diffstat | 6 files changed, 136 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/etc/NEWS Wed Nov 25 16:36:04 2009 +0000 +++ b/etc/NEWS Wed Nov 25 17:11:29 2009 +0000 @@ -150,6 +150,10 @@ ** Completions in the *Completions* buffer are sorted vertically 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. + ** 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.
--- a/lisp/ChangeLog Wed Nov 25 16:36:04 2009 +0000 +++ b/lisp/ChangeLog Wed Nov 25 17:11:29 2009 +0000 @@ -1,3 +1,32 @@ +2009-11-25 Juri Linkov <juri@jurta.org> + + 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'. + 2009-11-25 Stefan Monnier <monnier@iro.umontreal.ca> Really make the *Completions* window soft-dedicated (bug#5030).
--- a/lisp/dired.el Wed Nov 25 16:36:04 2009 +0000 +++ b/lisp/dired.el Wed Nov 25 17:11:29 2009 +0000 @@ -599,12 +599,8 @@ (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))))))) + (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 @@ -659,6 +655,15 @@ ;; (read-file-name (format "Dired %s(directory): " str) ;; nil default-directory nil)))))))) +(defun dired-file-name-at-point () + "Try to get a file name at point in the current dired buffer. +This hook is inteneded to be put in `file-name-at-point-functions'." + (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))))) + ;;;###autoload (define-key ctl-x-map "d" 'dired) ;;;###autoload (defun dired (dirname &optional switches) @@ -1772,6 +1777,7 @@ (when (featurep 'dnd) (set (make-local-variable 'dnd-protocol-alist) (append dired-dnd-protocol-alist dnd-protocol-alist))) + (add-hook 'file-name-at-point-functions 'dired-file-name-at-point nil t) (add-hook 'isearch-mode-hook 'dired-isearch-filenames-setup nil t) (run-mode-hooks 'dired-mode-hook))
--- a/lisp/ffap.el Wed Nov 25 16:36:04 2009 +0000 +++ b/lisp/ffap.el Wed Nov 25 17:11:29 2009 +0000 @@ -1893,6 +1893,29 @@ (call-interactively 'dired-at-point))) +;;; Hooks to put in `file-name-at-point-functions': + +;;;###autoload +(progn (defun ffap-guess-file-name-at-point () + "Try to get a file name at point. +This hook is inteneded to be put in `file-name-at-point-functions'." + (when (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)))))) + + ;;; Offer default global bindings (`ffap-bindings'): (defvar ffap-bindings
--- a/lisp/files.el Wed Nov 25 16:36:04 2009 +0000 +++ b/lisp/files.el Wed Nov 25 17:11:29 2009 +0000 @@ -411,6 +411,14 @@ :type '(hook :options (cvs-dired-noselect dired-noselect)) :group 'find-file) +;; FIXME: also add a hook for `(thing-at-point 'filename)' +(defcustom file-name-at-point-functions '(ffap-guess-file-name-at-point) + "List of functions to try in sequence to get a file name at point. +Each function should return either nil or a file name found at the +location of point in the current buffer." + :type '(hook :options (ffap-guess-file-name-at-point)) + :group 'find-file) + ;;;It is not useful to make this a local variable. ;;;(put 'find-file-not-found-hooks 'permanent-local t) (defvar find-file-not-found-functions nil @@ -1275,9 +1283,6 @@ ;;(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. @@ -1298,12 +1303,7 @@ (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))) + (list (read-file-name prompt nil default-directory mustmatch) t)) (defun find-file (filename &optional wildcards) @@ -2020,7 +2020,10 @@ In a Lisp program, if you want to be sure of accessing a file's contents literally, you should create a temporary buffer and then read the file contents into it using `insert-file-contents-literally'." - (interactive "FFind file literally: ") + (interactive + (list (read-file-name + "Find file literally: " nil default-directory + (confirm-nonexistent-file-or-buffer)))) (switch-to-buffer (find-file-noselect filename nil t))) (defvar after-find-file-from-revert-buffer nil)
--- 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)