comparison lisp/info.el @ 55751:450a4292b3b7

(Info-index-nodes): New var and fun. (Info-goto-index, Info-index, info-apropos) (Info-find-emacs-command-nodes): Rewrite to use Info-index-nodes. (Info-index): Fix docstring. Store and restore Info-history-list. (Info-complete-nodes): New var. (Info-complete-menu-item): Use it. (Info-index-node): New fun. (Info-final-node, Info-forward-node, Info-backward-node) (Info-build-toc, Info-try-follow-nearest-node, Info-fontify-node): Use Info-index-node. (Info-extract-menu-item, Info-extract-menu-counting): Set second arg of `Info-extract-menu-node-name' to non-nil for index nodes. (Info-find-node-2): If a node with period in its name not found, try to find a node without the name part after period. (Info-select-node): Call Info-fontify-node only if Info-fontify-maximum-menu-size is not nil. (info-apropos): Set Info-fontify-maximum-menu-size to nil. (Info-find-emacs-command-nodes, Info-goto-emacs-command-node): Preserve Info-history-list. (Info-toc): Set Info-current-file. (Info-build-toc): Move point to the beginning of the buffer. Add main-file variable. (Info-dir-remove-duplicates, Info-history, Info-toc, info-apropos): Use backslashed representation of the control character ^_.
author Juri Linkov <juri@jurta.org>
date Sun, 23 May 2004 20:53:42 +0000
parents 3616e8c83bfa
children 8926d01558fa
comparison
equal deleted inserted replaced
55750:3a482d346abb 55751:450a4292b3b7
861 ;; whether the node is right where we are, in case the 861 ;; whether the node is right where we are, in case the
862 ;; buffer begins with a node. 862 ;; buffer begins with a node.
863 (let ((pos (Info-find-node-in-buffer regexp))) 863 (let ((pos (Info-find-node-in-buffer regexp)))
864 (when pos 864 (when pos
865 (goto-char pos) 865 (goto-char pos)
866 (throw 'foo t)) 866 (throw 'foo t)))
867 ;; No such anchor in tag table or node in tag table or file 867
868 (error "No such node or anchor: %s" nodename))) 868 (when (string-match "\\([^.]+\\)\\." nodename)
869 (let (Info-point-loc)
870 (Info-find-node-2
871 filename (match-string 1 nodename) no-going-back))
872 (widen)
873 (throw 'foo t))
874
875 ;; No such anchor in tag table or node in tag table or file
876 (error "No such node or anchor: %s" nodename))
869 877
870 (Info-select-node) 878 (Info-select-node)
871 (goto-char (point-min)) 879 (goto-char (point-min))
872 (cond (anchorpos 880 (cond (anchorpos
873 (let ((new-history (list Info-current-file 881 (let ((new-history (list Info-current-file
1073 (defun Info-dir-remove-duplicates () 1081 (defun Info-dir-remove-duplicates ()
1074 (let (limit) 1082 (let (limit)
1075 (goto-char (point-min)) 1083 (goto-char (point-min))
1076 ;; Remove duplicate headings in the same menu. 1084 ;; Remove duplicate headings in the same menu.
1077 (while (search-forward "\n* Menu:" nil t) 1085 (while (search-forward "\n* Menu:" nil t)
1078 (setq limit (save-excursion (search-forward "\n" nil t))) 1086 (setq limit (save-excursion (search-forward "\n\^_" nil t)))
1079 ;; Look for the next heading to unify. 1087 ;; Look for the next heading to unify.
1080 (while (re-search-forward "^\\(\\w.*\\)\n\\*" limit t) 1088 (while (re-search-forward "^\\(\\w.*\\)\n\\*" limit t)
1081 (let ((name (match-string 1)) 1089 (let ((name (match-string 1))
1082 (start (match-beginning 0)) 1090 (start (match-beginning 0))
1083 (entries nil) re) 1091 (entries nil) re)
1284 (if Info-enable-active-nodes (eval active-expression)) 1292 (if Info-enable-active-nodes (eval active-expression))
1285 ;; Add a new unique history item to full history list 1293 ;; Add a new unique history item to full history list
1286 (let ((new-history (list Info-current-file Info-current-node))) 1294 (let ((new-history (list Info-current-file Info-current-node)))
1287 (setq Info-history-list 1295 (setq Info-history-list
1288 (cons new-history (delete new-history Info-history-list)))) 1296 (cons new-history (delete new-history Info-history-list))))
1289 (Info-fontify-node) 1297 (if (not (eq Info-fontify-maximum-menu-size nil))
1298 (Info-fontify-node))
1290 (Info-display-images-node) 1299 (Info-display-images-node)
1291 (Info-hide-cookies-node) 1300 (Info-hide-cookies-node)
1292 (run-hooks 'Info-selection-hook))))) 1301 (run-hooks 'Info-selection-hook)))))
1293 1302
1294 (defun Info-set-mode-line () 1303 (defun Info-set-mode-line ()
1644 p) 1653 p)
1645 (with-current-buffer (get-buffer-create " *info-history*") 1654 (with-current-buffer (get-buffer-create " *info-history*")
1646 (let ((inhibit-read-only t)) 1655 (let ((inhibit-read-only t))
1647 (erase-buffer) 1656 (erase-buffer)
1648 (goto-char (point-min)) 1657 (goto-char (point-min))
1649 (insert "\n\nFile: history Node: Top, Up: (dir)\n\n") 1658 (insert "\n\^_\nFile: history Node: Top, Up: (dir)\n\n")
1650 (insert "Recently Visited Nodes\n**********************\n\n") 1659 (insert "Recently Visited Nodes\n**********************\n\n")
1651 (insert "* Menu:\n\n") 1660 (insert "* Menu:\n\n")
1652 (let ((hl (delete '("history" "Top") Info-history-list))) 1661 (let ((hl (delete '("history" "Top") Info-history-list)))
1653 (while hl 1662 (while hl
1654 (let ((file (nth 0 (car hl))) 1663 (let ((file (nth 0 (car hl)))
1671 (with-current-buffer (get-buffer-create " *info-toc*") 1680 (with-current-buffer (get-buffer-create " *info-toc*")
1672 (let ((inhibit-read-only t) 1681 (let ((inhibit-read-only t)
1673 (node-list (Info-build-toc curr-file))) 1682 (node-list (Info-build-toc curr-file)))
1674 (erase-buffer) 1683 (erase-buffer)
1675 (goto-char (point-min)) 1684 (goto-char (point-min))
1676 (insert "\n\nFile: toc Node: Top, Up: (dir)\n\n") 1685 (insert "\n\^_\nFile: toc Node: Top, Up: (dir)\n\n")
1677 (insert "Table of Contents\n*****************\n\n") 1686 (insert "Table of Contents\n*****************\n\n")
1678 (insert "*Note Top::\n") 1687 (insert "*Note Top::\n")
1679 (Info-insert-toc 1688 (Info-insert-toc
1680 (nth 2 (assoc "Top" node-list)) ; get Top nodes 1689 (nth 2 (assoc "Top" node-list)) ; get Top nodes
1681 node-list 0 curr-file)) 1690 node-list 0 curr-file))
1682 (if (not (bobp)) 1691 (if (not (bobp))
1683 (let ((Info-hide-note-references 'hide) 1692 (let ((Info-hide-note-references 'hide)
1684 (Info-fontify-visited-nodes nil)) 1693 (Info-fontify-visited-nodes nil))
1685 (setq Info-current-node "Top") 1694 (setq Info-current-file "toc" Info-current-node "Top")
1686 (Info-fontify-node))) 1695 (Info-fontify-node)))
1687 (goto-char (point-min)) 1696 (goto-char (point-min))
1688 (if (setq p (search-forward (concat "*Note " curr-node ":") nil t)) 1697 (if (setq p (search-forward (concat "*Note " curr-node ":") nil t))
1689 (setq p (- p (length curr-node) 2)))) 1698 (setq p (- p (length curr-node) 2))))
1690 (Info-find-node "toc" "Top") 1699 (Info-find-node "toc" "Top")
1705 (defun Info-build-toc (file) 1714 (defun Info-build-toc (file)
1706 "Build table of contents from menus of Info FILE and its subfiles." 1715 "Build table of contents from menus of Info FILE and its subfiles."
1707 (if (equal file "dir") 1716 (if (equal file "dir")
1708 (error "Table of contents for Info directory is not supported yet")) 1717 (error "Table of contents for Info directory is not supported yet"))
1709 (with-temp-buffer 1718 (with-temp-buffer
1710 (let ((default-directory (or (and (stringp file) 1719 (let* ((default-directory (or (and (stringp file)
1711 (file-name-directory 1720 (file-name-directory
1712 (setq file (Info-find-file file)))) 1721 (setq file (Info-find-file file))))
1713 default-directory)) 1722 default-directory))
1714 (sections '(("Top" "Top"))) 1723 (main-file file)
1715 nodes subfiles) 1724 (sections '(("Top" "Top")))
1716 (while (or file subfiles) 1725 nodes subfiles)
1717 (or file (message "Searching subfile %s..." (car subfiles))) 1726 (while (or main-file subfiles)
1727 (or main-file (message "Searching subfile %s..." (car subfiles)))
1718 (erase-buffer) 1728 (erase-buffer)
1719 (info-insert-file-contents (or file (car subfiles))) 1729 (info-insert-file-contents (or main-file (car subfiles)))
1730 (goto-char (point-min))
1720 (while (and (search-forward "\n\^_\nFile:" nil 'move) 1731 (while (and (search-forward "\n\^_\nFile:" nil 'move)
1721 (search-forward "Node: " nil 'move)) 1732 (search-forward "Node: " nil 'move))
1722 (let ((nodename (substring-no-properties (Info-following-node-name))) 1733 (let ((nodename (substring-no-properties (Info-following-node-name)))
1723 (bound (- (or (save-excursion (search-forward "\n\^_" nil t)) 1734 (bound (- (or (save-excursion (search-forward "\n\^_" nil t))
1724 (point-max)) 2)) 1735 (point-max)) 2))
1725 (section "Top") 1736 (section "Top")
1726 menu-items) 1737 menu-items)
1727 (when (and (not (string-match "\\<index\\>" nodename)) 1738 (when (and (not (Info-index-node nodename file))
1728 (re-search-forward "^\\* Menu:" bound t)) 1739 (re-search-forward "^\\* Menu:" bound t))
1729 (forward-line 1) 1740 (forward-line 1)
1730 (beginning-of-line) 1741 (beginning-of-line)
1731 (setq bound (or (and (equal nodename "Top") 1742 (setq bound (or (and (equal nodename "Top")
1732 (save-excursion 1743 (save-excursion
1754 (setq nodes (cons (list nodename 1765 (setq nodes (cons (list nodename
1755 (cadr (assoc nodename sections)) 1766 (cadr (assoc nodename sections))
1756 (nreverse menu-items)) 1767 (nreverse menu-items))
1757 nodes)) 1768 nodes))
1758 (goto-char bound))) 1769 (goto-char bound)))
1759 (if file 1770 (if main-file
1760 (save-excursion 1771 (save-excursion
1761 (goto-char (point-min)) 1772 (goto-char (point-min))
1762 (if (search-forward "\n\^_\nIndirect:" nil t) 1773 (if (search-forward "\n\^_\nIndirect:" nil t)
1763 (let ((bound (save-excursion (search-forward "\n\^_" nil t)))) 1774 (let ((bound (save-excursion (search-forward "\n\^_" nil t))))
1764 (while (re-search-forward "^\\(.*\\): [0-9]+$" bound t) 1775 (while (re-search-forward "^\\(.*\\): [0-9]+$" bound t)
1765 (setq subfiles (cons (match-string-no-properties 1) 1776 (setq subfiles (cons (match-string-no-properties 1)
1766 subfiles))))) 1777 subfiles)))))
1767 (setq subfiles (nreverse subfiles) 1778 (setq subfiles (nreverse subfiles)
1768 file nil)) 1779 main-file nil))
1769 (setq subfiles (cdr subfiles)))) 1780 (setq subfiles (cdr subfiles))))
1770 (message "") 1781 (message "")
1771 (nreverse nodes)))) 1782 (nreverse nodes))))
1772 1783
1773 (defun Info-follow-reference (footnotename &optional fork) 1784 (defun Info-follow-reference (footnotename &optional fork)
1905 ;; (Info-menu (car list)) 1916 ;; (Info-menu (car list))
1906 ;; (setq list (cdr list)))) 1917 ;; (setq list (cdr list))))
1907 1918
1908 (defvar Info-complete-menu-buffer) 1919 (defvar Info-complete-menu-buffer)
1909 (defvar Info-complete-next-re nil) 1920 (defvar Info-complete-next-re nil)
1921 (defvar Info-complete-nodes nil)
1910 (defvar Info-complete-cache nil) 1922 (defvar Info-complete-cache nil)
1911 1923
1912 (defconst Info-node-spec-re 1924 (defconst Info-node-spec-re
1913 (concat (Info-following-node-name-re "^.,:") "[,:.]") 1925 (concat (Info-following-node-name-re "^.,:") "[,:.]")
1914 "Regexp to match the text after a : until the terminating `.'.") 1926 "Regexp to match the text after a : until the terminating `.'.")
1918 ;; - `Info-complete-menu-buffer' which contains the buffer in which 1930 ;; - `Info-complete-menu-buffer' which contains the buffer in which
1919 ;; is the menu of items we're trying to complete. 1931 ;; is the menu of items we're trying to complete.
1920 ;; - `Info-complete-next-re' which, if non-nil, indicates that we should 1932 ;; - `Info-complete-next-re' which, if non-nil, indicates that we should
1921 ;; also look for menu items in subsequent nodes as long as those 1933 ;; also look for menu items in subsequent nodes as long as those
1922 ;; nodes' names match `Info-complete-next-re'. This feature is currently 1934 ;; nodes' names match `Info-complete-next-re'. This feature is currently
1935 ;; not used.
1936 ;; - `Info-complete-nodes' which, if non-nil, indicates that we should
1937 ;; also look for menu items in these nodes. This feature is currently
1923 ;; only used for completion in Info-index. 1938 ;; only used for completion in Info-index.
1924 1939
1925 ;; Note that `Info-complete-menu-buffer' could be current already, 1940 ;; Note that `Info-complete-menu-buffer' could be current already,
1926 ;; so we want to save point. 1941 ;; so we want to save point.
1927 (save-excursion 1942 (save-excursion
1941 completions) 1956 completions)
1942 ;; Check the cache. 1957 ;; Check the cache.
1943 (if (and (equal (nth 0 Info-complete-cache) Info-current-file) 1958 (if (and (equal (nth 0 Info-complete-cache) Info-current-file)
1944 (equal (nth 1 Info-complete-cache) Info-current-node) 1959 (equal (nth 1 Info-complete-cache) Info-current-node)
1945 (equal (nth 2 Info-complete-cache) Info-complete-next-re) 1960 (equal (nth 2 Info-complete-cache) Info-complete-next-re)
1961 (equal (nth 5 Info-complete-cache) Info-complete-nodes)
1946 (let ((prev (nth 3 Info-complete-cache))) 1962 (let ((prev (nth 3 Info-complete-cache)))
1947 (eq t (compare-strings string 0 (length prev) 1963 (eq t (compare-strings string 0 (length prev)
1948 prev 0 nil t)))) 1964 prev 0 nil t))))
1949 ;; We can reuse the previous list. 1965 ;; We can reuse the previous list.
1950 (setq completions (nth 4 Info-complete-cache)) 1966 (setq completions (nth 4 Info-complete-cache))
1953 (progn 1969 (progn
1954 (while (re-search-forward pattern nil t) 1970 (while (re-search-forward pattern nil t)
1955 (push (match-string-no-properties 1) 1971 (push (match-string-no-properties 1)
1956 completions)) 1972 completions))
1957 ;; Check subsequent nodes if applicable. 1973 ;; Check subsequent nodes if applicable.
1958 (and Info-complete-next-re 1974 (or (and Info-complete-next-re
1959 (setq nextnode (Info-extract-pointer "next" t)) 1975 (setq nextnode (Info-extract-pointer "next" t))
1960 (string-match Info-complete-next-re nextnode))) 1976 (string-match Info-complete-next-re nextnode))
1977 (and Info-complete-nodes
1978 (setq Info-complete-nodes (cdr Info-complete-nodes)
1979 nextnode (car Info-complete-nodes)))))
1961 (Info-goto-node nextnode)) 1980 (Info-goto-node nextnode))
1962 ;; Go back to the start node (for the next completion). 1981 ;; Go back to the start node (for the next completion).
1963 (unless (equal Info-current-node orignode) 1982 (unless (equal Info-current-node orignode)
1964 (Info-goto-node orignode)) 1983 (Info-goto-node orignode))
1965 ;; Update the cache. 1984 ;; Update the cache.
1966 (set (make-local-variable 'Info-complete-cache) 1985 (set (make-local-variable 'Info-complete-cache)
1967 (list Info-current-file Info-current-node 1986 (list Info-current-file Info-current-node
1968 Info-complete-next-re string completions))) 1987 Info-complete-next-re string completions
1988 Info-complete-nodes)))
1969 (if action 1989 (if action
1970 (all-completions string completions predicate) 1990 (all-completions string completions predicate)
1971 (try-completion string completions predicate))))))) 1991 (try-completion string completions predicate)))))))
1972 1992
1973 1993
2032 (or (re-search-forward (concat "\n\\* +" menu-item ":") nil t) 2052 (or (re-search-forward (concat "\n\\* +" menu-item ":") nil t)
2033 (re-search-forward (concat "\n\\* +" menu-item) nil t) 2053 (re-search-forward (concat "\n\\* +" menu-item) nil t)
2034 (error "No such item in menu")) 2054 (error "No such item in menu"))
2035 (beginning-of-line) 2055 (beginning-of-line)
2036 (forward-char 2) 2056 (forward-char 2)
2037 (Info-extract-menu-node-name))))) 2057 (Info-extract-menu-node-name nil (Info-index-node))))))
2038 2058
2039 ;; If COUNT is nil, use the last item in the menu. 2059 ;; If COUNT is nil, use the last item in the menu.
2040 (defun Info-extract-menu-counting (count) 2060 (defun Info-extract-menu-counting (count)
2041 (let ((case-fold-search t)) 2061 (let ((case-fold-search t))
2042 (save-excursion 2062 (save-excursion
2047 (if count 2067 (if count
2048 (or (search-forward "\n* " nil t count) 2068 (or (search-forward "\n* " nil t count)
2049 (error "Too few items in menu")) 2069 (error "Too few items in menu"))
2050 (while (search-forward "\n* " nil t) 2070 (while (search-forward "\n* " nil t)
2051 nil)) 2071 nil))
2052 (Info-extract-menu-node-name))))) 2072 (Info-extract-menu-node-name nil (Info-index-node))))))
2053 2073
2054 (defun Info-nth-menu-item () 2074 (defun Info-nth-menu-item ()
2055 "Go to the node of the Nth menu item. 2075 "Go to the node of the Nth menu item.
2056 N is the digit argument used to invoke this command." 2076 N is the digit argument used to invoke this command."
2057 (interactive) 2077 (interactive)
2074 (Info-goto-node (Info-extract-menu-counting nil)) 2094 (Info-goto-node (Info-extract-menu-counting nil))
2075 ;; If the last node in the menu is not last in pointer structure, 2095 ;; If the last node in the menu is not last in pointer structure,
2076 ;; move forward until we can't go any farther. 2096 ;; move forward until we can't go any farther.
2077 (while (Info-forward-node t t) nil) 2097 (while (Info-forward-node t t) nil)
2078 ;; Then keep moving down to last subnode, unless we reach an index. 2098 ;; Then keep moving down to last subnode, unless we reach an index.
2079 (while (and (not (string-match "\\<index\\>" Info-current-node)) 2099 (while (and (not (Info-index-node))
2080 (save-excursion (search-forward "\n* Menu:" nil t))) 2100 (save-excursion (search-forward "\n* Menu:" nil t)))
2081 (Info-goto-node (Info-extract-menu-counting nil))))) 2101 (Info-goto-node (Info-extract-menu-counting nil)))))
2082 2102
2083 (defun Info-forward-node (&optional not-down no-error) 2103 (defun Info-forward-node (&optional not-down no-error)
2084 "Go forward one node, considering all nodes as forming one sequence." 2104 "Go forward one node, considering all nodes as forming one sequence."
2090 ;; 1. next node is in a menu in this node (but not in an index) 2110 ;; 1. next node is in a menu in this node (but not in an index)
2091 ;; 2. next node is next at same level 2111 ;; 2. next node is next at same level
2092 ;; 3. next node is up and next 2112 ;; 3. next node is up and next
2093 (cond ((and (not not-down) 2113 (cond ((and (not not-down)
2094 (save-excursion (search-forward "\n* menu:" nil t)) 2114 (save-excursion (search-forward "\n* menu:" nil t))
2095 (not (string-match "\\<index\\>" Info-current-node))) 2115 (not (Info-index-node)))
2096 (Info-goto-node (Info-extract-menu-counting 1)) 2116 (Info-goto-node (Info-extract-menu-counting 1))
2097 t) 2117 t)
2098 ((save-excursion (search-backward "next:" nil t)) 2118 ((save-excursion (search-backward "next:" nil t))
2099 (Info-next) 2119 (Info-next)
2100 t) 2120 t)
2128 (prevnode 2148 (prevnode
2129 ;; If we move back at the same level, 2149 ;; If we move back at the same level,
2130 ;; go down to find the last subnode*. 2150 ;; go down to find the last subnode*.
2131 (Info-prev) 2151 (Info-prev)
2132 (let (Info-history) 2152 (let (Info-history)
2133 (while (and (not (string-match "\\<index\\>" Info-current-node)) 2153 (while (and (not (Info-index-node))
2134 (save-excursion (search-forward "\n* Menu:" nil t))) 2154 (save-excursion (search-forward "\n* Menu:" nil t)))
2135 (Info-goto-node (Info-extract-menu-counting nil))))) 2155 (Info-goto-node (Info-extract-menu-counting nil)))))
2136 (t 2156 (t
2137 (error "No pointer backward from this node"))))) 2157 (error "No pointer backward from this node")))))
2138 2158
2319 (goto-char (or (match-beginning 1) (match-beginning 0))) 2339 (goto-char (or (match-beginning 1) (match-beginning 0)))
2320 (if (looking-at "\\* Menu:") 2340 (if (looking-at "\\* Menu:")
2321 (if recur 2341 (if recur
2322 (error "No cross references in this node") 2342 (error "No cross references in this node")
2323 (Info-prev-reference t))))) 2343 (Info-prev-reference t)))))
2344
2345 (defvar Info-index-nodes nil
2346 "Alist of cached index node names of visited Info files.
2347 Each element has the form (INFO-FILE INDEX-NODE-NAMES-LIST).")
2348
2349 (defun Info-index-nodes (&optional file)
2350 "Return a list of names of all index nodes in Info FILE.
2351 If FILE is omitted, it defaults to the current Info file.
2352 First look in a list of cached index node names. Then scan Info file
2353 and its subfiles for nodes with index cookie. Then try index nodes
2354 starting from the first node in the top level menu whose name
2355 contains the word \"Index\", plus any immediately following nodes
2356 whose names also contain the word \"Index\"."
2357 (or file (setq file Info-current-file))
2358 (or (assoc file Info-index-nodes)
2359 ;; Skip virtual Info files
2360 (member file '("dir" "history" "toc" "apropos"))
2361 ;; Find nodes with index cookie
2362 (let* ((default-directory (or (and (stringp file)
2363 (file-name-directory
2364 (setq file (Info-find-file file))))
2365 default-directory))
2366 (main-file file)
2367 (Info-fontify-maximum-menu-size nil)
2368 subfiles nodes node Info-history Info-history-list)
2369 (with-temp-buffer
2370 (while (or main-file subfiles)
2371 (erase-buffer)
2372 (info-insert-file-contents (or main-file (car subfiles)))
2373 (goto-char (point-min))
2374 (while (search-forward "\0\10[index\0\10]" nil 'move)
2375 (save-excursion
2376 (re-search-backward "^\^_")
2377 (search-forward "Node: ")
2378 (setq nodes (cons (Info-following-node-name) nodes))))
2379 (if main-file
2380 (save-excursion
2381 (goto-char (point-min))
2382 (if (search-forward "\n\^_\nIndirect:" nil t)
2383 (let ((bound (save-excursion (search-forward "\n\^_" nil t))))
2384 (while (re-search-forward "^\\(.*\\): [0-9]+$" bound t)
2385 (setq subfiles (cons (match-string-no-properties 1)
2386 subfiles)))))
2387 (setq subfiles (nreverse subfiles)
2388 main-file nil))
2389 (setq subfiles (cdr subfiles)))))
2390 (if nodes
2391 (setq nodes (nreverse nodes)
2392 Info-index-nodes (cons (cons file nodes) Info-index-nodes)))
2393 nodes)
2394 ;; Find nodes with string "Index" in node names
2395 (let ((Info-fontify-maximum-menu-size nil)
2396 (case-fold-search t)
2397 nodes node Info-history Info-history-list)
2398 (with-temp-buffer
2399 (Info-mode)
2400 (Info-find-node file "Top")
2401 (when (and (search-forward "\n* menu:" nil t)
2402 (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t))
2403 (goto-char (match-beginning 1))
2404 (setq nodes (list (Info-extract-menu-node-name)))
2405 (Info-goto-node (car nodes))
2406 (while (and (setq node (Info-extract-pointer "next" t))
2407 (string-match "\\<Index\\>" node))
2408 (setq nodes (cons node nodes))
2409 (Info-goto-node node))))
2410 (if nodes
2411 (setq nodes (nreverse nodes)
2412 Info-index-nodes (cons (cons file nodes) Info-index-nodes)))
2413 nodes)
2414 ;; Info file has no index nodes
2415 (setq Info-index-nodes (cons (cons file nil)
2416 Info-index-nodes)))
2417 (cdr (assoc file Info-index-nodes)))
2418
2419 (defun Info-index-node (&optional node file)
2420 "Return non-nil value if NODE is an index node.
2421 If NODE is nil, check the current Info node.
2422 If FILE is nil, check the current Info file."
2423 (member (or node Info-current-node) (Info-index-nodes file)))
2324 2424
2325 (defun Info-goto-index () 2425 (defun Info-goto-index ()
2326 (Info-goto-node "Top") 2426 "Go to the first index node."
2327 (or (search-forward "\n* menu:" nil t) 2427 (let ((node (car (Info-index-nodes))))
2328 (error "No index")) 2428 (or node (error "No index"))
2329 (or (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t) 2429 (Info-goto-node node)))
2330 (error "No index"))
2331 (goto-char (match-beginning 1))
2332 ;; Protect Info-history so that the current node (Top) is not added to it.
2333 (let ((Info-history nil))
2334 (Info-goto-node (Info-extract-menu-node-name))))
2335 2430
2336 ;;;###autoload 2431 ;;;###autoload
2337 (defun Info-index (topic) 2432 (defun Info-index (topic)
2338 "Look up a string TOPIC in the index for this file. 2433 "Look up a string TOPIC in the index for this file.
2339 The index is defined as the first node in the top level menu whose
2340 name contains the word \"Index\", plus any immediately following
2341 nodes whose names also contain the word \"Index\".
2342 If there are no exact matches to the specified topic, this chooses 2434 If there are no exact matches to the specified topic, this chooses
2343 the first match which is a case-insensitive substring of a topic. 2435 the first match which is a case-insensitive substring of a topic.
2344 Use the \\<Info-mode-map>\\[Info-index-next] command to see the other matches. 2436 Use the \\<Info-mode-map>\\[Info-index-next] command to see the other matches.
2345 Give a blank topic name to go to the Index node itself." 2437 Give a blank topic name to go to the Index node itself."
2346 (interactive 2438 (interactive
2347 (list 2439 (list
2348 (let ((Info-complete-menu-buffer (clone-buffer)) 2440 (let ((Info-complete-menu-buffer (clone-buffer))
2349 (Info-complete-next-re "\\<Index\\>")) 2441 (Info-complete-nodes (Info-index-nodes))
2442 (Info-history-list nil))
2350 (if (equal Info-current-file "dir") 2443 (if (equal Info-current-file "dir")
2351 (error "The Info directory node has no index; use m to select a manual")) 2444 (error "The Info directory node has no index; use m to select a manual"))
2352 (unwind-protect 2445 (unwind-protect
2353 (with-current-buffer Info-complete-menu-buffer 2446 (with-current-buffer Info-complete-menu-buffer
2354 (Info-goto-index) 2447 (Info-goto-index)
2357 (if (equal Info-current-file "dir") 2450 (if (equal Info-current-file "dir")
2358 (error "The Info directory node has no index; use m to select a manual")) 2451 (error "The Info directory node has no index; use m to select a manual"))
2359 (let ((orignode Info-current-node) 2452 (let ((orignode Info-current-node)
2360 (pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?" 2453 (pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
2361 (regexp-quote topic))) 2454 (regexp-quote topic)))
2362 node 2455 node (nodes (Info-index-nodes))
2456 (ohist-list Info-history-list)
2363 (case-fold-search t)) 2457 (case-fold-search t))
2364 (Info-goto-index) 2458 (Info-goto-index)
2365 (or (equal topic "") 2459 (or (equal topic "")
2366 (let ((matches nil) 2460 (let ((matches nil)
2367 (exact nil) 2461 (exact nil)
2379 (match-string-no-properties 2) 2473 (match-string-no-properties 2)
2380 Info-current-node 2474 Info-current-node
2381 (string-to-number (concat "0" 2475 (string-to-number (concat "0"
2382 (match-string 3)))) 2476 (match-string 3))))
2383 matches)) 2477 matches))
2384 (and (setq node (Info-extract-pointer "next" t)) 2478 (setq nodes (cdr nodes) node (car nodes)))
2385 (string-match "\\<Index\\>" node)))
2386 (Info-goto-node node)) 2479 (Info-goto-node node))
2387 (or matches 2480 (or matches
2388 (progn 2481 (progn
2389 (Info-goto-node orignode) 2482 (Info-goto-node orignode)
2390 (error "No `%s' in index" topic))) 2483 (error "No `%s' in index" topic)))
2391 ;; Here it is a feature that assoc is case-sensitive. 2484 ;; Here it is a feature that assoc is case-sensitive.
2392 (while (setq found (assoc topic matches)) 2485 (while (setq found (assoc topic matches))
2393 (setq exact (cons found exact) 2486 (setq exact (cons found exact)
2394 matches (delq found matches))) 2487 matches (delq found matches)))
2488 (setq Info-history-list ohist-list)
2395 (setq Info-index-alternatives (nconc exact (nreverse matches))) 2489 (setq Info-index-alternatives (nconc exact (nreverse matches)))
2396 (Info-index-next 0))))) 2490 (Info-index-next 0)))))
2397 2491
2398 (defun Info-index-next (num) 2492 (defun Info-index-next (num)
2399 "Go to the next matching index item from the last \\<Info-mode-map>\\[Info-index] command." 2493 "Go to the next matching index item from the last \\<Info-mode-map>\\[Info-index] command."
2452 (regexp-quote string))) 2546 (regexp-quote string)))
2453 (ohist Info-history) 2547 (ohist Info-history)
2454 (ohist-list Info-history-list) 2548 (ohist-list Info-history-list)
2455 (current-node Info-current-node) 2549 (current-node Info-current-node)
2456 (current-file Info-current-file) 2550 (current-file Info-current-file)
2457 manuals matches node) 2551 manuals matches node nodes)
2458 (let ((Info-fontify-maximum-menu-size 0) 2552 (let ((Info-fontify-maximum-menu-size nil))
2459 Info-use-header-lines
2460 Info-hide-note-references)
2461 (Info-directory) 2553 (Info-directory)
2462 (message "Searching indices...") 2554 (message "Searching indices...")
2463 (goto-char (point-min)) 2555 (goto-char (point-min))
2464 (re-search-forward "\\* Menu: *\n" nil t) 2556 (re-search-forward "\\* Menu: *\n" nil t)
2465 (while (re-search-forward "\\*.*: *(\\([^)]+\\))" nil t) 2557 (while (re-search-forward "\\*.*: *(\\([^)]+\\))" nil t)
2466 (add-to-list 'manuals (match-string 1))) 2558 (add-to-list 'manuals (match-string 1)))
2467 (dolist (manual manuals) 2559 (dolist (manual manuals)
2468 (message "Searching %s" manual) 2560 (message "Searching %s" manual)
2469 (condition-case nil 2561 (if (setq nodes (Info-index-nodes (Info-find-file manual)))
2470 (save-excursion 2562 (condition-case nil
2471 (Info-find-node manual "Top") 2563 (save-excursion
2472 (when (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t) 2564 (Info-find-node manual (car nodes))
2473 (goto-char (match-beginning 1)) 2565 (while
2474 (Info-goto-node (Info-extract-menu-node-name)) 2566 (progn
2475 (while 2567 (goto-char (point-min))
2476 (progn 2568 (while (re-search-forward pattern nil t)
2477 (goto-char (point-min)) 2569 (add-to-list 'matches
2478 (while (re-search-forward pattern nil t) 2570 (list manual
2479 (add-to-list 'matches 2571 (match-string-no-properties 1)
2480 (list manual 2572 (match-string-no-properties 2)
2481 (match-string-no-properties 1) 2573 (match-string-no-properties 3))))
2482 (match-string-no-properties 2) 2574 (setq nodes (cdr nodes) node (car nodes)))
2483 (match-string-no-properties 3)))) 2575 (Info-goto-node node)))
2484 (and (setq node (Info-extract-pointer "next" t)) 2576 (error nil)))))
2485 (string-match "\\<Index\\>" node)))
2486 (Info-goto-node node))))
2487 (error nil))))
2488 (Info-goto-node (concat "(" current-file ")" current-node)) 2577 (Info-goto-node (concat "(" current-file ")" current-node))
2489 (setq Info-history ohist 2578 (setq Info-history ohist
2490 Info-history-list ohist-list) 2579 Info-history-list ohist-list)
2491 (message "Searching indices...done") 2580 (message "Searching indices...done")
2492 (if (null matches) 2581 (if (null matches)
2493 (message "No matches found") 2582 (message "No matches found")
2494 (with-current-buffer (get-buffer-create " *info-apropos*") 2583 (with-current-buffer (get-buffer-create " *info-apropos*")
2495 (erase-buffer) 2584 (erase-buffer)
2496 (insert "\n\nFile: apropos, Node: Index, Up: (dir)\n") 2585 (insert "\n\^_\nFile: apropos, Node: Index, Up: (dir)\n")
2497 (insert "* Menu: \nNodes whose indices contain \"" string "\"\n\n") 2586 (insert "* Menu: \nNodes whose indices contain \"" string "\"\n\n")
2498 (dolist (entry matches) 2587 (dolist (entry matches)
2499 (insert 2588 (insert
2500 (format "* %-38s (%s)%s.%s\n" 2589 (format "* %-38s (%s)%s.%s\n"
2501 (concat (nth 1 entry) " [" (nth 0 entry) "]:") 2590 (concat (nth 1 entry) " [" (nth 0 entry) "]:")
2627 (Info-goto-node node fork)) 2716 (Info-goto-node node fork))
2628 ;; menu item: node name or index entry 2717 ;; menu item: node name or index entry
2629 ((Info-get-token (point) "\\* +" "\\* +\\(.*\\): ") 2718 ((Info-get-token (point) "\\* +" "\\* +\\(.*\\): ")
2630 (beginning-of-line) 2719 (beginning-of-line)
2631 (forward-char 2) 2720 (forward-char 2)
2632 (setq node (Info-extract-menu-node-name 2721 (setq node (Info-extract-menu-node-name nil (Info-index-node)))
2633 nil (string-match "\\<index\\>" Info-current-node)))
2634 (Info-goto-node node fork)) 2722 (Info-goto-node node fork))
2635 ((setq node (Info-get-token (point) "Up: " "Up: \\([^,\n\t]*\\)")) 2723 ((setq node (Info-get-token (point) "Up: " "Up: \\([^,\n\t]*\\)"))
2636 (Info-goto-node node fork)) 2724 (Info-goto-node node fork))
2637 ((setq node (Info-get-token (point) "Next: " "Next: \\([^,\n\t]*\\)")) 2725 ((setq node (Info-get-token (point) "Next: " "Next: \\([^,\n\t]*\\)"))
2638 (Info-goto-node node fork)) 2726 (Info-goto-node node fork))
3070 (error "Info file `%s' appears to lack an index" info-file)) 3158 (error "Info file `%s' appears to lack an index" info-file))
3071 (goto-char (match-beginning 1)) 3159 (goto-char (match-beginning 1))
3072 ;; Bind Info-history to nil, to prevent the index nodes from 3160 ;; Bind Info-history to nil, to prevent the index nodes from
3073 ;; getting into the node history. 3161 ;; getting into the node history.
3074 (let ((Info-history nil) 3162 (let ((Info-history nil)
3075 node) 3163 (Info-history-list nil)
3076 (Info-goto-node (Info-extract-menu-node-name)) 3164 node (nodes (Info-index-nodes)))
3165 (Info-goto-node (car nodes))
3077 (while 3166 (while
3078 (progn 3167 (progn
3079 (goto-char (point-min)) 3168 (goto-char (point-min))
3080 (while (re-search-forward cmd-desc nil t) 3169 (while (re-search-forward cmd-desc nil t)
3081 (setq where 3170 (setq where
3082 (cons (list Info-current-file 3171 (cons (list Info-current-file
3083 (match-string-no-properties 2) 3172 (match-string-no-properties 2)
3084 0) 3173 0)
3085 where))) 3174 where)))
3086 (and (setq node (Info-extract-pointer "next" t)) 3175 (and (setq nodes (cdr nodes) node (car nodes))))
3087 (string-match "\\<Index\\>" node)))
3088 (Info-goto-node node))) 3176 (Info-goto-node node)))
3089 where)) 3177 where))
3090 3178
3091 ;;;###autoload 3179 ;;;###autoload
3092 (defun Info-goto-emacs-command-node (command) 3180 (defun Info-goto-emacs-command-node (command)
3109 (info)) 3197 (info))
3110 (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) 3198 (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*"))
3111 ;; Bind Info-history to nil, to prevent the last Index node 3199 ;; Bind Info-history to nil, to prevent the last Index node
3112 ;; visited by Info-find-emacs-command-nodes from being 3200 ;; visited by Info-find-emacs-command-nodes from being
3113 ;; pushed onto the history. 3201 ;; pushed onto the history.
3114 (let ((Info-history nil)) 3202 (let ((Info-history nil) (Info-history-list nil))
3115 (Info-find-node (car (car where)) 3203 (Info-find-node (car (car where))
3116 (car (cdr (car where))))) 3204 (car (cdr (car where)))))
3117 (if (> num-matches 1) 3205 (if (> num-matches 1)
3118 (progn 3206 (progn
3119 ;; (car where) will be pushed onto Info-history 3207 ;; (car where) will be pushed onto Info-history
3446 3534
3447 ;; Fontify menu items 3535 ;; Fontify menu items
3448 (goto-char (point-min)) 3536 (goto-char (point-min))
3449 (when (and (or not-fontified-p fontify-visited-p) 3537 (when (and (or not-fontified-p fontify-visited-p)
3450 (search-forward "\n* Menu:" nil t) 3538 (search-forward "\n* Menu:" nil t)
3451 (not (string-match "\\<Index\\>" Info-current-node)) 3539 (not (Info-index-node))
3452 ;; Don't take time to annotate huge menus 3540 ;; Don't take time to annotate huge menus
3453 (< (- (point-max) (point)) Info-fontify-maximum-menu-size)) 3541 (< (- (point-max) (point)) Info-fontify-maximum-menu-size))
3454 (let ((n 0) 3542 (let ((n 0)
3455 cont) 3543 cont)
3456 (while (re-search-forward 3544 (while (re-search-forward
3535 (put-text-property (match-beginning 1) (match-end 1) 3623 (put-text-property (match-beginning 1) (match-end 1)
3536 'font-lock-face 'info-menu-header))) 3624 'font-lock-face 'info-menu-header)))
3537 3625
3538 ;; Hide index line numbers 3626 ;; Hide index line numbers
3539 (goto-char (point-min)) 3627 (goto-char (point-min))
3540 (when (and not-fontified-p (string-match "\\<Index\\>" Info-current-node)) 3628 (when (and not-fontified-p (Info-index-node))
3541 (while (re-search-forward "[ \t\n]*(line +[0-9]+)" nil t) 3629 (while (re-search-forward "[ \t\n]*(line +[0-9]+)" nil t)
3542 (put-text-property (match-beginning 0) (match-end 0) 3630 (put-text-property (match-beginning 0) (match-end 0)
3543 'invisible t))) 3631 'invisible t)))
3544 3632
3545 ;; Fontify http and ftp references 3633 ;; Fontify http and ftp references