aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1997-02-08 18:34:21 +0000
committerRichard M. Stallman1997-02-08 18:34:21 +0000
commitc5fe2ff17b803e7dc414cc58546fb531d4f2567b (patch)
tree0c4f1e8f682c4448b8f1ee6392e95a1d56671708
parent9317a85d0f549f88d1bd5797d420a9b7fe40d00f (diff)
downloademacs-c5fe2ff17b803e7dc414cc58546fb531d4f2567b.tar.gz
emacs-c5fe2ff17b803e7dc414cc58546fb531d4f2567b.zip
Handle multiple Info buffers.
(Info-tag-table-marker): Initialize to nil. (Info-tag-table-buffer): New variable. (Info-find-node): Don't switch buffers if already in Info mode. Use Info-tag-table-buffer to support multiple Info buffers. (Info-read-subfile): Don't switch to *info* buffer. (Info-build-node-completions): Handle buffer local bindings for Info-tag-table-marker. (Info-search): Add a save-excursion. (Info-mode): Make Info-tag-table-buffer buffer-local. Make a different marker in Info-tag-table-marker for each buffer. (Info-kill-buffer): New function, on kill-buffer-hook.
-rw-r--r--lisp/info.el136
1 files changed, 87 insertions, 49 deletions
diff --git a/lisp/info.el b/lisp/info.el
index 63076dfa93b..bf25a8522d0 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -114,10 +114,13 @@ or nil if current info file is not split into subfiles.")
114(defvar Info-current-node nil 114(defvar Info-current-node nil
115 "Name of node that Info is now looking at, or nil.") 115 "Name of node that Info is now looking at, or nil.")
116 116
117(defvar Info-tag-table-marker (make-marker) 117(defvar Info-tag-table-marker nil
118 "Marker pointing at beginning of current Info file's tag table. 118 "Marker pointing at beginning of current Info file's tag table.
119Marker points nowhere if file has no tag table.") 119Marker points nowhere if file has no tag table.")
120 120
121(defvar Info-tag-table-buffer nil
122 "Buffer used for indirect tag tables.")
123
121(defvar Info-current-file-completions nil 124(defvar Info-current-file-completions nil
122 "Cached completion list for current Info file.") 125 "Cached completion list for current Info file.")
123 126
@@ -301,7 +304,7 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
301 (cons (list Info-current-file Info-current-node (point)) 304 (cons (list Info-current-file Info-current-node (point))
302 Info-history))) 305 Info-history)))
303 ;; Go into info buffer. 306 ;; Go into info buffer.
304 (pop-to-buffer "*info*") 307 (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*"))
305 (buffer-disable-undo (current-buffer)) 308 (buffer-disable-undo (current-buffer))
306 (or (eq major-mode 'Info-mode) 309 (or (eq major-mode 'Info-mode)
307 (Info-mode)) 310 (Info-mode))
@@ -324,12 +327,12 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
324 (setq default-directory (file-name-directory filename))) 327 (setq default-directory (file-name-directory filename)))
325 (set-buffer-modified-p nil) 328 (set-buffer-modified-p nil)
326 ;; See whether file has a tag table. Record the location if yes. 329 ;; See whether file has a tag table. Record the location if yes.
327 (set-marker Info-tag-table-marker nil)
328 (goto-char (point-max)) 330 (goto-char (point-max))
329 (forward-line -8) 331 (forward-line -8)
330 ;; Use string-equal, not equal, to ignore text props. 332 ;; Use string-equal, not equal, to ignore text props.
331 (or (string-equal nodename "*") 333 (if (not (or (string-equal nodename "*")
332 (not (search-forward "\^_\nEnd tag table\n" nil t)) 334 (not
335 (search-forward "\^_\nEnd tag table\n" nil t))))
333 (let (pos) 336 (let (pos)
334 ;; We have a tag table. Find its beginning. 337 ;; We have a tag table. Find its beginning.
335 ;; Is this an indirect file? 338 ;; Is this an indirect file?
@@ -340,16 +343,21 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
340 (looking-at "(Indirect)\n")) 343 (looking-at "(Indirect)\n"))
341 ;; It is indirect. Copy it to another buffer 344 ;; It is indirect. Copy it to another buffer
342 ;; and record that the tag table is in that buffer. 345 ;; and record that the tag table is in that buffer.
343 (save-excursion 346 (let ((buf (current-buffer))
344 (let ((buf (current-buffer))) 347 (tagbuf
345 (set-buffer (get-buffer-create " *info tag table*")) 348 (or Info-tag-table-buffer
349 (generate-new-buffer " *info tag table*"))))
350 (setq Info-tag-table-buffer tagbuf)
351 (save-excursion
352 (set-buffer tagbuf)
346 (buffer-disable-undo (current-buffer)) 353 (buffer-disable-undo (current-buffer))
347 (setq case-fold-search t) 354 (setq case-fold-search t)
348 (erase-buffer) 355 (erase-buffer)
349 (insert-buffer-substring buf) 356 (insert-buffer-substring buf))
350 (set-marker Info-tag-table-marker 357 (set-marker Info-tag-table-marker
351 (match-end 0)))) 358 (match-end 0) tagbuf))
352 (set-marker Info-tag-table-marker pos)))) 359 (set-marker Info-tag-table-marker pos)))
360 (set-marker Info-tag-table-marker nil))
353 (setq Info-current-file 361 (setq Info-current-file
354 (if (eq filename t) "dir" filename)))) 362 (if (eq filename t) "dir" filename))))
355 ;; Use string-equal, not equal, to ignore text props. 363 ;; Use string-equal, not equal, to ignore text props.
@@ -364,18 +372,28 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
364 ;; read the proper subfile into this buffer. 372 ;; read the proper subfile into this buffer.
365 (if (marker-position Info-tag-table-marker) 373 (if (marker-position Info-tag-table-marker)
366 (save-excursion 374 (save-excursion
367 (set-buffer (marker-buffer Info-tag-table-marker)) 375 (let ((m Info-tag-table-marker)
368 (goto-char Info-tag-table-marker) 376 found found-mode)
369 (if (re-search-forward regexp nil t) 377 (save-excursion
370 (progn 378 (set-buffer (marker-buffer m))
371 (setq guesspos (read (current-buffer))) 379 (goto-char m)
372 ;; If this is an indirect file, 380 (beginning-of-line) ;so re-search will work.
373 ;; determine which file really holds this node 381 (setq found (re-search-forward regexp nil t))
374 ;; and read it in. 382 (if found
375 (if (not (eq (current-buffer) (get-buffer "*info*"))) 383 (setq guesspos (read (current-buffer))))
376 (setq guesspos 384 (setq found-mode major-mode))
377 (Info-read-subfile guesspos)))) 385 (if found
378 (error "No such node: %s" nodename)))) 386 (progn
387 ;; If this is an indirect file, determine
388 ;; which file really holds this node and
389 ;; read it in.
390 (if (not (eq found-mode 'Info-mode))
391 ;; Note that the current buffer must be
392 ;; the *info* buffer on entry to
393 ;; Info-read-subfile. Thus the hackery
394 ;; above.
395 (setq guesspos (Info-read-subfile guesspos))))
396 (error "No such node: %s" nodename)))))
379 (goto-char (max (point-min) (- guesspos 1000))) 397 (goto-char (max (point-min) (- guesspos 1000)))
380 ;; Now search from our advised position (or from beg of buffer) 398 ;; Now search from our advised position (or from beg of buffer)
381 ;; to find the actual node. 399 ;; to find the actual node.
@@ -548,6 +566,8 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
548 (setq Info-dir-contents (buffer-string))) 566 (setq Info-dir-contents (buffer-string)))
549 (setq default-directory Info-dir-contents-directory)) 567 (setq default-directory Info-dir-contents-directory))
550 568
569;; Note that on entry to this function the current-buffer must be the
570;; *info* buffer; not the info tags buffer.
551(defun Info-read-subfile (nodepos) 571(defun Info-read-subfile (nodepos)
552 ;; NODEPOS is either a position (in the Info file as a whole, 572 ;; NODEPOS is either a position (in the Info file as a whole,
553 ;; not relative to a subfile) or the name of a subfile. 573 ;; not relative to a subfile) or the name of a subfile.
@@ -577,7 +597,8 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
577 (forward-line 1))))) 597 (forward-line 1)))))
578 (setq lastfilename nodepos) 598 (setq lastfilename nodepos)
579 (setq lastfilepos 0)) 599 (setq lastfilepos 0))
580 (set-buffer (get-buffer "*info*")) 600 ;; Assume previous buffer is in Info-mode.
601 ;; (set-buffer (get-buffer "*info*"))
581 (or (equal Info-current-subfile lastfilename) 602 (or (equal Info-current-subfile lastfilename)
582 (let ((buffer-read-only nil)) 603 (let ((buffer-read-only nil))
583 (setq buffer-file-name nil) 604 (setq buffer-file-name nil)
@@ -686,10 +707,10 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
686 (save-excursion 707 (save-excursion
687 (save-restriction 708 (save-restriction
688 (if (marker-buffer Info-tag-table-marker) 709 (if (marker-buffer Info-tag-table-marker)
689 (progn 710 (let ((marker Info-tag-table-marker))
690 (set-buffer (marker-buffer Info-tag-table-marker)) 711 (set-buffer (marker-buffer marker))
691 (widen) 712 (widen)
692 (goto-char Info-tag-table-marker) 713 (goto-char marker)
693 (while (re-search-forward "\nNode: \\(.*\\)\177" nil t) 714 (while (re-search-forward "\nNode: \\(.*\\)\177" nil t)
694 (setq compl 715 (setq compl
695 (cons (list (buffer-substring (match-beginning 1) 716 (cons (list (buffer-substring (match-beginning 1)
@@ -747,27 +768,28 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
747 (if (not found) ;can only happen in subfile case -- else would have erred 768 (if (not found) ;can only happen in subfile case -- else would have erred
748 (unwind-protect 769 (unwind-protect
749 (let ((list ())) 770 (let ((list ()))
750 (set-buffer (marker-buffer Info-tag-table-marker)) 771 (save-excursion
751 (goto-char (point-min)) 772 (set-buffer (marker-buffer Info-tag-table-marker))
752 (search-forward "\n\^_\nIndirect:")
753 (save-restriction
754 (narrow-to-region (point)
755 (progn (search-forward "\n\^_")
756 (1- (point))))
757 (goto-char (point-min)) 773 (goto-char (point-min))
758 (search-forward (concat "\n" osubfile ": ")) 774 (search-forward "\n\^_\nIndirect:")
759 (beginning-of-line) 775 (save-restriction
760 (while (not (eobp)) 776 (narrow-to-region (point)
761 (re-search-forward "\\(^.*\\): [0-9]+$") 777 (progn (search-forward "\n\^_")
762 (goto-char (+ (match-end 1) 2)) 778 (1- (point))))
763 (setq list (cons (cons (read (current-buffer)) 779 (goto-char (point-min))
764 (buffer-substring (match-beginning 1) 780 (search-forward (concat "\n" osubfile ": "))
765 (match-end 1))) 781 (beginning-of-line)
766 list)) 782 (while (not (eobp))
767 (goto-char (1+ (match-end 0)))) 783 (re-search-forward "\\(^.*\\): [0-9]+$")
768 (setq list (nreverse list) 784 (goto-char (+ (match-end 1) 2))
769 current (car (car list)) 785 (setq list (cons (cons (read (current-buffer))
770 list (cdr list))) 786 (buffer-substring
787 (match-beginning 1) (match-end 1)))
788 list))
789 (goto-char (1+ (match-end 0))))
790 (setq list (nreverse list)
791 current (car (car list))
792 list (cdr list))))
771 (while list 793 (while list
772 (message "Searching subfile %s..." (cdr (car list))) 794 (message "Searching subfile %s..." (cdr (car list)))
773 (Info-read-subfile (car (car list))) 795 (Info-read-subfile (car (car list)))
@@ -809,7 +831,7 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
809 831
810;; Return the node name in the buffer following point. 832;; Return the node name in the buffer following point.
811;; ALLOWEDCHARS, if non-nil, goes within [...] to make a regexp 833;; ALLOWEDCHARS, if non-nil, goes within [...] to make a regexp
812;; saying which chas may appear in the node name. 834;; saying which chars may appear in the node name.
813(defun Info-following-node-name (&optional allowedchars) 835(defun Info-following-node-name (&optional allowedchars)
814 (skip-chars-forward " \t") 836 (skip-chars-forward " \t")
815 (buffer-substring-no-properties 837 (buffer-substring-no-properties
@@ -1735,6 +1757,9 @@ Advanced commands:
1735 (make-local-variable 'Info-current-subfile) 1757 (make-local-variable 'Info-current-subfile)
1736 (make-local-variable 'Info-current-node) 1758 (make-local-variable 'Info-current-node)
1737 (make-local-variable 'Info-tag-table-marker) 1759 (make-local-variable 'Info-tag-table-marker)
1760 (setq Info-tag-table-marker (make-marker))
1761 (make-local-variable 'Info-tag-table-buffer)
1762 (setq Info-tag-table-buffer nil)
1738 (make-local-variable 'Info-history) 1763 (make-local-variable 'Info-history)
1739 (make-local-variable 'Info-index-alternatives) 1764 (make-local-variable 'Info-index-alternatives)
1740 (if (memq (framep (selected-frame)) '(x pc w32)) 1765 (if (memq (framep (selected-frame)) '(x pc w32))
@@ -1874,6 +1899,8 @@ the variable `Info-file-list-for-emacs'."
1874 ;; Get Info running, and pop to it in another window. 1899 ;; Get Info running, and pop to it in another window.
1875 (save-window-excursion 1900 (save-window-excursion
1876 (info)) 1901 (info))
1902 ;; FIXME It would be cool if this could use a buffer other
1903 ;; than *info*.
1877 (pop-to-buffer "*info*") 1904 (pop-to-buffer "*info*")
1878 (Info-find-node (car (car where)) 1905 (Info-find-node (car (car where))
1879 (car (cdr (car where)))) 1906 (car (cdr (car where))))
@@ -1962,6 +1989,17 @@ The alist key is the character the title is underlined with (?*, ?= or ?-).")
1962 (put-text-property (match-beginning 1) (match-end 1) 1989 (put-text-property (match-beginning 1) (match-end 1)
1963 'mouse-face 'highlight)))) 1990 'mouse-face 'highlight))))
1964 (set-buffer-modified-p nil)))) 1991 (set-buffer-modified-p nil))))
1992
1993
1994;; When an Info buffer is killed, make sure the associated tags buffer
1995;; is killed too.
1996(defun Info-kill-buffer ()
1997 (and (eq major-mode 'Info-mode)
1998 Info-tag-table-buffer
1999 (kill-buffer Info-tag-table-buffer)))
2000
2001(add-hook 'kill-buffer-hook 'Info-kill-buffer)
2002
1965 2003
1966(provide 'info) 2004(provide 'info)
1967 2005