diff options
| author | Richard M. Stallman | 1997-02-08 18:34:21 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-02-08 18:34:21 +0000 |
| commit | c5fe2ff17b803e7dc414cc58546fb531d4f2567b (patch) | |
| tree | 0c4f1e8f682c4448b8f1ee6392e95a1d56671708 | |
| parent | 9317a85d0f549f88d1bd5797d420a9b7fe40d00f (diff) | |
| download | emacs-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.el | 136 |
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. |
| 119 | Marker points nowhere if file has no tag table.") | 119 | Marker 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 | ||