]> code.delx.au - gnu-emacs/blobdiff - lisp/ffap.el
; Comments.
[gnu-emacs] / lisp / ffap.el
index 0769469cbf299b49e838f53085cefab05ef9e60f..452275ab8c2a12686cb97a3e95b6a32901131915 100644 (file)
@@ -1,9 +1,9 @@
 ;;; ffap.el --- find file (or url) at point
 
 ;;; ffap.el --- find file (or url) at point
 
-;; Copyright (C) 1995-1997, 2000-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1997, 2000-2015 Free Software Foundation, Inc.
 
 ;; Author: Michelangelo Grigni <mic@mathcs.emory.edu>
 
 ;; Author: Michelangelo Grigni <mic@mathcs.emory.edu>
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Created: 29 Mar 1993
 ;; Keywords: files, hypermedia, matching, mouse, convenience
 ;; X-URL: ftp://ftp.mathcs.emory.edu/pub/mic/emacs/
 ;; Created: 29 Mar 1993
 ;; Keywords: files, hypermedia, matching, mouse, convenience
 ;; X-URL: ftp://ftp.mathcs.emory.edu/pub/mic/emacs/
@@ -163,10 +163,16 @@ schemes (e.g. \"ftp\"); in that case, only convert those URLs."
   :group 'ffap
   :version "24.3")
 
   :group 'ffap
   :version "24.3")
 
