(smtpmail-query-smtp-server): Allow `quit'-ing out in case the probe hangs.
[bpt/emacs.git] / lisp / info-look.el
index afdf123..13edc02 100644 (file)
@@ -1,7 +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,96,97,98,99,2001,2003  Free Software Foundation, Inc.
+;; Copyright (C) 1995-1999, 2001-2011 Free Software Foundation, Inc.
 
 ;; Author: Ralph Schleicher <rs@nunatak.allgaeu.org>
 ;;         (did not show signs of life (Nov 2001)  -stef)
@@ -9,10 +9,10 @@
 
 ;; This file is part of GNU Emacs.
 
-;; GNU Emacs is free software; you can redistribute it and/or modify
+;; GNU Emacs is free software: you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
 ;; Really cool code to lookup info indexes.
-;; Try especially info-lookup-symbol (aka C-h TAB).
+;; Try especially info-lookup-symbol (aka C-h S).
 
 ;;; Code:
 
@@ -47,7 +45,7 @@ Automatically becomes buffer local when set in any fashion.")
   "Non-nil means pop up the Info buffer in another window."
   :group 'info-lookup :type 'boolean)
 
-(defcustom info-lookup-highlight-face 'highlight
+(defcustom info-lookup-highlight-face 'match
   "Face for highlighting looked up help items.
 Setting this variable to nil disables highlighting."
   :group 'info-lookup :type 'face)
@@ -129,9 +127,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'.
@@ -143,7 +141,7 @@ to `symbol', and the help mode defaults to the current major mode."
   (apply 'info-lookup-add-help* nil arg))
 
 (defun info-lookup-maybe-add-help (&rest arg)
-  "Add a help specification iff none is defined.
+  "Add a help specification if none is defined.
 See the documentation of the function `info-lookup-add-help'
 for more details."
   (apply 'info-lookup-add-help* t arg))
@@ -245,19 +243,21 @@ system."
   (interactive)
   (setq info-lookup-cache nil))
 
+;;;###autoload (put 'info-lookup-symbol 'info-file "emacs")
 ;;;###autoload
 (defun info-lookup-symbol (symbol &optional mode)
   "Display the definition of SYMBOL, as found in the relevant manual.
-When this command is called interactively, it reads SYMBOL from the minibuffer.
-In the minibuffer, use M-n to yank the default argument value
-into the minibuffer so you can edit it.
-The default symbol is the one found at point.
+When this command is called interactively, it reads SYMBOL from the
+minibuffer.  In the minibuffer, use M-n to yank the default argument
+value into the minibuffer so you can edit it.  The default symbol is the
+one found at point.
 
 With prefix arg a query for the symbol help mode is offered."
   (interactive
    (info-lookup-interactive-arguments 'symbol current-prefix-arg))
   (info-lookup 'symbol symbol mode))
 
+;;;###autoload (put 'info-lookup-file 'info-file "emacs")
 ;;;###autoload
 (defun info-lookup-file (file &optional mode)
   "Display the documentation of a file.
@@ -321,36 +321,50 @@ If optional argument QUERY is non-nil, query for the help mode."
   (let* ((completions (info-lookup->completions topic mode))
          (ignore-case (info-lookup->ignore-case topic mode))
          (entry (or (assoc (if ignore-case (downcase item) item) completions)
-                    (assoc-ignore-case item completions)
+                    (assoc-string item completions t)
                     (error "Not documented as a %s: %s" topic (or item ""))))
          (modes (info-lookup->all-modes topic mode))
          (window (selected-window))
+        (new-Info-history
+         ;; Avoid clobbering Info-history with nodes searched during
+         ;; lookup.  If lookup succeeds set `Info-history' to
+         ;; `new-Info-history'.
+         (when (get-buffer "*info*")
+           (with-current-buffer "*info*"
+             (cons (list Info-current-file Info-current-node (point))
+                   Info-history))))
          found doc-spec node prefix suffix doc-found)
-    (if (or (not info-lookup-other-window-flag)
-           (eq (current-buffer) (get-buffer "*info*")))
-       (info)
-      (progn
+    (unless (eq major-mode 'Info-mode)
+      (if (not info-lookup-other-window-flag)
+         (info)
        (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))))
+       (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)))
-           (select-frame info-frame)
-         (switch-to-buffer-other-window "*info*")))))
+             ;; *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
-                   (Info-goto-node node)
-                   (setq doc-found t))
+                   ;; Don't need Index menu fontifications here, and
+                   ;; they slow down the lookup.
+                   (let (Info-fontify-maximum-menu-size
+                         Info-history-list)
+                     (Info-goto-node node)
+                     (setq doc-found t)))
                (error
                 (message "Cannot access Info node %s" node)
                 (sit-for 1)
@@ -393,6 +407,8 @@ If optional argument QUERY is non-nil, query for the help mode."
     (unless (or ignore-case
                 (string-equal item (car entry)))
       (message "Found in different case: %s" (car entry)))
+    (when found
+      (setq Info-history new-Info-history))
     (or doc-found
        (error "Info documentation for lookup was not found"))
     ;; Don't leave the Info buffer if the help item couldn't be looked up.
@@ -402,17 +418,17 @@ If optional argument QUERY is non-nil, query for the help mode."
 (defun info-lookup-setup-mode (topic mode)
   "Initialize the internal data structure."
   (or (info-lookup->initialized topic mode)
-      (let (cell data (initialized 0) completions refer-modes)
+      (let ((initialized 0)
+           cell data completions refer-modes Info-history-list)
        (if (not (info-lookup->mode-value topic mode))
            (message "No %s help available for `%s'" topic mode)
          ;; Recursively setup cross references.
          ;; But refer only to non-void modes.
-         (mapcar (lambda (arg)
-                   (or (info-lookup->initialized topic arg)
-                       (info-lookup-setup-mode topic arg))
-                   (and (eq (info-lookup->initialized topic arg) t)
-                        (setq refer-modes (cons arg refer-modes))))
-                 (info-lookup->other-modes topic mode))
+         (dolist (arg (info-lookup->other-modes topic mode))
+           (or (info-lookup->initialized topic arg)
+               (info-lookup-setup-mode topic arg))
+           (and (eq (info-lookup->initialized topic arg) t)
+                (setq refer-modes (cons arg refer-modes))))
          (setq refer-modes (nreverse refer-modes))
          ;; Build the full completion alist.
          (setq completions
@@ -438,6 +454,7 @@ If optional argument QUERY is non-nil, query for the help mode."
   (let ((doc-spec (info-lookup->doc-spec topic mode))
        (regexp (concat "^\\(" (info-lookup->regexp topic mode)
                        "\\)\\([ \t].*\\)?$"))
+       Info-history-list Info-fontify-maximum-menu-size
        node trans entry item prefix result doc-found
        (buffer (get-buffer-create " temp-info-look")))
     (with-current-buffer buffer
@@ -456,7 +473,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))
@@ -563,6 +580,45 @@ Return nil if there is nothing appropriate in the buffer near point."
               (concat prefix name))))
     (error nil)))
 
