diff options
| author | Juri Linkov | 2009-11-25 17:11:29 +0000 |
|---|---|---|
| committer | Juri Linkov | 2009-11-25 17:11:29 +0000 |
| commit | 7d371eac644665cdc4afcac57e7a09560e010a31 (patch) | |
| tree | 668947c7530c04603a2a5372cc13156c4f96ad0e | |
| parent | 04ae543a28153fda0c084a5d56f59e2f7b12510d (diff) | |
| download | emacs-7d371eac644665cdc4afcac57e7a09560e010a31.tar.gz emacs-7d371eac644665cdc4afcac57e7a09560e010a31.zip | |
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'.
| -rw-r--r-- | etc/NEWS | 4 | ||||
| -rw-r--r-- | lisp/ChangeLog | 29 | ||||
| -rw-r--r-- | lisp/dired.el | 18 | ||||
| -rw-r--r-- | lisp/ffap.el | 23 | ||||
| -rw-r--r-- | lisp/files.el | 23 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 56 |
6 files changed, 136 insertions, 17 deletions
| @@ -150,6 +150,10 @@ For instance, this can complete M-x lch to list-command-history. | |||
| 150 | ** Completions in the *Completions* buffer are sorted vertically | 150 | ** Completions in the *Completions* buffer are sorted vertically |
| 151 | when the value of the new variable `completions-format' is `vertical'. | 151 | when the value of the new variable `completions-format' is `vertical'. |
| 152 | 152 | ||
| 153 | ** M-n provides more default values in the minibuffer of commands that | ||
| 154 | read a file and directory name: a file name at point (when ffap is loaded | ||
| 155 | without ffap-bindings), a file name on the current line in the Dired buffer. | ||
| 156 | |||
| 153 | ** M-r is bound to the new `move-to-window-line-top-bottom' | 157 | ** M-r is bound to the new `move-to-window-line-top-bottom' |
| 154 | to mirror the new behavior of C-l in Emacs-23.1. | 158 | to mirror the new behavior of C-l in Emacs-23.1. |
| 155 | 159 | ||
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 3f392f8183e..5c7d0a1e25d 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,32 @@ | |||
| 1 | 2009-11-25 Juri Linkov <juri@jurta.org> | ||
| 2 | |||
| 3 | Provide additional default values (file name at point or at the | ||
| 4 | current Dired line) via M-n for file reading minibuffers. (Bug#5010) | ||
| 5 | |||
| 6 | * minibuffer.el (read-file-name-defaults): New function. | ||
| 7 | (read-file-name): Reset `minibuffer-default' to nil when | ||
| 8 | it duplicates initial input `insdef'. | ||
| 9 | Bind `minibuffer-default-add-function' to lambda that | ||
| 10 | calls `read-file-name-defaults' in `minibuffer-selected-window'. | ||
| 11 | (minibuffer-insert-file-name-at-point): New command. | ||
| 12 | |||
| 13 | * files.el (file-name-at-point-functions): New defcustom. | ||
| 14 | (find-file-default): Remove defvar. | ||
| 15 | (find-file-read-args): Don't use `find-file-default'. | ||
| 16 | Move `minibuffer-with-setup-hook' that sets `minibuffer-default' | ||
| 17 | to `read-file-name'. | ||
| 18 | (find-file-literally): Use `read-file-name' with | ||
| 19 | `confirm-nonexistent-file-or-buffer'. | ||
| 20 | |||
| 21 | * ffap.el (ffap-guess-file-name-at-point): New autoloaded function. | ||
| 22 | |||
| 23 | * dired.el (dired-read-dir-and-switches): | ||
| 24 | Move `minibuffer-with-setup-hook' that sets `minibuffer-default' | ||
| 25 | to `read-file-name'. | ||
| 26 | (dired-file-name-at-point): New function. | ||
| 27 | (dired-mode): Add hook `dired-file-name-at-point' to | ||
| 28 | `file-name-at-point-functions'. | ||
| 29 | |||
| 1 | 2009-11-25 Stefan Monnier <monnier@iro.umontreal.ca> | 30 | 2009-11-25 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 31 | ||
| 3 | Really make the *Completions* window soft-dedicated (bug#5030). | 32 | Really make the *Completions* window soft-dedicated (bug#5030). |
diff --git a/lisp/dired.el b/lisp/dired.el index 788c5be3289..17bb3449da9 100644 --- a/lisp/dired.el +++ b/lisp/dired.el | |||
| @@ -599,12 +599,8 @@ Don't use that together with FILTER." | |||
| 599 | (if (next-read-file-uses-dialog-p) | 599 | (if (next-read-file-uses-dialog-p) |
| 600 | (read-directory-name (format "Dired %s(directory): " str) | 600 | (read-directory-name (format "Dired %s(directory): " str) |
| 601 | nil default-directory nil) | 601 | nil default-directory nil) |
| 602 | (let ((default (and buffer-file-name | 602 | (read-file-name (format "Dired %s(directory): " str) |
| 603 | (abbreviate-file-name buffer-file-name)))) | 603 | nil default-directory nil))))) |
| 604 | (minibuffer-with-setup-hook | ||
| 605 | (lambda () (setq minibuffer-default default)) | ||
| 606 | (read-file-name (format "Dired %s(directory): " str) | ||
| 607 | nil default-directory nil))))))) | ||
| 608 | 604 | ||
| 609 | ;; We want to switch to a more sophisticated version of | 605 | ;; We want to switch to a more sophisticated version of |
| 610 | ;; dired-read-dir-and-switches like the following, if there is a way | 606 | ;; dired-read-dir-and-switches like the following, if there is a way |
| @@ -659,6 +655,15 @@ Don't use that together with FILTER." | |||
| 659 | ;; (read-file-name (format "Dired %s(directory): " str) | 655 | ;; (read-file-name (format "Dired %s(directory): " str) |
| 660 | ;; nil default-directory nil)))))))) | 656 | ;; nil default-directory nil)))))))) |
| 661 | 657 | ||
| 658 | (defun dired-file-name-at-point () | ||
| 659 | "Try to get a file name at point in the current dired buffer. | ||
| 660 | This hook is inteneded to be put in `file-name-at-point-functions'." | ||
| 661 | (let ((filename (dired-get-filename nil t))) | ||
| 662 | (when filename | ||
| 663 | (if (file-directory-p filename) | ||
| 664 | (file-name-as-directory (abbreviate-file-name filename)) | ||
| 665 | (abbreviate-file-name filename))))) | ||
| 666 | |||
| 662 | ;;;###autoload (define-key ctl-x-map "d" 'dired) | 667 | ;;;###autoload (define-key ctl-x-map "d" 'dired) |
| 663 | ;;;###autoload | 668 | ;;;###autoload |
| 664 | (defun dired (dirname &optional switches) | 669 | (defun dired (dirname &optional switches) |
| @@ -1772,6 +1777,7 @@ Keybindings: | |||
| 1772 | (when (featurep 'dnd) | 1777 | (when (featurep 'dnd) |
| 1773 | (set (make-local-variable 'dnd-protocol-alist) | 1778 | (set (make-local-variable 'dnd-protocol-alist) |
| 1774 | (append dired-dnd-protocol-alist dnd-protocol-alist))) | 1779 | (append dired-dnd-protocol-alist dnd-protocol-alist))) |
| 1780 | (add-hook 'file-name-at-point-functions 'dired-file-name-at-point nil t) | ||
| 1775 | (add-hook 'isearch-mode-hook 'dired-isearch-filenames-setup nil t) | 1781 | (add-hook 'isearch-mode-hook 'dired-isearch-filenames-setup nil t) |
| 1776 | (run-mode-hooks 'dired-mode-hook)) | 1782 | (run-mode-hooks 'dired-mode-hook)) |
| 1777 | 1783 | ||
diff --git a/lisp/ffap.el b/lisp/ffap.el index a0e0d411206..7d3f279f724 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el | |||
| @@ -1893,6 +1893,29 @@ Only intended for interactive use." | |||
| 1893 | (call-interactively 'dired-at-point))) | 1893 | (call-interactively 'dired-at-point))) |
| 1894 | 1894 | ||
| 1895 | 1895 | ||
| 1896 | ;;; Hooks to put in `file-name-at-point-functions': | ||
| 1897 | |||
| 1898 | ;;;###autoload | ||
| 1899 | (progn (defun ffap-guess-file-name-at-point () | ||
| 1900 | "Try to get a file name at point. | ||
| 1901 | This hook is inteneded to be put in `file-name-at-point-functions'." | ||
| 1902 | (when (fboundp 'ffap-guesser) | ||
| 1903 | ;; Logic from `ffap-read-file-or-url' and `dired-at-point-prompter'. | ||
| 1904 | (let ((guess (ffap-guesser))) | ||
| 1905 | (setq guess | ||
| 1906 | (if (or (not guess) | ||
| 1907 | (and (fboundp 'ffap-url-p) | ||
| 1908 | (ffap-url-p guess)) | ||
| 1909 | (and (fboundp 'ffap-file-remote-p) | ||
| 1910 | (ffap-file-remote-p guess))) | ||
| 1911 | guess | ||
| 1912 | (abbreviate-file-name (expand-file-name guess)))) | ||
| 1913 | (when guess | ||
| 1914 | (if (file-directory-p guess) | ||
| 1915 | (file-name-as-directory guess) | ||
| 1916 | guess)))))) | ||
| 1917 | |||
| 1918 | |||
| 1896 | ;;; Offer default global bindings (`ffap-bindings'): | 1919 | ;;; Offer default global bindings (`ffap-bindings'): |
| 1897 | 1920 | ||
| 1898 | (defvar ffap-bindings | 1921 | (defvar ffap-bindings |
diff --git a/lisp/files.el b/lisp/files.el index 1bde2be0ef0..8478151cf78 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -411,6 +411,14 @@ and should return either a buffer or nil." | |||
| 411 | :type '(hook :options (cvs-dired-noselect dired-noselect)) | 411 | :type '(hook :options (cvs-dired-noselect dired-noselect)) |
| 412 | :group 'find-file) | 412 | :group 'find-file) |
| 413 | 413 | ||
| 414 | ;; FIXME: also add a hook for `(thing-at-point 'filename)' | ||
| 415 | (defcustom file-name-at-point-functions '(ffap-guess-file-name-at-point) | ||
| 416 | "List of functions to try in sequence to get a file name at point. | ||
| 417 | Each function should return either nil or a file name found at the | ||
| 418 | location of point in the current buffer." | ||
| 419 | :type '(hook :options (ffap-guess-file-name-at-point)) | ||
| 420 | :group 'find-file) | ||
| 421 | |||
| 414 | ;;;It is not useful to make this a local variable. | 422 | ;;;It is not useful to make this a local variable. |
| 415 | ;;;(put 'find-file-not-found-hooks 'permanent-local t) | 423 | ;;;(put 'find-file-not-found-hooks 'permanent-local t) |
| 416 | (defvar find-file-not-found-functions nil | 424 | (defvar find-file-not-found-functions nil |
| @@ -1275,9 +1283,6 @@ its documentation for additional customization information." | |||
| 1275 | ;;(make-frame-visible (window-frame old-window)) | 1283 | ;;(make-frame-visible (window-frame old-window)) |
| 1276 | )) | 1284 | )) |
| 1277 | 1285 | ||
| 1278 | (defvar find-file-default nil | ||
| 1279 | "Used within `find-file-read-args'.") | ||
| 1280 | |||
| 1281 | (defmacro minibuffer-with-setup-hook (fun &rest body) | 1286 | (defmacro minibuffer-with-setup-hook (fun &rest body) |
| 1282 | "Add FUN to `minibuffer-setup-hook' while executing BODY. | 1287 | "Add FUN to `minibuffer-setup-hook' while executing BODY. |
| 1283 | BODY should use the minibuffer at most once. | 1288 | BODY should use the minibuffer at most once. |
| @@ -1298,12 +1303,7 @@ Recursive uses of the minibuffer will not be affected." | |||
| 1298 | (remove-hook 'minibuffer-setup-hook ,hook))))) | 1303 | (remove-hook 'minibuffer-setup-hook ,hook))))) |
| 1299 | 1304 | ||
| 1300 | (defun find-file-read-args (prompt mustmatch) | 1305 | (defun find-file-read-args (prompt mustmatch) |
| 1301 | (list (let ((find-file-default | 1306 | (list (read-file-name prompt nil default-directory mustmatch) |
| 1302 | (and buffer-file-name | ||
| 1303 | (abbreviate-file-name buffer-file-name)))) | ||
| 1304 | (minibuffer-with-setup-hook | ||
| 1305 | (lambda () (setq minibuffer-default find-file-default)) | ||
| 1306 | (read-file-name prompt nil default-directory mustmatch))) | ||
| 1307 | t)) | 1307 | t)) |
| 1308 | 1308 | ||
| 1309 | (defun find-file (filename &optional wildcards) | 1309 | (defun find-file (filename &optional wildcards) |
| @@ -2020,7 +2020,10 @@ regardless of whether it was created literally or not. | |||
| 2020 | In a Lisp program, if you want to be sure of accessing a file's | 2020 | In a Lisp program, if you want to be sure of accessing a file's |
| 2021 | contents literally, you should create a temporary buffer and then read | 2021 | contents literally, you should create a temporary buffer and then read |
| 2022 | the file contents into it using `insert-file-contents-literally'." | 2022 | the file contents into it using `insert-file-contents-literally'." |
| 2023 | (interactive "FFind file literally: ") | 2023 | (interactive |
| 2024 | (list (read-file-name | ||
| 2025 | "Find file literally: " nil default-directory | ||
| 2026 | (confirm-nonexistent-file-or-buffer)))) | ||
| 2024 | (switch-to-buffer (find-file-noselect filename nil t))) | 2027 | (switch-to-buffer (find-file-noselect filename nil t))) |
| 2025 | 2028 | ||
| 2026 | (defvar after-find-file-from-revert-buffer nil) | 2029 | (defvar after-find-file-from-revert-buffer nil) |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index fdf57f9a2f8..cfe4d6f90de 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -1321,6 +1321,32 @@ such as making the current buffer visit no file in the case of | |||
| 1321 | (declare-function x-file-dialog "xfns.c" | 1321 | (declare-function x-file-dialog "xfns.c" |
| 1322 | (prompt dir &optional default-filename mustmatch only-dir-p)) | 1322 | (prompt dir &optional default-filename mustmatch only-dir-p)) |
| 1323 | 1323 | ||
| 1324 | (defun read-file-name-defaults (&optional dir initial) | ||
| 1325 | (let ((default | ||
| 1326 | (cond | ||
| 1327 | ;; With non-nil `initial', use `dir' as the first default. | ||
| 1328 | ;; Essentially, this mean reversing the normal order of the | ||
| 1329 | ;; current directory name and the current file name, i.e. | ||
| 1330 | ;; 1. with normal file reading: | ||
| 1331 | ;; 1.1. initial input is the current directory | ||
| 1332 | ;; 1.2. the first default is the current file name | ||
| 1333 | ;; 2. with non-nil `initial' (e.g. for `find-alternate-file'): | ||
| 1334 | ;; 2.2. initial input is the current file name | ||
| 1335 | ;; 2.1. the first default is the current directory | ||
| 1336 | (initial (abbreviate-file-name dir)) | ||
| 1337 | ;; In file buffers, try to get the current file name | ||
| 1338 | (buffer-file-name | ||
| 1339 | (abbreviate-file-name buffer-file-name)))) | ||
| 1340 | (file-name-at-point | ||
| 1341 | (run-hook-with-args-until-success 'file-name-at-point-functions))) | ||
| 1342 | (when file-name-at-point | ||
| 1343 | (setq default (delete-dups | ||
| 1344 | (delete "" (delq nil (list file-name-at-point default)))))) | ||
| 1345 | ;; Append new defaults to the end of existing `minibuffer-default'. | ||
| 1346 | (append | ||
| 1347 | (if (listp minibuffer-default) minibuffer-default (list minibuffer-default)) | ||
| 1348 | (if (listp default) default (list default))))) | ||
| 1349 | |||
| 1324 | (defun read-file-name (prompt &optional dir default-filename mustmatch initial predicate) | 1350 | (defun read-file-name (prompt &optional dir default-filename mustmatch initial predicate) |
| 1325 | "Read file name, prompting with PROMPT and completing in directory DIR. | 1351 | "Read file name, prompting with PROMPT and completing in directory DIR. |
| 1326 | Value is not expanded---you must call `expand-file-name' yourself. | 1352 | Value is not expanded---you must call `expand-file-name' yourself. |
| @@ -1404,7 +1430,24 @@ and `read-file-name-function'." | |||
| 1404 | (lexical-let ((dir (file-name-as-directory | 1430 | (lexical-let ((dir (file-name-as-directory |
| 1405 | (expand-file-name dir)))) | 1431 | (expand-file-name dir)))) |
| 1406 | (minibuffer-with-setup-hook | 1432 | (minibuffer-with-setup-hook |
| 1407 | (lambda () (setq default-directory dir)) | 1433 | (lambda () |
| 1434 | (setq default-directory dir) | ||
| 1435 | ;; When the first default in `minibuffer-default' | ||
| 1436 | ;; duplicates initial input `insdef', | ||
| 1437 | ;; reset `minibuffer-default' to nil. | ||
| 1438 | (when (equal (or (car-safe insdef) insdef) | ||
| 1439 | (or (car-safe minibuffer-default) | ||
| 1440 | minibuffer-default)) | ||
| 1441 | (setq minibuffer-default | ||
| 1442 | (cdr-safe minibuffer-default))) | ||
| 1443 | ;; On the first request on `M-n' fill | ||
| 1444 | ;; `minibuffer-default' with a list of defaults | ||
| 1445 | ;; relevant for file-name reading. | ||
| 1446 | (set (make-local-variable 'minibuffer-default-add-function) | ||
| 1447 | (lambda () | ||
| 1448 | (with-current-buffer | ||
| 1449 | (window-buffer (minibuffer-selected-window)) | ||
| 1450 | (read-file-name-defaults dir initial))))) | ||
| 1408 | (completing-read prompt 'read-file-name-internal | 1451 | (completing-read prompt 'read-file-name-internal |
| 1409 | pred mustmatch insdef | 1452 | pred mustmatch insdef |
| 1410 | 'file-name-history default-filename))) | 1453 | 'file-name-history default-filename))) |
| @@ -1997,6 +2040,17 @@ filter out additional entries (because TABLE migth not obey PRED)." | |||
| 1997 | (when newstr | 2040 | (when newstr |
| 1998 | (completion-pcm-try-completion newstr table pred (length newstr))))) | 2041 | (completion-pcm-try-completion newstr table pred (length newstr))))) |
| 1999 | 2042 | ||
| 2043 | |||
| 2044 | ;; Miscellaneous | ||
| 2045 | |||
| 2046 | (defun minibuffer-insert-file-name-at-point () | ||
| 2047 | "Get a file name at point in original buffer and insert it to minibuffer." | ||
| 2048 | (interactive) | ||
| 2049 | (let ((file-name-at-point | ||
| 2050 | (with-current-buffer (window-buffer (minibuffer-selected-window)) | ||
| 2051 | (run-hook-with-args-until-success 'file-name-at-point-functions)))) | ||
| 2052 | (when file-name-at-point | ||
| 2053 | (insert file-name-at-point)))) | ||
| 2000 | 2054 | ||
| 2001 | (provide 'minibuffer) | 2055 | (provide 'minibuffer) |
| 2002 | 2056 | ||