;; info.el --- info package for Emacs
-;; Copyright (C) 1985-1986, 1992-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2012 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: help
;;; Code:
-(eval-when-compile (require 'cl))
-
(defgroup info nil
"Info subsystem."
:group 'help
"Face for Info nodes in a node header."
:group 'info)
+;; This is a defcustom largely so that we can get the benefit
+;; of custom-initialize-delay. Perhaps it would work to make it a
+;; defvar and explicitly give it a standard-value property, and
+;; call custom-initialize-delay on it.
+;; The progn forces the autoloader to include the whole thing, not
+;; just an abbreviated version.
+;;;###autoload
+(progn
+(defcustom Info-default-directory-list
+ (let* ((config-dir
+ (file-name-as-directory
+ ;; Self-contained NS build with info/ in the app-bundle.
+ (or (and (featurep 'ns)
+ (let ((dir (expand-file-name "../info" data-directory)))
+ (if (file-directory-p dir) dir)))
+ configure-info-directory)))
+ (prefixes
+ ;; Directory trees in which to look for info subdirectories
+ (prune-directory-list '("/usr/local/" "/usr/" "/opt/" "/")))
+ (suffixes
+ ;; Subdirectories in each directory tree that may contain info
+ ;; directories. Most of these are rather outdated.
+ ;; It ought to be fine to stop checking the "emacs" ones now,
+ ;; since this is Emacs and we have not installed info files
+ ;; into such directories for a looong time...
+ '("share/" "" "gnu/" "gnu/lib/" "gnu/lib/emacs/"
+ "emacs/" "lib/" "lib/emacs/"))
+ (standard-info-dirs
+ (apply #'nconc
+ (mapcar (lambda (pfx)
+ (let ((dirs
+ (mapcar (lambda (sfx)
+ (concat pfx sfx "info/"))
+ suffixes)))
+ (prune-directory-list dirs)))
+ prefixes)))
+ ;; If $(prefix)/share/info is not one of the standard info
+ ;; directories, they are probably installing an experimental
+ ;; version of Emacs, so make sure that experimental version's Info
+ ;; files override the ones in standard directories.
+ (dirs
+ (if (member config-dir standard-info-dirs)
+ ;; FIXME? What is the point of adding it again at the end
+ ;; when it is already present earlier in the list?
+ (nconc standard-info-dirs (list config-dir))
+ (cons config-dir standard-info-dirs))))
+ (if (not (eq system-type 'windows-nt))
+ dirs
+ ;; Include the info directory near where Emacs executable was installed.
+ (let* ((instdir (file-name-directory invocation-directory))
+ (dir1 (expand-file-name "../info/" instdir))
+ (dir2 (expand-file-name "../../../info/" instdir)))
+ (cond ((file-exists-p dir1) (append dirs (list dir1)))
+ ((file-exists-p dir2) (append dirs (list dir2)))
+ (t dirs)))))
+
+ "Default list of directories to search for Info documentation files.
+They are searched in the order they are given in the list.
+Therefore, the directory of Info files that come with Emacs
+normally should come last (so that local files override standard ones),
+unless Emacs is installed into a non-standard directory. In the latter
+case, the directory of Info files that come with Emacs should be
+first in this list.
+
+Once Info is started, the list of directories to search
+comes from the variable `Info-directory-list'.
+This variable `Info-default-directory-list' is used as the default
+for initializing `Info-directory-list' when Info is started, unless
+the environment variable INFOPATH is set.
+
+Although this is a customizable variable, that is mainly for technical
+reasons. Normally, you should either set INFOPATH or customize
+`Info-additional-directory-list', rather than changing this variable."
+ :initialize 'custom-initialize-delay
+ :type '(repeat directory)
+ :group 'info))
+
(defvar Info-directory-list nil
"List of directories to search for Info documentation files.
If nil, meaning not yet initialized, Info uses the environment
(const :tag "Replace tag and hide reference" t)
(const :tag "Hide tag and reference" hide)
(other :tag "Only replace tag" tag))
+ :set (lambda (sym val)
+ (set sym val)
+ (dolist (buffer (buffer-list))
+ (with-current-buffer buffer
+ (when (eq major-mode 'Info-mode)
+ (revert-buffer t t)))))
:group 'info)
(defcustom Info-refill-paragraphs nil
(defcustom Info-isearch-search t
"If non-nil, isearch in Info searches through multiple nodes.
Before leaving the initial Info node, where isearch was started,
-it fails once with the error message [initial node], and with
+it fails once with the error message [end of node], and with
subsequent C-s/C-r continues through other nodes without failing
with this error message in other nodes. When isearch fails for
-the rest of the manual, it wraps around the whole manual and
-restarts the search from the top/final node depending on
-search direction.
+the rest of the manual, it displays the error message [end of manual],
+wraps around the whole manual and restarts the search from the top/final
+node depending on search direction.
Setting this option to nil restores the default isearch behavior
with wrapping around the current Info node."
(defvar Info-standalone nil
"Non-nil if Emacs was started solely as an Info browser.")
+(defvar Info-file-attributes nil
+ "Alist of file attributes of visited Info files.
+Each element is a list (FILE-NAME FILE-ATTRIBUTES...).")
+
+(defvar Info-toc-nodes nil
+ "Alist of cached parent-children node information in visited Info files.
+Each element is (FILE (NODE-NAME PARENT SECTION CHILDREN) ...)
+where PARENT is the parent node extracted from the Up pointer,
+SECTION is the section name in the Top node where this node is placed,
+CHILDREN is a list of child nodes extracted from the node menu.")
+
+(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).")
+
(defvar Info-virtual-files nil
"List of definitions of virtual Info files.
Each element of the list has the format (FILENAME (OPERATION . HANDLER) ...)
(apply 'call-process-region (point-min) (point-max)
(car decoder) t t nil (cdr decoder))))
(let ((inhibit-null-byte-detection t)) ; Index nodes include null bytes
- (insert-file-contents fullname visit)))))
+ (insert-file-contents fullname visit)))
+
+ ;; Clear the caches of modified Info files.
+ (let* ((attribs-old (cdr (assoc fullname Info-file-attributes)))
+ (modtime-old (and attribs-old (nth 5 attribs-old)))
+ (attribs-new (and (stringp fullname) (file-attributes fullname)))
+ (modtime-new (and attribs-new (nth 5 attribs-new))))
+ (when (and modtime-old modtime-new
+ (> (float-time modtime-new) (float-time modtime-old)))
+ (setq Info-index-nodes (remove (assoc (or Info-current-file filename)
+ Info-index-nodes)
+ Info-index-nodes))
+ (setq Info-toc-nodes (remove (assoc (or Info-current-file filename)
+ Info-toc-nodes)
+ Info-toc-nodes)))
+ ;; Add new modtime to `Info-file-attributes'.
+ (setq Info-file-attributes
+ (cons (cons fullname attribs-new)
+ (remove (assoc fullname Info-file-attributes)
+ Info-file-attributes))))))
(defun Info-file-supports-index-cookies (&optional file)
"Return non-nil value if FILE supports Info index cookies.
(append (split-string (substring path 0 -1) sep)
(Info-default-dirs))
(split-string path sep))
- (Info-default-dirs)))))))
+ (Info-default-dirs))))
+ ;; For a self-contained (ie relocatable) NS build, AFAICS we
+ ;; always want the included info directory to be at the head of
+ ;; the search path, unless it's already in INFOPATH somewhere.
+ ;; It's at the head of Info-default-directory-list,
+ ;; but there's no way to get it at the head of Info-directory-list
+ ;; except by doing it here.
+ (and path
+ (featurep 'ns)
+ (let ((dir (expand-file-name "../info" data-directory)))
+ (and (file-directory-p dir)
+ (not (member dir (split-string path ":" t)))
+ (push dir Info-directory-list)))))))
;;;###autoload
(defun info-other-window (&optional file-or-node)
(interactive)
(info "emacs"))
+;;;###autoload
+(defun info-emacs-bug ()
+ "Display the \"Reporting Bugs\" section of the Emacs manual in Info mode."
+ (interactive)
+ (info "(emacs)Bugs"))
+
;;;###autoload
(defun info-standalone ()
"Run Emacs as a standalone Info reader.
(concat default-directory (buffer-name))))
(Info-find-node-2 nil nodename))
-;; It's perhaps a bit nasty to kill the *info* buffer to force a re-read,
-;; but at least it keeps this routine (which is for makeinfo-buffer and
-;; Info-revert-buffer-function) out of the way of normal operations.
-;;
(defun Info-revert-find-node (filename nodename)
"Go to an Info node FILENAME and NODENAME, re-reading disk contents.
When *info* is already displaying FILENAME and NODENAME, the window position
(or (eq major-mode 'Info-mode) (switch-to-buffer "*info*"))
(let ((old-filename Info-current-file)
(old-nodename Info-current-node)
- (old-buffer-name (buffer-name))
+ (window-selected (eq (selected-window) (get-buffer-window)))
(pcolumn (current-column))
(pline (count-lines (point-min) (line-beginning-position)))
(wline (count-lines (point-min) (window-start)))
- (old-history-forward Info-history-forward)
- (old-history Info-history)
(new-history (and Info-current-file
(list Info-current-file Info-current-node (point)))))
- (kill-buffer (current-buffer))
- (switch-to-buffer (or old-buffer-name "*info*"))
- (Info-mode)
+ ;; When `Info-current-file' is nil, `Info-find-node-2' rereads the file.
+ (setq Info-current-file nil)
(Info-find-node filename nodename)
- (setq Info-history-forward old-history-forward)
- (setq Info-history old-history)
(if (and (equal old-filename Info-current-file)
(equal old-nodename Info-current-node))
(progn
;; note goto-line is no good, we want to measure from point-min
- (goto-char (point-min))
- (forward-line wline)
- (set-window-start (selected-window) (point))
+ (when window-selected
+ (goto-char (point-min))
+ (forward-line wline)
+ (set-window-start (selected-window) (point)))
(goto-char (point-min))
(forward-line pline)
(move-to-column pcolumn))
(throw 'foo t))
;; No such anchor in tag table or node in tag table or file
- (error "No such node or anchor: %s" nodename))
+ (user-error "No such node or anchor: %s" nodename))
(Info-select-node)
(goto-char (point-min))
;; Add anchors to the history too
(setq Info-history-list
(cons new-history
- (delete new-history Info-history-list))))
+ (remove new-history Info-history-list))))
(goto-char anchorpos))
((numberp Info-point-loc)
(forward-line (- Info-point-loc 2))
(progn (setq file (expand-file-name "dir.info" truename))
(file-attributes file))
(progn (setq file (expand-file-name "DIR.INFO" truename))
+ (file-attributes file))
+ ;; Shouldn't really happen, but sometimes does,
+ ;; eg on Debian systems with buggy packages;
+ ;; so may as well try it.
+ ;; http://lists.gnu.org/archive/html/emacs-devel/2012-03/msg00005.html
+ (progn (setq file (expand-file-name "dir.gz" truename))
(file-attributes file)))))
(setq dirs-done
(cons truename
;; Add a new unique history item to full history list
(let ((new-history (list Info-current-file Info-current-node)))
(setq Info-history-list
- (cons new-history (delete new-history Info-history-list)))
+ (cons new-history (remove new-history Info-history-list)))
(setq Info-history-forward nil))
(if (not (eq Info-fontify-maximum-menu-size nil))
(Info-fontify-node))
(not bound)
(or give-up (and found (not (and (> found opoint-min)
(< found opoint-max))))))
- (signal 'search-failed (list regexp "initial node")))
+ (signal 'search-failed (list regexp "end of node")))
;; If no subfiles, give error now.
(if give-up
(if (null Info-current-subfile)
- (let ((search-spaces-regexp
- (if (or (not isearch-mode) isearch-regexp)
- Info-search-whitespace-regexp)))
- (if backward
- (re-search-backward regexp)
- (re-search-forward regexp)))
+ (if isearch-mode
+ (signal 'search-failed (list regexp "end of manual"))
+ (let ((search-spaces-regexp
+ (if (or (not isearch-mode) isearch-regexp)
+ Info-search-whitespace-regexp)))
+ (if backward
+ (re-search-backward regexp)
+ (re-search-forward regexp))))
(setq found nil)))
(if (and bound (not found))
(setq list nil)))
(if found
(message "")
- (signal 'search-failed (list regexp))))
+ (signal 'search-failed (if isearch-mode
+ (list regexp "end of manual")
+ (list regexp)))))
(if (not found)
(progn (Info-read-subfile osubfile)
(goto-char opoint)
(defun Info-isearch-search ()
(if Info-isearch-search
(lambda (string &optional bound noerror count)
- (if isearch-word
- (Info-search (concat "\\b" (replace-regexp-in-string
- "\\W+" "\\W+"
- (replace-regexp-in-string
- "^\\W+\\|\\W+$" "" string)
- nil t)
- ;; Lax version of word search
- (if (or isearch-nonincremental
- (eq (length string)
- (length (isearch-string-state
- (car isearch-cmds)))))
- "\\b"))
- bound noerror count
- (unless isearch-forward 'backward))
- (Info-search (if isearch-regexp string (regexp-quote string))
- bound noerror count
- (unless isearch-forward 'backward)))
+ (Info-search
+ (cond
+ (isearch-word
+ ;; Lax version of word search
+ (let ((lax (not (or isearch-nonincremental
+ (eq (length string)
+ (length (isearch--state-string
+ (car isearch-cmds))))))))
+ (if (functionp isearch-word)
+ (funcall isearch-word string lax)
+ (word-search-regexp string lax))))
+ (isearch-regexp string)
+ (t (regexp-quote string)))
+ bound noerror count
+ (unless isearch-forward 'backward))
(point))
- (let ((isearch-search-fun-function nil))
- (isearch-search-fun))))
+ (isearch-search-fun-default)))
(defun Info-isearch-wrap ()
(if Info-isearch-search
(concat name ":" (Info-following-node-name-re)) bound t)
(match-string-no-properties 1))
((not (eq errorname t))
- (error "Node has no %s"
- (capitalize (or errorname name)))))))))
+ (user-error "Node has no %s"
+ (capitalize (or errorname name)))))))))
(defun Info-following-node-name-re (&optional allowedchars)
"Return a regexp matching a node name.
"Go back in the history to the last node visited."
(interactive)
(or Info-history
- (error "This is the first Info node you looked at"))
+ (user-error "This is the first Info node you looked at"))
(let ((history-forward
(cons (list Info-current-file Info-current-node (point))
Info-history-forward))
"Go forward in the history of visited nodes."
(interactive)
(or Info-history-forward
- (error "This is the last Info node you looked at"))
+ (user-error "This is the last Info node you looked at"))
(let ((history-forward (cdr Info-history-forward))
filename nodename opoint)
(setq filename (car (car Info-history-forward)))
(insert "Recently Visited Nodes\n")
(insert "**********************\n\n")
(insert "* Menu:\n\n")
- (let ((hl (delete '("*History*" "Top") Info-history-list)))
+ (let ((hl (remove '("*History*" "Top") Info-history-list)))
(while hl
(let ((file (nth 0 (car hl)))
(node (nth 1 (car hl))))
(match-string-no-properties 1)))
(section "Top")
menu-items)
- (when (string-match "(" upnode) (setq upnode nil))
+ (when (and upnode (string-match "(" upnode)) (setq upnode nil))
(when (and (not (Info-index-node nodename file))
(re-search-forward "^\\* Menu:" bound t))
(forward-line 1)
(message "")
(nreverse nodes))))
-(defvar Info-toc-nodes nil
- "Alist of cached parent-children node information in visited Info files.
-Each element is (FILE (NODE-NAME PARENT SECTION CHILDREN) ...)
-where PARENT is the parent node extracted from the Up pointer,
-SECTION is the section name in the Top node where this node is placed,
-CHILDREN is a list of child nodes extracted from the node menu.")
-
(defun Info-toc-nodes (filename)
"Return a node list of Info FILENAME with parent-children information.
This information is cached in the variable `Info-toc-nodes' with the help
completions nil t)))
(list (if (equal input "")
default input) current-prefix-arg))
- (error "No cross-references in this node"))))
+ (user-error "No cross-references in this node"))))
(unless footnotename
(error "No reference was specified"))
(abs (- prev-ref (point))))
next-ref prev-ref))
((or next-ref prev-ref))
- ((error "No cross-reference named %s" footnotename))))
+ ((user-error "No cross-reference named %s"
+ footnotename))))
(setq target (Info-extract-menu-node-name t))))
(while (setq i (string-match "[ \t\n]+" target i))
(setq target (concat (substring target 0 i) " "
(save-excursion
(goto-char (point-min))
(if (not (search-forward "\n* menu:" nil t))
- (error "No menu in this node"))
+ (user-error "No menu in this node"))
(setq beg (point))
(and (< (point) p)
(save-excursion
(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) (if fork menu-item)))
+ (Info-goto-node (Info-extract-menu-item menu-item)
+ (and fork
+ (if (stringp fork) fork menu-item))))
(defun Info-extract-menu-item (menu-item)
(setq menu-item (regexp-quote menu-item))
(let ((case-fold-search t))
(goto-char (point-min))
(or (search-forward "\n* menu:" nil t)
- (error "No menu in this node"))
+ (user-error "No menu in this node"))
(or (re-search-forward (concat "\n\\* +" menu-item ":") nil t)
(re-search-forward (concat "\n\\* +" menu-item) nil t)
- (error "No such item in menu"))
+ (user-error "No such item in menu"))
(beginning-of-line)
(forward-char 2)
(Info-extract-menu-node-name nil (Info-index-node))))))
(match-beginning 0))))
(goto-char (point-min))
(or (search-forward "\n* menu:" bound t)
- (error "No menu in this node"))
+ (user-error "No menu in this node"))
(if count
(or (search-forward "\n* " bound t count)
(error "Too few items in menu"))
(if Info-history-skip-intermediate-nodes
(setq Info-history old-history)))))
(no-error nil)
- (t (error "No pointer forward from this node")))))
+ (t (user-error "No pointer forward from this node")))))
(defun Info-backward-node ()
"Go backward one node, considering all nodes as forming one sequence."
(upnode (Info-extract-pointer "up" t))
(case-fold-search t))
(cond ((and upnode (string-match "(" upnode))
- (error "First node in file"))
+ (user-error "First node in file"))
((and upnode (or (null prevnode)
;; Use string-equal, not equal,
;; to ignore text properties.
(if Info-history-skip-intermediate-nodes
(setq Info-history old-history))))
(t
- (error "No pointer backward from this node")))))
+ (user-error "No pointer backward from this node")))))
(defun Info-exit ()
"Exit Info by selecting some other buffer."
(and (search-forward "\n* " nil t)
(Info-extract-menu-node-name)))))
(if node (Info-goto-node node)
- (error "No more items in menu"))))
+ (user-error "No more items in menu"))))
(defun Info-last-menu-item ()
"Go to the node of the previous menu item."
(and (search-backward "\n* menu:" nil t)
(point)))))
(or (and beg (search-backward "\n* " beg t))
- (error "No previous items in menu")))
+ (user-error "No previous items in menu")))
(Info-goto-node (save-excursion
(goto-char (match-end 0))
(Info-extract-menu-node-name)))))
(defmacro Info-no-error (&rest body)
- (list 'condition-case nil (cons 'progn (append body '(t))) '(error nil)))
+ `(condition-case nil (progn ,@body t) (error nil)))
(defun Info-next-preorder ()
"Go to the next subnode or the next node, or go up a level."
(if Info-history-skip-intermediate-nodes
(setq Info-history old-history))))
(t
- (error "No more nodes"))))
+ (user-error "No more nodes"))))
(defun Info-last-preorder ()
"Go to the last node, popping up a level if there is none."
(let ((case-fold-search t))
(or (search-forward "\n* Menu:" nil t)
(goto-char (point-max)))))
- (t (error "No previous nodes"))))
+ (t (user-error "No previous nodes"))))
(defun Info-scroll-up ()
"Scroll one screenful forward in Info, considering all nodes as one sequence.
(or (re-search-forward pat nil t)
(progn
(goto-char old-pt)
- (error "No cross references in this node")))))
+ (user-error "No cross references in this node")))))
(goto-char (or (match-beginning 1) (match-beginning 0)))
(if (looking-at "\\* Menu:")
(if recur
- (error "No cross references in this node")
+ (user-error "No cross references in this node")
(Info-next-reference t))
(if (looking-at "^\\* ")
(forward-char 2)))))
(or (re-search-backward pat nil t)
(progn
(goto-char old-pt)
- (error "No cross references in this node")))))
+ (user-error "No cross references in this node")))))
(goto-char (or (match-beginning 1) (match-beginning 0)))
(if (looking-at "\\* Menu:")
(if recur
- (error "No cross references in this node")
+ (user-error "No cross references in this node")
(Info-prev-reference t))
(if (looking-at "^\\* ")
(forward-char 2)))))
\f
-(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.
(or matches
(progn
(Info-goto-node orignode)
- (error "No `%s' in index" topic)))
+ (user-error "No `%s' in index" topic)))
;; Here it is a feature that assoc is case-sensitive.
(while (setq found (assoc topic matches))
(setq exact (cons found exact)
"Go to the next matching index item from the last \\<Info-mode-map>\\[Info-index] command."
(interactive "p")
(or Info-index-alternatives
- (error "No previous `i' command"))
+ (user-error "No previous `i' command"))
(while (< num 0)
(setq num (+ num (length Info-index-alternatives))))
(while (> num 0)
(Info-index topic)
(push (cons (cons Info-current-file topic) Info-index-alternatives)
Info-virtual-index-nodes)
- ;; Clean up unneccessary side-effects of `Info-index'.
+ ;; Clean up unnecessary side-effects of `Info-index'.
(setq Info-history-list ohist-list)
(Info-goto-node orignode)
(message "")))
(declare-function finder-unknown-keywords "finder" ())
(declare-function lm-commentary "lisp-mnt" (&optional file))
(defvar finder-keywords-hash)
-(defvar package-alist) ; finder requires package
+(defvar package--builtins) ; finder requires package
(defun Info-finder-find-node (_filename nodename &optional _no-going-back)
"Finder-specific implementation of `Info-find-node-2'."
(insert "***************\n\n")
(insert "* Menu:\n\n")
(dolist (assoc (append '((all . "All package info")
- (unknown . "unknown keywords"))
+ (unknown . "Unknown keywords"))
finder-known-keywords))
(let ((keyword (car assoc)))
(insert (format "* %s %s.\n"
(concat (symbol-name keyword) ": "
- "kw:" (symbol-name keyword) ".")
+ "Keyword " (symbol-name keyword) ".")
(cdr assoc))))))
- ((equal nodename "unknown")
+ ((equal nodename "Keyword unknown")
;; Display unknown keywords
(insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n"
Info-finder-file nodename))
(mapc
(lambda (assoc)
(insert (format "* %-14s %s.\n"
- (concat (symbol-name (car assoc)) "::")
+ (concat (symbol-name (car assoc)) ": "
+ "Keyword " (symbol-name (car assoc)) ".")
(cdr assoc))))
(finder-unknown-keywords)))
- ((equal nodename "all")
+ ((equal nodename "Keyword all")
;; Display all package info.
(insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n"
Info-finder-file nodename))
(insert "Finder Package Info\n")
(insert "*******************\n\n")
- (dolist (package package-alist)
- (insert (format "%s - %s\n"
- (format "*Note %s::" (nth 0 package))
- (nth 1 package)))))
- ((string-match "\\`kw:" nodename)
+ (insert "* Menu:\n\n")
+ (let (desc)
+ (dolist (package package--builtins)
+ (setq desc (cdr-safe package))
+ (when (vectorp desc)
+ (insert (format "* %-16s %s.\n"
+ (concat (symbol-name (car package)) "::")
+ (aref desc 2)))))))
+ ((string-match "\\`Keyword " nodename)
(setq nodename (substring nodename (match-end 0)))
;; Display packages that match the keyword
;; or the list of keywords separated by comma.
- (insert (format "\n\^_\nFile: %s, Node: kw:%s, Up: Top\n\n"
+ (insert (format "\n\^_\nFile: %s, Node: Keyword %s, Up: Top\n\n"
Info-finder-file nodename))
(insert "Finder Packages\n")
(insert "***************\n\n")
(split-string nodename ",[ \t\n]*" t)
(list nodename))))
hits desc)
- (dolist (kw keywords)
- (push (copy-tree (gethash kw finder-keywords-hash)) hits))
+ (dolist (keyword keywords)
+ (push (copy-tree (gethash keyword finder-keywords-hash)) hits))
(setq hits (delete-dups (apply 'append hits)))
(dolist (package hits)
- (setq desc (cdr-safe (assq package package-alist)))
+ (setq desc (cdr-safe (assq package package--builtins)))
(when (vectorp desc)
(insert (format "* %-16s %s.\n"
(concat (symbol-name package) "::")
;; Don't raise an error when mouse-1 is bound to this - it's
;; often used to simply select the window or frame.
(eq 'mouse-1 (event-basic-type last-input-event)))
- (error "Point neither on reference nor in menu item description")))
+ (user-error "Point neither on reference nor in menu item description")))
;; Common subroutine.
(defun Info-try-follow-nearest-node (&optional fork)
(defun Info-mouse-follow-link (click)
"Follow a link where you click."
- (interactive "e")
+ (interactive "@e")
(let* ((position (event-start click))
(posn-string (and position (posn-string position)))
- (string (car-safe posn-string))
- (string-pos (cdr-safe posn-string))
- (link-args (and string string-pos
- (get-text-property string-pos 'link-args string))))
- (when link-args
- (Info-goto-node link-args))))
+ (link-args (if posn-string
+ (get-text-property (cdr posn-string)
+ 'link-args
+ (car posn-string))
+ (get-char-property (posn-point position)
+ 'link-args))))
+ (cond ((stringp link-args)
+ (Info-goto-node link-args))
+ ;; These special values of the `link-args' property are used
+ ;; for navigation; see `Info-fontify-node'.
+ ((eq link-args 'prev) (Info-prev))
+ ((eq link-args 'next) (Info-next))
+ ((eq link-args 'up) (Info-up)))))
\f
(defvar Info-mode-map
(define-key map "b" 'beginning-of-buffer)
(put 'beginning-of-buffer :advertised-binding "b")
(define-key map "d" 'Info-directory)
- (define-key map "e" 'Info-edit)
+ (define-key map "e" 'end-of-buffer)
(define-key map "f" 'Info-follow-reference)
(define-key map "g" 'Info-goto-node)
(define-key map "h" 'Info-help)
(define-key map "\177" 'Info-scroll-down)
(define-key map [mouse-2] 'Info-mouse-follow-nearest-node)
(define-key map [follow-link] 'mouse-face)
+ (define-key map [XF86Back] 'Info-history-back)
+ (define-key map [XF86Forward] 'Info-history-forward)
map)
"Keymap containing Info commands.")
With a zero prefix arg, put the name inside a function call to `info'."
(interactive "P")
(unless Info-current-node
- (error "No current Info node"))
+ (user-error "No current Info node"))
(let ((node (if (stringp Info-current-file)
(concat "(" (file-name-nondirectory Info-current-file) ") "
Info-current-node))))
(t
(Info-goto-emacs-command-node command)))))
\f
-(defvar Info-next-link-keymap
- (let ((keymap (make-sparse-keymap)))
- (define-key keymap [header-line mouse-1] 'Info-next)
- (define-key keymap [header-line mouse-2] 'Info-next)
- (define-key keymap [header-line down-mouse-1] 'ignore)
- (define-key keymap [mouse-2] 'Info-next)
- (define-key keymap [follow-link] 'mouse-face)
- keymap)
- "Keymap to put on the Next link in the text or the header line.")
-
-(defvar Info-prev-link-keymap
- (let ((keymap (make-sparse-keymap)))
- (define-key keymap [header-line mouse-1] 'Info-prev)
- (define-key keymap [header-line mouse-2] 'Info-prev)
- (define-key keymap [header-line down-mouse-1] 'ignore)
- (define-key keymap [mouse-2] 'Info-prev)
- (define-key keymap [follow-link] 'mouse-face)
- keymap)
- "Keymap to put on the Prev link in the text or the header line.")
-
-(defvar Info-up-link-keymap
- (let ((keymap (make-sparse-keymap)))
- (define-key keymap [header-line mouse-1] 'Info-up)
- (define-key keymap [header-line mouse-2] 'Info-up)
- (define-key keymap [header-line down-mouse-1] 'ignore)
- (define-key keymap [mouse-2] 'Info-up)
- (define-key keymap [follow-link] 'mouse-face)
- keymap)
- "Keymap to put on the Up link in the text or the header line.")
-
(defvar Info-link-keymap
(let ((keymap (make-sparse-keymap)))
- (define-key keymap [header-line mouse-1] 'Info-mouse-follow-link)
+ (define-key keymap [header-line down-mouse-1] 'mouse-drag-header-line)
+ (define-key keymap [header-line mouse-1] 'mouse-select-window)
(define-key keymap [header-line mouse-2] 'Info-mouse-follow-link)
- (define-key keymap [header-line down-mouse-1] 'ignore)
(define-key keymap [mouse-2] 'Info-mouse-follow-link)
(define-key keymap [follow-link] 'mouse-face)
keymap)
- "Keymap to put on the link in the text or the header line.")
+ "Keymap to put on Info links.
+This is used for the \"Next\", \"Prev\", and \"Up\" links in the
+first line or header line, and for breadcrumb links.")
(defun Info-breadcrumbs ()
(let ((nodes (Info-toc-nodes Info-current-file))
'help-echo
(concat "mouse-2: Go to node "
(buffer-substring nbeg nend)))
- ;; Always set up the text property keymap.
- ;; It will either be used in the buffer
- ;; or copied in the header line.
- (put-text-property
- tbeg nend 'keymap
- (cond
- ((string-equal (downcase tag) "prev") Info-prev-link-keymap)
- ((string-equal (downcase tag) "next") Info-next-link-keymap)
- ((string-equal (downcase tag) "up" ) Info-up-link-keymap))))))
+ ;; Set up the text property keymap. Depending on
+ ;; `Info-use-header-line', it is either used in the
+ ;; buffer, or copied to the header line. A symbol value
+ ;; of the `link-args' property is handled specially by
+ ;; `Info-mouse-follow-link'.
+ (put-text-property tbeg nend 'keymap Info-link-keymap)
+ (put-text-property tbeg nend 'link-args
+ (intern (downcase tag))))))
;; (when (> Info-breadcrumbs-depth 0)
;; (insert (Info-breadcrumbs)))
((not (bobp))
;; Hide the punctuation at the end, too.
(skip-chars-backward " \t,")
- (put-text-property (point) header-end 'invisible t))))))
+ (put-text-property (point) header-end 'invisible t)
+ ;; Hide the suffix of the Info file name.
+ (beginning-of-line)
+ (if (re-search-forward
+ (format "File: %s\\([^,\n\t]+\\),"
+ (if (stringp Info-current-file)
+ (file-name-nondirectory Info-current-file)
+ Info-current-file))
+ header-end t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'invisible t)))))))
;; Fontify titles
(goto-char (point-min))
(erase-buffer))
(Info-speedbar-hierarchy-buttons nil 0))
-(dolist (mess '("^First node in file$"
- "^No `.*' in index$"
- "^No cross-reference named"
- "^No cross.references in this node$"
- "^No current Info node$"
- "^No menu in this node$"
- "^No more items in menu$"
- "^No more nodes$"
- "^No pointer \\(?:forward\\|backward\\) from this node$"
- "^No previous `i' command$"
- "^No previous items in menu$"
- "^No previous nodes$"
- "^No such item in menu$"
- "^No such node or anchor"
- "^Node has no"
- "^Point neither on reference nor in menu item description$"
- "^This is the \\(?:first\\|last\\) Info node you looked at$"
- search-failed))
- (add-to-list 'debug-ignored-errors mess))
+;; FIXME: Really? Why here?
+(add-to-list 'debug-ignored-errors 'search-failed)
;;;; Desktop support
(defun Info-bookmark-make-record ()
"This implements the `bookmark-make-record-function' type (which see)
for Info nodes."
- `(,Info-current-node
- ,@(bookmark-make-record-default 'no-file)
- (filename . ,Info-current-file)
- (info-node . ,Info-current-node)
- (handler . Info-bookmark-jump)))
+ (let* ((file (and (stringp Info-current-file)
+ (file-name-nondirectory Info-current-file)))
+ (bookmark-name (if file
+ (concat "(" file ") " Info-current-node)
+ Info-current-node))
+ (defaults (delq nil (list bookmark-name file Info-current-node))))
+ `(,bookmark-name
+ ,@(bookmark-make-record-default 'no-file)
+ (filename . ,Info-current-file)
+ (info-node . ,Info-current-node)
+ (handler . Info-bookmark-jump)
+ (defaults . ,defaults))))
;;;###autoload
(defun Info-bookmark-jump (bmk)