+(defun info-lookup-guess-custom-symbol ()
+  "Get symbol at point in custom buffers."
+  (condition-case nil
+      (save-excursion
+       (let ((case-fold-search t)
+             (ignored-chars "][()`',:.\" \t\n")
+             (significant-chars "^][()`',:.\" \t\n")
+             beg end)
+         (cond
+          ((and (memq (get-char-property (point) 'face)
+                        '(custom-variable-tag custom-variable-tag-face))
+                  (setq beg (previous-single-char-property-change
+                             (point) 'face nil (line-beginning-position)))
+                  (setq end (next-single-char-property-change
+                             (point) 'face nil (line-end-position)))
+                  (> end beg))
+           (subst-char-in-string
+            ?\s ?\- (buffer-substring-no-properties beg end)))
+          ((or (and (looking-at (concat "[" significant-chars "]"))
+                    (save-excursion
+                      (skip-chars-backward significant-chars)
+                      (setq beg (point)))
+                    (skip-chars-forward significant-chars)
+                    (setq end (point))
+                    (> end beg))
+               (and (looking-at "[ \t\n]")
+                    (looking-back (concat "[" significant-chars "]"))
+                    (setq end (point))
+                    (skip-chars-backward significant-chars)
+                    (setq beg (point))
+                    (> end beg))
+               (and (skip-chars-forward ignored-chars)
+                    (setq beg (point))
+                    (skip-chars-forward significant-chars)
+                    (setq end (point))
+                    (> end beg)))
+           (buffer-substring-no-properties beg end)))))
+    (error nil)))
+
 ;;;###autoload
 (defun info-complete-symbol (&optional mode)
   "Perform completion on symbol preceding point."
@@ -585,44 +641,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.
@@ -631,11 +685,18 @@ Return nil if there is nothing appropriate in the buffer near point."
  :mode 'c-mode :topic 'symbol
  :regexp "\\(struct \\|union \\|enum \\)?[_a-zA-Z][_a-zA-Z0-9]*"
  :doc-spec '(("(libc)Function Index" nil
-             "^[ \t]+- \\(Function\\|Macro\\): .*\\<" "\\>")
+             "^[ \t]+-+ \\(Function\\|Macro\\): .*\\<" "\\>")
+             ;; prefix/suffix has to match things like
+             ;;   " -- Macro: int F_DUPFD"
+             ;;   " -- Variable: char * tzname [2]"
+             ;;   "`DBL_MAX'"    (texinfo @table)
+             ;; suffix "\\>" is not used because that sends DBL_MAX to
+             ;; DBL_MAX_EXP ("_" is a non-word char)
             ("(libc)Variable Index" nil
-             "^[ \t]+- \\(Variable\\|Macro\\): .*\\<" "\\>")
+              "^\\([ \t]+-+ \\(Variable\\|Macro\\): .*\\<\\|`\\)"
+              "\\( \\|'?$\\)")
             ("(libc)Type Index" nil
-             "^[ \t]+- Data Type: \\<" "\\>")
+             "^[ \t]+-+ Data Type: \\<" "\\>")
             ("(termcap)Var Index" nil
              "^[ \t]*`" "'"))
  :parse-rule 'info-lookup-guess-c-symbol)
@@ -657,11 +718,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.in, 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
@@ -671,7 +752,7 @@ Return nil if there is nothing appropriate in the buffer near point."
              (lambda (item)
                (if (string-match "^\\([a-zA-Z]+\\|[^a-zA-Z]\\)\\( .*\\)?$" item)
                    (concat "@" (match-string 1 item))))
-             "`" "'")))
+             "`" "[' ]")))
 
 (info-lookup-maybe-add-help
  :mode 'm4-mode
@@ -688,28 +769,31 @@ Return nil if there is nothing appropriate in the buffer near point."
              ("(autoconf)Autoconf Macro Index"
               (lambda (item)
                 (if (string-match "^A._" item) item (concat "AC_" item)))
-             "^[ \t]+- \\(Macro\\|Variable\\): .*\\<" "\\>")
+             "^[ \t]+-+ \\(Macro\\|Variable\\): .*\\<" "\\>")
              ;; M4 Macro Index entries are without "AS_" prefixes, and
              ;; mostly without "m4_" prefixes.  "dnl" is an exception, not
              ;; wanting any prefix.  So AS_ is added back to upper-case
