;; 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, 2011
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1992-2011 Free Software Foundation, Inc.
;; Maintainer: FSF
;; Keywords: help
;;; Code:
-(eval-when-compile (require 'jka-compr) (require 'cl))
+(eval-when-compile (require 'cl))
(defgroup info nil
"Info subsystem."
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
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.")
;; 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.
"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))
(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
- (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))
- (split-string path (regexp-quote path-separator)))
+ (split-string path sep))
(Info-default-dirs)))))))
;;;###autoload
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
(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.
(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)))
(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)))
;; \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
(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))))
(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)
+ "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)
(substring string 1)
predicate
code))
-
;; If a file name was given, then any node is fair game.
((string-match "\\`(" string)
(cond
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)
+ "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)))
(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
`(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))))
))
(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)))
-(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)
-(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
))
(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)))
-(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)
-(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")
(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)))
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
(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)
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))))
-(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)
-(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)))
"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)))
(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)
(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")
"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)
\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
- 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.
-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."
(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 "<" '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)
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
(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."
(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.
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)
;;; 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))
;;;; 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
'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."
(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