+(defcustom ffap-lax-url nil
+  "If non-nil, allow lax URL matching."
+  :type 'boolean
+  :group 'ffap
+  :version "25.1")
+
 (defcustom ffap-ftp-default-user "anonymous"
 (defcustom ffap-ftp-default-user "anonymous"
-  "User name in ftp file names generated by `ffap-host-to-path'.
+  "User name in FTP file names generated by `ffap-host-to-path'.
 Note this name may be omitted if it equals the default
 Note this name may be omitted if it equals the default
-\(either `efs-default-user' or `ange-ftp-default-user'\)."
+\(either `efs-default-user' or `ange-ftp-default-user')."
   :type 'string
   :group 'ffap)
 
   :type 'string
   :group 'ffap)
 
@@ -185,7 +191,7 @@ Note this name may be omitted if it equals the default
    "\\|"
    "\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://" ; needs host
    "\\)")
    "\\|"
    "\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://" ; needs host
    "\\)")
-  "Regexp matching the beginning of a URI, for FFAP.
+  "Regexp matching the beginning of a URI, for ffap.
 If the value is nil, disable URL-matching features in ffap.")
 
 (defcustom ffap-foo-at-bar-prefix "mailto"
 If the value is nil, disable URL-matching features in ffap.")
 
 (defcustom ffap-foo-at-bar-prefix "mailto"
@@ -228,7 +234,7 @@ it passes it on to `dired'."
   :group 'ffap)
 
 (defcustom ffap-pass-wildcards-to-dired nil
   :group 'ffap)
 
 (defcustom ffap-pass-wildcards-to-dired nil
-  "If non-nil, pass filenames matching `ffap-dired-wildcards' to dired."
+  "If non-nil, pass filenames matching `ffap-dired-wildcards' to Dired."
   :type 'boolean
   :group 'ffap)
 
   :type 'boolean
   :group 'ffap)
 
@@ -259,20 +265,10 @@ ffap most of the time."
   :group 'ffap
   :risky t)
 
   :group 'ffap
   :risky t)
 
-(defcustom ffap-url-fetcher
-  (if (fboundp 'browse-url)
-      'browse-url                      ; rely on browse-url-browser-function
-    'w3-fetch)
-  ;; Remote control references:
-  ;; http://www.ncsa.uiuc.edu/SDG/Software/XMosaic/remote-control.html
-  ;; http://home.netscape.com/newsref/std/x-remote.html
+(defcustom ffap-url-fetcher 'browse-url
   "A function of one argument, called by ffap to fetch an URL.
   "A function of one argument, called by ffap to fetch an URL.
-Reasonable choices are `w3-fetch' or a `browse-url-*' function.
 For a fancy alternative, get `ffap-url.el'."
 For a fancy alternative, get `ffap-url.el'."
-  :type '(choice (const w3-fetch)
-                (const browse-url)     ; in recent versions of browse-url
-                (const browse-url-netscape)
-                (const browse-url-mosaic)
+  :type '(choice (const browse-url)
                 function)
   :group 'ffap
   :risky t)
                 function)
   :group 'ffap
   :risky t)
@@ -291,8 +287,8 @@ For a fancy alternative, get `ffap-url.el'."
 
 (defcustom dired-at-point-require-prefix nil
   "If non-nil, reverse the prefix argument to `dired-at-point'.
 
 (defcustom dired-at-point-require-prefix nil
   "If non-nil, reverse the prefix argument to `dired-at-point'.
-This is nil so neophytes notice FFAP.  Experts may prefer to
-disable FFAP most of the time."
+This is nil so neophytes notice ffap.  Experts may prefer to
+disable ffap most of the time."
   :type 'boolean
   :group 'ffap
   :version "20.3")
   :type 'boolean
   :group 'ffap
   :version "20.3")
@@ -343,7 +339,7 @@ Only considers strings that match `ffap-next-regexp'."
   "Search buffer for next file or URL, and run ffap.
 Optional argument BACK says to search backwards.
 Optional argument WRAP says to try wrapping around if necessary.
   "Search buffer for next file or URL, and run ffap.
 Optional argument BACK says to search backwards.
 Optional argument WRAP says to try wrapping around if necessary.
-Interactively: use a single prefix to search backwards,
+Interactively: use a single prefix \\[universal-argument] to search backwards,
 double prefix to wrap forward, triple to wrap backwards.
 Actual search is done by the function `ffap-next-guess'."
   (interactive
 double prefix to wrap forward, triple to wrap backwards.
 Actual search is done by the function `ffap-next-guess'."
   (interactive
@@ -413,7 +409,7 @@ See `mail-extr.el' for the known domains."
 Depending on the domain (none, known, or unknown), follow the strategy
 named by the variable `ffap-machine-p-local', `ffap-machine-p-known',
 or `ffap-machine-p-unknown'.  Pinging uses `open-network-stream'.
 Depending on the domain (none, known, or unknown), follow the strategy
 named by the variable `ffap-machine-p-local', `ffap-machine-p-known',
 or `ffap-machine-p-unknown'.  Pinging uses `open-network-stream'.
-Optional SERVICE specifies the port used \(default \"discard\"\).
+Optional SERVICE specifies the port used (default \"discard\").
 Optional QUIET flag suppresses the \"Pinging...\" message.
 Optional STRATEGY overrides the three variables above.
 Returned values:
 Optional QUIET flag suppresses the \"Pinging...\" message.
 Optional STRATEGY overrides the three variables above.
 Returned values:
@@ -459,7 +455,8 @@ Returned values:
           (let ((mesg (car (cdr error))))
             (cond
              ;; v18:
           (let ((mesg (car (cdr error))))
             (cond
              ;; v18:
-             ((string-match "^Unknown host" mesg) nil)
+             ((string-match "\\(^Unknown host\\|Name or service not known$\\)"
+                            mesg) nil)
              ((string-match "not responding$" mesg) mesg)
              ;; v19:
              ;; (file-error "connection failed" "permission denied"
              ((string-match "not responding$" mesg) mesg)
              ;; v19:
              ;; (file-error "connection failed" "permission denied"
@@ -469,7 +466,7 @@ Returned values:
              ;; (file-error "connection failed" "address already in use"
              ;;             "ftp.uu.net" "ffap-machine-p")
              ((equal mesg "connection failed")
              ;; (file-error "connection failed" "address already in use"
              ;;             "ftp.uu.net" "ffap-machine-p")
              ((equal mesg "connection failed")
-              (if (equal (nth 2 error) "permission denied")
+              (if (string= (downcase (nth 2 error)) "permission denied")
                   nil                  ; host does not exist
                 ;; Other errors mean the host exists:
                 (nth 2 error)))
                   nil                  ; host does not exist
                 ;; Other errors mean the host exists:
                 (nth 2 error)))
@@ -641,7 +638,7 @@ Looks at `ffap-ftp-default-user', returns \"\" for \"localhost\"."
 
 (defun ffap-list-env (env &optional empty)
   "Return a list of strings parsed from environment variable ENV.
 
 (defun ffap-list-env (env &optional empty)
   "Return a list of strings parsed from environment variable ENV.
-Optional EMPTY is the default list if \(getenv ENV\) is undefined, and
+Optional EMPTY is the default list if (getenv ENV) is undefined, and
 also is substituted for the first empty-string component, if there is one.
 Uses `path-separator' to separate the path into substrings."
   ;; We cannot use parse-colon-path (files.el), since it kills
 also is substituted for the first empty-string component, if there is one.
 Uses `path-separator' to separate the path into substrings."
   ;; We cannot use parse-colon-path (files.el), since it kills
@@ -768,7 +765,7 @@ This uses `ffap-file-exists-string', which may try adding suffixes from
     ;; (lisp-interaction-mode . ffap-el-mode) ; maybe
     (finder-mode . ffap-el-mode)       ; type {C-h p} and try it
     (help-mode . ffap-el-mode)         ; maybe useful
     ;; (lisp-interaction-mode . ffap-el-mode) ; maybe
     (finder-mode . ffap-el-mode)       ; type {C-h p} and try it
     (help-mode . ffap-el-mode)         ; maybe useful
-    (c++-mode . ffap-c-mode)           ; search ffap-c-path
+    (c++-mode . ffap-c++-mode)         ; search ffap-c++-path
     (cc-mode . ffap-c-mode)            ; same
     ("\\.\\([chCH]\\|cc\\|hh\\)\\'" . ffap-c-mode) ; stdio.h
     (fortran-mode . ffap-fortran-mode) ; FORTRAN requested by MDB
     (cc-mode . ffap-c-mode)            ; same
     ("\\.\\([chCH]\\|cc\\|hh\\)\\'" . ffap-c-mode) ; stdio.h
     (fortran-mode . ffap-fortran-mode) ; FORTRAN requested by MDB
@@ -786,12 +783,12 @@ This uses `ffap-file-exists-string', which may try adding suffixes from
      . ffap-rfc)                       ; "100% RFC2100 compliant"
     (dired-mode . ffap-dired)          ; maybe in a subdirectory
     )
      . ffap-rfc)                       ; "100% RFC2100 compliant"
     (dired-mode . ffap-dired)          ; maybe in a subdirectory
     )
-  "Alist of \(KEY . FUNCTION\) pairs parsed by `ffap-file-at-point'.
+  "Alist of (KEY . FUNCTION) pairs parsed by `ffap-file-at-point'.
 If string NAME at point (maybe \"\") is not a file or URL, these pairs
 specify actions to try creating such a string.  A pair matches if either
   KEY is a symbol, and it equals `major-mode', or
   KEY is a string, it should match NAME as a regexp.
 If string NAME at point (maybe \"\") is not a file or URL, these pairs
 specify actions to try creating such a string.  A pair matches if either
   KEY is a symbol, and it equals `major-mode', or
   KEY is a string, it should match NAME as a regexp.
-On a match, \(FUNCTION NAME\) is called and should return a file, an
+On a match, (FUNCTION NAME) is called and should return a file, an
 URL, or nil.  If nil, search the alist for further matches.")
 
 (put 'ffap-alist 'risky-local-variable t)
 URL, or nil.  If nil, search the alist for further matches.")
 
 (put 'ffap-alist 'risky-local-variable t)
@@ -865,6 +862,28 @@ URL, or nil.  If nil, search the alist for further matches.")
 (defun ffap-c-mode (name)
   (ffap-locate-file name t ffap-c-path))
 
 (defun ffap-c-mode (name)
   (ffap-locate-file name t ffap-c-path))
 
+(defvar ffap-c++-path
+  (let ((c++-include-dir (with-temp-buffer
+                           (when (eq 0 (ignore-errors
+                                         (call-process "g++" nil t nil "-v")))
+                             (goto-char (point-min))
+                             (if (re-search-forward "--with-gxx-include-dir=\
+\\([^[:space:]]+\\)"
+                                                      nil 'noerror)
+                                 (match-string 1)
+                               (when (re-search-forward "gcc version \
+\\([[:digit:]]+.[[:digit:]]+.[[:digit:]]+\\)"
+                                                   nil 'noerror)
+                                 (expand-file-name (match-string 1)
+                                                   "/usr/include/c++/")))))))
+    (if c++-include-dir
+        (cons c++-include-dir ffap-c-path)
+      ffap-c-path))
+  "List of directories to search for include files.")
+
+(defun ffap-c++-mode (name)
+  (ffap-locate-file name t ffap-c++-path))
+
 (defvar ffap-fortran-path '("../include" "/usr/include"))
 
 (defun ffap-fortran-mode (name)
 (defvar ffap-fortran-path '("../include" "/usr/include"))
 
 (defun ffap-fortran-mode (name)
@@ -957,7 +976,7 @@ If t, `ffap-tex-init' will initialize this when needed.")
 (defcustom ffap-rfc-path
   (concat (ffap-host-to-filename "ftp.rfc-editor.org") "/in-notes/rfc%s.txt")
   "A `format' string making a filename for RFC documents.
 (defcustom ffap-rfc-path
   (concat (ffap-host-to-filename "ftp.rfc-editor.org") "/in-notes/rfc%s.txt")
   "A `format' string making a filename for RFC documents.
-This can be an ange-ftp or tramp remote filename to download, or
+This can be an ange-ftp or Tramp remote filename to download, or
 a local filename if you have full set of RFCs locally.  See also
 `ffap-rfc-directories'."
   :type 'string
 a local filename if you have full set of RFCs locally.  See also
 `ffap-rfc-directories'."
   :type 'string
@@ -985,7 +1004,7 @@ If a given RFC isn't in these then `ffap-rfc-path' is offered."
     ;; Slightly controversial decisions:
     ;; * strip trailing "@" and ":"
     ;; * no commas (good for latex)
     ;; Slightly controversial decisions:
     ;; * strip trailing "@" and ":"
     ;; * no commas (good for latex)
-    (file "--:\\\\$+<>@-Z_[:alpha:]~*?" "<@" "@>;.,!:")
+    (file "--:\\\\$\\{\\}+<>@-Z_[:alpha:]~*?" "<@" "@>;.,!:")
     ;; An url, or maybe a email/news message-id:
     (url "--:=&?$+@-Z_[:alpha:]~#,%;*()!'" "^[0-9a-zA-Z]" ":;.,!?")
     ;; Find a string that does *not* contain a colon:
     ;; An url, or maybe a email/news message-id:
     (url "--:=&?$+@-Z_[:alpha:]~#,%;*()!'" "^[0-9a-zA-Z]" ":;.,!?")
     ;; Find a string that does *not* contain a colon:
@@ -995,8 +1014,8 @@ If a given RFC isn't in these then `ffap-rfc-path' is offered."
     ;; Mathematica paths: allow backquotes
     (math-mode ",-:$+<>@-Z_[:lower:]~`" "<" "@>;.,!?`:")
     )
     ;; Mathematica paths: allow backquotes
     (math-mode ",-:$+<>@-Z_[:lower:]~`" "<" "@>;.,!?`:")
     )
-  "Alist of \(MODE CHARS BEG END\), where MODE is a symbol,
-possibly a major-mode name, or one of the symbol
+  "Alist of (MODE CHARS BEG END), where MODE is a symbol,
+possibly a major-mode name, or one of the symbols
 `file', `url', `machine', and `nocolon'.
 Function `ffap-string-at-point' uses the data fields as follows:
 1. find a maximal string of CHARS around point,
 `file', `url', `machine', and `nocolon'.
 Function `ffap-string-at-point' uses the data fields as follows:
 1. find a maximal string of CHARS around point,
@@ -1009,8 +1028,8 @@ Function `ffap-string-at-point' uses the data fields as follows:
 
 (defun ffap-string-at-point (&optional mode)
   "Return a string of characters from around point.
 
 (defun ffap-string-at-point (&optional mode)
   "Return a string of characters from around point.
-MODE (defaults to value of `major-mode') is a symbol used to look up string
-syntax parameters in `ffap-string-at-point-mode-alist'.
+MODE (defaults to value of `major-mode') is a symbol used to look up
+string syntax parameters in `ffap-string-at-point-mode-alist'.
 If MODE is not found, we use `file' instead of MODE.
 If the region is active, return a string from the region.
 Sets the variable `ffap-string-at-point' and the variable
 If MODE is not found, we use `file' instead of MODE.
 If the region is active, return a string from the region.
 Sets the variable `ffap-string-at-point' and the variable
@@ -1072,8 +1091,8 @@ Assumes the buffer has not changed."
     (or (and (eq major-mode 'w3-mode) ; In a w3 buffer button?
             (w3-view-this-url t))
        (let ((thing-at-point-beginning-of-url-regexp ffap-url-regexp)
     (or (and (eq major-mode 'w3-mode) ; In a w3 buffer button?
             (w3-view-this-url t))
        (let ((thing-at-point-beginning-of-url-regexp ffap-url-regexp)
-             (thing-at-point-default-mail-scheme ffap-foo-at-bar-prefix))
-         (thing-at-point-url-at-point t
+             (thing-at-point-default-mail-uri-scheme ffap-foo-at-bar-prefix))
+         (thing-at-point-url-at-point ffap-lax-url
                                       (if (use-region-p)
                                           (cons (region-beginning)
                                                 (region-end))))))))
                                       (if (use-region-p)
                                           (cons (region-beginning)
                                                 (region-end))))))))
@@ -1120,7 +1139,7 @@ The two subexpressions are the KEY and VALUE.")
    ;; Icky regexp avoids: default: 123: foo::bar cs:pub
    ;; It does match on: mic@cs: cs:/pub mathcs.emory.edu: (point at end)
    "\\`\\([^:@]+@[^:@]+:\\|[^@.:]+\\.[^@:]+:\\|[^:]+:[~/]\\)\\([^:]\\|\\'\\)")
    ;; Icky regexp avoids: default: 123: foo::bar cs:pub
    ;; It does match on: mic@cs: cs:/pub mathcs.emory.edu: (point at end)
    "\\`\\([^:@]+@[^:@]+:\\|[^@.:]+\\.[^@:]+:\\|[^:]+:[~/]\\)\\([^:]\\|\\'\\)")
-  "Strings matching this are coerced to ftp file names by ffap.
+  "Strings matching this are coerced to FTP file names by ffap.
 That is, ffap just prepends \"/\".  Set to nil to disable.")
 
 (defun ffap-file-at-point ()
 That is, ffap just prepends \"/\".  Set to nil to disable.")
 
 (defun ffap-file-at-point ()
@@ -1230,7 +1249,8 @@ which may actually result in an URL rather than a filename."
                         (not (ffap-file-exists-string dir))
                         (not (equal dir (setq dir (file-name-directory
                                                    (directory-file-name dir)))))))
                         (not (ffap-file-exists-string dir))
                         (not (equal dir (setq dir (file-name-directory
                                                    (directory-file-name dir)))))))
-            (ffap-file-exists-string dir)))
+            (and (not (string= dir "/"))
+                (ffap-file-exists-string dir))))
         )
       (set-match-data data))))
 \f
         )
       (set-match-data data))))
 \f
