changeset 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 3a482d346abb
children a7f7c0fa52a6
files lisp/info.el
diffstat 1 files changed, 166 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/info.el	Sun May 23 20:29:44 2004 +0000
+++ b/lisp/info.el	Sun May 23 20:53:42 2004 +0000
@@ -863,9 +863,17 @@
 	      (let ((pos (Info-find-node-in-buffer regexp)))
 		(when pos
 		  (goto-char pos)
-		  (throw 'foo t))
-                ;; No such anchor in tag table or node in tag table or file
-		(error "No such node or anchor: %s" nodename)))
+		  (throw 'foo t)))
+
+              (when (string-match "\\([^.]+\\)\\." nodename)
+                (let (Info-point-loc)
+                  (Info-find-node-2
+                   filename (match-string 1 nodename) no-going-back))
+                (widen)
+                (throw 'foo t))
+
+              ;; No such anchor in tag table or node in tag table or file
+              (error "No such node or anchor: %s" nodename))
 
 	    (Info-select-node)
 	    (goto-char (point-min))
@@ -1075,7 +1083,7 @@
     (goto-char (point-min))
     ;; Remove duplicate headings in the same menu.
     (while (search-forward "\n* Menu:" nil t)
-      (setq limit (save-excursion (search-forward "\n" nil t)))
+      (setq limit (save-excursion (search-forward "\n\^_" nil t)))
       ;; Look for the next heading to unify.
       (while (re-search-forward "^\\(\\w.*\\)\n\\*" limit t)
 	(let ((name (match-string 1))
@@ -1286,7 +1294,8 @@
 	(let ((new-history (list Info-current-file Info-current-node)))
 	  (setq Info-history-list
 		(cons new-history (delete new-history Info-history-list))))
-	(Info-fontify-node)
+	(if (not (eq Info-fontify-maximum-menu-size nil))
+            (Info-fontify-node))
 	(Info-display-images-node)
 	(Info-hide-cookies-node)
 	(run-hooks 'Info-selection-hook)))))
@@ -1646,7 +1655,7 @@
       (let ((inhibit-read-only t))
         (erase-buffer)
         (goto-char (point-min))
-        (insert "\n\nFile: history Node: Top, Up: (dir)\n\n")
+        (insert "\n\^_\nFile: history Node: Top, Up: (dir)\n\n")
         (insert "Recently Visited Nodes\n**********************\n\n")
         (insert "* Menu:\n\n")
         (let ((hl (delete '("history" "Top") Info-history-list)))
@@ -1673,7 +1682,7 @@
             (node-list (Info-build-toc curr-file)))
         (erase-buffer)
         (goto-char (point-min))
-        (insert "\n\nFile: toc Node: Top, Up: (dir)\n\n")
+        (insert "\n\^_\nFile: toc Node: Top, Up: (dir)\n\n")
         (insert "Table of Contents\n*****************\n\n")
         (insert "*Note Top::\n")
         (Info-insert-toc
@@ -1682,7 +1691,7 @@
       (if (not (bobp))
           (let ((Info-hide-note-references 'hide)
                 (Info-fontify-visited-nodes nil))
-            (setq Info-current-node "Top")
+            (setq Info-current-file "toc" Info-current-node "Top")
             (Info-fontify-node)))
       (goto-char (point-min))
       (if (setq p (search-forward (concat "*Note " curr-node ":") nil t))
@@ -1707,16 +1716,18 @@
   (if (equal file "dir")
       (error "Table of contents for Info directory is not supported yet"))
   (with-temp-buffer
-    (let ((default-directory (or (and (stringp file)
-                                      (file-name-directory
-                                       (setq file (Info-find-file file))))
-                                 default-directory))
-          (sections '(("Top" "Top")))
-          nodes subfiles)
-      (while (or file subfiles)
-        (or file (message "Searching subfile %s..." (car subfiles)))
+    (let* ((default-directory (or (and (stringp file)
+                                       (file-name-directory
+                                        (setq file (Info-find-file file))))
+                                  default-directory))
+           (main-file file)
+           (sections '(("Top" "Top")))
+           nodes subfiles)
+      (while (or main-file subfiles)
+        (or main-file (message "Searching subfile %s..." (car subfiles)))
         (erase-buffer)
-        (info-insert-file-contents (or file (car subfiles)))
+        (info-insert-file-contents (or main-file (car subfiles)))
+        (goto-char (point-min))
         (while (and (search-forward "\n\^_\nFile:" nil 'move)
                     (search-forward "Node: " nil 'move))
           (let ((nodename (substring-no-properties (Info-following-node-name)))
@@ -1724,7 +1735,7 @@
                               (point-max)) 2))
                 (section "Top")
                 menu-items)
-            (when (and (not (string-match "\\<index\\>" nodename))
+            (when (and (not (Info-index-node nodename file))
                        (re-search-forward "^\\* Menu:" bound t))
               (forward-line 1)
               (beginning-of-line)
@@ -1756,7 +1767,7 @@
                                     (nreverse menu-items))
                               nodes))
             (goto-char bound)))
-        (if file
+        (if main-file
             (save-excursion
               (goto-char (point-min))
               (if (search-forward "\n\^_\nIndirect:" nil t)
@@ -1765,7 +1776,7 @@
                       (setq subfiles (cons (match-string-no-properties 1)
                                            subfiles)))))
               (setq subfiles (nreverse subfiles)
-                    file nil))
+                    main-file nil))
           (setq subfiles (cdr subfiles))))
       (message "")
       (nreverse nodes))))
@@ -1907,6 +1918,7 @@
 
 (defvar Info-complete-menu-buffer)
 (defvar Info-complete-next-re nil)
+(defvar Info-complete-nodes nil)
 (defvar Info-complete-cache nil)
 
 (defconst Info-node-spec-re
@@ -1920,6 +1932,9 @@
   ;; - `Info-complete-next-re' which, if non-nil, indicates that we should
   ;; also look for menu items in subsequent nodes as long as those
   ;; nodes' names match `Info-complete-next-re'.  This feature is currently
+  ;; not used.
+  ;; - `Info-complete-nodes' which, if non-nil, indicates that we should
+  ;; also look for menu items in these nodes.  This feature is currently
   ;; only used for completion in Info-index.
 
   ;; Note that `Info-complete-menu-buffer' could be current already,
@@ -1943,6 +1958,7 @@
 	  (if (and (equal (nth 0 Info-complete-cache) Info-current-file)
 		   (equal (nth 1 Info-complete-cache) Info-current-node)
 		   (equal (nth 2 Info-complete-cache) Info-complete-next-re)
+		   (equal (nth 5 Info-complete-cache) Info-complete-nodes)
 		   (let ((prev (nth 3 Info-complete-cache)))
 		     (eq t (compare-strings string 0 (length prev)
 					    prev 0 nil t))))
@@ -1955,9 +1971,12 @@
 		    (push (match-string-no-properties 1)
 			  completions))
 		  ;; Check subsequent nodes if applicable.
-		  (and Info-complete-next-re
-		       (setq nextnode (Info-extract-pointer "next" t))
-		       (string-match Info-complete-next-re nextnode)))
+		  (or (and Info-complete-next-re
+		           (setq nextnode (Info-extract-pointer "next" t))
+		           (string-match Info-complete-next-re nextnode))
+		      (and Info-complete-nodes
+		           (setq Info-complete-nodes (cdr Info-complete-nodes)
+		                 nextnode (car Info-complete-nodes)))))
 	      (Info-goto-node nextnode))
 	    ;; Go back to the start node (for the next completion).
 	    (unless (equal Info-current-node orignode)
@@ -1965,7 +1984,8 @@
 	    ;; Update the cache.
 	    (set (make-local-variable 'Info-complete-cache)
 		 (list Info-current-file Info-current-node
-		       Info-complete-next-re string completions)))
+		       Info-complete-next-re string completions
+		       Info-complete-nodes)))
 	  (if action
 	      (all-completions string completions predicate)
 	    (try-completion string completions predicate)))))))
@@ -2034,7 +2054,7 @@
 	    (error "No such item in menu"))
 	(beginning-of-line)
 	(forward-char 2)
-	(Info-extract-menu-node-name)))))
+	(Info-extract-menu-node-name nil (Info-index-node))))))
 
 ;; If COUNT is nil, use the last item in the menu.
 (defun Info-extract-menu-counting (count)
@@ -2049,7 +2069,7 @@
 		(error "Too few items in menu"))
 	  (while (search-forward "\n* " nil t)
 	    nil))
