]> code.delx.au - gnu-emacs/blobdiff - lisp/info-look.el
Merge from emacs-24; up to 2013-01-02T10:15:31Z!michael.albinus@gmx.de
[gnu-emacs] / lisp / info-look.el
index fc8ff1e578b002ef87e527697ca0a644d6e99c4e..e43cd731547d24930831d5f4c5fb09cd2dc89187 100644 (file)
@@ -1,8 +1,7 @@
-;;; info-look.el --- major-mode-sensitive Info index lookup facility
+;;; info-look.el --- major-mode-sensitive Info index lookup facility -*- lexical-binding: t -*-
 ;; An older version of this was known as libc.el.
 
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 1995-1999, 2001-2013 Free Software Foundation, Inc.
 
 ;; Author: Ralph Schleicher <rs@nunatak.allgaeu.org>
 ;;         (did not show signs of life (Nov 2001)  -stef)
 ;; Really cool code to lookup info indexes.
 ;; Try especially info-lookup-symbol (aka C-h S).
 
+;; Some additional sources of (Tex)info files for non-GNU packages:
+;;
+;; Scheme: <URL:http://groups.csail.mit.edu/mac/ftpdir/scm/r5rs.info.tar.gz>
+;; LaTeX:
+;;  <URL:ftp://ctan.tug.org/tex-archive/info/latex2e-help-texinfo/latex2e.texi>
+;;  (or CTAN mirrors)
+;; Perl: <URL:ftp://ftp.cpan.org/pub/CPAN/doc/manual/texinfo/> (or CPAN mirrors)
+
 ;;; Code:
 
 (require 'info)
@@ -128,9 +135,9 @@ OTHER-MODES is a list of cross references to other help modes.")
 
 (defun info-lookup-add-help (&rest arg)
   "Add or update a help specification.
-Function arguments are one or more options of the form
+Function arguments are specified as keyword/argument pairs:
 
-    KEYWORD ARGUMENT
+    \(KEYWORD . ARGUMENT)
 
 KEYWORD is either `:topic', `:mode', `:regexp', `:ignore-case',
  `:doc-spec', `:parse-rule', or `:other-modes'.
@@ -299,6 +306,21 @@ If optional argument QUERY is non-nil, query for the help mode."
        (when (string-match (caar file-name-alist) file-name)
          (setq info-lookup-mode (cdar file-name-alist)))
        (setq file-name-alist (cdr file-name-alist)))))
+
+  ;; If major-mode has no setups in info-lookup-alist, under any topic, then
+  ;; search up through derived-mode-parent to find a parent mode which does
+  ;; have some setups.  This means that a `define-derived-mode' with no
+  ;; setups of its own will select its parent mode for lookups, if one of
+  ;; its parents has some setups.  Good for example on `makefile-gmake-mode'
+  ;; and similar derivatives of `makefile-mode'.
+  ;;
+  (let ((mode major-mode)) ;; Look for `mode' with some setups.
+    (while (and mode (not info-lookup-mode))
+      (dolist (topic-cell info-lookup-alist) ;; Usually only two topics here.
+        (if (info-lookup->mode-value (car topic-cell) mode)
+            (setq info-lookup-mode mode)))
+      (setq mode (get mode 'derived-mode-parent))))
+
   (or info-lookup-mode (setq info-lookup-mode major-mode)))
 
 (defun info-lookup-change-mode (topic)
@@ -335,29 +357,30 @@ If optional argument QUERY is non-nil, query for the help mode."
              (cons (list Info-current-file Info-current-node (point))
                    Info-history))))
          found doc-spec node prefix suffix doc-found)
-    (if (not (eq major-mode 'Info-mode))
-       (if (not info-lookup-other-window-flag)
-           (info)
-         (progn
-           (save-window-excursion (info))
-           ;; Determine whether or not the Info buffer is visible in
-           ;; another frame on the same display.  If it is, simply raise
-           ;; that frame.  Otherwise, display it in another window.
-           (let* ((window (get-buffer-window "*info*" t))
-                  (info-frame (and window (window-frame window))))
-             (if (and info-frame
-                      (display-multi-frame-p)
-                      (memq info-frame (frames-on-display-list))
-                      (not (eq info-frame (selected-frame))))
-                 (select-frame info-frame)
-               (switch-to-buffer-other-window "*info*"))))))
+    (unless (eq major-mode 'Info-mode)
+      (if (not info-lookup-other-window-flag)
+         (info)
+       (save-window-excursion (info))
+       (let* ((info-window (get-buffer-window "*info*" t))
+              (info-frame (and info-window (window-frame info-window))))
+         (if (and info-frame
+                  (not (eq info-frame (selected-frame)))
+                  (display-multi-frame-p)
+                  (memq info-frame (frames-on-display-list)))
+             ;; *info* is visible in another frame on same display.
+             ;; Raise that frame and select the window.
+             (progn
+               (select-window info-window)
+               (raise-frame info-frame))
+           ;; In any other case, switch to *info* in another window.
+           (switch-to-buffer-other-window "*info*")))))
     (while (and (not found) modes)
       (setq doc-spec (info-lookup->doc-spec topic (car modes)))
       (while (and (not found) doc-spec)
        (setq node (nth 0 (car doc-spec))
              prefix (nth 2 (car doc-spec))
              suffix (nth 3 (car doc-spec)))
-       (when (condition-case error-data
+       (when (condition-case nil
                  (progn
                    ;; Don't need Index menu fontifications here, and
                    ;; they slow down the lookup.
@@ -473,7 +496,7 @@ If optional argument QUERY is non-nil, query for the help mode."
                        (t (nth 1 (car doc-spec)))))
       (with-current-buffer buffer
        (message "Processing Info node `%s'..." node)
-       (when (condition-case error-data
+       (when (condition-case nil
                  (progn
                    (Info-goto-node node)
                    (setq doc-found t))
@@ -641,44 +664,42 @@ Return nil if there is nothing appropriate in the buffer near point."
                         info-lookup-mode
                       (info-lookup-change-mode 'file)))))
 
+(defun info-lookup-completions-at-point (topic mode)
+  "Try to complete a help item."
+  (or mode (setq mode (info-lookup-select-mode)))
+  (when (info-lookup->mode-value topic mode)
+    (let ((modes (info-lookup-quick-all-modes topic mode))
+          (start (point))
+          try)
+      (while (and (not try) modes)
+        (setq mode (car modes)
+              modes (cdr modes)
+              try (info-lookup-guess-default* topic mode))
+        (goto-char start))
+      (when try
+        (let ((completions (info-lookup->completions topic mode)))
+          (when completions
+            (when (info-lookup->ignore-case topic mode)
+              (setq completions
+                    (lambda (string pred action)
+                      (let ((completion-ignore-case t))
+                        (complete-with-action
+                         action completions string pred)))))
+            (save-excursion
+              ;; Find the original symbol and zap it.
+              (end-of-line)
+              (while (and (search-backward try nil t)
+                          (< start (point))))
+              (list (match-beginning 0) (match-end 0) completions
+                    :exclusive 'no))))))))
+
 (defun info-complete (topic mode)
   "Try to complete a help item."
   (barf-if-buffer-read-only)
-  (or mode (setq mode (info-lookup-select-mode)))
-  (or (info-lookup->mode-value topic mode)
-      (error "No %s completion available for `%s'" topic mode))
-  (let ((modes (info-lookup-quick-all-modes topic mode))
-       (start (point))
-       try)
-    (while (and (not try) modes)
-      (setq mode (car modes)
-           modes (cdr modes)
-           try (info-lookup-guess-default* topic mode))
-      (goto-char start))
-    (and (not try)
-        (error "Found no %S to complete" topic))
-    (let ((completions (info-lookup->completions topic mode))
-         (completion-ignore-case (info-lookup->ignore-case topic mode))
-         completion)
-      (setq completion (try-completion try completions))
-      (cond ((not completion)
-            (ding)
-            (message "No match"))
-           ((stringp completion)
-            (or (assoc completion completions)
-                (setq completion (completing-read
-                                  (format "Complete %S: " topic)
-                                  completions nil t completion
-                                  info-lookup-history)))
-            ;; Find the original symbol and zap it.
-            (end-of-line)
-            (while (and (search-backward try nil t)
-                        (< start (point))))
-            (replace-match "")
-            (insert completion))
-           (t
-            (message "%s is complete"
-                     (capitalize (prin1-to-string topic))))))))
+  (let ((data (info-lookup-completions-at-point topic mode)))
+    (if (null data)
+        (error "No %s completion available for `%s' at point" topic mode)
+      (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data)))))
 
 \f
 ;;; Initialize some common modes.
@@ -720,11 +741,31 @@ Return nil if there is nothing appropriate in the buffer near point."
  :mode 'makefile-mode
  :regexp "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z][_a-zA-Z0-9-]*"
  :doc-spec '(("(make)Name Index" nil
-             "^[ \t]*`" "'")
-            ("(automake)Macro and Variable Index" nil
              "^[ \t]*`" "'"))
- :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+"
- :other-modes '(automake-mode))
+ :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+")
+
+(info-lookup-maybe-add-help
+ :topic      'symbol
+ :mode       'makefile-automake-mode
+ ;; similar regexp/parse-rule as makefile-mode, but also the following
+ ;; (which have index entries),
+ ;;   "##" special automake comment
+ ;;   "+=" append operator, separate from the GNU make one
+ :regexp     "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z][_a-zA-Z0-9-]*\\|##\\|\\+="
+ :parse-rule "\\$[^({]\\|\\.[_A-Z]*\\|[_a-zA-Z0-9-]+\\|##\\|\\+="
+ :doc-spec   '(
+               ;; "(automake)Macro Index" is autoconf macros used in
+               ;; configure.ac, not Makefile.am, so don't have that here.
+               ("(automake)Variable Index" nil "^[ \t]*`" "'")
+               ;; In automake 1.4 macros and variables were a combined node.
+               ("(automake)Macro and Variable Index" nil "^[ \t]*`" "'")
+               ;; Directives like "if" are in the "General Index".
+               ;; Prefix "`" since the text for say `+=' isn't always an
+               ;; @item etc and so not always at the start of a line.
+               ("(automake)General Index" nil "`" "'")
+               ;; In automake 1.3 there was just a single "Index" node.
+               ("(automake)Index" nil "`" "'"))
+ :other-modes '(makefile-mode))
 
 (info-lookup-maybe-add-help
  :mode 'texinfo-mode
@@ -840,8 +881,11 @@ Return nil if there is nothing appropriate in the buffer near point."
 (info-lookup-maybe-add-help
  :mode 'latex-mode
  :regexp "\\\\\\([a-zA-Z]+\\|[^a-zA-Z]\\)"
- :doc-spec '(("(latex)Command Index" nil
-             "`" "\\({[^}]*}\\)?'")))
+ :doc-spec `((,(if (Info-find-file "latex2e" t)
+                  ;; From http://home.gna.org/latexrefman
+                  "(latex2e)Command Index"
+                "(latex)Command Index")
+             nil "`" "\\({[^}]*}\\)?'")))
 
 (info-lookup-maybe-add-help
  :mode 'emacs-lisp-mode
@@ -860,6 +904,12 @@ Return nil if there is nothing appropriate in the buffer near point."
              ;; sort of fallback match scheme existed.
              ("(elisp)Index"          nil "^ -+ .*: " "\\( \\|$\\)")))
 
+;; docstrings talk about elisp, so have apropos-mode follow emacs-lisp-mode
+(info-lookup-maybe-add-help
+ :mode 'apropos-mode
+ :regexp "[^][()`',\" \t\n]+" ;; same as emacs-lisp-mode above
+ :other-modes '(emacs-lisp-mode))
+
 (info-lookup-maybe-add-help
  :mode 'lisp-interaction-mode
  :regexp "[^][()`',\" \t\n]+"
@@ -929,11 +979,18 @@ Return nil if there is nothing appropriate in the buffer near point."
  :doc-spec '(("(bash)Builtin Index"       nil "^`" "[ .']")
              ("(bash)Reserved Word Index" nil "^`" "[ .']")
              ("(bash)Variable Index"      nil "^`" "[ .']")
+
              ;; coreutils (version 4.5.10) doesn't have a separate program
              ;; index, so exclude extraneous stuff (most of it) by demanding
              ;; "[a-z]+" in the trans-func.
+             ;; coreutils version 8.1 has node "Concept Index" and past
+             ;; versions have node "Index", look for both, whichever is
+             ;; absent is quietly ignored
              ("(coreutils)Index"
               (lambda (item) (if (string-match "\\`[a-z]+\\'" item) item)))
+             ("(coreutils)Concept Index"
+              (lambda (item) (if (string-match "\\`[a-z]+\\'" item) item)))
+
              ;; diff (version 2.8.1) has only a few programs, index entries
              ;; are things like "foo invocation".
              ("(diff)Index"
@@ -985,5 +1042,4 @@ Return nil if there is nothing appropriate in the buffer near point."
 \f
 (provide 'info-look)
 
-;; arch-tag: 0f1e3ea3-32a2-4461-bbab-3cff93539a74
 ;;; info-look.el ends here