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