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))))