;;; Code:
+(eval-when-compile (require 'jka-compr))
+
(defgroup info nil
"Info subsystem"
:group 'help
(defvar Info-current-file nil
"Info file that Info is now looking at, or nil.
This is the name that was specified in Info, not the actual file name.
-It doesn't contain directory names or file name extensions added by Info.")
+It doesn't contain directory names or file name extensions added by Info.
+Can also be t when using `Info-on-current-buffer'.")
(defvar Info-current-subfile nil
"Info subfile that is actually in the *info* buffer now,
(if (eq system-type 'ms-dos)
'( (".gz" . "gunzip")
(".z" . "gunzip")
+ (".bz2" . "bzip2 -dc")
(".inz" . "gunzip")
(".igz" . "gunzip")
(".info.Z" . "gunzip")
(".info.Y". "unyabba")
(".info.gz". "gunzip")
(".info.z". "gunzip")
+ (".info.bz2" . "bzip2 -dc")
(".info". nil)
("-info.Z". "uncompress")
("-info.Y". "unyabba")
("-info.gz". "gunzip")
+ ("-info.bz2" . "bzip2 -dc")
("-info.z". "gunzip")
("-info". nil)
("/index.Z". "uncompress")
("/index.Y". "unyabba")
("/index.gz". "gunzip")
("/index.z". "gunzip")
+ ("/index.bz2". "bzip2 -dc")
("/index". nil)
(".Z". "uncompress")
(".Y". "unyabba")
(".gz". "gunzip")
(".z". "gunzip")
+ (".bz2" . "bzip2 -dc")
("". nil)))
"List of file name suffixes and associated decoding commands.
Each entry should be (SUFFIX . STRING); the file is given to
;; Uninstalled, builddir == srcdir
(setq alternative source))
(if (or (member alternative Info-default-directory-list)
- (not (file-exists-p alternative))
;; On DOS/NT, we use movable executables always,
;; and we must always find the Info dir at run time.
(if (memq system-type '(ms-dos windows-nt))
;; only if we used it for exec-directory also.
(not (string= exec-directory
(expand-file-name "lib-src/"
- installation-directory)))))
+ installation-directory))))
+ (not (file-exists-p alternative)))
Info-default-directory-list
;; `alternative' contains the Info files that came with this
;; version, so we should look there first. `Info-insert-dir'
"Enter Info, the documentation browser.
Optional argument FILE specifies the file to examine;
the default is the top-level directory of Info.
+Called from a program, FILE may specify an Info node of the form
+`(FILENAME)NODENAME'.
In interactive use, a prefix argument directs this command
to read a file name from the minibuffer.
in all the directories in that path."
(interactive (if current-prefix-arg
(list (read-file-name "Info file name: " nil nil t))))
- (info-initialize)
(if file
(progn
(pop-to-buffer "*info*")
;; no-going-back is non-nil if recovering from an error in this function;
;; it says do not attempt further (recursive) error recovery.
(defun Info-find-node (filename nodename &optional no-going-back)
+ (info-initialize)
;; Convert filename to lower case if not found as specified.
;; Expand it.
- (if filename
+ (if (stringp filename)
(let (temp temp-downcase found)
(setq filename (substitute-in-file-name filename))
(if (string= (downcase filename) "dir")
Info-history)))
;; Go into info buffer.
(or (eq major-mode 'Info-mode) (pop-to-buffer "*info*"))
+ (Info-find-node-2 filename nodename no-going-back))
+
+(defun Info-on-current-buffer (&optional nodename)
+ "Use the `Info-mode' to browse the current info buffer.
+If a prefix arg is provided, it queries for the NODENAME which
+else defaults to `Top'."
+ (interactive
+ (list (if current-prefix-arg
+ (completing-read "Node name: " (Info-build-node-completions)
+ nil t "Top")
+ "Top")))
+ (Info-mode)
+ (set (make-local-variable 'Info-current-file) t)
+ (Info-find-node-2 nil nodename))
+
+(defun Info-find-node-2 (filename nodename &optional no-going-back)
(buffer-disable-undo (current-buffer))
(or (eq major-mode 'Info-mode)
(Info-mode))
(goto-char (setq anchorpos guesspos))
;; Else we may have a node, which we search for:
- (goto-char (max (point-min)
- (- (byte-to-position guesspos) 1000)))
+ (let ((guesschar
+ (or (byte-to-position guesspos)
+ (if (< (position-bytes (point-max)) guesspos)
+ (point-max)
+ (point-min)))))
+ (goto-char (max (point-min)
+ (- guesschar 1000))))
;; Now search from our advised position
;; (or from beg of buffer)
;; to find the actual node.
(concat
" Info: ("
(if Info-current-file
- (file-name-nondirectory Info-current-file)
+ (file-name-nondirectory (if (stringp Info-current-file)
+ Info-current-file
+ (or buffer-file-name "")))
"")
")"
(or Info-current-node ""))))
;; Go to an info node specified with a filename-and-nodename string
;; of the sort that is found in pointers in nodes.
-(defun Info-goto-node (nodename)
- "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME."
- (interactive (list (Info-read-node-name "Goto node: ")))
+(defun Info-goto-node (nodename &optional fork)
+ "Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME.
+If FORK is non-nil, show the node in a new info buffer.
+If FORK is a string, it is the name to use for the new buffer."
+ (interactive (list (Info-read-node-name "Goto node: ") current-prefix-arg))
+ (info-initialize)
+ (if fork
+ (set-buffer
+ (clone-buffer (concat "*info-" (if (stringp fork) fork nodename) "*") t)))
(let (filename)
(string-match "\\s *\\((\\s *\\([^\t)]*\\)\\s *)\\s *\\|\\)\\(.*\\)"
nodename)
(cons (list (buffer-substring (match-beginning 1)
(match-end 1)))
compl))))))))
+ (setq compl (cons '("*") compl))
(setq Info-current-file-completions compl))))
\f
(defun Info-restore-point (hl)
If SAME-FILE is non-nil, do not move to a different Info file."
(interactive)
(let ((node (Info-extract-pointer "up")))
- (and same-file
+ (and (or same-file (not (stringp Info-current-file)))
(string-match "^(" node)
(error "Up node is in another Info file"))
(Info-goto-node node))
nil t))))))
-(defun Info-menu (menu-item)
+(defun Info-menu (menu-item &optional fork)
"Go to node for menu item named (or abbreviated) NAME.
Completion is allowed, and the menu item point is on is the default."
(interactive
(setq item default)
;; ask again
(setq item nil))))
- (list item))))
+ (list item current-prefix-arg))))
;; there is a problem here in that if several menu items have the same
;; name you can only go to the node of the first with this command.
- (Info-goto-node (Info-extract-menu-item menu-item)))
+ (Info-goto-node (Info-extract-menu-item menu-item) (if fork menu-item)))
(defun Info-extract-menu-item (menu-item)
(setq menu-item (regexp-quote menu-item))
(define-key Info-mode-map "s" 'Info-search)
;; For consistency with Rmail.
(define-key Info-mode-map "\M-s" 'Info-search)
+ (define-key Info-mode-map "\M-n" 'clone-buffer)
(define-key Info-mode-map "t" 'Info-top-node)
(define-key Info-mode-map "u" 'Info-up)
(define-key Info-mode-map "," 'Info-index-next)
;; This is for the sake of the invisible text we use handling titles.
(make-local-variable 'line-move-ignore-invisible)
(setq line-move-ignore-invisible t)
+ (add-hook (make-local-hook 'clone-buffer-hook) 'Info-clone-buffer-hook nil t)
(Info-set-mode-line)
(run-hooks 'Info-mode-hook))
+(defun Info-clone-buffer-hook ()
+ (when (bufferp Info-tag-table-buffer)
+ (setq Info-tag-table-buffer
+ (with-current-buffer Info-tag-table-buffer (clone-buffer)))
+ (let ((m Info-tag-table-marker))
+ (when (and (markerp m) (marker-position m))
+ (setq Info-tag-table-marker
+ (with-current-buffer Info-tag-table-buffer
+ (copy-marker (marker-position m))))))))
+
(defvar Info-edit-map nil
"Local keymap used within `e' command of Info.")
(if Info-edit-map
(message "Tags may have changed. Use Info-tagify if necessary")))
\f
(defvar Info-file-list-for-emacs
- '("ediff" "forms" "gnus" "info" ("mh" . "mh-e") "sc")
+ '("ediff" "forms" "gnus" "info" ("mh" . "mh-e") "sc" "message"
+ ("dired" . "dired-x") ("c" . "ccmode") "viper")
"List of Info files that describe Emacs commands.
An element can be a file name, or a list of the form (PREFIX . FILE)
where PREFIX is a name prefix and FILE is the file to look in.