Mercurial > emacs
comparison lisp/ffap.el @ 58923:481f80f548e1
(ffap-dired-wildcards): Set default to "[*?][^/]*\\'". Doc fix.
(ffap-directory-finder): New variable.
(ffap-string-at-point-mode-alist): Add * and ? to `file'.
(ffap-file-at-point): Add /* to immediately rejected names.
Return absolute file names matching ffap-dired-wildcards.
(ffap-read-file-or-url): Set default value for `completing-read'
to `buffer-file-name'.
(find-file-at-point): When filename matches ffap-dired-wildcards,
call ffap-file-finder with t arg `wildcards', instead of dired.
(ffap-other-window, ffap-other-frame): Return visited buffers.
(ffap-read-only, ffap-read-only-other-window)
(ffap-read-only-other-frame, ffap-alternate-file): New commands.
(dired-at-point): Call ffap-directory-finder instead of dired.
(ffap-dired-other-window, ffap-dired-other-frame)
(ffap-list-directory): New commands.
(ffap-bindings): New keybindings for new commands.
author | Juri Linkov <juri@jurta.org> |
---|---|
date | Mon, 13 Dec 2004 05:16:25 +0000 |
parents | 73c87f418eba |
children | ef1861e51db0 fb79180b618d |
comparison
equal
deleted
inserted
replaced
58922:3e3c16ff820c | 58923:481f80f548e1 |
---|---|
40 ;; | 40 ;; |
41 ;; (ffap-bindings) ; do default key bindings | 41 ;; (ffap-bindings) ; do default key bindings |
42 ;; | 42 ;; |
43 ;; ffap-bindings makes the following global key bindings: | 43 ;; ffap-bindings makes the following global key bindings: |
44 ;; | 44 ;; |
45 ;; C-x C-f find-file-at-point (abbreviated as ffap) | 45 ;; C-x C-f find-file-at-point (abbreviated as ffap) |
46 ;; C-x d dired-at-point | 46 ;; C-x C-r ffap-read-only |
47 ;; C-x 4 f ffap-other-window | 47 ;; C-x C-v ffap-alternate-file |
48 ;; C-x 5 f ffap-other-frame | 48 ;; |
49 ;; C-x d dired-at-point | |
50 ;; C-x C-d ffap-list-directory | |
51 ;; | |
52 ;; C-x 4 f ffap-other-window | |
53 ;; C-x 4 r ffap-read-only-other-window | |
54 ;; C-x 4 d ffap-dired-other-window | |
55 ;; | |
56 ;; C-x 5 f ffap-other-frame | |
57 ;; C-x 5 r ffap-read-only-other-frame | |
58 ;; C-x 5 d ffap-dired-other-frame | |
59 ;; | |
49 ;; S-mouse-3 ffap-at-mouse | 60 ;; S-mouse-3 ffap-at-mouse |
50 ;; C-S-mouse-3 ffap-menu | 61 ;; C-S-mouse-3 ffap-menu |
51 ;; | 62 ;; |
52 ;; ffap-bindings also adds hooks to make the following local bindings | 63 ;; ffap-bindings also adds hooks to make the following local bindings |
53 ;; in vm, gnus, and rmail: | 64 ;; in vm, gnus, and rmail: |
200 ;; those features interesting but not clear winners (a matter of | 211 ;; those features interesting but not clear winners (a matter of |
201 ;; personal taste) I try to leave options to enable them. Read | 212 ;; personal taste) I try to leave options to enable them. Read |
202 ;; through this section for features that you like, put an appropriate | 213 ;; through this section for features that you like, put an appropriate |
203 ;; enabler in your .emacs file. | 214 ;; enabler in your .emacs file. |
204 | 215 |
205 (defcustom ffap-dired-wildcards nil | 216 (defcustom ffap-dired-wildcards "[*?][^/]*\\'" |
206 ;; Suggestion from RHOGEE, 07 Jul 1994. Disabled, dired is still | |
207 ;; available by "C-x C-d <pattern>", and valid filenames may | |
208 ;; sometimes contain wildcard characters. | |
209 "*A regexp matching filename wildcard characters, or nil. | 217 "*A regexp matching filename wildcard characters, or nil. |
218 | |
210 If `find-file-at-point' gets a filename matching this pattern, | 219 If `find-file-at-point' gets a filename matching this pattern, |
211 it passes it on to `dired' instead of `find-file'." | 220 it passes it on to `find-file' with non-nil WILDCARDS argument, |
221 which expands wildcards and visits multiple files. To visit | |
222 a file whose name contains wildcard characters you can suppress | |
223 wildcard expansion by setting `find-file-wildcards'. | |
224 | |
225 If `dired-at-point' gets a filename matching this pattern, | |
226 it passes it on to `dired'." | |
212 :type '(choice (const :tag "Disable" nil) | 227 :type '(choice (const :tag "Disable" nil) |
213 (const :tag "Enable" "[*?][^/]*\\'") | 228 (const :tag "Enable" "[*?][^/]*\\'") |
214 ;; regexp -- probably not useful | 229 ;; regexp -- probably not useful |
215 ) | 230 ) |
216 :group 'ffap) | 231 :group 'ffap) |
233 (defcustom ffap-file-finder 'find-file | 248 (defcustom ffap-file-finder 'find-file |
234 "*The command called by `find-file-at-point' to find a file." | 249 "*The command called by `find-file-at-point' to find a file." |
235 :type 'function | 250 :type 'function |
236 :group 'ffap) | 251 :group 'ffap) |
237 (put 'ffap-file-finder 'risky-local-variable t) | 252 (put 'ffap-file-finder 'risky-local-variable t) |
253 | |
254 (defcustom ffap-directory-finder 'dired | |
255 "*The command called by `dired-at-point' to find a directory." | |
256 :type 'function | |
257 :group 'ffap) | |
258 (put 'ffap-directory-finder 'risky-local-variable t) | |
238 | 259 |
239 (defcustom ffap-url-fetcher | 260 (defcustom ffap-url-fetcher |
240 (if (fboundp 'browse-url) | 261 (if (fboundp 'browse-url) |
241 'browse-url ; rely on browse-url-browser-function | 262 'browse-url ; rely on browse-url-browser-function |
242 'w3-fetch) | 263 'w3-fetch) |
937 '( | 958 '( |
938 ;; The default, used when the `major-mode' is not found. | 959 ;; The default, used when the `major-mode' is not found. |
939 ;; Slightly controversial decisions: | 960 ;; Slightly controversial decisions: |
940 ;; * strip trailing "@" and ":" | 961 ;; * strip trailing "@" and ":" |
941 ;; * no commas (good for latex) | 962 ;; * no commas (good for latex) |
942 (file "--:$+<>@-Z_a-z~" "<@" "@>;.,!?:") | 963 (file "--:$+<>@-Z_a-z~*?" "<@" "@>;.,!:") |
943 ;; An url, or maybe a email/news message-id: | 964 ;; An url, or maybe a email/news message-id: |
944 (url "--:=&?$+@-Z_a-z~#,%;" "^A-Za-z0-9" ":;.,!?") | 965 (url "--:=&?$+@-Z_a-z~#,%;" "^A-Za-z0-9" ":;.,!?") |
945 ;; Find a string that does *not* contain a colon: | 966 ;; Find a string that does *not* contain a colon: |
946 (nocolon "--9$+<>@-Z_a-z~" "<@" "@>;.,!?") | 967 (nocolon "--9$+<>@-Z_a-z~" "<@" "@>;.,!?") |
947 ;; A machine: | 968 ;; A machine: |
1118 string)) | 1139 string)) |
1119 (abs (file-name-absolute-p name)) | 1140 (abs (file-name-absolute-p name)) |
1120 (default-directory default-directory)) | 1141 (default-directory default-directory)) |
1121 (unwind-protect | 1142 (unwind-protect |
1122 (cond | 1143 (cond |
1123 ;; Immediate rejects (/ and // are too common in C++): | 1144 ;; Immediate rejects (/ and // and /* are too common in C/C++): |
1124 ((member name '("" "/" "//" ".")) nil) | 1145 ((member name '("" "/" "//" "/*" ".")) nil) |
1125 ;; Immediately test local filenames. If default-directory is | 1146 ;; Immediately test local filenames. If default-directory is |
1126 ;; remote, you probably already have a connection. | 1147 ;; remote, you probably already have a connection. |
1127 ((and (not abs) (ffap-file-exists-string name))) | 1148 ((and (not abs) (ffap-file-exists-string name))) |
1128 ;; Try stripping off line numbers; good for compilation/grep output. | 1149 ;; Try stripping off line numbers; good for compilation/grep output. |
1129 ((and (not abs) (string-match ":[0-9]" name) | 1150 ((and (not abs) (string-match ":[0-9]" name) |
1185 (ffap-file-exists-string | 1206 (ffap-file-exists-string |
1186 (ffap-replace-file-component | 1207 (ffap-replace-file-component |
1187 remote-dir (substring name (match-end 1))))) | 1208 remote-dir (substring name (match-end 1))))) |
1188 (ffap-file-exists-string | 1209 (ffap-file-exists-string |
1189 (ffap-replace-file-component remote-dir name)))))) | 1210 (ffap-replace-file-component remote-dir name)))))) |
1211 ((and ffap-dired-wildcards | |
1212 (string-match ffap-dired-wildcards name) | |
1213 abs | |
1214 (ffap-file-exists-string (file-name-directory | |
1215 (directory-file-name name))) | |
1216 name)) | |
1190 ;; Try all parent directories by deleting the trailing directory | 1217 ;; Try all parent directories by deleting the trailing directory |
1191 ;; name until existing directory is found or name stops changing | 1218 ;; name until existing directory is found or name stops changing |
1192 ((let ((dir name)) | 1219 ((let ((dir name)) |
1193 (while (and dir | 1220 (while (and dir |
1194 (not (ffap-file-exists-string dir)) | 1221 (not (ffap-file-exists-string dir)) |
1225 prompt | 1252 prompt |
1226 'ffap-read-file-or-url-internal | 1253 'ffap-read-file-or-url-internal |
1227 dir | 1254 dir |
1228 nil | 1255 nil |
1229 (if dir (cons guess (length dir)) guess) | 1256 (if dir (cons guess (length dir)) guess) |
1230 (list 'file-name-history)))) | 1257 (list 'file-name-history) |
1258 (and buffer-file-name | |
1259 (abbreviate-file-name buffer-file-name))))) | |
1231 ;; Do file substitution like (interactive "F"), suggested by MCOOK. | 1260 ;; Do file substitution like (interactive "F"), suggested by MCOOK. |
1232 (or (ffap-url-p guess) (setq guess (substitute-in-file-name guess))) | 1261 (or (ffap-url-p guess) (setq guess (substitute-in-file-name guess))) |
1233 ;; Should not do it on url's, where $ is a common (VMS?) character. | 1262 ;; Should not do it on url's, where $ is a common (VMS?) character. |
1234 ;; Note: upcoming url.el package ought to handle this automatically. | 1263 ;; Note: upcoming url.el package ought to handle this automatically. |
1235 guess)) | 1264 guess)) |
1355 (or filename (setq filename (ffap-prompter))) | 1384 (or filename (setq filename (ffap-prompter))) |
1356 (cond | 1385 (cond |
1357 ((ffap-url-p filename) | 1386 ((ffap-url-p filename) |
1358 (let (current-prefix-arg) ; w3 2.3.25 bug, reported by KPC | 1387 (let (current-prefix-arg) ; w3 2.3.25 bug, reported by KPC |
1359 (funcall ffap-url-fetcher filename))) | 1388 (funcall ffap-url-fetcher filename))) |
1360 ;; This junk more properly belongs in a modified ffap-file-finder: | |
1361 ((and ffap-dired-wildcards | 1389 ((and ffap-dired-wildcards |
1362 (string-match ffap-dired-wildcards filename)) | 1390 (string-match ffap-dired-wildcards filename) |
1363 (dired filename)) | 1391 find-file-wildcards |
1392 ;; Check if it's find-file that supports wildcards arg | |
1393 (memq ffap-file-finder '(find-file find-alternate-file))) | |
1394 (funcall ffap-file-finder (expand-file-name filename) t)) | |
1364 ((or (not ffap-newfile-prompt) | 1395 ((or (not ffap-newfile-prompt) |
1365 (file-exists-p filename) | 1396 (file-exists-p filename) |
1366 (y-or-n-p "File does not exist, create buffer? ")) | 1397 (y-or-n-p "File does not exist, create buffer? ")) |
1367 (funcall ffap-file-finder | 1398 (funcall ffap-file-finder |
1368 ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR. | 1399 ;; expand-file-name fixes "~/~/.emacs" bug sent by CHUCKR. |
1554 nil)) ; no fallback, return nil | 1585 nil)) ; no fallback, return nil |
1555 ;; failure: return nil | 1586 ;; failure: return nil |
1556 ))) | 1587 ))) |
1557 | 1588 |
1558 | 1589 |
1559 ;;; ffap-other-* commands: | 1590 ;;; ffap-other-*, ffap-read-only-*, ffap-alternate-* commands: |
1560 ;; | |
1561 ;; Requested by KPC. | |
1562 | 1591 |
1563 ;; There could be a real `ffap-noselect' function, but we would need | 1592 ;; There could be a real `ffap-noselect' function, but we would need |
1564 ;; at least two new user variables, and there is no w3-fetch-noselect. | 1593 ;; at least two new user variables, and there is no w3-fetch-noselect. |
1565 ;; So instead, we just fake it with a slow save-window-excursion. | 1594 ;; So instead, we just fake it with a slow save-window-excursion. |
1566 | 1595 |
1567 (defun ffap-other-window nil | 1596 (defun ffap-other-window nil |
1568 "Like `ffap', but put buffer in another window. | 1597 "Like `ffap', but put buffer in another window. |
1569 Only intended for interactive use." | 1598 Only intended for interactive use." |
1570 (interactive) | 1599 (interactive) |
1571 (switch-to-buffer-other-window | 1600 (let (value) |
1572 (save-window-excursion (call-interactively 'ffap) (current-buffer)))) | 1601 (switch-to-buffer-other-window |
1602 (save-window-excursion | |
1603 (setq value (call-interactively 'ffap)) | |
1604 (unless (or (bufferp value) (bufferp (car-safe value))) | |
1605 (setq value (current-buffer))) | |
1606 (current-buffer))) | |
1607 value)) | |
1573 | 1608 |
1574 (defun ffap-other-frame nil | 1609 (defun ffap-other-frame nil |
1575 "Like `ffap', but put buffer in another frame. | 1610 "Like `ffap', but put buffer in another frame. |
1576 Only intended for interactive use." | 1611 Only intended for interactive use." |
1577 (interactive) | 1612 (interactive) |
1578 ;; Extra code works around dedicated windows (noted by JENS, 7/96): | 1613 ;; Extra code works around dedicated windows (noted by JENS, 7/96): |
1579 (let* ((win (selected-window)) (wdp (window-dedicated-p win))) | 1614 (let* ((win (selected-window)) |
1615 (wdp (window-dedicated-p win)) | |
1616 value) | |
1580 (unwind-protect | 1617 (unwind-protect |
1581 (progn | 1618 (progn |
1582 (set-window-dedicated-p win nil) | 1619 (set-window-dedicated-p win nil) |
1583 (switch-to-buffer-other-frame | 1620 (switch-to-buffer-other-frame |
1584 (save-window-excursion | 1621 (save-window-excursion |
1585 (call-interactively 'ffap) | 1622 (setq value (call-interactively 'ffap)) |
1623 (unless (or (bufferp value) (bufferp (car-safe value))) | |
1624 (setq value (current-buffer))) | |
1586 (current-buffer)))) | 1625 (current-buffer)))) |
1587 (set-window-dedicated-p win wdp)))) | 1626 (set-window-dedicated-p win wdp)) |
1627 value)) | |
1628 | |
1629 (defun ffap-read-only () | |
1630 "Like `ffap', but mark buffer as read-only. | |
1631 Only intended for interactive use." | |
1632 (interactive) | |
1633 (let ((value (call-interactively 'ffap))) | |
1634 (unless (or (bufferp value) (bufferp (car-safe value))) | |
1635 (setq value (current-buffer))) | |
1636 (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1))) | |
1637 (if (listp value) value (list value))) | |
1638 value)) | |
1639 | |
1640 (defun ffap-read-only-other-window () | |
1641 "Like `ffap', but put buffer in another window and mark as read-only. | |
1642 Only intended for interactive use." | |
1643 (interactive) | |
1644 (let ((value (ffap-other-window))) | |
1645 (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1))) | |
1646 (if (listp value) value (list value))) | |
1647 value)) | |
1648 | |
1649 (defun ffap-read-only-other-frame () | |
1650 "Like `ffap', but put buffer in another frame and mark as read-only. | |
1651 Only intended for interactive use." | |
1652 (interactive) | |
1653 (let ((value (ffap-other-frame))) | |
1654 (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1))) | |
1655 (if (listp value) value (list value))) | |
1656 value)) | |
1657 | |
1658 (defun ffap-alternate-file () | |
1659 "Like `ffap' and `find-alternate-file'. | |
1660 Only intended for interactive use." | |
1661 (interactive) | |
1662 (let ((ffap-file-finder 'find-alternate-file)) | |
1663 (call-interactively 'ffap))) | |
1588 | 1664 |
1589 | 1665 |
1590 ;;; Bug Reporter: | 1666 ;;; Bug Reporter: |
1591 | 1667 |
1592 (defun ffap-bug nil | 1668 (defun ffap-bug nil |
1663 (if (and (interactive-p) | 1739 (if (and (interactive-p) |
1664 (if dired-at-point-require-prefix | 1740 (if dired-at-point-require-prefix |
1665 (not current-prefix-arg) | 1741 (not current-prefix-arg) |
1666 current-prefix-arg)) | 1742 current-prefix-arg)) |
1667 (let (current-prefix-arg) ; already interpreted | 1743 (let (current-prefix-arg) ; already interpreted |
1668 (call-interactively 'dired)) | 1744 (call-interactively ffap-directory-finder)) |
1669 (or filename (setq filename (dired-at-point-prompter))) | 1745 (or filename (setq filename (dired-at-point-prompter))) |
1670 (cond | 1746 (cond |
1671 ((ffap-url-p filename) | 1747 ((ffap-url-p filename) |
1672 (funcall ffap-url-fetcher filename)) | 1748 (funcall ffap-url-fetcher filename)) |
1673 ((and ffap-dired-wildcards | 1749 ((and ffap-dired-wildcards |
1674 (string-match ffap-dired-wildcards filename)) | 1750 (string-match ffap-dired-wildcards filename)) |
1675 (dired filename)) | 1751 (funcall ffap-directory-finder filename)) |
1676 ((file-exists-p filename) | 1752 ((file-exists-p filename) |
1677 (if (file-directory-p filename) | 1753 (if (file-directory-p filename) |
1678 (dired (expand-file-name filename)) | 1754 (funcall ffap-directory-finder |
1679 (dired (concat (expand-file-name filename) "*")))) | 1755 (expand-file-name filename)) |
1756 (funcall ffap-directory-finder | |
1757 (concat (expand-file-name filename) "*")))) | |
1680 ((and (file-writable-p | 1758 ((and (file-writable-p |
1681 (or (file-name-directory (directory-file-name filename)) | 1759 (or (file-name-directory (directory-file-name filename)) |
1682 filename)) | 1760 filename)) |
1683 (y-or-n-p "Directory does not exist, create it? ")) | 1761 (y-or-n-p "Directory does not exist, create it? ")) |
1684 (make-directory filename) | 1762 (make-directory filename) |
1685 (dired filename)) | 1763 (funcall ffap-directory-finder filename)) |
1686 ((error "No such file or directory `%s'" filename))))) | 1764 ((error "No such file or directory `%s'" filename))))) |
1687 | 1765 |
1688 (defun dired-at-point-prompter (&optional guess) | 1766 (defun dired-at-point-prompter (&optional guess) |
1689 ;; Does guess and prompt step for find-file-at-point. | 1767 ;; Does guess and prompt step for find-file-at-point. |
1690 ;; Extra complication for the temporary highlighting. | 1768 ;; Extra complication for the temporary highlighting. |
1710 (guess)))) | 1788 (guess)))) |
1711 )) | 1789 )) |
1712 (and guess (ffap-highlight)))) | 1790 (and guess (ffap-highlight)))) |
1713 (ffap-highlight t))) | 1791 (ffap-highlight t))) |
1714 | 1792 |
1793 ;;; ffap-dired-other-*, ffap-list-directory commands: | |
1794 | |
1795 (defun ffap-dired-other-window () | |
1796 "Like `dired-at-point', but put buffer in another window. | |
1797 Only intended for interactive use." | |
1798 (interactive) | |
1799 (let (value) | |
1800 (switch-to-buffer-other-window | |
1801 (save-window-excursion | |
1802 (setq value (call-interactively 'dired-at-point)) | |
1803 (current-buffer))) | |
1804 value)) | |
1805 | |
1806 (defun ffap-dired-other-frame () | |
1807 "Like `dired-at-point', but put buffer in another frame. | |
1808 Only intended for interactive use." | |
1809 (interactive) | |
1810 ;; Extra code works around dedicated windows (noted by JENS, 7/96): | |
1811 (let* ((win (selected-window)) | |
1812 (wdp (window-dedicated-p win)) | |
1813 value) | |
1814 (unwind-protect | |
1815 (progn | |
1816 (set-window-dedicated-p win nil) | |
1817 (switch-to-buffer-other-frame | |
1818 (save-window-excursion | |
1819 (setq value (call-interactively 'dired-at-point)) | |
1820 (current-buffer)))) | |
1821 (set-window-dedicated-p win wdp)) | |
1822 value)) | |
1823 | |
1824 (defun ffap-list-directory () | |
1825 "Like `dired-at-point' and `list-directory'. | |
1826 Only intended for interactive use." | |
1827 (interactive) | |
1828 (let ((ffap-directory-finder 'list-directory)) | |
1829 (call-interactively 'dired-at-point))) | |
1830 | |
1831 | |
1715 ;;; Offer default global bindings (`ffap-bindings'): | 1832 ;;; Offer default global bindings (`ffap-bindings'): |
1716 | 1833 |
1717 (defvar ffap-bindings | 1834 (defvar ffap-bindings |
1718 '( | 1835 '( |
1719 (global-set-key [S-mouse-3] 'ffap-at-mouse) | 1836 (global-set-key [S-mouse-3] 'ffap-at-mouse) |
1720 (global-set-key [C-S-mouse-3] 'ffap-menu) | 1837 (global-set-key [C-S-mouse-3] 'ffap-menu) |
1838 | |
1721 (global-set-key "\C-x\C-f" 'find-file-at-point) | 1839 (global-set-key "\C-x\C-f" 'find-file-at-point) |
1840 (global-set-key "\C-x\C-r" 'ffap-read-only) | |
1841 (global-set-key "\C-x\C-v" 'ffap-alternate-file) | |
1842 | |
1722 (global-set-key "\C-x4f" 'ffap-other-window) | 1843 (global-set-key "\C-x4f" 'ffap-other-window) |
1723 (global-set-key "\C-x5f" 'ffap-other-frame) | 1844 (global-set-key "\C-x5f" 'ffap-other-frame) |
1845 (global-set-key "\C-x4r" 'ffap-read-only-other-window) | |
1846 (global-set-key "\C-x5r" 'ffap-read-only-other-frame) | |
1847 | |
1724 (global-set-key "\C-xd" 'dired-at-point) | 1848 (global-set-key "\C-xd" 'dired-at-point) |
1849 (global-set-key "\C-x4d" 'ffap-dired-other-window) | |
1850 (global-set-key "\C-x5d" 'ffap-dired-other-frame) | |
1851 (global-set-key "\C-x\C-d" 'ffap-list-directory) | |
1852 | |
1725 (add-hook 'gnus-summary-mode-hook 'ffap-gnus-hook) | 1853 (add-hook 'gnus-summary-mode-hook 'ffap-gnus-hook) |
1726 (add-hook 'gnus-article-mode-hook 'ffap-gnus-hook) | 1854 (add-hook 'gnus-article-mode-hook 'ffap-gnus-hook) |
1727 (add-hook 'vm-mode-hook 'ffap-ro-mode-hook) | 1855 (add-hook 'vm-mode-hook 'ffap-ro-mode-hook) |
1728 (add-hook 'rmail-mode-hook 'ffap-ro-mode-hook) | 1856 (add-hook 'rmail-mode-hook 'ffap-ro-mode-hook) |
1729 ;; (setq dired-x-hands-off-my-keys t) ; the default | 1857 ;; (setq dired-x-hands-off-my-keys t) ; the default |