# HG changeset patch # User Juri Linkov # Date 1085345622 0 # Node ID 450a4292b3b7f6a2ac60a88f33486d880cd2ad36 # Parent 3a482d346abbd2c5aa04f04a2e582d35b4774d6a (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 ^_. diff -r 3a482d346abb -r 450a4292b3b7 lisp/info.el --- 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 "\\" 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 "\\" 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 "\\" 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 "\\" 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\\* \\(.*\\\\)" 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 "\\" 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\\* \\(.*\\\\)" 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-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 "\\")) + (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 "\\" 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\\* \\(.*\\\\)" 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 "\\" 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 "\\" 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 "\\" 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 "\\" 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 "\\" 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)))