-	(Info-extract-menu-node-name)))))
+	(Info-extract-menu-node-name nil (Info-index-node))))))
 
 (defun Info-nth-menu-item ()
   "Go to the node of the Nth menu item.
@@ -2076,7 +2096,7 @@
     ;; move forward until we can't go any farther.
     (while (Info-forward-node t t) nil)
     ;; Then keep moving down to last subnode, unless we reach an index.
-    (while (and (not (string-match "\\<index\\>" Info-current-node))
+    (while (and (not (Info-index-node))
 		(save-excursion (search-forward "\n* Menu:" nil t)))
       (Info-goto-node (Info-extract-menu-counting nil)))))
 
@@ -2092,7 +2112,7 @@
     ;;     3. next node is up and next
     (cond ((and (not not-down)
 		(save-excursion (search-forward "\n* menu:" nil t))
-		(not (string-match "\\<index\\>" Info-current-node)))
+		(not (Info-index-node)))
 	   (Info-goto-node (Info-extract-menu-counting 1))
 	   t)
 	  ((save-excursion (search-backward "next:" nil t))
@@ -2130,7 +2150,7 @@
 	   ;; go down to find the last subnode*.
 	   (Info-prev)
 	   (let (Info-history)
-	     (while (and (not (string-match "\\<index\\>" Info-current-node))
+	     (while (and (not (Info-index-node))
 			 (save-excursion (search-forward "\n* Menu:" nil t)))
 	       (Info-goto-node (Info-extract-menu-counting nil)))))
 	  (t
@@ -2321,24 +2341,96 @@
 	(if recur
 	    (error "No cross references in this node")
 	  (Info-prev-reference t)))))
+
+(defvar Info-index-nodes nil
+  "Alist of cached index node names of visited Info files.
+Each element has the form (INFO-FILE INDEX-NODE-NAMES-LIST).")
+
+(defun Info-index-nodes (&optional file)
+  "Return a list of names of all index nodes in Info FILE.
+If FILE is omitted, it defaults to the current Info file.
+First look in a list of cached index node names.  Then scan Info file
+and its subfiles for nodes with index cookie.  Then try index nodes
+starting from the first node in the top level menu whose name
+contains the word \"Index\", plus any immediately following nodes
+whose names also contain the word \"Index\"."
+  (or file (setq file Info-current-file))
+  (or (assoc file Info-index-nodes)
+      ;; Skip virtual Info files
+      (member file '("dir" "history" "toc" "apropos"))
+      ;; Find nodes with index cookie
+      (let* ((default-directory (or (and (stringp file)
+                                         (file-name-directory
+                                          (setq file (Info-find-file file))))
+                                    default-directory))
+             (main-file file)
+             (Info-fontify-maximum-menu-size nil)
+             subfiles nodes node Info-history Info-history-list)
+        (with-temp-buffer
+          (while (or main-file subfiles)
+            (erase-buffer)
+            (info-insert-file-contents (or main-file (car subfiles)))
+            (goto-char (point-min))
+            (while (search-forward "\0\10[index\0\10]" nil 'move)
+              (save-excursion
+                (re-search-backward "^\^_")
+                (search-forward "Node: ")
+                (setq nodes (cons (Info-following-node-name) nodes))))
+            (if main-file
+                (save-excursion
+                  (goto-char (point-min))
+                  (if (search-forward "\n\^_\nIndirect:" nil t)
+                      (let ((bound (save-excursion (search-forward "\n\^_" nil t))))
+                        (while (re-search-forward "^\\(.*\\): [0-9]+$" bound t)
+                          (setq subfiles (cons (match-string-no-properties 1)
+                                               subfiles)))))
+                  (setq subfiles (nreverse subfiles)
+                        main-file nil))
+              (setq subfiles (cdr subfiles)))))
+        (if nodes
+            (setq nodes (nreverse nodes)
+                  Info-index-nodes (cons (cons file nodes) Info-index-nodes)))
+        nodes)
+      ;; Find nodes with string "Index" in node names
+      (let ((Info-fontify-maximum-menu-size nil)
+            (case-fold-search t)
+            nodes node Info-history Info-history-list)
+        (with-temp-buffer
+          (Info-mode)
+          (Info-find-node file "Top")
+          (when (and (search-forward "\n* menu:" nil t)
+                     (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t))
+            (goto-char (match-beginning 1))
+            (setq nodes (list (Info-extract-menu-node-name)))
+            (Info-goto-node (car nodes))
+            (while (and (setq node (Info-extract-pointer "next" t))
+                        (string-match "\\<Index\\>" node))
+              (setq nodes (cons node nodes))
+              (Info-goto-node node))))
+        (if nodes
+            (setq nodes (nreverse nodes)
+                  Info-index-nodes (cons (cons file nodes) Info-index-nodes)))
+        nodes)
+      ;; Info file has no index nodes
+      (setq Info-index-nodes (cons (cons file nil)
+                                   Info-index-nodes)))
+  (cdr (assoc file Info-index-nodes)))
+
+(defun Info-index-node (&optional node file)
+  "Return non-nil value if NODE is an index node.
+If NODE is nil, check the current Info node.
+If FILE is nil, check the current Info file."
+  (member (or node Info-current-node) (Info-index-nodes file)))
 
 (defun Info-goto-index ()
-  (Info-goto-node "Top")
-  (or (search-forward "\n* menu:" nil t)
-      (error "No index"))
-  (or (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t)
-      (error "No index"))
-  (goto-char (match-beginning 1))
-  ;; Protect Info-history so that the current node (Top) is not added to it.
-  (let ((Info-history nil))
-    (Info-goto-node (Info-extract-menu-node-name))))
+  "Go to the first index node."
+  (let ((node (car (Info-index-nodes))))
+    (or node (error "No index"))
+    (Info-goto-node node)))
 
 ;;;###autoload
 (defun Info-index (topic)
   "Look up a string TOPIC in the index for this file.
-The index is defined as the first node in the top level menu whose
-name contains the word \"Index\", plus any immediately following
-nodes whose names also contain the word \"Index\".
 If there are no exact matches to the specified topic, this chooses
 the first match which is a case-insensitive substring of a topic.
 Use the \\<Info-mode-map>\\[Info-index-next] command to see the other matches.
@@ -2346,7 +2438,8 @@
   (interactive
    (list
     (let ((Info-complete-menu-buffer (clone-buffer))
-	  (Info-complete-next-re "\\<Index\\>"))
+	  (Info-complete-nodes (Info-index-nodes))
+	  (Info-history-list nil))
       (if (equal Info-current-file "dir")
 	  (error "The Info directory node has no index; use m to select a manual"))
       (unwind-protect
@@ -2359,7 +2452,8 @@
   (let ((orignode Info-current-node)
 	(pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
 			 (regexp-quote topic)))
-	node
+	node (nodes (Info-index-nodes))
+	(ohist-list Info-history-list)
 	(case-fold-search t))
     (Info-goto-index)
     (or (equal topic "")
@@ -2381,8 +2475,7 @@
 			      (string-to-number (concat "0"
 							(match-string 3))))
 			matches))
-		(and (setq node (Info-extract-pointer "next" t))
-		     (string-match "\\<Index\\>" node)))
+		(setq nodes (cdr nodes) node (car nodes)))
 	    (Info-goto-node node))
 	  (or matches
 	      (progn
@@ -2392,6 +2485,7 @@
 	  (while (setq found (assoc topic matches))
 	    (setq exact (cons found exact)
 		  matches (delq found matches)))
+          (setq Info-history-list ohist-list)
 	  (setq Info-index-alternatives (nconc exact (nreverse matches)))
 	  (Info-index-next 0)))))
 
