Function: ffap-file-at-point
ffap-file-at-point is a byte-compiled function defined in ffap.el.gz.
Signature
(ffap-file-at-point)
Documentation
Return filename from around point if it exists, or nil.
Existence test is skipped for names that look remote.
If the filename is not obvious, it also tries ffap-alist,
which may actually result in an URL rather than a filename.
Source Code
;; Defined in /usr/src/emacs/lisp/ffap.el.gz
(defun ffap-file-at-point ()
"Return filename from around point if it exists, or nil.
Existence test is skipped for names that look remote.
If the filename is not obvious, it also tries `ffap-alist',
which may actually result in an URL rather than a filename."
;; Note: this function does not need to look for url's, just
;; filenames. On the other hand, it is responsible for converting
;; a pseudo-url "site.com://dir" to an ftp file name
(let* ((case-fold-search t) ; url prefixes are case-insensitive
(data (match-data))
(string (ffap-string-at-point)) ; uses mode alist
(name
(or (condition-case nil
(and (not (string-search "//" string)) ; foo.com://bar
(substitute-in-file-name string))
(error nil))
string))
(abs (file-name-absolute-p name))
(default-directory default-directory)
(remote-p (and ffap-prefer-remote-file
(file-remote-p default-directory)))
(oname name))
(unwind-protect
(cond
;; Immediate rejects (/ and // and /* are too common in C/C++):
((member name '("" "/" "//" "/*" ".")) nil)
;; Immediately test local filenames. If default-directory is
;; remote, you probably already have a connection.
((and (not abs) (ffap-file-exists-string name)))
;; Try stripping off line numbers; good for compilation/grep output.
((and (not abs) (string-match ":[0-9]" name)
(ffap-file-exists-string (substring name 0 (match-beginning 0)))))
;; Try stripping off prominent (non-root - #) shell prompts
;; if the ffap-shell-prompt-regexp is non-nil.
((and ffap-shell-prompt-regexp
(not abs) (string-match ffap-shell-prompt-regexp name)
(ffap-file-exists-string (substring name (match-end 0)))))
;; Accept remote names without actual checking (too slow):
((and abs (ffap-file-remote-p name)))
;; Ok, not remote, try the existence test even if it is absolute:
((and abs (ffap-file-exists-string name nil remote-p)))
;; Try stripping off line numbers.
((and abs (string-match ":[0-9]" name)
(ffap-file-exists-string (substring name 0 (match-beginning 0))
nil remote-p)))
;; If it contains a colon, get rid of it (and return if exists)
((and (string-match path-separator name)
(let ((this-name (ffap-string-at-point 'nocolon)))
;; But don't interpret the first part if ":/bin" as
;; the empty string.
(when (> (length this-name) 0)
(setq name this-name)
(ffap-file-exists-string name nil remote-p)))))
;; File does not exist, try the alist:
((let ((alist ffap-alist) tem try case-fold-search)
(while (and alist (not try))
(setq tem (car alist) alist (cdr alist))
(if (or (eq major-mode (car tem))
(and (stringp (car tem))
(string-match (car tem) name)))
(and (setq try
(condition-case nil
(funcall (cdr tem) name)
(error nil)))
(setq try (or
(ffap-url-p try) ; not a file!
(ffap-file-remote-p try)
(ffap-file-exists-string try nil remote-p))))))
try))
;; Try adding a leading "/" (common omission in ftp file names).
;; Note that this uses oname, which still has any colon part.
;; This should have a lower priority than the alist stuff,
;; else it matches things like "ffap.el:1234:56:Warning".
((and (not abs)
ffap-ftp-sans-slash-regexp
(string-match ffap-ftp-sans-slash-regexp oname)
(ffap-file-remote-p (concat "/" oname))))
;; Alist failed? Try to guess an active remote connection
;; from buffer variables, and try once more, both as an
;; absolute and relative file name on that remote host.
((let* (ffap-rfs-regexp ; suppress
(remote-dir
(cond
((ffap-file-remote-p default-directory))
((and (eq major-mode 'internal-ange-ftp-mode)
(string-match "^\\*ftp \\(.*\\)@\\(.*\\)\\*$"
(buffer-name)))
(concat "/" (substring (buffer-name) 5 -1) ":")))))
(and remote-dir
(or
(and (string-match "\\`\\(/?~?ftp\\)/" name)
(ffap-file-exists-string
(ffap-replace-file-component
remote-dir (substring name (match-end 1)))))
(ffap-file-exists-string
(ffap-replace-file-component remote-dir name))))))
((and ffap-dired-wildcards
(string-match ffap-dired-wildcards name)
abs
(ffap-file-exists-string (file-name-directory
(directory-file-name name))
nil remote-p)
name))
;; Try all parent directories by deleting the trailing directory
;; name until existing directory is found or name stops changing
((let ((dir name))
(while (and dir
(not (ffap-file-exists-string dir nil remote-p))
(not (equal dir (setq dir (file-name-directory
(directory-file-name dir)))))))
(and (not (string= dir "/"))
(ffap-file-exists-string dir nil remote-p))))
)
(set-match-data data))))