]> code.delx.au - gnu-emacs/blobdiff - lisp/info.el
When running under emacs -q, always refuse to save the customisations, even if the...
[gnu-emacs] / lisp / info.el
index 163ca25815995dd6af951843aebe53af527307ef..447c86b3e9ec1a40f360418f261cf9ae5d7c2bee 100644 (file)
@@ -1,8 +1,6 @@
 ;; info.el --- info package for Emacs
 
 ;; info.el --- info package for Emacs
 
-;; Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;;   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-;;   2010  Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2011  Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: help
 
 ;; Maintainer: FSF
 ;; Keywords: help
@@ -34,7 +32,7 @@
 
 ;;; Code:
 
 
 ;;; Code:
 
-(eval-when-compile (require 'jka-compr) (require 'cl))
+(eval-when-compile (require 'cl))
 
 (defgroup info nil
   "Info subsystem."
 
 (defgroup info nil
   "Info subsystem."
@@ -167,7 +165,7 @@ A header-line does not scroll with the rest of the buffer."
 If nil, meaning not yet initialized, Info uses the environment
 variable INFOPATH to initialize it, or `Info-default-directory-list'
 if there is no INFOPATH variable in the environment, or the
 If nil, meaning not yet initialized, Info uses the environment
 variable INFOPATH to initialize it, or `Info-default-directory-list'
 if there is no INFOPATH variable in the environment, or the
-concatenation of the two if INFOPATH ends with a colon.
+concatenation of the two if INFOPATH ends with a `path-separator'.
 
 When `Info-directory-list' is initialized from the value of
 `Info-default-directory-list', and Emacs is installed in one of the
 
 When `Info-directory-list' is initialized from the value of
 `Info-default-directory-list', and Emacs is installed in one of the
@@ -345,9 +343,8 @@ Each element of the list has the format (NODENAME (OPERATION . HANDLER) ...)
 where NODENAME is a regexp that matches a class of virtual Info node names.
 It should be carefully chosen to not cause node name clashes with
 existing node names.  OPERATION is one of the following operation
 where NODENAME is a regexp that matches a class of virtual Info node names.
 It should be carefully chosen to not cause node name clashes with
 existing node names.  OPERATION is one of the following operation
-symbols `find-node' that define what HANDLER
-function to call instead of calling the default corresponding function
-to override it.")
+symbols `find-node' that define what HANDLER function to call instead
+of calling the default corresponding function to override it.")
 
 (defvar Info-current-node-virtual nil
   "Non-nil if the current Info node is virtual.")
 
 (defvar Info-current-node-virtual nil
   "Non-nil if the current Info node is virtual.")
@@ -381,50 +378,50 @@ or `Info-virtual-nodes'."
   ;; The MS-DOS list should work both when long file names are
   ;; supported (Windows 9X), and when only 8+3 file names are available.
   (if (eq system-type 'ms-dos)
   ;; The MS-DOS list should work both when long file names are
   ;; supported (Windows 9X), and when only 8+3 file names are available.
   (if (eq system-type 'ms-dos)
-      '( (".gz"      . "gunzip")
-        (".z"       . "gunzip")
-        (".bz2"     . ("bzip2" "-dc"))
-        (".inz"     . "gunzip")
-        (".igz"     . "gunzip")
-        (".info.Z"  . "gunzip")
-        (".info.gz" . "gunzip")
-        ("-info.Z"  . "gunzip")
-        ("-info.gz" . "gunzip")
-        ("/index.gz". "gunzip")
-        ("/index.z" . "gunzip")
-        (".inf"     . nil)
-        (".info"    . nil)
-        ("-info"    . nil)
-        ("/index"   . nil)
-        (""         . nil))
-    '( (".info.Z".    "uncompress")
-       (".info.Y".    "unyabba")
-       (".info.gz".   "gunzip")
-       (".info.z".    "gunzip")
-       (".info.bz2" . ("bzip2" "-dc"))
-       (".info.xz".   "unxz")
-       (".info".      nil)
-       ("-info.Z".   "uncompress")
-       ("-info.Y".   "unyabba")
-       ("-info.gz" "gunzip")
-       ("-info.bz2" . ("bzip2" "-dc"))
-       ("-info.z".   "gunzip")
-       ("-info.xz" "unxz")
-       ("-info".     nil)
-       ("/index.Z".   "uncompress")
-       ("/index.Y".   "unyabba")
-       ("/index.gz" "gunzip")
-       ("/index.z".   "gunzip")
-       ("/index.bz2". ("bzip2" "-dc"))
-       ("/index.xz" "unxz")
-       ("/index".     nil)
-       (".Z".         "uncompress")
-       (".Y".         "unyabba")
-       (".gz".        "gunzip")
-       (".z".         "gunzip")
-       (".bz2" .      ("bzip2" "-dc"))
-       (".xz".        "unxz")
-       ("".           nil)))
+      '( (".gz"       . "gunzip")
+        (".z"        . "gunzip")
+        (".bz2"      . ("bzip2" "-dc"))
+        (".inz"      . "gunzip")
+        (".igz"      . "gunzip")
+        (".info.Z"   . "gunzip")
+        (".info.gz"  . "gunzip")
+        ("-info.Z"   . "gunzip")
+        ("-info.gz"  . "gunzip")
+        ("/index.gz" . "gunzip")
+        ("/index.z"  . "gunzip")
+        (".inf"      . nil)
+        (".info"     . nil)
+        ("-info"     . nil)
+        ("/index"    . nil)
+        (""          . nil))
+    '( (".info.Z"    . "uncompress")
+       (".info.Y"    . "unyabba")
+       (".info.gz"   . "gunzip")
+       (".info.z"    . "gunzip")
+       (".info.bz2"  . ("bzip2" "-dc"))
+       (".info.xz"   . "unxz")
+       (".info"      . nil)
+       ("-info.Z"    . "uncompress")
+       ("-info.Y"    . "unyabba")
+       ("-info.gz"   . "gunzip")
+       ("-info.bz2"  . ("bzip2" "-dc"))
+       ("-info.z"    . "gunzip")
+       ("-info.xz"   . "unxz")
+       ("-info"      . nil)
+       ("/index.Z"   . "uncompress")
+       ("/index.Y"   . "unyabba")
+       ("/index.gz"  . "gunzip")
+       ("/index.z"   . "gunzip")
+       ("/index.bz2" . ("bzip2" "-dc"))
+       ("/index.xz"  . "unxz")
+       ("/index"     . nil)
+       (".Z"         . "uncompress")
+       (".Y"         . "unyabba")
+       (".gz"        . "gunzip")
+       (".z"         . "gunzip")
+       (".bz2"       . ("bzip2" "-dc"))
+       (".xz"        . "unxz")
+       (""           . nil)))
   "List of file name suffixes and associated decoding commands.
 Each entry should be (SUFFIX . STRING); the file is given to
 the command as standard input.
   "List of file name suffixes and associated decoding commands.
 Each entry should be (SUFFIX . STRING); the file is given to
 the command as standard input.
@@ -467,6 +464,7 @@ be last in the list.")
   "Insert the contents of an Info file in the current buffer.
 Do the right thing if the file has been compressed or zipped."
   (let* ((tail Info-suffix-list)
   "Insert the contents of an Info file in the current buffer.
 Do the right thing if the file has been compressed or zipped."
   (let* ((tail Info-suffix-list)
+        (jka-compr-verbose nil)
         (lfn (if (fboundp 'msdos-long-file-names)
                  (msdos-long-file-names)
                t))
         (lfn (if (fboundp 'msdos-long-file-names)
                  (msdos-long-file-names)
                t))
@@ -596,15 +594,15 @@ in `Info-file-supports-index-cookies-list'."
 (defun info-initialize ()
   "Initialize `Info-directory-list', if that hasn't been done yet."
   (unless Info-directory-list
 (defun info-initialize ()
   "Initialize `Info-directory-list', if that hasn't been done yet."
   (unless Info-directory-list
-    (let ((path (getenv "INFOPATH")))
+    (let ((path (getenv "INFOPATH"))
+         (sep (regexp-quote path-separator)))
       (setq Info-directory-list
            (prune-directory-list
             (if path
       (setq Info-directory-list
            (prune-directory-list
             (if path
-                (if (string-match ":\\'" path)
-                    (append (split-string (substring path 0 -1)
-                                          (regexp-quote path-separator))
+                (if (string-match-p (concat sep "\\'") path)
+                    (append (split-string (substring path 0 -1) sep)
                             (Info-default-dirs))
                             (Info-default-dirs))
-                  (split-string path (regexp-quote path-separator)))
+                  (split-string path sep))
               (Info-default-dirs)))))))
 
 ;;;###autoload
               (Info-default-dirs)))))))
 
 ;;;###autoload
@@ -624,7 +622,7 @@ in `Info-file-supports-index-cookies-list'."
 Optional argument FILE-OR-NODE specifies the file to examine;
 the default is the top-level directory of Info.
 Called from a program, FILE-OR-NODE may specify an Info node of the form
 Optional argument FILE-OR-NODE specifies the file to examine;
 the default is the top-level directory of Info.
 Called from a program, FILE-OR-NODE may specify an Info node of the form
-`(FILENAME)NODENAME'.
+\"(FILENAME)NODENAME\".
 Optional argument BUFFER specifies the Info buffer name;
 the default buffer name is *info*.  If BUFFER exists,
 just switch to BUFFER.  Otherwise, create a new buffer
 Optional argument BUFFER specifies the Info buffer name;
 the default buffer name is *info*.  If BUFFER exists,
 just switch to BUFFER.  Otherwise, create a new buffer
@@ -707,7 +705,7 @@ In standalone mode, \\<Info-mode-map>\\[Info-exit] exits Emacs itself."
         (re-search-backward regexp beg t))))
 
 (defun Info-find-file (filename &optional noerror)
         (re-search-backward regexp beg t))))
 
 (defun Info-find-file (filename &optional noerror)
-  "Return expanded FILENAME, or t, if FILENAME is \"dir\".
+  "Return expanded FILENAME, or t if FILENAME is \"dir\".
 Optional second argument NOERROR, if t, means if file is not found
 just return nil (no error)."
   ;; Convert filename to lower case if not found as specified.
 Optional second argument NOERROR, if t, means if file is not found
 just return nil (no error)."
   ;; Convert filename to lower case if not found as specified.
@@ -731,6 +729,11 @@ just return nil (no error)."
                          (append Info-directory-list
                                  Info-additional-directory-list)
                        Info-directory-list)))))
                          (append Info-directory-list
                                  Info-additional-directory-list)
                        Info-directory-list)))))