-             ;; names, m4_ to others which don't already an m4_.
+             ;; names (if needed), m4_ to others which don't already an m4_.
              ("(autoconf)M4 Macro Index"
               (lambda (item)
                 (let ((case-fold-search nil))
                   (cond ((or (string-equal item "dnl")
-                             (string-match "^m4_" item))
+                             (string-match "^m4_" item)
+                             ;; Autoconf 2.62 index includes some macros
+                             ;; (e.g., AS_HELP_STRING), so avoid prefixing.
+                             (string-match "^AS_" item))
                          item)
                         ((string-match "^[A-Z0-9_]+$" item)
                          (concat "AS_" item))
                         (t
                          (concat "m4_" item)))))
-             "^[ \t]+- Macro: .*\\<" "\\>")
+             "^[ \t]+-+ Macro: .*\\<" "\\>")
              ;; Autotest Macro Index entries are without "AT_".
              ("(autoconf)Autotest Macro Index" "AT_"
-             "^[ \t]+- Macro: .*\\<" "\\>")
+             "^[ \t]+-+ Macro: .*\\<" "\\>")
             ;; This is for older versions (probably pre autoconf 2.5x):
             ("(autoconf)Macro Index" "AC_"
-             "^[ \t]+- \\(Macro\\|Variable\\): .*\\<" "\\>")
+             "^[ \t]+-+ \\(Macro\\|Variable\\): .*\\<" "\\>")
             ;; Automake has index entries for its notes on various autoconf
             ;; macros (eg. AC_PROG_CC).  Ensure this is after the autoconf
             ;; index, so as to prefer the autoconf docs.
