+ (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))))))))
+
+\f
+;;; Initialize some common modes.
+
+(info-lookup-maybe-add-help
+ :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\\): .*\\<" "\\>")
+ ("(libc)Variable Index" nil
+ "^[ \t]+- \\(Variable\\|Macro\\): .*\\<" "\\>")
+ ("(libc)Type Index" nil
+ "^[ \t]+- Data Type: \\<" "\\>")
+ ("(termcap)Var Index" nil
+ "^[ \t]*`" "'"))
+ :parse-rule 'info-lookup-guess-c-symbol)
+
+(info-lookup-maybe-add-help
+ :mode 'c-mode :topic 'file
+ :regexp "[_a-zA-Z0-9./+-]+"
+ :doc-spec '(("(libc)File Index")))
+
+(info-lookup-maybe-add-help
+ :mode 'bison-mode
+ :regexp "[:;|]\\|%\\([%{}]\\|[_a-z]+\\)\\|YY[_A-Z]+\\|yy[_a-z]+"
+ :doc-spec '(("(bison)Index" nil
+ "`" "'"))
+ :parse-rule "[:;|]\\|%\\([%{}]\\|[_a-zA-Z][_a-zA-Z0-9]*\\)"
+ :other-modes '(c-mode))
+
+(info-lookup-maybe-add-help
+ :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))
+
+(info-lookup-maybe-add-help
+ :mode 'texinfo-mode
+ :regexp "@\\([a-zA-Z]+\\|[^a-zA-Z]\\)"
+ :doc-spec '(("(texinfo)Command and Variable Index"
+ ;; Ignore Emacs commands and prepend a `@'.
+ (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
+ :regexp "[_a-zA-Z][_a-zA-Z0-9]*"
+ :doc-spec '(("(m4)Macro index"))
+ :parse-rule "[_a-zA-Z0-9]+")
+
+(info-lookup-maybe-add-help
+ :mode 'autoconf-mode
+ :regexp "A[CM]_[_A-Z0-9]+"
+ :doc-spec '(("(autoconf)Macro Index" "AC_"
+ "^[ \t]+- \\(Macro\\|Variable\\): .*\\<" "\\>")
+ ("(automake)Macro and Variable Index" nil
+ "^[ \t]*`" "'"))
+ ;; Autoconf symbols are M4 macros. Thus use M4's parser.
+ :parse-rule 'ignore
+ :other-modes '(m4-mode))
+
+(info-lookup-maybe-add-help
+ :mode 'awk-mode
+ :regexp "[_a-zA-Z]+"
+ :doc-spec '(("(gawk)Index"
+ (lambda (item)
+ (let ((case-fold-search nil))
+ (cond
+ ;; `BEGIN' and `END'.
+ ((string-match "^\\([A-Z]+\\) special pattern\\b" item)
+ (match-string 1 item))
+ ;; `if', `while', `do', ...
+ ((string-match "^\\([a-z]+\\) statement\\b" item)
+ (if (not (string-equal (match-string 1 item) "control"))
+ (match-string 1 item)))
+ ;; `NR', `NF', ...
+ ((string-match "^[A-Z]+$" item)
+ item)
+ ;; Built-in functions (matches to many entries).
+ ((string-match "^[a-z]+$" item)
+ item))))
+ "`" "\\([ \t]*([^)]*)\\)?'")))
+
+(info-lookup-maybe-add-help
+ :mode 'perl-mode
+ :regexp "[$@%][^a-zA-Z]\\|\\$\\^[A-Z]\\|[$@%]?[a-zA-Z][_a-zA-Z0-9]*"
+ :doc-spec '(("(perl5)Function Index"
+ (lambda (item)
+ (if (string-match "^\\([a-zA-Z0-9]+\\)" item)
+ (match-string 1 item)))
+ "^" "\\b")
+ ("(perl5)Variable Index"
+ (lambda (item)
+ ;; Work around bad formatted array variables.
+ (let ((sym (cond ((or (string-match "^\\$\\(.\\|@@\\)$" item)
+ (string-match "^\\$\\^[A-Z]$" item))
+ item)
+ ((string-match
+ "^\\([$%@]\\|@@\\)?[_a-zA-Z0-9]+" item)
+ (match-string 0 item))
+ (t ""))))
+ (if (string-match "@@" sym)
+ (setq sym (concat (substring sym 0 (match-beginning 0))
+ (substring sym (1- (match-end 0))))))
+ (if (string-equal sym "") nil sym)))
+ "^" "\\b"))
+ :parse-rule "[$@%]?\\([_a-zA-Z0-9]+\\|[^a-zA-Z]\\)")
+
+(info-lookup-maybe-add-help
+ :mode 'cperl-mode
+ :regexp "[$@%][^a-zA-Z]\\|\\$\\^[A-Z]\\|[$@%]?[a-zA-Z][_a-zA-Z0-9]*"
+ :other-modes '(perl-mode))
+
+(info-lookup-maybe-add-help
+ :mode 'latex-mode
+ :regexp "\\\\\\([a-zA-Z]+\\|[^a-zA-Z]\\)"
+ :doc-spec '(("(latex)Command Index" nil
+ "`" "\\({[^}]*}\\)?'")))
+
+(info-lookup-maybe-add-help
+ :mode 'emacs-lisp-mode
+ :regexp "[^][()'\" \t\n]+"
+ :doc-spec '(("(emacs)Command Index")
+ ("(emacs)Variable Index")
+ ("(elisp)Index")))
+
+(info-lookup-maybe-add-help
+ :mode 'lisp-interaction-mode
+ :regexp "[^][()'\" \t\n]+"
+ :parse-rule 'ignore
+ :other-modes '(emacs-lisp-mode))
+
+(info-lookup-maybe-add-help
+ :mode 'lisp-mode
+ :regexp "[^()'\" \t\n]+"
+ :parse-rule 'ignore
+ :other-modes '(emacs-lisp-mode))
+
+(info-lookup-maybe-add-help
+ :mode 'scheme-mode
+ :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")))
+
+(info-lookup-maybe-add-help
+ :mode 'octave-mode
+ :regexp "[_a-zA-Z0-9]+"
+ :doc-spec '(("(octave)Function Index" nil
+ "^ - [^:]+:[ ]+\\(\\[[^=]*=[ ]+\\)?" nil)
+ ("(octave)Variable Index" nil "^ - [^:]+:[ ]+" nil)
+ ;; Catch lines of the form "xyz statement"
+ ("(octave)Concept Index"
+ (lambda (item)
+ (cond
+ ((string-match "^\\([A-Z]+\\) statement\\b" item)
+ (match-string 1 item))
+ (t nil)))
+ nil; "^ - [^:]+:[ ]+" don't think this prefix is useful here.
+ nil)))
+\f