summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard M. Stallman <rms@gnu.org>1997-01-02 07:19:58 +0000
committerRichard M. Stallman <rms@gnu.org>1997-01-02 07:19:58 +0000
commit5c2962b5a8393ed15e2506e1714617ce3aa02933 (patch)
tree59966470deb668af40e157cc25361be1258e7f6b
parent4a86d65a8b2d5080ab58c301fee328b825e3cbce (diff)
downloademacs-5c2962b5a8393ed15e2506e1714617ce3aa02933.tar.gz
Initial revision
-rw-r--r--lisp/=word-help.el717
1 files changed, 717 insertions, 0 deletions
diff --git a/lisp/=word-help.el b/lisp/=word-help.el
new file mode 100644
index 00000000000..f442aef1a6a
--- /dev/null
+++ b/lisp/=word-help.el
@@ -0,0 +1,717 @@
+;;; word-help.el --- keyword help for any language doc'd in TeXinfo.
+
+;; Copyright (c) 1996 Free Software Foundation, Inc.
+
+;; Maintainer: Jens T. Berger Thielemann, <jensthi@ifi.uio.no>
+;; Keywords: help, keyword, languages
+
+;; This file is part of GNU Emacs.
+
+;; This program 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.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; 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.
+
+;;; Commentary:
+
+;; This package provides a rather general interface for doing keyword
+;; help in most languages. In short, it'll determine which Texinfo
+;; file which is relevant for the current mode; cache the index and
+;; use regexps to give you help on the keyword you're looking at.
+
+;; Installation
+;; ************
+
+;; For the default setup to work for all supported modes, make sure
+;; the Texinfo files from the following packages are installed:
+
+;; Texinfo file | Available in archive or URL | Notes
+;; autoconf.info | autoconf-2.10.tar.gz | -
+;; bison.info | bison-1.25.tar.gz | -
+;; libc.info | glibc-1.09.1.tar.gz | -
+;; elisp.info | elisp-manual-19-2.4.tar.gz | -
+;; latex.info | ftp://ftp.dante.de/pub/tex/info/latex2e-help-texinfo/latex2e.texi
+;; groff.info | groff-1.10.tar.gz | -
+;; m4.info | m4-1.4.tar.gz | -
+;; make.info | make-3.75.tar.gz | -
+;; perl.info | http://www.perl.com/CPAN/doc/manual/info/
+;; simula.info | Mail bjort@ifi.uio.no | Written in Norwegian
+;; texinfo.info | texinfo-3.9.tar.gz | -
+
+;; BTW: We refer to Texinfo files by just their last component, not
+;; with an absolute file name. You must thus set up
+;; `Info-directory-list' and `Info-default-directory-list' so that
+;; these can automatically be located.
+
+;; Usage
+;; *****
+;;
+;; Place the cursor over the function/variable/type/whatever you want
+;; help on. Type "C-h C-i". `word-help' will then make a suggestion
+;; to an index topic; press return to accept this. If not, you may use
+;; tab-completion to find the topic you're interested in.
+
+;; Usually, `word-help' is able to determine the relevant Texinfo
+;; file from looking at the buffer's `mode-name'; if not, you can use
+;; the interactive function `set-help-file' to set this.
+
+;; Customizing
+;; ***********
+;;
+;; User interface
+;; --------------
+;;
+;; Two variables control the behaviour of the user-interface of
+;; `word-help': `word-help-split-window' and
+;; `word-help-magic-index'. Do C-h v to get more information on
+;; these.
+
+;; Adding more Texinfo files
+;; -------------------------
+;;
+;; Associations between mode-names and Texinfo files can be done
+;; through the `word-help-mode-alist' variable, which defines an
+;; `alist' making `set-help-file' able to initialize the necessary
+;; variable.
+
+;; Contacting the author
+;; *********************
+;;
+;; If you wish to contact me for any reason, please feel free to write
+;; to:
+
+;; Jens Berger
+;; Spektrumveien 4
+;; N-0666 Oslo
+;; Norway
+;;
+;; E-mail: <jensthi@ifi.uio.no>
+
+;; Have fun.
+
+;;
+;;; Code:
+;;
+
+(require 'info)
+
+;;;--------------------
+;;; USER OPTIONS
+;;;--------------------
+
+(defvar word-help-split-window t
+ "*Non-nil means that the info buffer will pop up in a separate window.
+If nil, we will just switch to it.")
+
+(defvar word-help-magic-index t
+"*Non-nil means that the keyword will be searched for in the requested node.
+This is done by determining whether the line the point is positioned
+on after using `Info-goto-node', actually contains the keyword. If
+not, we will search for the first occurence of the keyword. This may
+help when the info file isn't correctly indexed.")
+
+;;; ---- end of user configurable variables
+
+;;;-------------------------
+;;; ADVANCED USER OPTIONS
+;;;-------------------------
+
+(defvar word-help-mode-alist
+ '(("autoconf"
+ (("autoconf" "Macro Index") ("m4" "Macro index"))
+ (("AC_\\([A-Za-z0-9_]+\\)" 1)
+ ("[a-z]+")))
+
+ ("Bison"
+ (("bison" "Index")
+ ("libc" "Type Index" "Function Index" "Variable Index"))
+ (("%[A-Za-z]+")
+ ("[A-Za-z]+")
+ ("[A-Za-z_][A-Za-z0-9_]+")))
+ ("YACC" . "Bison")
+
+ ("C" (("libc" "Type Index" "Function Index" "Variable Index")))
+ ("C++" . "C")
+
+ ("Emacs-Lisp"
+ (("elisp" "Index"))
+ (("[^][ ()\n\t.\"'#]+")))
+
+ ("LaTeX"
+ (("latex" "Command Index"))
+ (("\\\\\\(begin\\|end\\){\\([^}\n]+\\)}" 2 0)
+ ("\\\\[A-Za-z]+")
+ ("\\\\[^A-Za-z]")
+ ("[A-Za-z]+")))
+
+ ("Nroff"
+ (("groff" "Macro Index" "Register Index" "Request Index"))
+ ((".[^A-Za-z]")
+ (".[A-Za-z]+")
+ (".\\([A-Za-z]+\\)" 1)))
+ ("Groff" . "Nroff")
+
+ ("m4" (("m4" "Macro index")))
+
+ ("Makefile"
+ (("make" "Name Index" "Concept Index"))
+ (("\\.[A-Za-z]+")
+ ("\\$[^()]")
+ ("\\$([^()= \t]+)")
+ ("[A-Za-z]+")))
+
+ ("Perl"
+ (("perl" "Variable Index" "Function Index"))
+ (("\\$[^A-Za-z^]")
+ ("\\$\\^[A-Za-z]?")
+ ("\\$[A-Za-z][A-Za-z_0-9]+")
+ ("[A-Za-z_][A-Za-z_0-9]+"))
+ nil
+ (("^\\([^ \t\n]+\\)" 1)))
+
+ ("Simula" (("simula" "Index")) nil t)
+ ("Ifi Simula" . "Simula")
+ ("SIMULA" . "Simula")
+
+ ("Texinfo"
+ (("texinfo" "Command and Variable Index"))
+ (("@\\([A-Za-z]+\\)" 1)))
+
+ )
+ "Assoc list between `mode-name' and Texinfo files.
+The variable should be initialized with a list of elements with the
+following form:
+
+\(mode-name (word-help-info-files) (word-help-keyword-regexps)
+ word-help-ignore-case word-help-index-mapper)
+
+where `word-help-info-files', `word-help-keyword-regexps' and so
+forth of course are the values which should be put in these variables
+for this mode. Note that `mode-name' doesn't have to be a legal
+mode-name; the user may use the call `set-help-file', where
+`mode-name' will be used in the `completing-read'.
+
+Example entry (for C):
+
+\(\"C\" ((\"libc\" \"Type Index\" \"Function Index\" \"Variable Index\"))
+ ((\"[A-Za-z_][A-Za-z0-9]+\")))
+
+The two first variables must be initialized; the two remaining will
+get default values if you omit them or set them to nil. The default
+values are:
+
+word-help-keyword-regexps: (\"[A-Za-z_][A-Za-z0-9]+\")
+word-help-ignore-case: nil
+
+More settings may be defined in the future.
+
+You may also define aliases, if there are several relevant mode-names
+to a single entry. These should be of the form:
+
+\(MODE-NAME-ALIAS . MODE-NAME-REAL)
+
+For C++, you would use the alias
+
+\(\"C++\" . \"C\")
+
+to make C++ mode use the same help files as C files do. Please note
+that you can shoot yourself in the foot with this possibility, by
+defining recursive aliases.")
+
+;;; --- end of advanced user options
+
+(defvar word-help-ignore-case nil
+ "Non-nil means that case is ignored when doing lookup.")
+(make-variable-buffer-local 'word-help-ignore-case)
+
+(defvar word-help-info-files nil
+"List of infofiles with respective nodes for the current mode.
+
+This should be a list of the following form:
+
+\((INFO-FILE-1 NODE-NAME-1 NODE-NAME-2 ...)
+ (INFO-FILE-1 NODE-NAME-1 NODE-NAME-2 ...)
+ : : :
+ (INFO-FILE-1 NODE-NAME-1 NODE-NAME-2 ...))
+
+An example entry for e.g. C would be:
+
+\((\"/local/share/gnu/info/libc\" \"Function Index\" \"Type Index\"
+ \"Variable Index\"))
+
+The files and nodes will be searched/cached in the order specified.
+This variable is usually set by the `word-help-switch-help-file'
+function, which utilizes the `word-help-mode-alist'.")
+(make-variable-buffer-local 'word-help-info-files)
+
+(defvar word-help-keyword-regexps nil
+ "Regexps for finding keywords in the current mode.
+
+This is constructed as a list of the following form:
+
+\((REGEXP SUBMATCH-LOOKUP SUBMATCH-CURSOR)
+ (REGEXP SUBMATCH-LOOKUP SUBMATCH-CURSOR)
+ : : :
+ (REGEXP SUBMATCH-LOOKUP SUBMATCH-CURSOR))
+
+The regexps will be searched in order for a match which the cursor is
+within.
+
+submatch-lookup is the submatch number which will be looked for in the
+index. May be omitted; defaults to 0 (e.g. the entire pattern). This is
+useful in for instance configure lookup; each command is there prefixed
+with 'AC_', which must be ignored when doing a lookup. Example regexp
+entry for this:
+
+\(\"AC_\\\\([A-Za-z0-9]+\\\\)\" 1)
+
+submatch-cursor is the part of the match which the cursor must be within.
+May be omitted; defaults to 0 (e.g. the entire pattern).")
+(make-variable-buffer-local 'word-help-keyword-regexps)
+(set-default 'word-help-keyword-regexps '(("[A-Za-z_][A-Za-z_0-9]*")))
+
+(defvar word-help-index-mapper nil
+ "Regexps to use for massaging index-entries into keywords.
+This variable should contain a list of regexps with sub-expressions,
+where we will only look for the sub-expression in the user text.
+
+The regexp list should be formatted as:
+
+ ((REGEXP SUBEXP) (REGEXP SUBEXP) ... )
+
+If the index entry does not match any of the regexps, it will be ignored.
+
+Example:
+
+Perl has index entries of the following form:
+
+* abs VALUE: perlfunc.
+* accept NEWSOCKET,GENERICSOCKET: perlfunc.
+* alarm SECONDS: perlfunc.
+* atan2 Y,X: perlfunc.
+* bind SOCKET,NAME: perlfunc.
+ : : :
+
+We will thus try to extract the first word in the index entry -
+\"abs\" from \"abs VALUE\", etc. This is done by the following entry:
+
+\((\"^\\\\([^ \\t\\n]+\\\\)\" 1))")
+(make-variable-buffer-local 'word-help-index-mapper)
+
+(defvar word-help-main-index nil
+"List of all index entries.
+
+See `word-help-process-indexes' for structure formatting.
+
+Minor note: This variable is a list if it is initialized, t if
+initializing failed and nil if uninitialized.")
+(make-variable-buffer-local 'word-help-main-index)
+
+(defvar word-help-main-obarray nil
+"Global work variable for `word-help' system.
+Do Not mess with this!")
+
+(defvar word-help-history nil
+ "History for `word-help' minibuffer queries.")
+(make-local-variable 'word-help-history)
+
+(defvar word-help-current-help-file nil
+ "Current help file active for this mode.")
+
+(defvar word-help-index-alist nil
+ "An assoc list mapping help files to info indexes.
+This means that `word-help-mode-index' can be init'ed faster.")
+
+(defvar word-help-help-mode nil
+ "Which mode the help system is bound to for the current mode.")
+(make-variable-buffer-local 'word-help-help-mode)
+
+
+;;; Debugging
+
+;;;###autoload
+(defun reset-word-help ()
+ "Clear all cached indexes in the `word-help' system.
+You should only need this when installing new info files, and/or
+adding more Texinfo files to the `word-help' system."
+ (interactive)
+ (setq word-help-index-alist nil
+ word-help-main-index nil))
+
+
+;;; Changing help file
+
+;;;###autoload
+(defun set-help-file ()
+ "Change which set of Texinfo files used for word help.
+
+`word-help' maintains a list over which Texinfo files which are
+relevant for each programming language (`word-help-mode-alist'). It
+usually selects the correct one, based upon the value of `mode-name'.
+If this guess is incorrect, you may also use this function manually to
+instruct future `word-help' calls which Texinfo files to use."
+ (interactive)
+ (let (helpfile helpguess (case-comp completion-ignore-case))
+ (setq helpguess (cond
+ (word-help-current-help-file)
+ ((word-help-guess-help-file))))
+
+ (setq completion-ignore-case t
+ helpfile (completing-read
+ (if helpguess
+ (format "Select help mode (default %s): " helpguess)
+ "Select help mode: ")
+ word-help-mode-alist
+ nil t nil nil))
+ (setq completion-ignore-case case-comp)
+ (if (equal "" helpfile)
+ (setq helpfile helpguess))
+ (if helpfile
+ (word-help-switch-help-file helpfile))
+ )
+ )
+
+;;; Main user interface
+
+;;;###autoload
+(defun word-help ()
+ "Find documentation on the keyword under the cursor.
+The determination of which language the keyword belongs to, is based upon
+The relevant info file is selected by matching `mode-name' (the major
+mode) against the assoc list `word-help-mode-alist'.
+
+If this is not possible, `set-help-file' will be invoked for selecting
+the relevant info file. `set-help-file' may also be invoked
+interactively by the user.
+
+If the keyword you are looking at is not available in any index, no
+default suggestion will be presented. "
+ (interactive)
+ (let (helpguess myguess guess index-info case-store)
+;; Set necessary variables for later lookup
+ (if (not word-help-info-files)
+ (if (setq helpguess (word-help-guess-help-file))
+ (word-help-switch-help-file helpguess)
+ (set-help-file)))
+;; Have we previously cached datas?
+ (word-help-process-indexes)
+ (if
+ (atom word-help-main-index)
+ (message "No help file available for this mode.")
+;; First make a guess at what the user is looking for
+ (setq myguess (word-help-guess
+ (point)
+ (cond
+ ((not (atom word-help-main-index))
+ (car word-help-main-index)))
+ word-help-keyword-regexps))
+;; Ask the user himself
+ (setq case-store completion-ignore-case
+ completion-ignore-case word-help-ignore-case)
+ (setq guess (completing-read
+ ; Format string
+ (if myguess
+ (format "Look up keyword (default %s): " myguess)
+ "Look up keyword: ")
+ ; Collection
+ (car word-help-main-index)
+ nil t nil 'word-help-history))
+ (setq completion-ignore-case case-store)
+ (if (equal guess "")
+ (setq guess myguess))
+;; If we've got anything meaningful to lookup, do so
+ (if (not guess)
+ (message "Help aborted.")
+ (setq index-info (word-help-find-index-node
+ guess
+ word-help-main-index))
+ (if (not index-info)
+ (message "Oops, I could not find \"%s\" anyway! Bug?" guess)
+ (word-help-goto-index-node index-info)
+ )
+ )
+ )
+ )
+ )
+
+;;; Index mappers
+
+(defun word-help-map-index-entries (str re-list)
+ (let ((regexp (car (car re-list)))
+ (subexp (car (cdr (car re-list))))
+ (next (cdr re-list)))
+ (cond
+ ((string-match regexp str)
+ (substring str (match-beginning subexp) (match-end subexp)))
+ (next
+ (word-help-map-index-entries str next)))))
+
+
+;;; Mode lookup
+
+(defun word-help-guess-help-file ()
+ "Guesses a relevant help file based on mode name.
+Returns nil if no guess could be made. Uses `word-help-mode-alist'."
+ (let (guess)
+ (cond
+ ((setq guess (assoc mode-name word-help-mode-alist))
+ (car guess)))))
+
+
+(defun word-help-switch-help-file (helpfile)
+ "Changes the help-file to the mode name given.
+Uses `word-help-mode-alist'."
+ (if helpfile
+ (let (helpdesc)
+ (if (not (setq helpdesc (assoc helpfile word-help-mode-alist)))
+ (message "No help defined for \"%s\"." helpfile)
+ (if (stringp (cdr helpdesc))
+ (word-help-switch-help-file (cdr helpdesc))
+ (word-help-make-default-map
+ helpdesc
+ (list 'word-help-help-mode
+ 'word-help-info-files
+ 'word-help-keyword-regexps
+ 'word-help-ignore-case
+ 'word-help-index-mapper))))
+ (setq word-help-main-index nil))))
+
+;;; Default mapping
+
+(defun word-help-make-default-map (list vars)
+ "Makes a default mapping for `vars', which must be listed in order.
+vars is a list of quoted symbols. If the nth entry in the list is
+non-nil, the nth variable will be given this value. If nil, the var
+will be given the global default value."
+ (set (car vars) (cond ((car list)) ((default-value (car vars)))))
+ (if (cdr vars)
+ (word-help-make-default-map (cdr list) (cdr vars))))
+
+
+;;; Index collection
+
+(defun word-help-extract-index (file-name index-list index-map ignore-case)
+ "Extract index from filename and the first node name in index list.
+`file-name' is the name of the info file, while `index-list' is a list
+of node-names to search."
+ (let (cmd1 cmdlow nodename ob-array next)
+ (setq nodename (car index-list))
+ (setq ob-array (make-vector 211 0))
+ (message "Processing \"%s\" in %s..." nodename file-name)
+ (save-window-excursion
+ (Info-goto-node (concat "(" file-name ")" nodename))
+ (end-of-buffer)
+ (while (re-search-backward "\\* \\([^\n:]+\\):" nil t)
+ (setq cmd1 (buffer-substring (match-beginning 1) (match-end 1)))
+ (setq cmdlow (if ignore-case (downcase cmd1) cmd1))
+ (if index-map
+ (setq cmdlow (word-help-map-index-entries cmdlow
+ index-map)))
+;; We have to do this workaround to support case-insensitive matching
+ (cond
+ (cmdlow
+ (put (intern cmdlow ob-array) 'word-help-real-name cmd1)
+ (intern cmdlow word-help-main-obarray)))))
+ (setq next (cond
+ ((cdr index-list)
+ (word-help-extract-index file-name (cdr index-list)
+ index-map ignore-case))))
+ (nconc (list (list nodename ob-array)) next)))
+
+
+(defun word-help-collect-indexes (info-file)
+ "Process all the indexes in an info file.
+
+Uses `word-help-extract-index' on each node, and returns an entry
+suitable for merging into `word-help-process-indexes'. `info-file'
+is an entry of the form
+
+\(FILE-NAME INDEX-NAME-1 INDEX-NAME-2 ...)"
+ (let ((file (car info-file))
+ (nodes (cdr info-file)))
+ (nconc (list file) (word-help-extract-index file nodes
+ word-help-index-mapper
+ word-help-ignore-case))
+ )
+ )
+
+(defun word-help-process-indexes ()
+ "Process all the entries in the global variable `word-help-info-files'.
+Returns a list formatted as follows:
+
+\(all-entries-ob
+ (file-name-1 (node-name-1 this-node-entries-ob)
+ (node-name-2 this-node-entries-ob)
+ : : :
+ (node-name-n this-node-entries-ob))
+ (file-name-2 (node-name-1 this-node-entries-ob)
+ (node-name-2 this-node-entries-ob)
+ : : :
+ (node-name-n this-node-entries-ob))
+ : : : : : : : : :
+ (file-name-n (node-name-1 this-node-entries-ob)
+ (node-name-2 this-node-entries-ob)
+ : : :
+ (node-name-n this-node-entries-ob)))
+
+The symbols in the obarrays may contain the additional property
+`word-help-real-name', which tells the *real* node to go to.
+
+Note that we use `word-help-index-alist' to speed up the process. Note
+that `word-help-switch-help-file' must have been called before this function.
+
+This structure is then later searched by `word-help-find-index-node'."
+ (let (index-words old-index)
+ (if (not word-help-main-index)
+ (cond
+ ((setq old-index
+ (assoc word-help-help-mode word-help-index-alist))
+ (setq word-help-main-index (nth 1 old-index)))
+ (word-help-info-files
+ (setq word-help-main-obarray (make-vector 307 0)
+ index-words (mapcar 'word-help-collect-indexes
+ word-help-info-files)
+ word-help-main-index
+ (append (list word-help-main-obarray) index-words))
+ (setq word-help-index-alist (cons (list word-help-help-mode
+ word-help-main-index)
+ word-help-index-alist)))
+ (t (setq word-help-main-index t))))))
+
+
+;;; Keyword lookup
+
+(defun word-help-guess (cur-point cmd-array re-list)
+ "Guesses what keyword the user is looking at, and returns that.
+CUR-POINT should be the current value of `point', CMD-ARRAY an obarray
+of all the keywords which are defined for the current mode, and
+RE-LIST a list of regexps use for the hunt. See also
+`word-help-keyword-regexps'."
+ (let (guess pre-guess regexp submatch cursmatch end-point)
+ (setq regexp (car (car re-list))
+ submatch (cond ((nth 1 (car re-list))) (0))
+ cursmatch (cond ((nth 2 (car re-list))) (0)))
+;; Store where the old point was
+ (save-excursion
+ (end-of-line)
+;; We won't accept matches after the line
+ (setq end-point (point))
+;; Start at the beginning
+ (beginning-of-line)
+ (setq guess nil)
+ (while (and (not guess) (re-search-forward regexp end-point t))
+ (setq pre-guess (buffer-substring (match-beginning submatch)
+ (match-end submatch)))
+;; Look whether the cursor is within the match
+ (if (and (<= (match-beginning cursmatch) cur-point)
+ (>= (match-end cursmatch) cur-point)
+ (cond
+ (cmd-array (intern-soft (if word-help-ignore-case
+ (downcase pre-guess)
+ pre-guess) cmd-array))
+ (t)))
+ (setq guess pre-guess))
+ )
+;; If we found anything, return it, else call ourselves again
+ (cond
+ (guess)
+ ((cdr re-list) (word-help-guess cur-point cmd-array (cdr re-list)))
+ )
+ )
+ )
+ )
+
+;;; Find an index entry
+
+(defun word-help-find-index-node (node index-reg)
+ "Finds the node named `node' in the index-register `index-reg'.
+`index-reg' has the format as returned (and documented) by the
+`word-help-process-indexes' call. In most cases, this will be equal to
+`word-help-main-index'.
+
+Returns a list with format
+ (file-name index-node-name index-entry)
+which contains the file and index where the entry can be found.
+Returns nil if the entry can't be found."
+ (let (file-info node-name)
+ (setq node-name (cond (word-help-ignore-case (downcase node)) (node)))
+ (if (intern-soft node-name (car index-reg))
+ (setq file-info (word-help-index-search-file node-name
+ (cdr index-reg))))
+ file-info
+ )
+ )
+
+(defun word-help-index-search-file (entry file-data)
+ "Searches a cached file for the index-entry `entry'."
+ (let (this-file next-files file-name node node-infos)
+ (setq this-file (car file-data)
+ next-files (cdr file-data)
+ file-name (car this-file)
+ node-infos (cdr this-file)
+ node (word-help-index-search-nodes entry node-infos))
+ (cond
+ (node
+ (cons file-name node))
+ (next-files (word-help-index-search-file entry next-files))
+ )
+ )
+ )
+
+(defun word-help-index-search-nodes (entry node-info)
+ "Searches a cached list of nodes for the entry `entry'."
+ (let (this-node next-nodes node-name node-ob node-sym)
+ (setq this-node (car node-info)
+ next-nodes (cdr node-info)
+ node-name (car this-node)
+ node-ob (car (cdr this-node))
+ node-sym (intern-soft entry node-ob))
+ (cond
+ (node-sym
+ (list node-name (get node-sym 'word-help-real-name)))
+ (next-nodes (word-help-index-search-nodes entry next-nodes)))))
+
+;;; Switch to a node in an index
+
+(defun word-help-goto-index-node (index-info)
+ "Jumps to an index node.
+`index-info' should be a list with the following format:
+
+\(FILE-NAME INDEX-NODE-NAME INDEX-ENTRY)"
+
+ (let* ((file-name (car index-info))
+ (node-name (nth 1 index-info))
+ (entry-name (nth 2 index-info))
+ (entry-regexp (concat "\\<" (regexp-quote (nth 2 index-info)) "\\>"))
+ (buffer (current-buffer))
+ end-point)
+ (if word-help-split-window
+ (pop-to-buffer nil))
+ (Info-goto-node (concat "(" file-name ")" node-name))
+ (Info-menu entry-name)
+;; Do magic keyword search
+ (cond
+ (word-help-magic-index
+ (end-of-line)
+ (setq end-point (point))
+ (beginning-of-line)
+ (cond
+ ((not (re-search-forward entry-regexp end-point t))
+ (re-search-forward entry-regexp)
+ (recenter 0)))))
+ (if word-help-split-window
+ (pop-to-buffer buffer))))
+
+(provide 'word-help)
+
+;;; word-help.el ends here