@@ -2454,10 +2548,8 @@
 	  (ohist-list Info-history-list)
 	  (current-node Info-current-node)
 	  (current-file Info-current-file)
-	  manuals matches node)
-      (let ((Info-fontify-maximum-menu-size 0)
-	    Info-use-header-lines
-	    Info-hide-note-references)
+	  manuals matches node nodes)
+      (let ((Info-fontify-maximum-menu-size nil))
 	(Info-directory)
 	(message "Searching indices...")
 	(goto-char (point-min))
@@ -2466,25 +2558,22 @@
 	  (add-to-list 'manuals (match-string 1)))
 	(dolist (manual manuals)
 	  (message "Searching %s" manual)
-	  (condition-case nil
-	      (save-excursion
-		(Info-find-node manual "Top")
-		(when (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t)
-		  (goto-char (match-beginning 1))
-		  (Info-goto-node (Info-extract-menu-node-name))
-		  (while
-		      (progn
-			(goto-char (point-min))
-			(while (re-search-forward pattern nil t)
-			  (add-to-list 'matches
-				       (list manual
-					     (match-string-no-properties 1)
-					     (match-string-no-properties 2)
-					     (match-string-no-properties 3))))
-			(and (setq node (Info-extract-pointer "next" t))
-			     (string-match "\\<Index\\>" node)))
-		    (Info-goto-node node))))
-	    (error nil))))
+	  (if (setq nodes (Info-index-nodes (Info-find-file manual)))
+              (condition-case nil
+                  (save-excursion
+                    (Info-find-node manual (car nodes))
+                    (while
+                        (progn
+                          (goto-char (point-min))
+                          (while (re-search-forward pattern nil t)
+                            (add-to-list 'matches
+                                         (list manual
+                                               (match-string-no-properties 1)
+                                               (match-string-no-properties 2)
+                                               (match-string-no-properties 3))))
+                          (setq nodes (cdr nodes) node (car nodes)))
+                      (Info-goto-node node)))
+                (error nil)))))
       (Info-goto-node (concat "(" current-file ")" current-node))
       (setq Info-history ohist
 	    Info-history-list ohist-list)