@@ -1409,7 +1429,7 @@ and the functions `ffap-file-at-point' and `ffap-url-at-point'."
                 (expand-file-name filename)))
        ;; User does not want to find a non-existent file:
        ((signal 'file-error (list "Opening file buffer"
                 (expand-file-name filename)))
        ;; User does not want to find a non-existent file:
        ((signal 'file-error (list "Opening file buffer"
-                                 "no such file or directory"
+                                 "No such file or directory"
                                  filename)))))))
 
 ;; Shortcut: allow {M-x ffap} rather than {M-x find-file-at-point}.
                                  filename)))))))
 
 ;; Shortcut: allow {M-x ffap} rather than {M-x find-file-at-point}.
@@ -1422,7 +1442,7 @@ and the functions `ffap-file-at-point' and `ffap-url-at-point'."
 (defcustom ffap-menu-regexp nil
   "If non-nil, regexp overriding `ffap-next-regexp' in `ffap-menu'.
 Make this more restrictive for faster menu building.
 (defcustom ffap-menu-regexp nil
   "If non-nil, regexp overriding `ffap-next-regexp' in `ffap-menu'.
 Make this more restrictive for faster menu building.
-For example, try \":/\" for URL (and some ftp) references."
+For example, try \":/\" for URL (and some FTP) references."
   :type '(choice (const nil) regexp)
   :group 'ffap)
 
   :type '(choice (const nil) regexp)
   :group 'ffap)
 
@@ -1442,7 +1462,7 @@ These properties may be used to fontify the menu references.")
   "Put up a menu of files and URLs mentioned in this buffer.
 Then set mark, jump to choice, and try to fetch it.  The menu is
 cached in `ffap-menu-alist', and rebuilt by `ffap-menu-rescan'.
   "Put up a menu of files and URLs mentioned in this buffer.
 Then set mark, jump to choice, and try to fetch it.  The menu is
 cached in `ffap-menu-alist', and rebuilt by `ffap-menu-rescan'.
-The optional RESCAN argument \(a prefix, interactively\) forces
+The optional RESCAN argument (a prefix, interactively) forces
 a rebuild.  Searches with `ffap-menu-regexp'."
   (interactive "P")
   ;; (require 'imenu) -- no longer used, but roughly emulated
 a rebuild.  Searches with `ffap-menu-regexp'."
   (interactive "P")
   ;; (require 'imenu) -- no longer used, but roughly emulated
@@ -1475,7 +1495,7 @@ a rebuild.  Searches with `ffap-menu-regexp'."
 
 (defun ffap-menu-ask (title alist cont)
   "Prompt from a menu of choices, and then apply some action.
 
 (defun ffap-menu-ask (title alist cont)
   "Prompt from a menu of choices, and then apply some action.
-Arguments are TITLE, ALIST, and CONT \(a continuation function\).
+Arguments are TITLE, ALIST, and CONT (a continuation function).
 This uses either a menu or the minibuffer depending on invocation.
 The TITLE string is used as either the prompt or menu title.
 Each ALIST entry looks like (STRING . DATA) and defines one choice.
 This uses either a menu or the minibuffer depending on invocation.
 The TITLE string is used as either the prompt or menu title.
 Each ALIST entry looks like (STRING . DATA) and defines one choice.
@@ -1735,7 +1755,7 @@ Only intended for interactive use."
   ;; Preserve selected buffer, but do not do save-window-excursion,
   ;; since we want to see any window created by the form.  Temporarily
   ;; select the article buffer, so we can see any point movement.
   ;; Preserve selected buffer, but do not do save-window-excursion,
   ;; since we want to see any window created by the form.  Temporarily
   ;; select the article buffer, so we can see any point movement.
-  (let ((sb (window-buffer (selected-window))))
+  (let ((sb (window-buffer)))
     (gnus-configure-windows 'article)
     (pop-to-buffer gnus-article-buffer)
     (widen)
     (gnus-configure-windows 'article)
     (pop-to-buffer gnus-article-buffer)
     (widen)