@@ -779,47 +863,54 @@ Return nil if there is nothing appropriate in the buffer near point."
 
 (info-lookup-maybe-add-help
  :mode 'emacs-lisp-mode
- :regexp "[^][()'\" \t\n]+"
+ :regexp "[^][()`',\" \t\n]+"
  :doc-spec '(;; Commands with key sequences appear in nodes as `foo' and
              ;; those without as `M-x foo'.
              ("(emacs)Command Index"  nil "`\\(M-x[ \t\n]+\\)?" "'")
              ;; Variables normally appear in nodes as just `foo'.
              ("(emacs)Variable Index" nil "`" "'")
              ;; Almost all functions, variables, etc appear in nodes as
-             ;; " - Function: foo" etc.  A small number of aliases and
+             ;; " -- Function: foo" etc.  A small number of aliases and
              ;; symbols appear only as `foo', and will miss out on exact
              ;; positions.  Allowing `foo' would hit too many false matches
              ;; for things that should go to Function: etc, and those latter
              ;; are much more important.  Perhaps this could change if some
              ;; sort of fallback match scheme existed.
-             ("(elisp)Index"          nil "^ - .*: " "\\( \\|$\\)")))
+             ("(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]+"
+ :regexp "[^][()`',\" \t\n]+"
  :parse-rule 'ignore
  :other-modes '(emacs-lisp-mode))
 
 (info-lookup-maybe-add-help
  :mode 'lisp-mode
- :regexp "[^()'\" \t\n]+"
+ :regexp "[^()`',\" \t\n]+"
  :parse-rule 'ignore
  :other-modes '(emacs-lisp-mode))
 
 (info-lookup-maybe-add-help
  :mode 'scheme-mode
- :regexp "[^()'\" \t\n]+"
+ :regexp "[^()`',\" \t\n]+"
  :ignore-case t
  ;; Aubrey Jaffer's rendition from <URL:ftp://ftp-swiss.ai.mit.edu/pub/scm>
  :doc-spec '(("(r5rs)Index" nil
-             "^[ \t]+- [^:]+:[ \t]*" "\\b")))
+             "^[ \t]+-+ [^:]+:[ \t]*" "\\b")))
 
 (info-lookup-maybe-add-help
  :mode 'octave-mode
- :regexp "[_a-zA-Z0-9]+"
+ :regexp "[_a-zA-Z0-9]+\\|\\s.+\\|[-!=^|*/.\\,><~&+]\\{1,3\\}\\|[][();,\"']"
  :doc-spec '(("(octave)Function Index" nil
-             "^ - [^:]+:[ ]+\\(\\[[^=]*=[ ]+\\)?" nil)
-            ("(octave)Variable Index" nil "^ - [^:]+:[ ]+" nil)
+             "^ -+ [^:]+:[ ]+\\(\\[[^=]*=[ ]+\\)?" nil)
+            ("(octave)Variable Index" nil "^ -+ [^:]+:[ ]+" nil)
+             ("(octave)Operator Index" nil nil nil)
             ;; Catch lines of the form "xyz statement"
             ("(octave)Concept Index"
              (lambda (item)
@@ -827,9 +918,21 @@ Return nil if there is nothing appropriate in the buffer near point."
                 ((string-match "^\\([A-Z]+\\) statement\\b" item)
                    (match-string 1 item))
                 (t nil)))
-             nil; "^ - [^:]+:[ ]+" don't think this prefix is useful here.
+             nil; "^ -+ [^:]+:[ ]+" don't think this prefix is useful here.
              nil)))
 
+(info-lookup-maybe-add-help
+ :mode 'maxima-mode
+ :ignore-case t
+ :regexp "[a-zA-Z0-9_%]+"
+ :doc-spec '( ("(maxima)Function and Variable Index" nil
+              "^ -+ [^:]+:[ ]+\\(\\[[^=]*=[ ]+\\)?" nil)))
+
+(info-lookup-maybe-add-help
+ :mode 'inferior-maxima-mode
+ :regexp "[a-zA-Z0-9_%]+"
+ :other-modes '(maxima-mode))
+
 ;; coreutils and bash builtins overlap in places, eg. printf, so there's a
 ;; question which should come first.  Some of the coreutils descriptions are
 ;; more detailed, but if bash is usually /bin/sh on a GNU system then the
@@ -850,11 +953,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"
@@ -875,6 +985,34 @@ Return nil if there is nothing appropriate in the buffer near point."
                        "awk")
                       ((string-equal item "gawk, versions of, information about, printing")
                        "gawk"))))))
+
+;; This misses some things which occur as node names but not in the
+;; index.  Unfortunately it also picks up the wrong one of multiple
+;; entries for the same term in some cases.  --fx
+(info-lookup-maybe-add-help
+ :mode 'cfengine-mode
+ :regexp "[[:alnum:]_]+\\(?:()\\)?"
+ :doc-spec '(("(cfengine-Reference)Variable Index"
+             (lambda (item)
+               ;; Index entries may be like `IsPlain()'
+               (if (string-match "\\([[:alnum:]_]+\\)()" item)
+                   (match-string 1 item)
+                 item))
+             ;; This gets functions in evaluated classes.  Other
+             ;; possible patterns don't seem to work too well.
+             "`" "(")))
+
+(info-lookup-maybe-add-help
+ :mode 'Custom-mode
+ :ignore-case t
+ :regexp "[^][()`',:\" \t\n]+"
+ :parse-rule 'info-lookup-guess-custom-symbol
+ :other-modes '(emacs-lisp-mode))
+
+(info-lookup-maybe-add-help
+ :mode 'help-mode
+ :regexp "[^][()`',:\" \t\n]+"
+ :other-modes '(emacs-lisp-mode))
 \f
 (provide 'info-look)