@@ -2493,7 +2582,7 @@
 	  (message "No matches found")
 	(with-current-buffer (get-buffer-create " *info-apropos*")
 	  (erase-buffer)
-	  (insert "\n\nFile: apropos, Node: Index, Up: (dir)\n")
+	  (insert "\n\^_\nFile: apropos, Node: Index, Up: (dir)\n")
 	  (insert "* Menu: \nNodes whose indices contain \"" string "\"\n\n")
 	  (dolist (entry matches)
 	    (insert
@@ -2629,8 +2718,7 @@
      ((Info-get-token (point) "\\* +" "\\* +\\(.*\\): ")
       (beginning-of-line)
       (forward-char 2)
-      (setq node (Info-extract-menu-node-name
-                  nil (string-match "\\<index\\>" Info-current-node)))
+      (setq node (Info-extract-menu-node-name nil (Info-index-node)))
       (Info-goto-node node fork))
      ((setq node (Info-get-token (point) "Up: " "Up: \\([^,\n\t]*\\)"))
       (Info-goto-node node fork))
@@ -3072,8 +3160,9 @@
     ;; Bind Info-history to nil, to prevent the index nodes from
     ;; getting into the node history.
     (let ((Info-history nil)
-	  node)
-      (Info-goto-node (Info-extract-menu-node-name))
+          (Info-history-list nil)
+	  node (nodes (Info-index-nodes)))
+      (Info-goto-node (car nodes))
       (while
 	  (progn
 	    (goto-char (point-min))
@@ -3083,8 +3172,7 @@
 				(match-string-no-properties 2)
 				0)
 			  where)))
-	    (and (setq node (Info-extract-pointer "next" t))
-		 (string-match "\\<Index\\>" node)))
+	    (and (setq nodes (cdr nodes) node (car nodes))))
 	(Info-goto-node node)))
     where))
 