+       ;; Fall back on the installation directory if we can't find
+       ;; the info node anywhere else.
+       (when installation-directory
+         (setq dirs (append dirs (list (expand-file-name
+                                        "info" installation-directory)))))
        ;; Search the directory list for file FILENAME.
        (while (and dirs (not found))
          (setq temp (expand-file-name filename (car dirs)))
        ;; Search the directory list for file FILENAME.
        (while (and dirs (not found))
          (setq temp (expand-file-name filename (car dirs)))
@@ -837,7 +840,7 @@ is preserved, if possible."
       (if new-history
          (setq Info-history (cons new-history Info-history))))))
 
       (if new-history
          (setq Info-history (cons new-history Info-history))))))
 
-(defun Info-revert-buffer-function (ignore-auto noconfirm)
+(defun Info-revert-buffer-function (_ignore-auto noconfirm)
   (when (or noconfirm (y-or-n-p "Revert info buffer? "))
     (Info-revert-find-node Info-current-file Info-current-node)
     (message "Reverted %s" Info-current-file)))
   (when (or noconfirm (y-or-n-p "Revert info buffer? "))
     (Info-revert-find-node Info-current-file Info-current-node)
     (message "Reverted %s" Info-current-file)))
@@ -888,17 +891,16 @@ Value is the position at which a match was found, or nil if not found."
   (let ((case-fold-search case-fold)
        found)
     (save-excursion
   (let ((case-fold-search case-fold)
        found)
     (save-excursion
-      (when (Info-node-at-bob-matching regexp)
-       (setq found (point)))
-      (while (and (not found)
-                 (search-forward "\n\^_" nil t))
-       (forward-line 1)
-       (let ((beg (point)))
-         (forward-line 1)
-         (when (re-search-backward regexp beg t)
-           (beginning-of-line)
-           (setq found (point)))))
-      found)))
+      (if (Info-node-at-bob-matching regexp)
+          (setq found (point))
+        (while (and (not found)
+                    (search-forward "\n\^_" nil t))
+          (forward-line 1)
+          (let ((beg (point)))
+            (forward-line 1)
+            (if (re-search-backward regexp beg t)
+                (setq found (line-beginning-position)))))))
+    found))
 
 (defun Info-find-node-in-buffer (regexp)
   "Find a node or anchor in the current buffer.
 
 (defun Info-find-node-in-buffer (regexp)
   "Find a node or anchor in the current buffer.
@@ -1397,10 +1399,11 @@ a case-insensitive match is tried."
 ;;   \0\h[image param=value ...\h\0]
 ;; into the Info file for handling images.
 (defun Info-split-parameter-string (parameter-string)
 ;;   \0\h[image param=value ...\h\0]
 ;; into the Info file for handling images.
 (defun Info-split-parameter-string (parameter-string)
-  "Return alist of (\"KEY\" . \"VALUE\") from PARAMETER-STRING; a
-whitespace separated list of KEY=VALUE pairs.  If VALUE contains
-whitespace or double quotes, it must be quoted in double quotes and
-any double quotes or backslashes must be escaped (\\\",\\\\)."
+  "Return alist of (\"KEY\" . \"VALUE\") from PARAMETER-STRING.
+PARAMETER-STRING is a whitespace separated list of KEY=VALUE pairs.
+If VALUE contains whitespace or double quotes, it must be quoted
+in double quotes and any double quotes or backslashes must be
+escaped (\\\",\\\\)."
   (let ((start 0)
        (parameter-alist))
     (while (string-match
   (let ((start 0)
        (parameter-alist))
     (while (string-match
@@ -1575,8 +1578,12 @@ If FORK is a string, it is the name to use for the new buffer."
 (defvar Info-read-node-completion-table)
 
 (defun Info-read-node-name-2 (dirs suffixes string pred action)
 (defvar Info-read-node-completion-table)
 
 (defun Info-read-node-name-2 (dirs suffixes string pred action)
-  "Virtual completion table for file names input in Info node names.
-PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
+  "Internal function used to complete Info node names.
+Return a completion table for Info files---the FILENAME part of a
+node named \"(FILENAME)NODENAME\".  DIRS is a list of Info
+directories to search if FILENAME is not absolute; SUFFIXES is a
+list of valid filename suffixes for Info files.  See
+`try-completion' for a description of the remaining arguments."
   (setq suffixes (remove "" suffixes))
   (when (file-name-absolute-p string)
     (setq dirs (list (file-name-directory string))))
   (setq suffixes (remove "" suffixes))
   (when (file-name-absolute-p string)
     (setq dirs (list (file-name-directory string))))
@@ -1606,10 +1613,9 @@ PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
            (push (if string-dir (concat string-dir file) file) names)))))
     (complete-with-action action names string pred)))
 
            (push (if string-dir (concat string-dir file) file) names)))))
     (complete-with-action action names string pred)))
 
-;; This function is used as the "completion table" while reading a node name.
-;; It does completion using the alist in Info-read-node-completion-table
-;; unless STRING starts with an open-paren.
 (defun Info-read-node-name-1 (string predicate code)
 (defun Info-read-node-name-1 (string predicate code)
+  "Internal function used by `Info-read-node-name'.
+See `completing-read' for a description of arguments and usage."
   (cond
    ;; First complete embedded file names.
    ((string-match "\\`([^)]*\\'" string)
   (cond
    ;; First complete embedded file names.
    ((string-match "\\`([^)]*\\'" string)
@@ -1622,7 +1628,6 @@ PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
      (substring string 1)
      predicate
      code))
      (substring string 1)
      predicate
      code))
-
    ;; If a file name was given, then any node is fair game.
    ((string-match "\\`(" string)
     (cond
    ;; If a file name was given, then any node is fair game.
    ((string-match "\\`(" string)
     (cond
@@ -1634,9 +1639,10 @@ PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
        code Info-read-node-completion-table string predicate))))
 
 ;; Arrange to highlight the proper letters in the completion list buffer.
        code Info-read-node-completion-table string predicate))))
 
 ;; Arrange to highlight the proper letters in the completion list buffer.
-
-
 (defun Info-read-node-name (prompt)
 (defun Info-read-node-name (prompt)
+  "Read an Info node name with completion, prompting with PROMPT.
+A node name can have the form \"NODENAME\", referring to a node
+in the current Info file, or \"(FILENAME)NODENAME\"."
   (let* ((completion-ignore-case t)
         (Info-read-node-completion-table (Info-build-node-completions))
         (nodename (completing-read prompt 'Info-read-node-name-1 nil t)))
   (let* ((completion-ignore-case t)
         (Info-read-node-completion-table (Info-build-node-completions))
         (nodename (completing-read prompt 'Info-read-node-name-1 nil t)))
@@ -1697,7 +1703,7 @@ PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
 (defvar Info-search-case-fold nil
   "The value of `case-fold-search' from previous `Info-search' command.")
 
 (defvar Info-search-case-fold nil
   "The value of `case-fold-search' from previous `Info-search' command.")
 
-(defun Info-search (regexp &optional bound noerror count direction)
+(defun Info-search (regexp &optional bound _noerror _count direction)
   "Search for REGEXP, starting from point, and select node it's found in.
 If DIRECTION is `backward', search in the reverse direction."
   (interactive (list (read-string
   "Search for REGEXP, starting from point, and select node it's found in.
 If DIRECTION is `backward', search in the reverse direction."
   (interactive (list (read-string
@@ -1918,7 +1924,7 @@ If DIRECTION is `backward', search in the reverse direction."
   `(lambda (cmd)
      (Info-isearch-pop-state cmd ',Info-current-file ',Info-current-node)))
 
   `(lambda (cmd)
      (Info-isearch-pop-state cmd ',Info-current-file ',Info-current-node)))
 
-(defun Info-isearch-pop-state (cmd file node)
+(defun Info-isearch-pop-state (_cmd file node)
   (or (and (equal Info-current-file file)
            (equal Info-current-node node))
       (progn (Info-find-node file node) (sit-for 0))))
   (or (and (equal Info-current-file file)
            (equal Info-current-node node))
       (progn (Info-find-node file node) (sit-for 0))))
@@ -2096,16 +2102,16 @@ If SAME-FILE is non-nil, do not move to a different Info file."
               ))
 
 (defun Info-directory-toc-nodes (filename)
               ))
 
 (defun Info-directory-toc-nodes (filename)
-  "Directory-specific implementation of Info-directory-toc-nodes."
+  "Directory-specific implementation of `Info-toc-nodes'."
   `(,filename
     ("Top" nil nil nil)))
 
   `(,filename
     ("Top" nil nil nil)))
 
-(defun Info-directory-find-file (filename &optional noerror)
-  "Directory-specific implementation of Info-find-file."
+(defun Info-directory-find-file (filename &optional _noerror)
+  "Directory-specific implementation of `Info-find-file'."
   filename)
 
   filename)
 
-(defun Info-directory-find-node (filename nodename &optional no-going-back)
-  "Directory-specific implementation of Info-find-node-2."
+(defun Info-directory-find-node (_filename _nodename &optional _no-going-back)
+  "Directory-specific implementation of `Info-find-node-2'."
   (Info-insert-dir))
 
 ;;;###autoload
   (Info-insert-dir))
 
 ;;;###autoload
@@ -2122,16 +2128,16 @@ If SAME-FILE is non-nil, do not move to a different Info file."
               ))
 
 (defun Info-history-toc-nodes (filename)
               ))
 
 (defun Info-history-toc-nodes (filename)
-  "History-specific implementation of Info-history-toc-nodes."
+  "History-specific implementation of `Info-history-toc-nodes'."
   `(,filename
     ("Top" nil nil nil)))
 
   `(,filename
     ("Top" nil nil nil)))
 
-(defun Info-history-find-file (filename &optional noerror)
-  "History-specific implementation of Info-find-file."
+(defun Info-history-find-file (filename &optional _noerror)
+  "History-specific implementation of `Info-find-file'."
   filename)
 
   filename)
 
-(defun Info-history-find-node (filename nodename &optional no-going-back)
-  "History-specific implementation of Info-find-node-2."
+(defun Info-history-find-node (filename nodename &optional _no-going-back)
+  "History-specific implementation of `Info-find-node-2'."
   (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: (dir)\n\n"
                  (or filename Info-current-file) nodename))
   (insert "Recently Visited Nodes\n")
   (insert (format "\n\^_\nFile: %s,  Node: %s,  Up: (dir)\n\n"
                  (or filename Info-current-file) nodename))
   (insert "Recently Visited Nodes\n")
@@ -2160,8 +2166,8 @@ If SAME-FILE is non-nil, do not move to a different Info file."
               (find-node . Info-toc-find-node)
               ))
 
               (find-node . Info-toc-find-node)
               ))
 
-(defun Info-toc-find-node (filename nodename &optional no-going-back)
-  "Toc-specific implementation of Info-find-node-2."
+(defun Info-toc-find-node (filename nodename &optional _no-going-back)
+  "Toc-specific implementation of `Info-find-node-2'."
   (let* ((curr-file (substring-no-properties (or filename Info-current-file)))
         (curr-node (substring-no-properties (or nodename Info-current-node)))
         (node-list (Info-toc-nodes curr-file)))
   (let* ((curr-file (substring-no-properties (or filename Info-current-file)))
         (curr-node (substring-no-properties (or nodename Info-current-node)))
         (node-list (Info-toc-nodes curr-file)))
@@ -2323,11 +2329,8 @@ new buffer."
         completions default alt-default (start-point (point)) str i bol eol)
      (save-excursion
        ;; Store end and beginning of line.
         completions default alt-default (start-point (point)) str i bol eol)
      (save-excursion
        ;; Store end and beginning of line.
-       (end-of-line)
-       (setq eol (point))
-       (beginning-of-line)
-       (setq bol (point))
-
+       (setq eol (line-end-position)
+             bol (line-beginning-position))
        (goto-char (point-min))
        (while (re-search-forward "\\*note[ \n\t]+\\([^:]*\\):" nil t)
         (setq str (match-string-no-properties 1))
        (goto-char (point-min))
        (while (re-search-forward "\\*note[ \n\t]+\\([^:]*\\):" nil t)
         (setq str (match-string-no-properties 1))
@@ -2843,12 +2846,9 @@ parent node."
         (virtual-end
          (and Info-scroll-prefer-subnodes
               (save-excursion
         (virtual-end
          (and Info-scroll-prefer-subnodes
               (save-excursion
-                (beginning-of-line)
-                (setq current-point (point))
+                (setq current-point (line-beginning-position))
                 (goto-char (point-min))
                 (goto-char (point-min))
-                (search-forward "\n* Menu:"
-                                current-point
-                                t)))))
+                (search-forward "\n* Menu:" current-point t)))))
     (if (or virtual-end
            (pos-visible-in-window-p (point-min) nil t))
        (Info-last-preorder)
     (if (or virtual-end
            (pos-visible-in-window-p (point-min) nil t))
        (Info-last-preorder)
@@ -3147,8 +3147,8 @@ FILENAME is the file name of the manual,
 TOPIC is the search string given as an argument to `Info-virtual-index',
 MATCHES is a list of index matches found by `Info-index'.")
 
 TOPIC is the search string given as an argument to `Info-virtual-index',
 MATCHES is a list of index matches found by `Info-index'.")
 
-(defun Info-virtual-index-find-node (filename nodename &optional no-going-back)
-  "Index-specific implementation of Info-find-node-2."
+(defun Info-virtual-index-find-node (filename nodename &optional _no-going-back)
+  "Index-specific implementation of `Info-find-node-2'."
   ;; Generate Index-like menu of matches
   (if (string-match "^\\*Index for `\\(.+\\)'\\*$" nodename)
       ;; Generate Index-like menu of matches
   ;; Generate Index-like menu of matches
   (if (string-match "^\\*Index for `\\(.+\\)'\\*$" nodename)
       ;; Generate Index-like menu of matches
@@ -3210,8 +3210,7 @@ search results."
       (Info-find-node Info-current-file "*Index*")
     (unless (assoc (cons Info-current-file topic) Info-virtual-index-nodes)
       (let ((orignode Info-current-node)
       (Info-find-node Info-current-file "*Index*")
     (unless (assoc (cons Info-current-file topic) Info-virtual-index-nodes)
       (let ((orignode Info-current-node)
-           (ohist-list Info-history-list)
-           nodename)
+           (ohist-list Info-history-list))
        ;; Reuse `Info-index' to set `Info-index-alternatives'.
        (Info-index topic)
        (push (cons (cons Info-current-file topic) Info-index-alternatives)
        ;; Reuse `Info-index' to set `Info-index-alternatives'.
        (Info-index topic)
        (push (cons (cons Info-current-file topic) Info-index-alternatives)
@@ -3241,18 +3240,18 @@ STRING is the search string given as an argument to `info-apropos',
 MATCHES is a list of index matches found by `Info-apropos-matches'.")
 
 (defun Info-apropos-toc-nodes (filename)
 MATCHES is a list of index matches found by `Info-apropos-matches'.")
 
 (defun Info-apropos-toc-nodes (filename)
-  "Apropos-specific implementation of Info-apropos-toc-nodes."
+  "Apropos-specific implementation of `Info-toc-nodes'."
   (let ((nodes (mapcar 'car (reverse Info-apropos-nodes))))
     `(,filename
       ("Top" nil nil ,nodes)
       ,@(mapcar (lambda (node) `(,node "Top" nil nil)) nodes))))
 
   (let ((nodes (mapcar 'car (reverse Info-apropos-nodes))))
     `(,filename
       ("Top" nil nil ,nodes)
       ,@(mapcar (lambda (node) `(,node "Top" nil nil)) nodes))))
 
-(defun Info-apropos-find-file (filename &optional noerror)
-  "Apropos-specific implementation of Info-find-file."
+(defun Info-apropos-find-file (filename &optional _noerror)
+  "Apropos-specific implementation of `Info-find-file'."
   filename)
 
   filename)
 
-(defun Info-apropos-find-node (filename nodename &optional no-going-back)
-  "Apropos-specific implementation of Info-find-node-2."
+(defun Info-apropos-find-node (_filename nodename &optional _no-going-back)
+  "Apropos-specific implementation of `Info-find-node-2'."
   (if (equal nodename "Top")
       ;; Generate Top menu
       (let ((nodes (reverse Info-apropos-nodes)))
   (if (equal nodename "Top")
       ;; Generate Top menu
       (let ((nodes (reverse Info-apropos-nodes)))
@@ -3292,7 +3291,6 @@ MATCHES is a list of index matches found by `Info-apropos-matches'.")
   "Collect STRING matches from all known Info files on your system.
 Return a list of matches where each element is in the format
 \((FILENAME INDEXTEXT NODENAME LINENUMBER))."
   "Collect STRING matches from all known Info files on your system.
 Return a list of matches where each element is in the format
 \((FILENAME INDEXTEXT NODENAME LINENUMBER))."
-  (interactive "sIndex apropos: ")
   (unless (string= string "")
     (let ((pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]+\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
                           (regexp-quote string)))
   (unless (string= string "")
     (let ((pattern (format "\n\\* +\\([^\n]*%s[^\n]*\\):[ \t]+\\([^\n]+\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?"
                           (regexp-quote string)))
@@ -3371,8 +3369,8 @@ Build a menu of the possible matches."
 (defvar Info-finder-file "*Finder*"
   "Info file name of the virtual Info keyword finder manual.")
 
 (defvar Info-finder-file "*Finder*"
   "Info file name of the virtual Info keyword finder manual.")
 
-(defun Info-finder-find-file (filename &optional noerror)
-  "Finder-specific implementation of Info-find-file."
+(defun Info-finder-find-file (filename &optional _noerror)
+  "Finder-specific implementation of `Info-find-file'."
   filename)
 
 (defvar finder-known-keywords)
   filename)
 
 (defvar finder-known-keywords)
@@ -3382,8 +3380,8 @@ Build a menu of the possible matches."
 (defvar finder-keywords-hash)
 (defvar package-alist)                  ; finder requires package
 
 (defvar finder-keywords-hash)
 (defvar package-alist)                  ; finder requires package
 
-(defun Info-finder-find-node (filename nodename &optional no-going-back)
-  "Finder-specific implementation of Info-find-node-2."
+(defun Info-finder-find-node (_filename nodename &optional _no-going-back)
+  "Finder-specific implementation of `Info-find-node-2'."
   (require 'finder)
   (cond
    ((equal nodename "Top")
   (require 'finder)
   (cond
    ((equal nodename "Top")
@@ -3477,7 +3475,7 @@ Build a menu of the possible matches."
   "Display descriptions of the keywords in the Finder virtual manual.
 In interactive use, a prefix argument directs this command to read
 a list of keywords separated by comma.  After that, it displays a node
   "Display descriptions of the keywords in the Finder virtual manual.
 In interactive use, a prefix argument directs this command to read
 a list of keywords separated by comma.  After that, it displays a node
-with a list packages that contain all specified keywords."
+with a list of packages that contain all specified keywords."
   (interactive
    (when current-prefix-arg
      (require 'finder)
   (interactive
    (when current-prefix-arg
      (require 'finder)
@@ -3529,14 +3527,14 @@ with a list packages that contain all specified keywords."
 \f
 (defun Info-get-token (pos start all &optional errorstring)
   "Return the token around POS.
 \f
 (defun Info-get-token (pos start all &optional errorstring)
   "Return the token around POS.
-POS must be somewhere inside the token
+POS must be somewhere inside the token.
 START is a regular expression which will match the
 START is a regular expression which will match the
-    beginning of the tokens delimited string
+    beginning of the tokens delimited string.
 ALL is a regular expression with a single
     parenthesized subpattern which is the token to be
     returned.  E.g. '{\(.*\)}' would return any string
     enclosed in braces around POS.
 ALL is a regular expression with a single
     parenthesized subpattern which is the token to be
     returned.  E.g. '{\(.*\)}' would return any string
     enclosed in braces around POS.
-ERRORSTRING optional fourth argument, controls action on no match
+ERRORSTRING optional fourth argument, controls action on no match:
     nil: return nil
     t: beep
     a string: signal an error, using that string."
     nil: return nil
     t: beep
     a string: signal an error, using that string."
@@ -3657,7 +3655,6 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
     (define-key map "\C-m" 'Info-follow-nearest-node)
     (define-key map "\t" 'Info-next-reference)
     (define-key map "\e\t" 'Info-prev-reference)
     (define-key map "\C-m" 'Info-follow-nearest-node)
     (define-key map "\t" 'Info-next-reference)
     (define-key map "\e\t" 'Info-prev-reference)
-    (define-key map [(shift tab)] 'Info-prev-reference)
     (define-key map [backtab] 'Info-prev-reference)
     (define-key map "1" 'Info-nth-menu-item)
     (define-key map "2" 'Info-nth-menu-item)
     (define-key map [backtab] 'Info-prev-reference)
     (define-key map "1" 'Info-nth-menu-item)
     (define-key map "2" 'Info-nth-menu-item)
@@ -3675,6 +3672,7 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
     (define-key map "<" 'Info-top-node)
     (define-key map ">" 'Info-final-node)
     (define-key map "b" 'beginning-of-buffer)
     (define-key map "<" 'Info-top-node)
     (define-key map ">" 'Info-final-node)
     (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 "f" 'Info-follow-reference)
     (define-key map "d" 'Info-directory)
     (define-key map "e" 'Info-edit)
     (define-key map "f" 'Info-follow-reference)
@@ -3770,21 +3768,30 @@ If FORK is non-nil, it is passed to `Info-goto-node'."
   (let ((map (make-sparse-keymap)))
     (tool-bar-local-item-from-menu 'Info-history-back "left-arrow" map Info-mode-map
                                   :rtl "right-arrow"
   (let ((map (make-sparse-keymap)))
     (tool-bar-local-item-from-menu 'Info-history-back "left-arrow" map Info-mode-map
                                   :rtl "right-arrow"
-                                  :label "Back")
+                                  :label "Back"
+                                  :vert-only t)
     (tool-bar-local-item-from-menu 'Info-history-forward "right-arrow" map Info-mode-map
                                   :rtl "left-arrow"
     (tool-bar-local-item-from-menu 'Info-history-forward "right-arrow" map Info-mode-map
                                   :rtl "left-arrow"
-                                  :label "Forward")
+                                  :label "Forward"
+                                  :vert-only t)
+    (define-key-after map [separator-1] menu-bar-separator)
     (tool-bar-local-item-from-menu 'Info-prev "prev-node" map Info-mode-map
                                   :rtl "next-node")
     (tool-bar-local-item-from-menu 'Info-next "next-node" map Info-mode-map
                                   :rtl "prev-node")
     (tool-bar-local-item-from-menu 'Info-prev "prev-node" map Info-mode-map
                                   :rtl "next-node")
     (tool-bar-local-item-from-menu 'Info-next "next-node" map Info-mode-map
                                   :rtl "prev-node")
-    (tool-bar-local-item-from-menu 'Info-up "up-node" map Info-mode-map)
-    (tool-bar-local-item-from-menu 'Info-top-node "home" map Info-mode-map)
+    (tool-bar-local-item-from-menu 'Info-up "up-node" map Info-mode-map
+                                  :vert-only t)
+    (define-key-after map [separator-2] menu-bar-separator)
+    (tool-bar-local-item-from-menu 'Info-top-node "home" map Info-mode-map
+                                  :vert-only t)
     (tool-bar-local-item-from-menu 'Info-goto-node "jump-to" map Info-mode-map)
     (tool-bar-local-item-from-menu 'Info-goto-node "jump-to" map Info-mode-map)
+    (define-key-after map [separator-3] menu-bar-separator)
     (tool-bar-local-item-from-menu 'Info-index "index" map Info-mode-map
     (tool-bar-local-item-from-menu 'Info-index "index" map Info-mode-map
-                                  :label "Index Search")
-    (tool-bar-local-item-from-menu 'Info-search "search" map Info-mode-map)
-    (tool-bar-local-item-from-menu 'Info-exit "exit" map Info-mode-map)
+                                  :label "Index")
+    (tool-bar-local-item-from-menu 'Info-search "search" map Info-mode-map
+                                  :vert-only t)
+    (tool-bar-local-item-from-menu 'Info-exit "exit" map Info-mode-map
+                                  :vert-only t)
     map))
 
 (defvar Info-menu-last-node nil)
     map))
 
 (defvar Info-menu-last-node nil)
@@ -4089,7 +4096,7 @@ The `info-file' property of COMMAND says which Info manual to search.
 If COMMAND has no property, the variable `Info-file-list-for-emacs'
 defines heuristics for which Info manual to try.
 The locations are of the format used in `Info-history', i.e.
 If COMMAND has no property, the variable `Info-file-list-for-emacs'
 defines heuristics for which Info manual to try.
 The locations are of the format used in `Info-history', i.e.
-\(FILENAME NODENAME BUFFERPOS\), where BUFFERPOS is the line number
+\(FILENAME NODENAME BUFFERPOS), where BUFFERPOS is the line number
 in the first element of the returned list (which is treated specially in
 `Info-goto-emacs-command-node'), and 0 for the rest elements of a list."
   (let ((where '()) line-number
 in the first element of the returned list (which is treated specially in
 `Info-goto-emacs-command-node'), and 0 for the rest elements of a list."
   (let ((where '()) line-number
@@ -4674,7 +4681,7 @@ the variable `Info-file-list-for-emacs'."
 (eval-when-compile (require 'speedbar))
 
 (defvar Info-speedbar-key-map nil
 (eval-when-compile (require 'speedbar))
 
 (defvar Info-speedbar-key-map nil
-  "Keymap used when in the info display mode.")
+  "Keymap used when in the Info display mode.")
 
 (defun Info-install-speedbar-variables ()
   "Install those variables used by speedbar to enhance Info."
 
 (defun Info-install-speedbar-variables ()
   "Install those variables used by speedbar to enhance Info."
@@ -4722,7 +4729,7 @@ This will add a speedbar major display mode."
   (speedbar-change-initial-expansion-list "Info")
   )
 
   (speedbar-change-initial-expansion-list "Info")
   )
 
-(defun Info-speedbar-hierarchy-buttons (directory depth &optional node)
+(defun Info-speedbar-hierarchy-buttons (_directory depth &optional node)
   "Display an Info directory hierarchy in speedbar.
 DIRECTORY is the current directory in the attached frame.
 DEPTH is the current indentation depth.
   "Display an Info directory hierarchy in speedbar.
 DIRECTORY is the current directory in the attached frame.
 DEPTH is the current indentation depth.
@@ -4756,7 +4763,7 @@ specific node to expand."
           t)
        nil))))
 
           t)
        nil))))
 
-(defun Info-speedbar-goto-node (text node indent)
+(defun Info-speedbar-goto-node (_text node _indent)
   "When user clicks on TEXT, go to an info NODE.
 The INDENT level is ignored."
   (speedbar-select-attached-frame)
   "When user clicks on TEXT, go to an info NODE.
 The INDENT level is ignored."
   (speedbar-select-attached-frame)
@@ -4835,7 +4842,7 @@ NODESPEC is a string of the form: (file)node."
 
 ;;; Info mode node listing
 ;; This is called by `speedbar-add-localized-speedbar-support'
 
 ;;; Info mode node listing
 ;; This is called by `speedbar-add-localized-speedbar-support'
-(defun Info-speedbar-buttons (buffer)
+(defun Info-speedbar-buttons (_buffer)
   "Create a speedbar display to help navigation in an Info file.
 BUFFER is the buffer speedbar is requesting buttons for."
   (if (save-excursion (goto-char (point-min))
   "Create a speedbar display to help navigation in an Info file.
 BUFFER is the buffer speedbar is requesting buttons for."
   (if (save-excursion (goto-char (point-min))
@@ -4866,7 +4873,7 @@ BUFFER is the buffer speedbar is requesting buttons for."
 
 ;;;;  Desktop support
 
 
 ;;;;  Desktop support
 
-(defun Info-desktop-buffer-misc-data (desktop-dirname)
+(defun Info-desktop-buffer-misc-data (_desktop-dirname)
   "Auxiliary information to be saved in desktop file."
   (list Info-current-file
        Info-current-node
   "Auxiliary information to be saved in desktop file."
   (list Info-current-file
        Info-current-node
@@ -4878,7 +4885,7 @@ BUFFER is the buffer speedbar is requesting buttons for."
                         'slow Info-current-file Info-current-node)
                        (cons 'slow t))))))
 
                         'slow Info-current-file Info-current-node)
                        (cons 'slow t))))))
 
-(defun Info-restore-desktop-buffer (desktop-buffer-file-name
+(defun Info-restore-desktop-buffer (_desktop-buffer-file-name
                                     desktop-buffer-name
                                     desktop-buffer-misc)
   "Restore an Info buffer specified in a desktop file."
                                     desktop-buffer-name
                                     desktop-buffer-misc)
   "Restore an Info buffer specified in a desktop file."
@@ -4930,6 +4937,27 @@ type returned by `Info-bookmark-make-record', which see."
     (bookmark-default-handler
      `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk)))))
 
     (bookmark-default-handler
      `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk)))))
 
+\f
+;;;###autoload
+(defun info-display-manual (manual)
+  "Go to Info buffer that displays MANUAL, creating it if none already exists."
+  (interactive "sManual name: ")
+  (let ((blist (buffer-list))
+       (manual-re (concat "\\(/\\|\\`\\)" manual "\\(\\.\\|\\'\\)"))
+       (case-fold-search t)
+       found)
+    (dolist (buffer blist)
+      (with-current-buffer buffer
+       (when (and (eq major-mode 'Info-mode)
+                  (stringp Info-current-file)
+                  (string-match manual-re Info-current-file))
+         (setq found buffer
+               blist nil))))
+    (if found
+       (pop-to-buffer found)
+      (info-initialize)
+      (info (Info-find-file manual)))))
+
 (provide 'info)
 
 ;;; info.el ends here
 (provide 'info)
 
 ;;; info.el ends here