@@ -3111,7 +3199,7 @@
 	  ;; Bind Info-history to nil, to prevent the last Index node
 	  ;; visited by Info-find-emacs-command-nodes from being
 	  ;; pushed onto the history.
-	  (let ((Info-history nil))
+	  (let ((Info-history nil) (Info-history-list nil))
 	    (Info-find-node (car (car where))
 			    (car (cdr (car where)))))
 	  (if (> num-matches 1)
@@ -3448,7 +3536,7 @@
       (goto-char (point-min))
       (when (and (or not-fontified-p fontify-visited-p)
                  (search-forward "\n* Menu:" nil t)
-                 (not (string-match "\\<Index\\>" Info-current-node))
+                 (not (Info-index-node))
                  ;; Don't take time to annotate huge menus
                  (< (- (point-max) (point)) Info-fontify-maximum-menu-size))
         (let ((n 0)
@@ -3537,7 +3625,7 @@
 
       ;; Hide index line numbers
       (goto-char (point-min))
-      (when (and not-fontified-p (string-match "\\<Index\\>" Info-current-node))
+      (when (and not-fontified-p (Info-index-node))
         (while (re-search-forward "[ \t\n]*(line +[0-9]+)" nil t)
           (put-text-property (match-beginning 0) (match-end 0)
                              'invisible t)))