;;; info+.el --- Extensions to `info.el'. ;; ;; Filename: info+.el ;; Description: Extensions to `info.el'. ;; Author: Drew Adams ;; Maintainer: Drew Adams ;; Copyright (C) 1996-2007, Drew Adams, all rights reserved. ;; Created: Tue Sep 12 16:30:11 1995 ;; Version: 21.1 ;; Last-Updated: Fri Jul 13 10:19:57 2007 (-25200 Pacific Daylight Time) ;; By: dradams ;; Update #: 3041 ;; URL: http://www.emacswiki.org/cgi-bin/wiki/info+.el ;; Keywords: help, docs, internal ;; Compatibility: GNU Emacs 20.x, GNU Emacs 21.x, GNU Emacs 22.x ;; ;; Features that might be required by this library: ;; ;; `avoid', `fit-frame', `frame-cmds', `frame-fns', `info', ;; `info+', `misc-fns', `strings', `thingatpt', `thingatpt+'. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: ;; ;; Extensions to `info.el'. ;; ;; Faces defined here: ;; ;; `info-elisp-command-ref-item', ;; `info-elisp-function-ref-item',`info-elisp-macro-ref-item', ;; `info-elisp-reference-item', `info-elisp-special-form-ref-item', ;; `info-elisp-syntax-class-item', ;; `info-elisp-user-option-ref-item', ;; `info-elisp-variable-ref-item', `info-file', `info-menu', ;; `info-node', `info-quoted-name', `info-string', `info-xref', ;; `minibuffer-prompt'. ;; ;; Options (variables) defined here: ;; ;; `Info-display-node-header-fn', `Info-fit-frame-flag', ;; `Info-fontify-quotations-flag', `Info-subtree-separator'. ;; ;; Functions defined here: ;; ;; `Info-display-node-default-header', ;; `Info-display-node-time-header', `info-emacs-manual', ;; `Info-follow-nearest-node-new-window', ;; `info-fontify-quotations', `info-fontify-reference-items', ;; `Info-merge-subnodes', ;; `Info-mouse-follow-nearest-node-new-window', ;; `menu-bar-read-lispintro', `menu-bar-read-lispref'. ;; ;; Internal variables defined here: ;; ;; `Info-merged-map'. ;; ;; ;; ***** NOTE: The following standard faces defined in `info.el' ;; (Emacs 21+) have been REDEFINED HERE: ;; ;; `info-title-1', `info-title-2', `info-title-3', `info-title-4'. ;; ;; ;; ***** NOTE: The following standard functions defined in `info.el' ;; have been REDEFINED HERE: ;; ;; `Info-find-emacs-command-nodes' - Added in-progress message. ;; `Info-find-node', `Info-find-node-2' - ;; Call `fit-frame' if `Info-fit-frame-flag'. ;; `Info-fontify-node' - ;; 1. File name in face `info-file'. ;; 2. Node names in face `info-node'. ;; 3. Menu items in face `info-menu'. ;; 4. Only 5th and 9th menu items have their `*' colored. ;; 5. Notes in face `info-xref'. ;; 6. If `Info-fontify-quotations-flag', then fontify `...' in ;; face `info-quoted-name' and "..." in face `info-string'. ;; `Info-goto-emacs-command-node' - ;; 1. Uses `completing-read' in interactive spec, with, ;; as default, `symbol-nearest-point'. ;; 2. Message if single node found. ;; 3. Returns `num-matches' if found; nil if not. ;; `Info-goto-emacs-key-command-node' - ;; If key's command not found, then `Info-search's for key ;; sequence in text and displays message about repeating. ;; `Info-mode' - Doc string shows all bindings. ;; `Info-search' - 1. Fits frame. ;; 2. Highlights found regexp if `search-highlight'. ;; `Info-mouse-follow-nearest-node' (Emacs 21+) - ;; With prefix arg, show node in new info buffer. ;; ;; ;; ***** NOTE: The following behavior defined in `info.el' ;; has been changed. ;; ;; "*info" has been removed from `same-window-buffer-names', so that ;; a separate window can be used if the user so chooses. ;; ;; ;; NOTE: The faces defined here look best on a medium-dark background. ;; Try, for example, setting the background to "LightSteelBlue" ;; in your `~/.emacs' file. You can do this is via ;; `special-display-buffer-names': ;; ;; (setq special-display-buffer-names ;; (cons '("*info*" (background-color . "LightSteelBlue")) ;; special-display-buffer-names)) ;; ;; You can alternatively change the background value of ;; `special-display-frame-alist' and set ;; `special-display-regexps' to something matching "*info*": ;; ;; (setq special-display-frame-alist ;; (cons '(background-color . "LightSteelBlue") ;; special-display-frame-alist)) ;; (setq special-display-regexps '("[ ]?[*][^*]+[*]")) ;; ;; ;; The following bindings are made here for Info-mode: ;; ;; `?' `describe-mode' (replaces `Info-summary') ;; `+' `Info-merge-subnodes' ;; `mouse-4' `Info-history-back' ;; `mouse-5' `Info-history-forward' ;; `S-mouse-2' `Info-mouse-follow-nearest-node-new-window' ;; `S-RET' `Info-follow-nearest-node-new-window' ;; ;; The following bindings are made here for merged Info buffers: ;; ;; `.' `beginning-of-buffer' ;; `b' `beginning-of-buffer' ;; `q' `quit-window' ;; `s' `nonincremental-re-search-forward' ;; `M-s' `nonincremental-re-search-forward' ;; `TAB' `Info-next-reference' ;; `ESC TAB' `Info-prev-reference' ;; ;; ;; ;; This file should be loaded after loading the standard GNU file ;; `info.el'. So, in your `~/.emacs' file, do this: ;; (eval-after-load "info" '(require 'info+)) ;; ;; ;; Acknowledgement: ;; ;; Lennart Borgman and Stefan Monnier for regexp suggestions. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Change log: ;; ;; 2007/07/13 dadams ;; Info-find-node: Redefine only for Emacs < 21. ;; 2006/09/15 dadams ;; Info-mouse-follow-nearest-node redefinition is only for Emacs >= 22. ;; Changed Emacs 22 tests to just (>= emacs-major-version 22). ;; Bind tool-bar-map for Emacs 21. Otherwise, binding of [tool-bar] gives an error (why?). ;; 2006/08/18 dadams ;; Everywhere: Corrected previous change: minibuffer-selected-window to window-minibuffer-p. ;; 2006/08/14 dadams ;; Everywhere: fit-frame only if not a minibuffer window. ;; 2006/08/12 dadams ;; Info-merge-subnodes: Bug fixes: ;; Added concat for insertion of main node when recursive-display-p is negative. ;; Don't recurse down Index menus. ;; When checking for subnodes menu, check for nonfile menu item also. ;; After come back from recursion, go back to Info buffer before trying to go back in history. ;; Call fit-frame at end. ;; 2006/06/10 dadams ;; Added: Info(-mouse)-follow-nearest-node-new-window. Bound to S-RET, S-mouse-2. ;; 2006/03/31 dadams ;; info-menu-header: Removed :underline, because links are underlined in Emacs 22. ;; No longer use display-in-minibuffer. ;; 2006/01/08 dadams ;; Added: redefinition of Info-mouse-follow-nearest-node. ;; 2006/01/07 dadams ;; Added :link for sending bug report. ;; 2006/01/06 dadams ;; Added defgroup Info-Plus and used it. Added :link. ;; 2005/12/30 dadams ;; Moved everything from setup-info.el to here, after getting rid of some of it. ;; Use defface for all faces. Renamed faces, without "-face". ;; Use minibuffer-prompt face, not info-msg-face. ;; No longer require setup-info.el. No longer require cl.el when compile. ;; 2005/11/21 dadams ;; Info-search for Emacs 22: Don't display repeat `s' message if isearch-mode. ;; 2005/11/09 dadams ;; Info-fontify-node: Updated to reflect latest CVS (replaced Info-escape-percent header). ;; 2005/10/31 dadams ;; Use nil as init-value arg in calls to completing-read, everywhere. ;; 2005/07/04 dadams ;; info-fontify-quotations: Use font-lock-face property, instead of face, for Emacs 22. ;; Wrap re-search-forward in condition-case for stack overflow. ;; 2005/07/02 dadams ;; Info-search: fit-frame. Added Emacs 22 version too. ;; Info-goto-emacs-command-node, Info-goto-emacs-key-command-node, ;; Info-merge-subnodes: Use Info-history-back for Emacs 22. ;; Info-mode: Added Emacs 22 version. ;; 2005/06/23 dadams ;; Info-fontify-node: Fontify reference items if in Emacs-Lisp manual. ;; Added: info-fontify-reference-items ;; 2005/05/17 dadams ;; Updated to work with Emacs 22.x. ;; 2004/11/20 dadams ;; Info-find-emacs-command-nodes: bug fix: regexp (cmd-desc) was only for Emacs 21. ;; Refined to deal with Emacs 21 < 21.3.50 (soon to be 22.x) ;; 2004/10/09 dadams ;; info-fontify-quotations: ;; 1) Allow all characters inside `...'. ;; 2) Treat case of "..." preceded by backslashes ;; Info-fontify-node (for Emacs 21): Moved info-fontify-quotations ;; before fontification of titles. ;; 2004/10/07 dadams ;; Renamed Info-resize-frame-p to Info-fit-frame-flag. ;; 2004/10/05 dadams ;; Improved regexp treatment further for fontifying quotations. ;; 2004/10/04 dadams ;; Improved regexp treatment for fontifying quotations. ;; Added info-fontify-quotations. Removed info-fontify-strings-p. ;; Renamed Info-fontify-quotations-p to Info-fontify-quotations-flag. ;; 2004/10/03/dadams ;; Major update: updated to work with Emacs 21 also. ;; Made require of setup-info.el mandatory. ;; Removed all variables and keys to setup-info.el. ;; Renamed to Emacs 21 names and only define for Emacs < 21: ;; emacs-info -> info-emacs-manual ;; 2004/09/28 dadams ;; Removed dir-info (same as Info-directory). ;; Renamed to Emacs 21 names and only define for Emacs < 21: ;; emacs-lisp-info -> menu-bar-read-lispref ;; 2004/06/01 dadams ;; Renamed: Info-fit-frame-p to Info-resize-frame-p ;; and shrink-frame-to-fit to resize-frame. ;; 2000/09/27 dadams ;; 1. Added: Info-fit-frame-p. ;; 2. Info-find-node: added shrink-frame-to-fit. ;; 1999/04/14 dadams ;; Info-fontify-node: Fontify indexes too. ;; 1999/04/14 dadams ;; 1. Added vars: info-file-face, info-menu-face, info-node-face, ;; info-quoted-name-face, info-string-face, info-xref-face. ;; 2. No longer use (or define) faces: info-node, info-file, info-xref, ;; info-menu-5, info-quoted-name, info-string. ;; 3. Info-fontify-node: Use new face variables instead of faces in #2, above. ;; Corrected: node names in info-node-face (was xref). Use info-menu-face ;; for * and menu item. ;; 4. Info-mode: Redefined like original, but: no make-face's; use face vars. ;; Added user options description to doc string. ;; 1999/04/08 dadams ;; Info-goto-emacs-key-command-node: regexp-quote pp-key for Info-search. ;; 1999/04/07 dadams ;; Info-goto-emacs-key-command-node: a) messages only if interactive, ;; b) return nil if not found, else non-nil, c) "is undefined" -> "doc not ;; found", d) use display-in-minibuffer more, e) corrected error handler. ;; 1999/04/01 dadams ;; 1. Added: (remove-hook 'same-window-buffer-names "*info*"). ;; 2. Info-find-node: switch-to-buffer-other-window -> pop-to-buffer. ;; 1999/03/31 dadams ;; 1. Added (put 'Info-goto-emacs-(key-)command-node 'info-file "emacs"). ;; 2. Info-find-node: Mention searched file in error messages. ;; 3. Added (replacement): Info-find-emacs-command-nodes, with progress msg. ;; 4. a. Info-goto-emacs-key-command-node: Use global-map, unless menu item. ;; b. Added message "Not found using Index ...". ;; 1999/03/31 dadams ;; 1. Info-goto-emacs(-key)-command-node: Only display-in-minibuffer if ;; interactive-p. ;; 2. Info-goto-emacs-key-command-node: Messages: "key"; other entries. ;; 1999/03/31 dadams ;; 1. Added (put 'info 'info-file "emacs") so find doc on `info' cmd. ;; 2. Info-goto-emacs-command-node: ;; a. Added message when =< 1 match. ;; b. Return num-matches if found. ;; c. Uses `display-in-minibuffer' instead of `message'. ;; 3. a. Wrapped call to Info-search in condition-case, not if. ;; b. Info-goto-emacs-key-command-node: Return num-matches if found. ;; 1999/03/30 dadams ;; 1. Added Info menu bar menu. ;; 2. Info-goto-emacs-command-node: Only error if interactive-p. ;; 3. Info-goto-emacs-key-command-node: ;; a. Print key in msgs ;; b. If Info-goto-emacs-command-node doesn't find it, then try ;; Info-search. If found & interactive-p, then msg ("repeat"). ;; Else error. ;; 4. Info-search: Msg ("repeat") if found & interactive-p. ;; 1999/03/17 dadams ;; 1. Updated to correspond with Emacs 34.1 version. ;; 2. Protect with fboundp. ;; 1996/07/11 dadams ;; Added redefinitions of Info-goto-emacs-(key-)command-node. ;; 1996/04/26 dadams ;; Put escaped newlines on long-line strings. ;; 1996/04/16 dadams ;; Added: info-file, info-quoted-name, info-string, Info-fontify-quotations-flag, ;; info-fontify-strings-p. Take into account in Info-fontify-node. ;; 1996/02/23 dadams ;; 1. Changed binding of Info-merge-subnodes back to `r', but now ;; requires user confirmation when invoked. ;; 2. Info-subtree-separator: Incorporates "\n* ". variable-interactive prop. ;; 1996/02/22 dadams ;; display-Info-node-subtree: ;; 1. display-Info-node-subtree -> Info-merge-subnodes (renamed). ;; 2. Changed binding of Info-merge-subnodes from `r' to `C-d'. ;; 3. Don't pick up text between menu-item-line and "\n* ". Hardwire "\n* ". ;; 4. Untabify menu-item-line, so can count chars to underline. ;; 5. indent-rigidly, not indent-region. ;; 1996/02/22 dadams ;; 1. Bind describe-mode and display-Info-node-subtree. ;; 2. Added redefinition of Info-mode: Only the doc string was changed. ;; 3. Added Info-subtree-separator. ;; 3. display-Info-node-subtree: Info-subtree-separator. Doc. Garbage-collect. ;; 1996/02/22 dadams ;; Info-merge-subnodes: Rewrote it, adding optional args. Renamed (defaliased) it ;; to display-Info-node-subtree. ;; 1996/02/22 dadams ;; Added redefinition of Info-merge-subnodes (cleanup, corrections). ;; 1996/02/20 dadams ;; 1. Make info-node, info-xref, info-menu-5 here. (Diff faces than before.) ;; 2. Added redefinition of Info-find-node. (Uses other window.) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth ;; Floor, Boston, MA 02110-1301, USA. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Code: (require 'info) (when (< emacs-major-version 20) (eval-when-compile (require 'cl))) ;; caar, cadr, when, unless ;; These are optional, for cosmetic purposes. (require 'thingatpt nil t) ;; (no error if not found): symbol-at-point (require 'thingatpt+ nil t) ;; (no error if not found): symbol-nearest-point (require 'strings nil t) ;; (no error if not found): concat-w-faces (require 'fit-frame nil t) ;; (no error if not found): fit-frame ;; Quiet the byte compiler a bit (when (< emacs-major-version 21) (eval-when-compile (defvar Info-fontify-visited-nodes) (defvar Info-hide-note-references) (defvar Info-history-list) (defvar Info-menu-entry-name-re) (defvar Info-next-link-keymap) (defvar Info-node-spec-re) (defvar Info-point-loc) (defvar Info-prev-link-keymap) (defvar Info-refill-paragraphs) (defvar Info-up-link-keymap) (defvar Info-use-header-line) (defvar desktop-save-buffer) (defvar header-line-format) (defvar info-tool-bar-map))) ;;; You will likely get byte-compiler messages saying that variable ;;; node-name is free. In addition, in Emacs < 21, you might get ;;; byte-compiler messages saying that these variables are free: ;; ;;; Info-isearch-initial-node, Info-isearch-search, ;;; Info-search-case-fold, Info-search-history, ;;; Info-search-whitespace-regexp, widen-automatically. ;;; ;;; In Emacs < 21 you might also get a byte-compiler message saying ;;; that these functions are not known to be defined: ;;; ;;; Info-escape-percent, Info-find-in-tag-table, ;;; Info-find-node-in-buffer, Info-find-node-2, Info-history-back, ;;; Info-index-node, Info-index-nodes, replace-regexp-in-string, ;;; run-mode-hooks, set-face-attribute, substring-no-properties. ;;;;;;;;;;;;;;;;;;;; (provide 'info+) (require 'info+) ;; Ensure loaded before compiling. ;;;;;;;;;;;;;;;;;;;; ;;; KEYS & MENUS ;;;;;;;;;;;;;;;;;;;;;;;; (define-key Info-mode-map "?" 'describe-mode) ; Don't use `Info-summary'. (define-key Info-mode-map "+" 'Info-merge-subnodes) ;; Define mouse back and forward buttons (when (>= emacs-major-version 22) (define-key Info-mode-map [S-mouse-2] 'Info-mouse-follow-nearest-node-new-window) (define-key Info-mode-map [S-return] 'Info-follow-nearest-node-new-window) (define-key Info-mode-map [mouse-4] 'Info-history-back) (define-key Info-mode-map [mouse-5] 'Info-history-forward)) ;;; FACES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defgroup Info-Plus nil "Various enhancements to Info." :group 'info :link `(url-link :tag "Send Bug Report" ,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\ info+.el bug: \ &body=Describe bug here, starting with `emacs -q'. \ Don't forget to mention your Emacs and library versions.")) :link '(url-link :tag "Other Libraries by Drew" "http://www.emacswiki.org/cgi-bin/wiki/DrewsElispLibraries") :link '(url-link :tag "Download" "http://www.emacswiki.org/cgi-bin/wiki/info+.el") :link '(url-link :tag "Description" "http://www.emacswiki.org/cgi-bin/wiki/InfoPlus") :link '(emacs-commentary-link :tag "Commentary" "info+") ) ;; This is defined in `faces.el', Emacs 22. This definition is adapted to Emacs 20. (unless (facep 'minibuffer-prompt) (defface minibuffer-prompt '((((background dark)) (:foreground "cyan")) (t (:foreground "dark blue"))) "Face for minibuffer prompts." :group 'basic-faces)) (defface info-file '((t (:foreground "DarkBlue" :background "LightGray"))) "*Face used for file heading labels in `info'." :group 'Info-Plus :group 'faces) (defface info-menu '((t (:foreground "Blue"))) "*Face used for menu items in `info'." :group 'Info-Plus :group 'faces) ;; (defface info-xref '((t (:foreground "Blue"))) ;; "*Face used for cross reference \"Note\" links in `info'." :group 'Info-Plus :group 'faces) ;; (defface info-node '((t (:foreground "Blue" :background "SkyBlue"))) ;; "*Face used for node heading labels in `info'." :group 'Info-Plus :group 'faces) (defface info-quoted-name ; For `...' '((t (:inherit font-lock-constant-face))) "Face used for quoted names (`...') in `info'." :group 'Info-Plus) (set-face-foreground 'info-quoted-name "yellow") (defface info-string ; For "..." '((t (:inherit font-lock-string-face))) "Face used for strings (\"...\") in `info'." :group 'Info-Plus) (set-face-foreground 'info-string "red3") (cond ((fboundp 'set-face-attribute) ;; Other faces to possibly change: ;; info-menu-5, info-xref, info-xref-visited, info-header-xref (set-face-attribute 'info-menu-header nil :foreground "DarkBlue" :weight 'bold) (set-face-attribute 'info-header-node nil :foreground "DarkBlue" :background "LightGray" :weight 'bold :slant 'italic) (set-face-attribute 'info-node nil :weight 'bold :slant 'italic) ) (t ; Emacs 20 - cannot use set-face-attribute. (set-face-foreground 'info-node "Blue") (set-face-background 'info-node "SkyBlue") (set-face-foreground 'info-xref "Blue") ;; (set-face-underline-p 'info-xref t) )) (when (facep 'header-line) ; Emacs 22 (set-face-attribute 'header-line nil :foreground "Black" :background "PaleGoldenrod" :weight 'bold)) ;; Standard faces from Emacs 22 `info.el'. ;; Use them also for other versions, but without :height and :inherit. (defface info-title-1 '((((type tty pc) (class color)) :foreground "green" :weight bold)) "Face for info titles at level 1." :group (if (facep 'info-title-1) 'info 'Info-Plus)) ;; backward-compatibility alias (put 'Info-title-1-face 'face-alias 'info-title-1) (defface info-title-2 '((((type tty pc) (class color)) :foreground "lightblue" :weight bold)) "Face for info titles at level 2." :group (if (facep 'info-title-1) 'info 'Info-Plus)) ;; backward-compatibility alias (put 'Info-title-2-face 'face-alias 'info-title-2) (defface info-title-3 '((((type tty pc) (class color)) :weight bold)) "Face for info titles at level 3." :group (if (facep 'info-title-1) 'info 'Info-Plus)) ;; backward-compatibility alias (put 'Info-title-3-face 'face-alias 'info-title-3) (defface info-title-4 '((((type tty pc) (class color)) :weight bold)) "Face for info titles at level 4." :group (if (facep 'info-title-1) 'info 'Info-Plus)) ;; backward-compatibility alias (put 'Info-title-4-face 'face-alias 'info-title-4) ;; But we change the colors. (set-face-foreground 'info-title-1 "DarkBlue") (set-face-background 'info-title-1 "LightGray") (set-face-foreground 'info-title-2 "Firebrick") (set-face-background 'info-title-2 "LightGray") (set-face-foreground 'info-title-3 "DarkGreen") (set-face-background 'info-title-3 "LightGray") (set-face-foreground 'info-title-4 "DarkMagenta") (set-face-background 'info-title-4 "LightGray") (when (<= emacs-major-version 21) (setq Info-title-face-alist '((?* info-title-1 bold underline) (?= info-title-2 bold-italic underline) (?- info-title-4 italic underline)))) ;;; Faces for highlighting reference items in Emacs-Lisp manual (defface info-elisp-function-ref-item '((t (:foreground "DarkBlue" :background "LightGray"))) "Face used for \"Function:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-variable-ref-item '((t (:foreground "FireBrick" :background "LightGray"))) "Face used for \"Variable:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-special-form-ref-item '((t (:foreground "DarkMagenta" :background "LightGray"))) "Face used for \"Special Form:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-command-ref-item '((t (:foreground "Blue" :background "LightGray"))) "Face used for \"Command:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-user-option-ref-item '((t (:foreground "Red" :background "LightGray"))) "Face used for \"User Option:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-macro-ref-item '((t (:foreground "DarkMagenta" :background "LightGray"))) "Face used for \"Macro:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-syntax-class-item '((t (:foreground "DarkGreen" :background "LightGray"))) "Face used for \"Syntax Class:\" reference items in `info' Elisp manual." :group 'Info-Plus) (defface info-elisp-reference-item '((t (:background "LightGray"))) "Face used for reference items in `info' Elisp manual." :group 'Info-Plus) ;;; USER OPTIONS (VARIABLES) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;###autoload (defcustom Info-fit-frame-flag t "*Non-nil means call `fit-frame' on Info buffer." :type 'boolean :group 'Info-Plus :group 'Fit-Frame) ;;;###autoload (defcustom Info-fontify-quotations-flag t "*Non-nil means `info' fontifies text between quotes. This applies to double-quote strings (\"...\") and text between single-quotes (`...'). Note: This fontification can never be 100% reliable. It aims to be useful in most Info texts, but it can occasionally result in fontification that you might not expect. This is not a bug; it is part of the design to be able to appropriately fontify a great variety of texts. Set this flag to nil if you do not find this fontification useful." :type 'boolean :group 'Info-Plus) ;;;###autoload (defcustom Info-display-node-header-fn 'Info-display-node-default-header "*Function to insert header by `Info-merge-subnodes'." :type 'function :group 'Info-Plus) ;;;###autoload (defcustom Info-subtree-separator "\n* " "*A string used to separate Info node descriptions. Inserted by `Info-merge-subnodes' just before each node title. Setting this to a string that includes a form-feed (^L), such as \"\f\n* \", will cause a page break before each node description. Use command `set-variable' to set this, quoting any control characters you want to include, such as form-feed (^L) and newline (^J), with ^Q. For example, type `^Q^L^Q^J* ' to set this to \"\f\n* \"." :type 'string :group 'Info-Plus) (put 'Info-subtree-separator 'variable-interactive "sString to be inserted before node titles (^Q to quote control chars): ") ;;; NEW COMMANDS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (when (>= emacs-major-version 22) (defun Info-mouse-follow-nearest-node-new-window (click) "Open the link at the mouse pointer in a new window." (interactive "e") (Info-mouse-follow-nearest-node click t)) (defun Info-follow-nearest-node-new-window () "Open the link near the text cursor in a new window." (interactive) (Info-follow-nearest-node t))) ;;; INTERNAL VARIABLES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defvar Info-merged-map nil "Keymap for merged Info buffer.") (if Info-merged-map nil (setq Info-merged-map (make-keymap)) (suppress-keymap Info-merged-map) (define-key Info-merged-map "." 'beginning-of-buffer) (define-key Info-merged-map "\t" 'Info-next-reference) (define-key Info-merged-map "\e\t" 'Info-prev-reference) (define-key Info-merged-map "b" 'beginning-of-buffer) (define-key Info-merged-map "q" 'quit-window) (define-key Info-merged-map "s" 'nonincremental-re-search-forward) (define-key Info-merged-map "\M-s" 'nonincremental-re-search-forward)) (if (>= emacs-major-version 22) (easy-menu-define Info-mode-menu Info-mode-map "Menu for info files." '("Info" ["Table of Contents" Info-toc :help "Go to table of contents"] ["Find...(Regexp)" Info-search :help "Search for regular expression in this Info file"] ["Find Case-Sensitively..." Info-search-case-sensitively :help "Search for regular expression case sensitively"] ["Find Again" Info-search-next :help "Search for another occurrence of same regular expression"] ("Index" ["Find with Index..." Info-index :help "Look for a string in the index"] ["Find Again with Index" Info-index-next :active Info-index-alternatives :help "Look for string again in index"] ["Find In All Indexes..." info-apropos :help "Look for a string in the indexes of all manuals"]) "--" ["Back (History)" Info-history-back :active Info-history :help "Go back in history to the last node you were at"] ["Forward (History)" Info-history-forward :active Info-history-forward :help "Go forward in history"] ["History List" Info-history :active Info-history-list :help "Go to menu of visited nodes"] "--" ["Top" Info-directory :help "Go to the list of manuals (Info top level)"] ["Up" Info-up :active (Info-check-pointer "up") :help "Go up in the Info tree"] ["Next" Info-next :active (Info-check-pointer "next") :help "Go to the next node"] ["Previous" Info-prev :active (Info-check-pointer "prev[ious]*") :help "Go to the previous node"] ("Menu Item" ["You should never see this" report-emacs-bug t]) ("Reference" ["You should never see this" report-emacs-bug t]) ["Go to Node..." Info-goto-node :help "Go to a named node"] "--" ["Forward" Info-forward-node :help "Go forward one node, considering all as a sequence"] ["Backward" Info-backward-node :help "Go backward one node, considering all as a sequence"] ["First in File" Info-top-node :help "Go to top node of file"] ["Last in File" Info-final-node :help "Go to final node in this file"] ["Beginning of This Node" beginning-of-buffer :help "Go to beginning of this node"] "--" ["Clone Info Buffer" clone-buffer :help "Create a twin copy of the current Info buffer."] ["Copy Node Name" Info-copy-current-node-name :help "Copy the name of the current node into the kill ring"] ["Merge Subnodes" Info-merge-subnodes :help "Integrate current node with nodes referred to in its Menu"] ["Edit" Info-edit :help "Edit contents of this node" :active Info-enable-edit] ["Quit Info" Info-exit :help "Exit from Info"])) (easy-menu-define Info-mode-menu Info-mode-map "Menu for Info files." '("Info" ["Back" Info-last Info-history] ("Menu item" ["You should never see this" report-emacs-bug t]) ("Reference" ["You should never see this" report-emacs-bug t]) "--" ["Up" Info-up (Info-check-pointer "up")] ["Next" Info-next (Info-check-pointer "next")] ["Previous" Info-prev (Info-check-pointer "prev[ious]*")] ["Top" Info-directory t] ["Goto Node..." Info-goto-node t] "--" ["Forward in File" Info-forward-node t] ["Backward in File" Info-backward-node t] ["First in File" Info-top-node t] ["Last in File" Info-final-node t] "--" ["Next Link in Node" Info-next-reference t] ["Previous Link in Node" Info-prev-reference t] "--" ["Search (regexp)" Info-search t] ["Info on Key" Info-goto-emacs-key-command-node t] ["Info on Command" Info-goto-emacs-command-node t] ["Find with Index" Info-index t] "--" ["Merge Subnodes" Info-merge-subnodes t] ["Edit Node" Info-edit t] "--" ["Tutorial" Info-help t] ["Quit Info" Info-exit t]))) (easy-menu-define Info-merged-menu Info-merged-map "Menu for merged `info' buffers." '("Info" ["Next Link" Info-next-reference t] ["Previous Link" Info-prev-reference t] ["Search (regexp)" Info-search t] ["Quit" quit-window t])) ;; Do this to counteract what is done in `info.el'. There is no ;; reason not to use a separate window, if the user, e.g., sets ;; `pop-up-windows' or `pop-up-frames' non-nil. ;; ;;;###autoload (if (>= emacs-major-version 22) (remove-hook 'same-window-regexps "\\*info\\*\\(\\|<[0-9]+>\\)") (remove-hook 'same-window-buffer-names "*info*")) ;; Make `Info-find-emacs-command-nodes' look for these commands in the ;; Emacs manual. In particular, don't look for command `info' in Info ;; manual, because that has no index. (put 'info 'info-file "emacs") (put 'Info-goto-emacs-command-node 'info-file "emacs") (put 'Info-goto-emacs-key-command-node 'info-file "emacs") ;;;###autoload (unless (>= emacs-major-version 22) ;; I previously called this `emacs-info', but Emacs 21 came out with this name. (defun info-emacs-manual () "Access the Emacs manual via \"Info\"." (interactive) (info "emacs")) ;; I previously called this `emacs-lisp-info', but Emacs 21 came out with this name. (defun menu-bar-read-lispref () "Access the Emacs Lisp manual via \"Info\"." (interactive) (info "elisp")) ;; From Emacs 21 `menu-bar.el'. Of course, the file `eintr.info' needs to be there. (defun menu-bar-read-lispintro () "Display the Introduction to Emacs Lisp Programming in Info mode." (interactive) (info "eintr"))) ;; REPLACES ORIGINAL in `info.el': ;; Calls `fit-frame' if `Info-fit-frame-flag'. ;; ;;;###autoload (when (< emacs-major-version 21) (defun Info-find-node (filename nodename &optional no-going-back) ;; Go to an info node specified as separate FILENAME and NODENAME. ;; NO-GOING-BACK is non-nil if recovering from an error in this function; ;; it says do not attempt further (recursive) error recovery. ;; Convert filename to lower case if not found as specified. ;; Expand it. (if filename (let (temp temp-downcase found) (setq filename (substitute-in-file-name filename)) (if (string= (downcase filename) "dir") (setq found t) (let ((dirs (if (string-match "^\\./" filename) ;; If specified name starts with `./' ;; then just try current directory. '("./") (if (file-name-absolute-p filename) ;; No point in searching for an absolute file name. '(nil) (if Info-additional-directory-list (append Info-directory-list Info-additional-directory-list) Info-directory-list))))) ;; Search the directory list for file FILENAME. (while (and dirs (not found)) (setq temp (expand-file-name filename (car dirs))) (setq temp-downcase (expand-file-name (downcase filename) (car dirs))) ;; Try several variants of specified name. (let ((suffix-list Info-suffix-list)) (while (and suffix-list (not found)) (cond ((info-file-exists-p (info-insert-file-contents-1 temp (caar suffix-list))) (setq found temp)) ((info-file-exists-p (info-insert-file-contents-1 temp-downcase (caar suffix-list))) (setq found temp-downcase))) (setq suffix-list (cdr suffix-list)))) (setq dirs (cdr dirs))))) (if found (setq filename found) (error "Info file `%s' does not exist" filename)))) ;; Record the node we are leaving. (if (and Info-current-file (not no-going-back)) (setq Info-history (cons (list Info-current-file Info-current-node (point)) Info-history))) ;; Go into info buffer. (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) (buffer-disable-undo (current-buffer)) (or (eq major-mode 'Info-mode) (Info-mode)) (widen) (setq Info-current-node nil) (unwind-protect ;; Bind case-fold-search in case the user sets it to nil. (let ((case-fold-search t) anchorpos) ;; Switch files if necessary (or (null filename) (equal Info-current-file filename) (let ((buffer-read-only nil)) (setq Info-current-file nil Info-current-subfile nil Info-current-file-completions nil buffer-file-name nil) (erase-buffer) (if (eq filename t) (Info-insert-dir) (info-insert-file-contents filename t) (setq default-directory (file-name-directory filename))) (set-buffer-modified-p nil) ;; See whether file has a tag table. Record the location if yes. (goto-char (point-max)) (forward-line -8) ;; Use string-equal, not equal, to ignore text props. (if (not (or (string-equal nodename "*") (not (search-forward "\^_\nEnd tag table\n" nil t)))) (let (pos) ;; We have a tag table. Find its beginning. ;; Is this an indirect file? (search-backward "\nTag table:\n") (setq pos (point)) (if (save-excursion (forward-line 2) (looking-at "(Indirect)\n")) ;; It is indirect. Copy it to another buffer ;; and record that the tag table is in that buffer. (let ((buf (current-buffer)) (tagbuf (or Info-tag-table-buffer (generate-new-buffer " *info tag table*")))) (setq Info-tag-table-buffer tagbuf) (save-excursion (set-buffer tagbuf) (buffer-disable-undo (current-buffer)) (setq case-fold-search t) (erase-buffer) (insert-buffer-substring buf)) (set-marker Info-tag-table-marker (match-end 0) tagbuf)) (set-marker Info-tag-table-marker pos))) (set-marker Info-tag-table-marker nil)) (setq Info-current-file (if (eq filename t) "dir" filename)))) ;; Use string-equal, not equal, to ignore text props. (if (string-equal nodename "*") (progn (setq Info-current-node nodename) (Info-set-mode-line)) ;; Possibilities: ;; ;; 1. Anchor found in tag table ;; 2. Anchor *not* in tag table ;; ;; 3. Node found in tag table ;; 4. Node *not* found in tag table, but found in file ;; 5. Node *not* in tag table, and *not* in file ;; ;; *Or* the same, but in an indirect subfile. ;; Search file for a suitable node. (let ((guesspos (point-min)) (regexp (concat "\\(Node:\\|Ref:\\) *\\(" (regexp-quote nodename) "\\) *[,\t\n\177]")) (nodepos nil)) ;; First, search a tag table, if any (if (marker-position Info-tag-table-marker) (let ((found-in-tag-table t) found-anchor found-mode (m Info-tag-table-marker)) (save-excursion (set-buffer (marker-buffer m)) (goto-char m) (beginning-of-line) ; so re-search will work. ;; Search tag table (catch 'foo (while (re-search-forward regexp nil t) (setq found-anchor (string-equal "Ref:" (match-string 1))) (or nodepos (setq nodepos (point)) (if (string-equal (match-string 2) nodename) (throw 'foo t)))) (if nodepos (goto-char nodepos) (setq found-in-tag-table nil))) (if found-in-tag-table (setq guesspos (1+ (read (current-buffer))))) (setq found-mode major-mode)) ;; Indirect file among split files (if found-in-tag-table (progn ;; If this is an indirect file, determine ;; which file really holds this node and ;; read it in. (if (not (eq found-mode 'Info-mode)) ;; Note that the current buffer must be ;; the *info* buffer on entry to ;; Info-read-subfile. Thus the hackery ;; above. (setq guesspos (Info-read-subfile guesspos))))) ;; Handle anchor (if found-anchor (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))) ;; Now search from our advised position ;; (or from beg of buffer) ;; to find the actual node. ;; First, check whether the node is right ;; where we are, in case the buffer begins ;; with a node. (setq nodepos nil) (or (and (string< "20.5" emacs-version) (Info-node-at-bob-matching regexp)) (catch 'foo (while (search-forward "\n\^_" nil t) (forward-line 1) (let ((beg (point))) (forward-line 1) (if (re-search-backward regexp beg t) (if (string-equal (match-string 2) nodename) (progn (beginning-of-line) (throw 'foo t)) (or nodepos (setq nodepos (point))))))) (if nodepos (progn (goto-char nodepos) (beginning-of-line)) (error "No such anchor in tag table or node in tag table \ or file: `%s'" nodename)))))) (goto-char (max (point-min) (- guesspos 1000))) ;; Now search from our advised position (or from beg of buffer) ;; to find the actual node. ;; First, check whether the node is right where we are, in case ;; the buffer begins with a node. (setq nodepos nil) (or (and (string< "20.5" emacs-version) (Info-node-at-bob-matching regexp)) (catch 'foo (while (search-forward "\n\^_" nil t) (forward-line 1) (let ((beg (point))) (forward-line 1) (if (re-search-backward regexp beg t) (if (string-equal (match-string 2) nodename) (throw 'foo t) (or nodepos (setq nodepos (point))))))) (if nodepos (goto-char nodepos) (error "No such node: `%s'" nodename)))))) (Info-select-node) (goto-char (or anchorpos (point-min)))) (when (and (one-window-p t) (not (window-minibuffer-p)) (fboundp 'fit-frame) ; Defined in `fit-frame.el'. Info-fit-frame-flag) (fit-frame))) ;; If we did not finish finding the specified node, ;; go back to the previous one. (or Info-current-node no-going-back (null Info-history) (let ((hist (car Info-history))) (setq Info-history (cdr Info-history)) (Info-find-node (nth 0 hist) (nth 1 hist) t) (goto-char (nth 2 hist))))))) ;; REPLACES ORIGINAL in `info.el': ;; Calls `fit-frame' if `Info-fit-frame-flag'. ;; ;;;###autoload (when (eq emacs-major-version 21) (defun Info-find-node-2 (filename nodename &optional no-going-back) (buffer-disable-undo (current-buffer)) (or (eq major-mode 'Info-mode) (Info-mode)) (widen) (setq Info-current-node nil) (unwind-protect (let ((case-fold-search t) anchorpos) ;; Switch files if necessary (or (null filename) (equal Info-current-file filename) (let ((buffer-read-only nil)) (setq Info-current-file nil Info-current-subfile nil Info-current-file-completions nil buffer-file-name nil) (erase-buffer) (if (eq filename t) (Info-insert-dir) (info-insert-file-contents filename t) (setq default-directory (file-name-directory filename))) (set-buffer-modified-p nil) ;; See whether file has a tag table. Record the location if yes. (goto-char (point-max)) (forward-line -8) ;; Use string-equal, not equal, to ignore text props. (if (not (or (string-equal nodename "*") (not (search-forward "\^_\nEnd tag table\n" nil t)))) (let (pos) ;; We have a tag table. Find its beginning. ;; Is this an indirect file? (search-backward "\nTag table:\n") (setq pos (point)) (if (save-excursion (forward-line 2) (looking-at "(Indirect)\n")) ;; It is indirect. Copy it to another buffer ;; and record that the tag table is in that buffer. (let ((buf (current-buffer)) (tagbuf (or Info-tag-table-buffer (generate-new-buffer " *info tag table*")))) (setq Info-tag-table-buffer tagbuf) (save-excursion (set-buffer tagbuf) (buffer-disable-undo (current-buffer)) (setq case-fold-search t) (erase-buffer) (insert-buffer-substring buf)) (set-marker Info-tag-table-marker (match-end 0) tagbuf)) (set-marker Info-tag-table-marker pos))) (set-marker Info-tag-table-marker nil)) (setq Info-current-file (if (eq filename t) "dir" filename)))) ;; Use string-equal, not equal, to ignore text props. (if (string-equal nodename "*") (progn (setq Info-current-node nodename) (Info-set-mode-line)) ;; Possibilities: ;; ;; 1. Anchor found in tag table ;; 2. Anchor *not* in tag table ;; ;; 3. Node found in tag table ;; 4. Node *not* found in tag table, but found in file ;; 5. Node *not* in tag table, and *not* in file ;; ;; *Or* the same, but in an indirect subfile. ;; Search file for a suitable node. (let ((guesspos (point-min)) (regexp (concat "\\(Node:\\|Ref:\\) *\\(" (if (stringp nodename) (regexp-quote nodename) "") "\\) *[,\t\n\177]")) (nodepos nil)) (catch 'foo ;; First, search a tag table, if any (when (marker-position Info-tag-table-marker) (let* ((m Info-tag-table-marker) (found (Info-find-in-tag-table m regexp))) (when found ;; FOUND is (ANCHOR POS MODE). (setq guesspos (nth 1 found)) ;; If this is an indirect file, determine which ;; file really holds this node and read it in. (unless (eq (nth 2 found) 'Info-mode) ;; Note that the current buffer must be the ;; *info* buffer on entry to ;; Info-read-subfile. Thus the hackery above. (setq guesspos (Info-read-subfile guesspos))) ;; Handle anchor (when (nth 0 found) (goto-char (setq anchorpos guesspos)) (throw 'foo t))))) ;; Else we may have a node, which we search for: (goto-char (max (point-min) (- (byte-to-position guesspos) 1000))) ;; Now search from our advised position (or from beg of ;; buffer) to find the actual node. First, check ;; whether the node is right where we are, in case the ;; buffer begins with a node. (let ((pos (Info-find-node-in-buffer regexp))) (when pos (goto-char pos) (throw 'foo t)) (error "No such anchor in tag table or node in tag table or file: %s" nodename))) (Info-select-node) (goto-char (or anchorpos (point-min))))) (when (and (one-window-p t) (not (window-minibuffer-p)) (fboundp 'fit-frame) ; Defined in `fit-frame.el'. Info-fit-frame-flag) (fit-frame))) ;; If we did not finish finding the specified node, ;; go back to the previous one. (or Info-current-node no-going-back (null Info-history) (let ((hist (car Info-history))) (setq Info-history (cdr Info-history)) (Info-find-node (nth 0 hist) (nth 1 hist) t) (goto-char (nth 2 hist))))))) ;; REPLACES ORIGINAL in `info.el': ;; Calls `fit-frame' if `Info-fit-frame-flag'. ;; ;;;###autoload (when (>= emacs-major-version 22) (defun Info-find-node-2 (filename nodename &optional no-going-back) (buffer-disable-undo (current-buffer)) (or (eq major-mode 'Info-mode) (Info-mode)) (widen) (setq Info-current-node nil) (unwind-protect (let ((case-fold-search t) anchorpos) ;; Switch files if necessary (or (null filename) (equal Info-current-file filename) (let ((buffer-read-only nil)) (setq Info-current-file nil Info-current-subfile nil Info-current-file-completions nil buffer-file-name nil) (erase-buffer) (cond ((eq filename t) (Info-insert-dir)) ((eq filename 'apropos) (insert-buffer-substring " *info-apropos*")) ((eq filename 'history) (insert-buffer-substring " *info-history*")) ((eq filename 'toc) (insert-buffer-substring " *info-toc*")) (t (info-insert-file-contents filename nil) (setq default-directory (file-name-directory filename)))) (set-buffer-modified-p nil) ;; Check makeinfo version for index cookie support (let ((found nil)) (goto-char (point-min)) (condition-case () (if (and (re-search-forward "makeinfo[ \n]version[ \n]\\([0-9]+.[0-9]+\\)" (line-beginning-position 3) t) (not (version< (match-string 1) "4.7"))) (setq found t)) (error nil)) (set (make-local-variable 'Info-file-supports-index-cookies) found)) ;; See whether file has a tag table. Record the location if yes. (goto-char (point-max)) (forward-line -8) ;; Use string-equal, not equal, to ignore text props. (if (not (or (string-equal nodename "*") (not (search-forward "\^_\nEnd tag table\n" nil t)))) (let (pos) ;; We have a tag table. Find its beginning. ;; Is this an indirect file? (search-backward "\nTag table:\n") (setq pos (point)) (if (save-excursion (forward-line 2) (looking-at "(Indirect)\n")) ;; It is indirect. Copy it to another buffer ;; and record that the tag table is in that buffer. (let ((buf (current-buffer)) (tagbuf (or Info-tag-table-buffer (generate-new-buffer " *info tag table*")))) (setq Info-tag-table-buffer tagbuf) (save-excursion (set-buffer tagbuf) (buffer-disable-undo (current-buffer)) (setq case-fold-search t) (erase-buffer) (insert-buffer-substring buf)) (set-marker Info-tag-table-marker (match-end 0) tagbuf)) (set-marker Info-tag-table-marker pos))) (set-marker Info-tag-table-marker nil)) (setq Info-current-file (cond ((eq filename t) "dir") (t filename))) )) ;; Use string-equal, not equal, to ignore text props. (if (string-equal nodename "*") (progn (setq Info-current-node nodename) (Info-set-mode-line)) ;; Possibilities: ;; ;; 1. Anchor found in tag table ;; 2. Anchor *not* in tag table ;; ;; 3. Node found in tag table ;; 4. Node *not* found in tag table, but found in file ;; 5. Node *not* in tag table, and *not* in file ;; ;; *Or* the same, but in an indirect subfile. ;; Search file for a suitable node. (let ((guesspos (point-min)) (regexp (concat "\\(Node:\\|Ref:\\) *\\(" (if (stringp nodename) (regexp-quote nodename) "") "\\) *[,\t\n\177]"))) (catch 'foo ;; First, search a tag table, if any (when (marker-position Info-tag-table-marker) (let* ((m Info-tag-table-marker) (found (Info-find-in-tag-table m regexp))) (when found ;; FOUND is (ANCHOR POS MODE). (setq guesspos (nth 1 found)) ;; If this is an indirect file, determine which ;; file really holds this node and read it in. (unless (eq (nth 2 found) 'Info-mode) ;; Note that the current buffer must be the ;; *info* buffer on entry to ;; Info-read-subfile. Thus the hackery above. (setq guesspos (Info-read-subfile guesspos))) ;; Handle anchor (when (nth 0 found) (goto-char (setq anchorpos guesspos)) (throw 'foo t))))) ;; Else we may have a node, which we search for: (goto-char (max (point-min) (- (byte-to-position guesspos) 1000))) ;; Now search from our advised position (or from beg of ;; buffer) to find the actual node. First, check ;; whether the node is right where we are, in case the ;; buffer begins with a node. (let ((pos (Info-find-node-in-buffer regexp))) (when pos (goto-char pos) (throw 'foo t))) (when (string-match "\\([^.]+\\)\\." nodename) (let (Info-point-loc) (Info-find-node-2 filename (match-string 1 nodename) no-going-back)) (widen) (throw 'foo t)) ;; No such anchor in tag table or node in tag table or file (error "No such node or anchor: %s" nodename)) (Info-select-node) (goto-char (point-min)) (cond (anchorpos (let ((new-history (list Info-current-file (substring-no-properties nodename)))) ;; Add anchors to the history too (setq Info-history-list (cons new-history (delete new-history Info-history-list)))) (goto-char anchorpos)) ((numberp Info-point-loc) (forward-line (1- Info-point-loc)) (setq Info-point-loc nil)) ((stringp Info-point-loc) (Info-find-index-name Info-point-loc) (setq Info-point-loc nil))) (when (and (one-window-p t) (not (window-minibuffer-p)) (fboundp 'fit-frame) ; Defined in `fit-frame.el'. Info-fit-frame-flag) (fit-frame))))) ;; If we did not finish finding the specified node, ;; go back to the previous one. (or Info-current-node no-going-back (null Info-history) (let ((hist (car Info-history))) (setq Info-history (cdr Info-history)) (Info-find-node (nth 0 hist) (nth 1 hist) t) (goto-char (nth 2 hist))))))) ;; REPLACES ORIGINAL in `info.el': ;; 1. Added in-progress message ("Looking...") ;; 2, Returns nil if not found. (defun Info-find-emacs-command-nodes (command) "Return a list of locations documenting COMMAND. 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 variable `Info-history', that is, (FILENAME NODENAME BUFFERPOS\)." (let ((where '()) (cmd-desc (concat "^\\* +" (regexp-quote (symbol-name command)) (if (< emacs-major-version 21) ":\\s *\\(.*\\)\\.$" "\\( <[0-9]+>\\)?:\\s *\\(.*\\)\\.$"))) (info-file "emacs")) ;default ;; Determine which info file this command is documented in. (if (get command 'info-file) (setq info-file (get command 'info-file)) ;; If it doesn't say explicitly, test its name against ;; various prefixes that we know. (let ((file-list Info-file-list-for-emacs)) (while file-list (let* ((elt (car file-list)) (name (if (consp elt) (car elt) elt)) (file (if (consp elt) (cdr elt) elt)) (regexp (concat "\\`" (regexp-quote name) "\\(\\'\\|-\\)"))) (if (string-match regexp (symbol-name command)) (setq info-file file file-list nil)) (setq file-list (cdr file-list)))))) (message "Looking for command `%s' in Info manual `%s'..." command (file-name-nondirectory info-file)) (cond ((>= emacs-major-version 22) (save-excursion (condition-case nil (progn (Info-find-node info-file "Top") (or (and (search-forward "\n* menu:" nil t) (re-search-forward "\n\\* \\(.*\\\\)" nil t)) (error "Info file `%s' appears to lack an index" info-file))) (error nil)) ; Return nil: not found. (goto-char (match-beginning 1)) ;; Bind Info-history to nil, to prevent the index nodes from ;; getting into the node history. (let ((Info-history nil) (Info-history-list nil) node (nodes (Info-index-nodes))) (Info-goto-node (car nodes)) (while (progn (goto-char (point-min)) (while (re-search-forward cmd-desc nil t) (setq where (cons (list Info-current-file (match-string-no-properties 2) 0) where))) (and (setq nodes (cdr nodes) node (car nodes)))) (Info-goto-node node))) where)) ((>= emacs-major-version 21) (save-excursion (condition-case nil (progn (Info-find-node info-file "Top") (or (and (search-forward "\n* menu:" nil t) (re-search-forward "\n\\* \\(.*\\\\)" nil t)) (error "Info file `%s' appears to lack an index" info-file))) (error nil)) ; Return nil: not found. (goto-char (match-beginning 1)) ;; Bind Info-history to nil, to prevent the index nodes from ;; getting into the node history. (let ((Info-history nil) (exact nil) node found) (Info-goto-node (Info-extract-menu-node-name)) (while (progn (goto-char (point-min)) (while (re-search-forward cmd-desc nil t) (setq where (cons (list Info-current-file (match-string-no-properties 2) 0) where))) (and (setq node (Info-extract-pointer "next" t)) (string-match "\\" node))) (Info-goto-node node))) where)) (t (save-excursion (condition-case nil (Info-find-node info-file "Command Index") ;; Some manuals may not have a separate Command Index node, ;; so try just Index instead. (error (condition-case nil (Info-find-node info-file "Index") (error nil)))) ; Return nil: not found. ;; Take the index node off the Info history. (setq Info-history (cdr Info-history)) (goto-char (point-max)) (while (re-search-backward cmd-desc nil t) (setq where (cons (list Info-current-file (buffer-substring (match-beginning 1) (match-end 1)) 0) where))) where))))) ;; REPLACES ORIGINAL in `info.el': ;; 1. Uses `completing-read' in interactive spec, with `symbol-nearest-point' ;; (defined in `thingatpt+.el') or `symbol-at-point' (defined in `thingatpt.el'). ;; 2. Message if single node found. ;; 3. Returns `num-matches' if found; nil if not. ;; ;;;###autoload (defun Info-goto-emacs-command-node (command) "Go to the Info node in the Emacs manual for command COMMAND. The command is found by looking it up in Emacs manual's indexes, or in another manual found via COMMAND's `info-file' property or the variable `Info-file-list-for-emacs'. COMMAND must be a symbol or string." (interactive (let ((symb (cond ((fboundp 'symbol-nearest-point) (symbol-nearest-point)) ((fboundp 'symbol-at-point) (symbol-at-point)) (t nil))) (enable-recursive-minibuffers t)) (list (intern (completing-read "Find documentation for command: " obarray 'commandp t nil nil symb t))))) (unless (commandp command) (signal 'wrong-type-argument (list 'commandp command))) (let ((where (Info-find-emacs-command-nodes command))) (if where (let ((num-matches (length where))) ;; Get Info running, and pop to it in another window. (save-window-excursion (info)) (or (eq major-mode 'Info-mode) (pop-to-buffer "*info*")) ;; Bind Info-history to nil, to prevent the last Index node ;; visited by Info-find-emacs-command-nodes from being ;; pushed onto the history. (let ((Info-history nil) (Info-history-list nil)) (Info-find-node (car (car where)) (car (cdr (car where))))) (if (<= num-matches 1) (when (interactive-p) (message "This info node documents command `%s'." command)) ;; (car where) will be pushed onto Info-history ;; when/if they go to another node. Put the other ;; nodes that were found on the history. (setq Info-history (nconc (cdr where) Info-history)) (when (interactive-p) (message "Found %d other entr%s. Use %s to see %s." (1- num-matches) (if (> num-matches 2) "ies" "y") (substitute-command-keys (if (>= emacs-major-version 22) "\\\\[Info-history-back]" "\\\\[Info-last]")) (if (> num-matches 2) "them" "it")))) num-matches) ; Return num-matches found. (and (interactive-p) ; Return nil for unfound. (error "No documentation found for command `%s'" command))))) ;; REPLACES ORIGINAL in `info.el': ;; If key's command is not found, then `Info-search' for key sequence in text. ;; Message for repeating. ;; ;;;###autoload (defun Info-goto-emacs-key-command-node (key) "Go to the node in the Emacs manual describing command bound to KEY. KEY is a string. Interactively, if the binding is `execute-extended-command', then a command is read. The command is found by looking it up in Emacs manual's indexes, or in another manual's index found via COMMAND's `info-file' property or the variable `Info-file-list-for-emacs'. If key's command cannot be found by looking in indexes, then `Info-search' is used to search for the key sequence in the info text." (interactive "kFind documentation for key: ") (let* ((command (lookup-key global-map key)) (pp-key (key-description key))) (when (natnump command) (setq command (key-binding key))) ; E.g. menu item. (cond ((null command) (when (interactive-p) (message "No doc found for key sequence `%s'." pp-key)) nil) ; RETURN nil: not found. ((and (interactive-p);; Read a new command name. (eq command 'execute-extended-command)) (Info-goto-emacs-command-node (read-command "Find documentation for command: "))) (t (let ((this-file Info-current-file) (this-node Info-current-node) (num-cmd-matches (Info-goto-emacs-command-node command))) (cond (num-cmd-matches ;; Found key's command via a manual index. (when (interactive-p) (if (<= num-cmd-matches 1) (message "This info node documents key `%s'." pp-key) (message (substitute-command-keys (concat "Found %d other entr%s. Use " (if (>= emacs-major-version 22) "\\`\\[Info-history-back]' to see %s." "\\`\\[Info-last]' to see %s."))) (1- num-cmd-matches) (if (> num-cmd-matches 2) "ies" "y") (if (> num-cmd-matches 2) "them" "it")))) num-cmd-matches) ; RETURN num-cmd-matches: found. (t ;; Couldn't find key's command via a manual index. ;; Get back to where we were. ;; Would be better if there were a save-xxx-excursion-xxx ;; that would work. (Info-goto-node (concat "(" this-file ")" this-node)) ;; Would be better to now try looking for the key in indexes (e.g. Key ;; Index). Instead, just look for the key sequence in the text. (when (interactive-p) (message "Not found using Index. Searching for \"%s\" in text..." pp-key) (sit-for 3)) (condition-case err (progn (Info-search (regexp-quote pp-key)) (when (interactive-p) (message (substitute-command-keys "Use \\`\\[Info-search] RET' \ to search again for `%s'.") pp-key)) t) ; RETURN t: found. (search-failed (message "No documentation found for key `%s'." pp-key) nil))))))))) ; RETURN nil: not found. ;;;###autoload (unless (>= emacs-major-version 22) ;; REPLACES ORIGINAL in `info.el': ;; 1. File name in face `info-file'. ;; 2. Node names in face `info-node'. ;; 3. Menu items in face `info-menu'. ;; 4. Only 5th and 9th menu items have their `*' colored. ;; 5. Notes in face `info-xref'. ;; 6. If `Info-fontify-quotations-flag', fontify `...' in face `info-quoted-name' ;; and "..." in face `info-string'. (defun Info-fontify-node () (save-excursion (let ((buffer-read-only nil) (case-fold-search t)) (goto-char (point-min)) ;; Header line. (when (looking-at "^File: \\([^,: \t]+\\),?[ \t]+") (put-text-property (match-beginning 1) (match-end 1) 'face 'info-file) (goto-char (match-end 0)) ;; Node names in menu at top of buffer. (while (looking-at "[ \t]*\\([^:, \t\n]+\\):[ \t]+\\([^:,\t\n]+\\),?") (goto-char (match-end 0)) (if (save-excursion (goto-char (match-beginning 1)) (save-match-data (looking-at "Node:"))) (put-text-property (match-beginning 2) (match-end 2) 'face 'info-node) (put-text-property (match-beginning 2) (match-end 2) 'face 'info-xref) (put-text-property (match-beginning 2) (match-end 2) 'mouse-face 'highlight)))) (goto-char (point-min)) ;; Text headings: replace ***'s, ---'s, ==='s by faces. (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\)$" nil t) (put-text-property (match-beginning 1) (match-end 1) 'face (cdr (assq (preceding-char) Info-title-face-alist))) ;; This is a serious problem for trying to handle multiple ;; frame types at once. We want this text to be invisible ;; on frames that can display the font above. (if (memq (framep (selected-frame)) '(x pc w32 win32)) (put-text-property (match-end 1) (match-end 2) 'invisible t))) (goto-char (point-min)) ;; Cross references. (while (re-search-forward "\\*Note[ \n\t]+\\([^:]*\\):" nil t) (unless (= (char-after (1- (match-beginning 0))) ?\") ; hack (put-text-property (match-beginning 1) (match-end 1) 'face 'info-xref) (put-text-property (match-beginning 1) (match-end 1) 'mouse-face 'highlight))) (goto-char (point-min)) ;; Menus. (when (and (search-forward "\n* Menu:" nil t) ;; Fontify indexes too. ;;(not (string-match "\\" Info-current-node)) ;; Don't take time to annotate huge menus (< (- (point-max) (point)) Info-fontify-maximum-menu-size)) (let ((n 0)) (while (re-search-forward "^\\* +\\([^:\t\n]*\\):" nil t) (setq n (1+ n)) (when (memq n '(5 9)) ; visual aids to help with 1-9 keys (put-text-property (match-beginning 0) (1+ (match-beginning 0)) 'face 'info-menu)) ; was: info-menu-5 (put-text-property (match-beginning 1) (match-end 1) 'face 'info-menu) ; was: info-xref (put-text-property (match-beginning 1) (match-end 1) 'mouse-face 'highlight)))) ;; Fontify `...' and "..." (goto-char (point-min)) (when Info-fontify-quotations-flag (info-fontify-quotations)) ; Fontify `...' and "..." ;; Fontify reference items if in Emacs-Lisp manual. (goto-char (point-min)) (when (string-equal "elisp" (file-name-nondirectory Info-current-file)) (info-fontify-reference-items)) ; Fontify -- Function, -- Variable, etc. (set-buffer-modified-p nil))))) ;;;###autoload (when (>= emacs-major-version 22) ;; REPLACES ORIGINAL in `info.el': ;; 1. File name in face `info-file'. ;; 2. If `Info-fontify-quotations-flag', fontify `...' in face `info-quoted-name' ;; and "..." in face `info-string'. (defun Info-fontify-node () "Fontify the node." (save-excursion (let* ((inhibit-read-only t) (case-fold-search t) paragraph-markers (not-fontified-p ; the node hasn't already been fontified (not (let ((where (next-property-change (point-min)))) (and where (not (= where (point-max))))))) (fontify-visited-p ; visited nodes need to be re-fontified (and Info-fontify-visited-nodes ;; Don't take time to refontify visited nodes in huge nodes (< (- (point-max) (point-min)) Info-fontify-maximum-menu-size)))) ;; Fontify header line (goto-char (point-min)) (when (and not-fontified-p (looking-at "^File: \\([^,: \t]+\\),?[ \t]+")) (put-text-property (match-beginning 1) (match-end 1) 'face 'info-file)) (goto-char (point-min)) (when (and not-fontified-p (looking-at "^\\(File: [^,: \t]+,?[ \t]+\\)?")) (while (looking-at "[ \t]*\\([^:, \t\n]+\\):[ \t]+\\([^:,\t\n]+\\),?") (goto-char (match-end 0)) (let* ((nbeg (match-beginning 2)) (nend (match-end 2)) (tbeg (match-beginning 1)) (tag (match-string 1))) (if (string-equal tag "Node") (put-text-property nbeg nend 'font-lock-face 'info-header-node) (put-text-property nbeg nend 'font-lock-face 'info-header-xref) (put-text-property tbeg nend 'mouse-face 'highlight) (put-text-property tbeg nend 'help-echo (concat "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 ((equal tag "Prev") Info-prev-link-keymap) ((equal tag "Next") Info-next-link-keymap) ((equal tag "Up") Info-up-link-keymap)))))) (when Info-use-header-line (goto-char (point-min)) (let ((header-end (line-end-position)) header) ;; If we find neither Next: nor Prev: link, show the entire ;; node header. Otherwise, don't show the File: and Node: ;; parts, to avoid wasting precious space on information that ;; is available in the mode line. (if (re-search-forward "\\(next\\|up\\|prev[ious]*\\): " header-end t) (progn (goto-char (match-beginning 1)) (setq header (buffer-substring (point) header-end))) (if (re-search-forward "node:[ \t]*[^ \t]+[ \t]*" header-end t) (setq header (concat "No next, prev or up links -- " (buffer-substring (point) header-end))) (setq header (buffer-substring (point) header-end)))) (put-text-property (point-min) (1+ (point-min)) 'header-line (replace-regexp-in-string "%" ;; Preserve text properties on duplicated `%'. (lambda (s) (concat s s)) header)) ;; Hide the part of the first line ;; that is in the header, if it is just part. (unless (bobp) ;; Hide the punctuation at the end, too. (skip-chars-backward " \t,") (put-text-property (point) header-end 'invisible t))))) ;; Fontify `...' and "..." (goto-char (point-min)) (when Info-fontify-quotations-flag (info-fontify-quotations)) ;; Fontify reference items if in Emacs-Lisp manual. (goto-char (point-min)) (when (string-equal "elisp" (file-name-nondirectory Info-current-file)) (info-fontify-reference-items)) ; Fontify -- Function, -- Variable, etc. ;; Fontify titles (goto-char (point-min)) (when not-fontified-p (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\|\\.+\\)$" nil t) (let* ((c (preceding-char)) (face (cond ((= c ?*) 'Info-title-1-face) ((= c ?=) 'Info-title-2-face) ((= c ?-) 'Info-title-3-face) (t 'Info-title-4-face)))) (put-text-property (match-beginning 1) (match-end 1) 'font-lock-face face)) ;; This is a serious problem for trying to handle multiple ;; frame types at once. We want this text to be invisible ;; on frames that can display the font above. (when (memq (framep (selected-frame)) '(x pc w32 mac)) (add-text-properties (1- (match-beginning 2)) (match-end 2) '(invisible t front-sticky nil rear-nonsticky t))))) ;; Fontify cross references (goto-char (point-min)) (when (or not-fontified-p fontify-visited-p) (while (re-search-forward "\\(\\*Note[ \n\t]+\\)\\([^:]*\\)\\(:[ \t]*\\([^.,:(]*\\)\\(\\(([^)]\ *)\\)[^.,:]*\\)?[,:]?\n?\\)" nil t) (let ((start (match-beginning 0)) (next (point)) other-tag) (when not-fontified-p (when Info-hide-note-references ;; *Note is often used where *note should have been (goto-char start) (skip-syntax-backward " ") (setq other-tag (cond ((memq (char-before) '(nil ?\. ?! ??)) "See ") ((memq (char-before) '(?\, ?\; ?\: ?-)) "see ") ((memq (char-before) '(?\( ?\[ ?\{)) ;; Check whether the paren is preceded by ;; an end of sentence (skip-syntax-backward " (") (if (memq (char-before) '(nil ?\. ?! ??)) "See " "see ")) ((save-match-data (looking-at "\n\n")) "See "))) (goto-char next) (add-text-properties (match-beginning 1) (or (save-match-data ;; Don't hide \n after *Note (let ((start1 (match-beginning 1))) (if (string-match "\n" (match-string 1)) (+ start1 (match-beginning 0))))) (match-end 1)) (if (and other-tag (not (eq Info-hide-note-references 'hide))) `(display ,other-tag front-sticky nil rear-nonsticky t) '(invisible t front-sticky nil rear-nonsticky t)))) (add-text-properties (match-beginning 2) (match-end 2) (list 'help-echo (if (or (match-end 5) (not (equal (match-string 4) ""))) (concat "mouse-2: go to " (or (match-string 5) (match-string 4))) "mouse-2: go to this node") 'mouse-face 'highlight))) (when (or not-fontified-p fontify-visited-p) (add-text-properties (match-beginning 2) (match-end 2) (list 'font-lock-face ;; Display visited nodes in a different face (if (and Info-fontify-visited-nodes (save-match-data (let* ((node (replace-regexp-in-string "^[ \t]+" "" (replace-regexp-in-string "[ \t\n]+" " " (or (match-string 5) (and (not (equal (match-string 4) "")) (match-string 4)) (match-string 2))))) (file (file-name-nondirectory Info-current-file)) (hl Info-history-list) res) (if (string-match "(\\([^)]+\\))\\([^)]*\\)" node) (setq file (file-name-nondirectory (match-string 1 node)) node (if (equal (match-string 2 node) "") "Top" (match-string 2 node)))) (while hl (if (and (string-equal node (nth 1 (car hl))) (string-equal file (file-name-nondirectory (nth 0 (car hl))))) (setq res (car hl) hl nil) (setq hl (cdr hl)))) res))) 'info-xref-visited 'info-xref)))) (when not-fontified-p (when (memq Info-hide-note-references '(t hide)) (add-text-properties (match-beginning 3) (match-end 3) '(invisible t front-sticky nil rear-nonsticky t)) ;; Unhide the file name of the external reference in parens (if (and (match-string 6) (not (eq Info-hide-note-references 'hide))) (remove-text-properties (match-beginning 6) (match-end 6) '(invisible t front-sticky nil rear-nonsticky t))) ;; Unhide newline because hidden newlines cause too long lines (save-match-data (let ((beg3 (match-beginning 3)) (end3 (match-end 3))) (if (and (string-match "\n[ \t]*" (match-string 3)) (not (save-match-data (save-excursion (goto-char (1+ end3)) (looking-at "[.)]*$"))))) (remove-text-properties (+ beg3 (match-beginning 0)) (+ beg3 (match-end 0)) '(invisible t front-sticky nil rear-nonsticky t)))))) (when (and Info-refill-paragraphs Info-hide-note-references) (push (set-marker (make-marker) start) paragraph-markers)))))) ;; Refill paragraphs (experimental feature) (when (and not-fontified-p Info-refill-paragraphs paragraph-markers) (let ((fill-nobreak-invisible t) (fill-individual-varying-indent nil) (paragraph-start "\f\\|[ \t]*[-*]\\|[ \t]*$") (paragraph-separate ".*\\.[ \t]*\n[ \t]\\|[ \t]*[-*]\\|[ \t\f]*$") (adaptive-fill-mode nil)) (goto-char (point-max)) (while paragraph-markers (let ((m (car paragraph-markers))) (setq paragraph-markers (cdr paragraph-markers)) (when (< m (point)) (goto-char m) (beginning-of-line) (let ((beg (point))) (when (zerop (forward-paragraph)) (fill-individual-paragraphs beg (point) nil nil) (goto-char beg)))) (set-marker m nil))))) ;; Fontify menu items (goto-char (point-min)) (when (and (or not-fontified-p fontify-visited-p) (search-forward "\n* Menu:" nil t) (not (Info-index-node)) ;; Don't take time to annotate huge menus (< (- (point-max) (point)) Info-fontify-maximum-menu-size)) (let ((n 0) cont) (while (re-search-forward (concat "^\\* +\\(" Info-menu-entry-name-re "\\)\\(:" Info-node-spec-re "\\([ \t]*\\)\\)") nil t) (when not-fontified-p (setq n (1+ n)) (if (and (<= n 9) (zerop (% n 3))) ; visual aids to help with 1-9 keys (put-text-property (match-beginning 0) (1+ (match-beginning 0)) 'font-lock-face 'info-menu-5))) (when not-fontified-p (add-text-properties (match-beginning 1) (match-end 1) (list 'help-echo (if (match-end 3) (concat "mouse-2: go to " (match-string 3)) "mouse-2: go to this node") 'mouse-face 'highlight))) (when (or not-fontified-p fontify-visited-p) (add-text-properties (match-beginning 1) (match-end 1) (list 'font-lock-face ;; Display visited menu items in a different face (if (and Info-fontify-visited-nodes (save-match-data (let ((node (if (equal (match-string 3) "") (match-string 1) (match-string 3))) (file (file-name-nondirectory Info-current-file)) (hl Info-history-list) res) (if (string-match "(\\([^)]+\\))\\([^)]*\\)" node) (setq file (file-name-nondirectory (match-string 1 node)) node (if (equal (match-string 2 node) "") "Top" (match-string 2 node)))) (while hl (if (and (string-equal node (nth 1 (car hl))) (string-equal file (file-name-nondirectory (nth 0 (car hl))))) (setq res (car hl) hl nil) (setq hl (cdr hl)))) res))) 'info-xref-visited 'info-xref)))) (when (and not-fontified-p (memq Info-hide-note-references '(t hide))) (put-text-property (match-beginning 2) (1- (match-end 6)) 'invisible t) ;; Unhide the file name in parens (if (and (match-end 4) (not (eq (char-after (match-end 4)) ?.))) (remove-text-properties (match-beginning 4) (match-end 4) '(invisible t))) ;; We need a stretchable space like :align-to but with ;; a minimum value. (put-text-property (1- (match-end 6)) (match-end 6) 'display (if (>= 22 (- (match-end 1) (match-beginning 0))) '(space :align-to 24) '(space :width 2))) (setq cont (looking-at ".")) (while (and (= (forward-line 1) 0) (looking-at "\\([ \t]+\\)[^*\n]")) (put-text-property (match-beginning 1) (1- (match-end 1)) 'invisible t) (put-text-property (1- (match-end 1)) (match-end 1) 'display (if cont '(space :align-to 26) '(space :align-to 24))) (setq cont t)))))) ;; Fontify menu headers ;; Add the face `info-menu-header' to any header before a menu entry (goto-char (point-min)) (when (and not-fontified-p (re-search-forward "^\\* Menu:" nil t)) (put-text-property (match-beginning 0) (match-end 0) 'font-lock-face 'info-menu-header) (while (re-search-forward "\n\n\\([^*\n ].*\\)\n\n?[*]" nil t) (put-text-property (match-beginning 1) (match-end 1) 'font-lock-face 'info-menu-header))) ;; Hide index line numbers (goto-char (point-min)) (when (and not-fontified-p (Info-index-node)) (while (re-search-forward "[ \t\n]*(line +[0-9]+)" nil t) (put-text-property (match-beginning 0) (match-end 0) 'invisible t))) ;; Fontify http and ftp references (goto-char (point-min)) (when not-fontified-p (while (re-search-forward "[hf]t?tp://[^ \t\n\"`({<>})']+" nil t) (add-text-properties (match-beginning 0) (match-end 0) '(font-lock-face info-xref mouse-face highlight help-echo "mouse-2: go to this URL")))) (set-buffer-modified-p nil))))) ;; The regexp has these parts: double-quoted string or single-quoted stuff. ;; ;; String has, inside "...", zero or more of these characters: ;; - any character except \ and " ;; - \ followed by any character ;; ;; Single-quoted stuff has, inside `...': any character except ' ;; ;; The regexp matches `...' or "...". The latter case also includes ;; pseudo-strings that start with \". The second branch of the ;; conditional tests this: if that is the match, then it moves past ;; the \. (if (< emacs-major-version 21) (defun info-fontify-quotations () "Fontify text between double-quotes (\"...\") and single-quotes (`...') For single-quotes, use face `info-quoted-name'. For double-quotes, use face `info-string'." (while (condition-case nil (re-search-forward ; Match `...' or "..." "\"\\([^\\\"]\\|\\\\\\(.\\|[\n]\\)\\)*\"\\|`[^']+'" nil t) (error nil)) (cond ((eq ?` (aref (match-string 0) 0)) ; `...' (put-text-property (1+ (match-beginning 0)) (1- (match-end 0)) 'face 'info-quoted-name)) ((and (goto-char (match-beginning 0)) ; "...": If preceded by \, skip it (= 1 (mod (save-excursion (skip-chars-backward "\\\\")) 2))) (forward-char 1)) ((goto-char (match-end 0)) (put-text-property (match-beginning 0) (match-end 0) 'face 'info-string))))) (defun info-fontify-quotations () "Fontify text between double-quotes (\"...\") and single-quotes (`...') For single-quotes, use face `info-quoted-name'. For double-quotes, use face `info-string'." (while (condition-case nil (re-search-forward ; Match `...' or "..." "\"\\(?:[^\\\"]\\|\\\\\\(?:.\\|[\n]\\)\\)*\"\\|`[^']+'" nil t) (error nil)) (cond ((eq ?` (aref (match-string 0) 0)) ; `...' (put-text-property (1+ (match-beginning 0)) (1- (match-end 0)) 'font-lock-face 'info-quoted-name)) ((and (goto-char (match-beginning 0)) ; "...": If preceded by \, skip it (= 1 (mod (save-excursion (skip-chars-backward "\\\\")) 2))) (forward-char 1)) ((goto-char (match-end 0)) ; "..." not preceded by \ (put-text-property (match-beginning 0) (match-end 0) 'font-lock-face 'info-string)))))) (defun info-fontify-reference-items () "Fontify reference items such as \"Function:\" in Emacs Lisp Info buffer." (while (re-search-forward "^ --? \\(Function:\\|Variable:\\|Special Form:\\|\ Command:\\|User Option:\\|Macro:\\|Syntax class:\\)\\(.*\\)" nil t) (let ((symb (intern (match-string 1)))) (put-text-property (match-beginning 1) (match-end 1) 'face (case symb ('Function: 'info-elisp-function-ref-item) ('Variable: 'info-elisp-variable-ref-item) ('Special\ Form: 'info-elisp-special-form-ref-item) ('Command: 'info-elisp-command-ref-item) ('User\ Option: 'info-elisp-user-option-ref-item) ('Macro: 'info-elisp-macro-ref-item) ('Syntax\ class: 'info-elisp-syntax-class-item))) (put-text-property (match-beginning 2) (match-end 2) 'face 'info-elisp-reference-item)))) ;; REPLACES ORIGINAL in `info.el': ;; 1. Fits frame if `one-window-p'. ;; 2. Highlights the found regexp if `search-highlight'. ;; ;;;###autoload (unless (>= emacs-major-version 22) (defun Info-search (regexp) "Search for REGEXP, starting from point, and select node it's found in. Fits frame if `one-window-p'. Highlights current location of found regexp if `search-highlight'. Note that the highlighting remains, after the search is over. To remove the highlighting, just start an incremental search: \ `\\[isearch-forward]'." (interactive "sSearch (regexp): ") (when transient-mark-mode (deactivate-mark)) (if (equal regexp "") (setq regexp Info-last-search) (setq Info-last-search regexp)) (when regexp (prog1 (let ((found ()) current (onode Info-current-node) (ofile Info-current-file) (opoint (point)) (ostart (window-start)) (osubfile Info-current-subfile)) (save-excursion (save-restriction (widen) (if (null Info-current-subfile) (progn (re-search-forward regexp) (setq found (point))) (condition-case err (progn (re-search-forward regexp) (setq found (point))) (search-failed nil))))) ;; Can only happen in subfile case -- else would have erred. (unless found (unwind-protect (let ((list ())) (save-excursion (set-buffer (marker-buffer Info-tag-table-marker)) (goto-char (point-min)) (search-forward "\n\^_\nIndirect:") (save-restriction (narrow-to-region (point) (progn (search-forward "\n\^_") (1- (point)))) (goto-char (point-min)) (search-forward (concat "\n" osubfile ": ")) (beginning-of-line) (while (not (eobp)) (re-search-forward "\\(^.*\\): [0-9]+$") (goto-char (+ (match-end 1) 2)) (setq list (cons (cons (read (current-buffer)) (buffer-substring (match-beginning 1) (match-end 1))) list)) (goto-char (1+ (match-end 0)))) (setq list (nreverse list)) (setq current (caar list)) (setq list (cdr list)))) (while list (message "Searching subfile `%s'..." (cdr (car list))) (Info-read-subfile (car (car list))) (setq list (cdr list)) ;; (goto-char (point-min)) (when (re-search-forward regexp nil t) (setq found (point) list ()))) (if found (message "") (signal 'search-failed (list regexp)))) (unless found (Info-read-subfile osubfile) (goto-char opoint) (Info-select-node) (set-window-start (selected-window) ostart)))) (widen) (goto-char found) (when search-highlight (isearch-highlight (match-beginning 0) (match-end 0))) (Info-select-node) ;; Use string-equal, not equal, to ignore text props. (or (and (string-equal onode Info-current-node) (equal ofile Info-current-file)) (setq Info-history (cons (list ofile onode opoint) Info-history))) (when (and (one-window-p t) (not (window-minibuffer-p)) (fboundp 'fit-frame) ; Defined in `fit-frame.el'. Info-fit-frame-flag) (fit-frame))) (when (interactive-p) (message (substitute-command-keys "Use \\`\\[Info-search] RET' to search again for `%s'.") regexp)))))) ;; REPLACES ORIGINAL in `info.el': ;; 1. Fits frame if `one-window-p'. ;; 2. Highlights the found regexp if `search-highlight'. ;; ;;;###autoload (when (>= emacs-major-version 22) (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. Fits frame if `one-window-p'. Highlights current location of found regexp if `search-highlight'. Note that the highlighting remains, after the search is over. To remove the highlighting, just start an incremental search: \ `\\[isearch-forward]'." (interactive (list (read-string (if Info-search-history (format "Regexp search%s (default `%s'): " (if case-fold-search "" " case-sensitively") (car Info-search-history)) (format "Regexp search%s: " (if case-fold-search "" " case-sensitively"))) nil 'Info-search-history))) (when transient-mark-mode (deactivate-mark)) (when (equal regexp "") (setq regexp (car Info-search-history))) (when regexp (prog1 (let (found beg-found give-up (backward (eq direction 'backward)) (onode Info-current-node) (ofile Info-current-file) (opoint (point)) (opoint-min (point-min)) (opoint-max (point-max)) (ostart (window-start)) (osubfile Info-current-subfile)) (setq Info-search-case-fold case-fold-search) (save-excursion (save-restriction (widen) (when backward ;; Hide Info file header for backward search (narrow-to-region (save-excursion (goto-char (point-min)) (search-forward "\n\^_") (1- (point))) (point-max))) (while (and (not give-up) (save-match-data (or (null found) (if backward (isearch-range-invisible found beg-found) (isearch-range-invisible beg-found found)) ;; Skip node header line (and (save-excursion (forward-line -1) (looking-at "\^_")) (forward-line (if backward -1 1))) ;; Skip Tag Table node (save-excursion (and (search-backward "\^_" nil t) (looking-at "\^_\nTag Table")))))) (let ((search-spaces-regexp Info-search-whitespace-regexp)) (if (if backward (re-search-backward regexp bound t) (re-search-forward regexp bound t)) (setq found (point) beg-found (if backward (match-end 0) (match-beginning 0))) (setq give-up t)))))) (when (and isearch-mode Info-isearch-search (not Info-isearch-initial-node) (not bound) (or give-up (and found (not (and (> found opoint-min) (< found opoint-max)))))) (signal 'search-failed (list regexp "initial node"))) ;; If no subfiles, give error now. (if give-up (if (null Info-current-subfile) (let ((search-spaces-regexp Info-search-whitespace-regexp)) (if backward (re-search-backward regexp) (re-search-forward regexp))) (setq found nil))) (if (and bound (not found)) (signal 'search-failed (list regexp))) (unless (or found bound) (unwind-protect ;; Try other subfiles. (let ((list ())) (save-excursion (set-buffer (marker-buffer Info-tag-table-marker)) (goto-char (point-min)) (search-forward "\n\^_\nIndirect:") (save-restriction (narrow-to-region (point) (progn (search-forward "\n\^_") (1- (point)))) (goto-char (point-min)) ;; Find the subfile we just searched. (search-forward (concat "\n" osubfile ": ")) ;; Skip that one. (forward-line (if backward 0 1)) (if backward (forward-char -1)) ;; Make a list of all following subfiles. ;; Each elt has the form (VIRT-POSITION . SUBFILENAME). (while (not (if backward (bobp) (eobp))) (if backward (re-search-backward "\\(^.*\\): [0-9]+$") (re-search-forward "\\(^.*\\): [0-9]+$")) (goto-char (+ (match-end 1) 2)) (setq list (cons (cons (+ (point-min) (read (current-buffer))) (match-string-no-properties 1)) list)) (goto-char (if backward (1- (match-beginning 0)) (1+ (match-end 0))))) ;; Put in forward order (setq list (nreverse list)))) (while list (message "Searching subfile %s..." (cdr (car list))) (Info-read-subfile (car (car list))) (when backward ;; Hide Info file header for backward search (narrow-to-region (save-excursion (goto-char (point-min)) (search-forward "\n\^_") (1- (point))) (point-max)) (goto-char (point-max))) (setq list (cdr list)) (setq give-up nil found nil) (while (and (not give-up) (save-match-data (or (null found) (if backward (isearch-range-invisible found beg-found) (isearch-range-invisible beg-found found)) ;; Skip node header line (and (save-excursion (forward-line -1) (looking-at "\^_")) (forward-line (if backward -1 1))) ;; Skip Tag Table node (save-excursion (and (search-backward "\^_" nil t) (looking-at "\^_\nTag Table")))))) (let ((search-spaces-regexp Info-search-whitespace-regexp)) (if (if backward (re-search-backward regexp nil t) (re-search-forward regexp nil t)) (setq found (point) beg-found (if backward (match-end 0) (match-beginning 0))) (setq give-up t)))) (if give-up (setq found nil)) (if found (setq list nil))) (if found (message "") (signal 'search-failed (list regexp)))) (if (not found) (progn (Info-read-subfile osubfile) (goto-char opoint) (Info-select-node) (set-window-start (selected-window) ostart))))) (if (and (string= osubfile Info-current-subfile) (> found opoint-min) (< found opoint-max)) ;; Search landed in the same node (goto-char found) (widen) (goto-char found) (save-match-data (Info-select-node))) ;; Highlight regexp. (when search-highlight (isearch-highlight (match-beginning 0) (match-end 0))) ;; Use string-equal, not equal, to ignore text props. (or (and (string-equal onode Info-current-node) (equal ofile Info-current-file)) (and isearch-mode isearch-wrapped (eq opoint (if isearch-forward opoint-min opoint-max))) (setq Info-history (cons (list ofile onode opoint) Info-history))) (when (and (one-window-p t) (not (window-minibuffer-p)) (fboundp 'fit-frame) ; Defined in `fit-frame.el'. Info-fit-frame-flag) (fit-frame))) (unless isearch-mode (message (substitute-command-keys "Use \\`\\[Info-search] RET' to search again for `%s'.") regexp)))))) ;; REPLACES ORIGINAL in `info.el': ;; Added optional arg FORK. ;; ;;;###autoload (when (>= emacs-major-version 22) (defun Info-mouse-follow-nearest-node (click &optional fork) "\\Follow a node reference near point. Like \\[Info-menu], \\[Info-follow-reference], \\[Info-next], \\[Info-prev] or \\[Info-up] \ command, depending on where you click. At end of the node's text, moves to the next node, or up if none. With a prefix argument, open the node in a separate window." (interactive "e\nP") (mouse-set-point click) (and (not (Info-try-follow-nearest-node fork)) (save-excursion (forward-line 1) (eobp)) (Info-next-preorder)))) ;; REPLACES ORIGINAL in `info.el': ;; Doc string changed: displays all bindings. ;; ;;;###autoload (when (< emacs-major-version 21) (defun Info-mode () "\\ Info mode provides commands for browsing through the Info doc tree. Documentation in Info is divided into \"nodes\", each of which discusses one topic and contains hyperlink references to other nodes which discuss related topics. Info has commands to follow the references. The most important commands to know are: \ `\\[Info-mouse-follow-nearest-node]', `\\[Info-last]', and `\\[Info-search]'. Help commands ------------- \\[describe-mode]\tDisplay this help. \\[Info-help]\tThe Info tutorial. Learn about Info while using it. Selecting other nodes (basic) ----------------------------- \\[Info-mouse-follow-nearest-node]\tFollow a node reference you click on. \ This works with menu \titems, cross references ( \"(*note...)\" ), \"Next\", \"Previous\" \tand \"Up\" references, depending on where you click. \tAt end of node's text, goes to \"Next\", or \"Up\" if no \"Next\". \\[Info-follow-nearest-node]\tLike `\\[Info-mouse-follow-nearest-node]', \ except cursor location, not mouse location. \\[Info-last]\tGo back to the last node you were at. (chronological) Structural navigation commands ------------------------------ \\[Info-menu]\tGo to a menu item's node. Completion available for its name. 1\tGo to first menu item's node. 2, 3, 4, 5, 6, 7, 8, 9\tGo to second...ninth menu item's node. \\[Info-next]\tGo to this node's \"Next\" node. \\[Info-prev]\tGo to this node's \"Previous\" node. (*not* chronological) \\[Info-up]\tGo \"Up\" from this node to its parent node. \\[Info-directory]\tGo to the Info directory (root) node. \\[Info-index]\tLook up a topic in this file's Index and move to its node. \\[Info-index-next]\t(comma) Go to the next match from a previous \ `\\[Info-index]' command. \\[Info-follow-reference]\tFollow a cross reference ( \"(*note...)\" ). \ Reads ref name. Moving within a node -------------------- \\[Info-scroll-up]\tNormally, scroll forward a full screen. If end of \ buffer is \talready visible, try to go to next menu entry, or up if none. \\[Info-scroll-down]\tNormally, scroll backward. If beginning of buffer is \ already \tvisible, try to go to previous menu entry, or up if none. \\[beginning-of-buffer]\tGo to beginning of node. \\[Info-next-reference]\tMove cursor to next cross-reference or menu item in \ this node. \\[Info-prev-reference]\tMove cursor to previous cross-reference or menu item. Other navigation commands ------------------------- \\[Info-goto-node]\tGo to a node with a given name. (No completion available.) \tYou may include a filename as well, as \"(FILENAME)NODENAME\". \\[universal-argument] \\[info]\tGo to a new Info file. (Completion \ available.) \\[Info-top-node]\tGo to first node (\"Top\") of current Info file. \\[Info-final-node]\tGo to final node of current Info file. \\[Info-forward-node]\tGo forward a node, considering all nodes as one \ sequence. \\[Info-backward-node]\tGo backward a node, considering all nodes as one \ sequence. Other commands -------------- \\[Info-search]\tSearch through nodes of this Info file for specified regexp, \tand go to node where next occurrence is found. \tNote that other search functions (e.g. `\\[isearch-forward]') will only \ search \twithin the current node. \\[Info-edit]\tEdit contents of current node. \ \(\\`\\[Info-cease-edit]'\\ to end editing.) \tEditing is enabled only if `Info-enable-edit' is non-nil. \\[Info-merge-subnodes]\tIntegrate current node with nodes referred to \ in its Menu. \tDisplay the result outside of Info. `\\[universal-argument]': Recursively. \\[Info-exit]\tQuit Info. User options ------------ Some user options (variables you can define, via `defvar'): `Info-subtree-separator' - See `Info-merge-subnodes'. `Info-fontify-quotations-flag' - Non-nil means fontify single-quoted names (`...') and strings between double-quotes (\"...\") `info-file' - Face used for file heading labels `info-node' - Face used for node heading labels `info-menu' - Face used for menu items `info-xref' - Face used for cross reference \"Note\" links `info-string' - Face used for strings (e.g. \"toto\"). `info-quoted-name' - Face used for quoted names (e.g. `toto'). These are all of the current Info Mode bindings: \\{Info-mode-map}" (kill-all-local-variables) (setq major-mode 'Info-mode) (setq mode-name "Info") (setq tab-width 8) (use-local-map Info-mode-map) (make-local-hook 'activate-menubar-hook) (add-hook 'activate-menubar-hook 'Info-menu-update nil t) (set-syntax-table text-mode-syntax-table) (setq local-abbrev-table text-mode-abbrev-table) (setq case-fold-search t) (setq buffer-read-only t) (make-local-variable 'Info-current-file) (make-local-variable 'Info-current-subfile) (make-local-variable 'Info-current-node) (make-local-variable 'Info-tag-table-marker) (setq Info-tag-table-marker (make-marker)) (make-local-variable 'Info-tag-table-buffer) (setq Info-tag-table-buffer nil) (make-local-variable 'Info-history) (make-local-variable 'Info-index-alternatives) ;; 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) (Info-set-mode-line) (run-hooks 'Info-mode-hook))) ;; REPLACES ORIGINAL in `info.el': ;; Only the doc string is changed: displays all bindings. ;; ;;;###autoload (when (eq emacs-major-version 21) ;; For some reason, this doesn't seem to be bound when `tool-bar.el' is loaded (?) in Emacs 21. (defvar tool-bar-map (make-sparse-keymap) ; Taken from `tool-bar.el'. "Keymap for the tool bar. Define this locally to override the global tool bar.") (defun Info-mode () "Info mode provides commands for browsing through the Info doc tree. Documentation in Info is divided into \"nodes\", each of which discusses one topic and contains hyperlink references to other nodes that discuss related topics. Info has commands to follow the references. The most important commands to know are: \ \\\ `\\[Info-exit]', `\\[Info-mouse-follow-nearest-node]', `\\[Info-last]', and `\\[Info-search]'. Help commands ------------- \\[describe-mode]\tDisplay this help. \\[Info-help]\tThe Info tutorial. Learn about Info while using it. Selecting other nodes (basic) ----------------------------- \\[Info-mouse-follow-nearest-node]\tFollow a node reference you click. \ This works with menu \titems, cross references, \"Next\", \"Previous\" \tand \"Up\" references, depending on where you click. \tAt end of node's text, goes to \"Next\", or \"Up\" if no \"Next\". \\[Info-follow-nearest-node]\tLike `\\[Info-mouse-follow-nearest-node]', \ except cursor location, not mouse location. \\[Info-last]\tGo back to the last node you were at. (chronological) \\[Info-history]\tGo to menu of visited nodes. \\[Info-toc]\tGo to table of contents of the current Info file. \\[Info-index]\tLook up a topic in this file's Index and move to its node. \\[Info-index-next]\t(comma) Go to the next match from a previous \ `\\[Info-index]' command. Structural navigation commands ------------------------------ \\[Info-menu]\tGo to a menu item's node. Completion available for its name. 1\tGo to first menu item's node. 2, 3, 4, 5, 6, 7, 8, 9\tGo to second...ninth menu item's node. \\[Info-next]\tGo to this node's \"Next\" node. \\[Info-prev]\tGo to this node's \"Previous\" node. (*not* chronological) \\[Info-up]\tGo \"Up\" from this node to its parent node. \\[Info-directory]\tGo to the Info directory (root) node. \\[Info-follow-reference]\tFollow a cross reference. Prompts for name. Moving within a node -------------------- \\[Info-scroll-up]\tNormally, scroll forward a full screen. \tIf node's menu appears below cursor, go to first menu item. \tIf node's menu appears above cursor, go to parent node. \\[Info-scroll-down]\tNormally, scroll backward. If beginning of buffer is \ already \tvisible, go to previous menu entry, or up if there is none. \\[beginning-of-buffer]\tGo to beginning of node. \\[Info-next-reference]\tMove cursor to next cross-reference or menu item in \ this node. \\[Info-prev-reference]\tMove cursor to previous cross-reference or menu item. Other navigation commands ------------------------- \\[Info-exit]\tQuit Info. \\[Info-goto-node]\tGo to a node with a given name. (No completion available.) \tYou may include a filename as well, as \"(FILENAME)NODENAME\". \\[universal-argument] \\[info]\tGo to a new Info file. (Completion \ available.) \\[universal-argument] N \\[info]\tOpen Info with number in buffer name: *info*. \\[Info-top-node]\tGo to first node (\"Top\") of current Info file. \\[Info-final-node]\tGo to final node of current Info file. \\[Info-forward-node]\tGo forward a node, considering all nodes as one \ sequence. \\[Info-backward-node]\tGo backward a node, considering all nodes as one \ sequence. Other commands -------------- \\[Info-search]\tSearch this Info file for specified regexp, and go to node \twith next occurrence. (Not case-sensitive.) \\[Info-search-case-sensitively]\tLike \\[Info-search], but case-sensitive. \\[Info-search-next]\tSearch for another occurrence of regexp from \ta previous `\\[Info-search]' command. Other search commands, such as `\\[isearch-forward]', \tsearch only within the current node. \\[info-apropos]\tLook for a string in the indexes of all manuals. \\[Info-copy-current-node-name]\tPut name of current info node in the kill ring. \\[clone-buffer]\tSelect a new cloned Info buffer in another window. \\[Info-merge-subnodes]\tIntegrate current node with nodes referred to \ in its Menu. \tDisplay the result outside of Info. `\\[universal-argument]': Recursively. \\[Info-edit]\tEdit contents of current node. \ \(\\`\\[Info-cease-edit]'\\ to end editing.) \tEditing is enabled only if `Info-enable-edit' is non-nil. User options ------------ Some user options (variables you can define, via `defvar'): `Info-subtree-separator' - See `Info-merge-subnodes'. `Info-fontify-quotations-flag' - Non-nil means fontify single-quoted names (`...') and strings between double-quotes (\"...\") `info-file' - Face used for file heading labels `info-string' - Face used for strings (e.g. \"toto\"). `info-quoted-name' - Face used for quoted names (e.g. `toto'). These are all of the current Info Mode bindings: \\{Info-mode-map}" (kill-all-local-variables) (setq major-mode 'Info-mode) (setq mode-name "Info") (setq tab-width 8) (use-local-map Info-mode-map) (add-hook 'activate-menubar-hook 'Info-menu-update nil t) (set-syntax-table text-mode-syntax-table) (setq local-abbrev-table text-mode-abbrev-table) (setq case-fold-search t) (setq buffer-read-only t) (make-local-variable 'Info-current-file) (make-local-variable 'Info-current-subfile) (make-local-variable 'Info-current-node) (make-local-variable 'Info-tag-table-marker) (setq Info-tag-table-marker (make-marker)) (make-local-variable 'Info-tag-table-buffer) (setq Info-tag-table-buffer nil) (make-local-variable 'Info-history) (make-local-variable 'Info-index-alternatives) (set (make-local-variable 'tool-bar-map) info-tool-bar-map) ;; 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 'clone-buffer-hook 'Info-clone-buffer-hook nil t) (Info-set-mode-line) (run-hooks 'Info-mode-hook))) ;; REPLACES ORIGINAL in `info.el': ;; Doc string changed: displays all bindings. ;; ;;;###autoload (when (>= emacs-major-version 22) (defun Info-mode () "Provides commands for browsing through the Info documentation tree. Documentation in Info is divided into \"nodes\", each of which discusses one topic and contains hyperlink references to other nodes that discuss related topics. Info has commands to follow the references. The most important commands to know are: \ \\\ `\\[Info-exit]', `\\[Info-mouse-follow-nearest-node]', `\\[Info-history-back]', and `\\[Info-search]'. Help commands ------------- \\[describe-mode]\tDisplay this help. \\[Info-help]\tThe Info tutorial. Learn about Info while using it. Selecting other nodes (basic) ----------------------------- \\[Info-mouse-follow-nearest-node]\tFollow a node reference you click. \ This works with menu \titems, cross references, \"Next\", \"Previous\" \tand \"Up\" references, depending on where you click. \tAt end of node's text, goes to \"Next\", or \"Up\" if no \"Next\". \\[Info-follow-nearest-node]\tLike `\\[Info-mouse-follow-nearest-node]', \ except cursor location, not mouse location. \\[Info-history-back]\tGo back to the last node you were at. (chronological) \\[Info-history-forward]\tGo forward to where you were before using \\[Info-history-back]. \\[Info-history]\tGo to menu of visited nodes. \\[Info-toc]\tGo to table of contents of the current Info file. \\[Info-index]\tLook up a topic in this file's Index and move to its node. \\[Info-index-next]\t(comma) Go to the next match from a previous \ `\\[Info-index]' command. Structural navigation commands ------------------------------ \\[Info-menu]\tGo to a menu item's node. Completion available for its name. 1\tGo to first menu item's node. 2, 3, 4, 5, 6, 7, 8, 9\tGo to second...ninth menu item's node. \\[Info-next]\tGo to this node's \"Next\" node. \\[Info-prev]\tGo to this node's \"Previous\" node. (*not* chronological) \\[Info-up]\tGo \"Up\" from this node to its parent node. \\[Info-directory]\tGo to the Info directory (root) node. \\[Info-follow-reference]\tFollow a cross reference. Prompts for name. Moving within a node -------------------- \\[Info-scroll-up]\tNormally, scroll forward a full screen. \tIf node's menu appears below cursor, go to first menu item. \tIf node's menu appears above cursor, go to parent node. \\[Info-scroll-down]\tNormally, scroll backward. If beginning of buffer is \ already \tvisible, go to previous menu entry, or up if there is none. \\[beginning-of-buffer]\tGo to beginning of node. \\[Info-next-reference]\tMove cursor to next cross-reference or menu item in \ this node. \\[Info-prev-reference]\tMove cursor to previous cross-reference or menu item. Other navigation commands ------------------------- \\[Info-exit]\tQuit Info. \\[Info-goto-node]\tGo to a node with a given name. (No completion available.) \tYou may include a filename as well, as \"(FILENAME)NODENAME\". \\[universal-argument] \\[info]\tGo to a new Info file. (Completion \ available.) \\[universal-argument] N \\[info]\tOpen Info with number in buffer name: *info*. \\[Info-top-node]\tGo to first node (\"Top\") of current Info file. \\[Info-final-node]\tGo to final node of current Info file. \\[Info-forward-node]\tGo forward a node, considering all nodes as one \ sequence. \\[Info-backward-node]\tGo backward a node, considering all nodes as one \ sequence. Other commands -------------- \\[Info-search]\tSearch this Info file for specified regexp, and go to node \twith next occurrence. (Not case-sensitive.) \\[Info-search-case-sensitively]\tLike \\[Info-search], but case-sensitive. \\[Info-search-next]\tSearch for another occurrence of regexp from \ta previous `\\[Info-search]' command. Other search commands, such as `\\[isearch-forward]', \tsearch only within the current node. \\[info-apropos]\tLook for a string in the indexes of all manuals. \\[Info-copy-current-node-name]\tPut name of current info node in the kill ring. \\[clone-buffer]\tSelect a new cloned Info buffer in another window. \\[Info-merge-subnodes]\tIntegrate current node with nodes referred to \ in its Menu. \tDisplay the result outside of Info. `\\[universal-argument]': Recursively. \\[Info-edit]\tEdit contents of current node. \ \(\\`\\[Info-cease-edit]'\\ to end editing.) \tEditing is enabled only if `Info-enable-edit' is non-nil. User options ------------ Some user options (variables you can define, via `defvar'): `Info-subtree-separator' - See `Info-merge-subnodes'. `Info-fontify-quotations-flag' - Non-nil means fontify single-quoted names (`...') and strings between double-quotes (\"...\") `info-file' - Face used for file heading labels `info-string' - Face used for strings (e.g. \"toto\"). `info-quoted-name' - Face used for quoted names (e.g. `toto'). These are all of the current Info Mode bindings: \\{Info-mode-map}" (kill-all-local-variables) (setq major-mode 'Info-mode) (setq mode-name "Info") (setq tab-width 8) (use-local-map Info-mode-map) (add-hook 'activate-menubar-hook 'Info-menu-update nil t) (set-syntax-table text-mode-syntax-table) (setq local-abbrev-table text-mode-abbrev-table) (setq case-fold-search t) (setq buffer-read-only t) (make-local-variable 'Info-current-file) (make-local-variable 'Info-current-subfile) (make-local-variable 'Info-current-node) (make-local-variable 'Info-tag-table-marker) (setq Info-tag-table-marker (make-marker)) (make-local-variable 'Info-tag-table-buffer) (setq Info-tag-table-buffer nil) (make-local-variable 'Info-history) (make-local-variable 'Info-history-forward) (make-local-variable 'Info-index-alternatives) (setq header-line-format (if Info-use-header-line '(:eval (get-text-property (point-min) 'header-line)) nil)) ; so the header line isn't displayed (set (make-local-variable 'tool-bar-map) info-tool-bar-map) ;; 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) (make-local-variable 'desktop-save-buffer) (make-local-variable 'widen-automatically) (setq widen-automatically nil) (setq desktop-save-buffer 'Info-desktop-buffer-misc-data) (add-hook 'kill-buffer-hook 'Info-kill-buffer nil t) (add-hook 'clone-buffer-hook 'Info-clone-buffer-hook nil t) (add-hook 'change-major-mode-hook 'font-lock-defontify nil t) (add-hook 'isearch-mode-hook 'Info-isearch-start nil t) (set (make-local-variable 'isearch-search-fun-function) 'Info-isearch-search) (set (make-local-variable 'isearch-wrap-function) 'Info-isearch-wrap) (set (make-local-variable 'isearch-push-state-function) 'Info-isearch-push-state) (set (make-local-variable 'search-whitespace-regexp) Info-search-whitespace-regexp) (Info-set-mode-line) (run-mode-hooks 'Info-mode-hook))) (defun Info-display-node-default-header () "Insert node name as header." (insert (if (fboundp 'concat-w-faces) ;; `node-name' is free here - bound in `Info-merge-subnodes'. (concat-w-faces (if (< emacs-major-version 21) (list 'info-node node-name) (list 'Info-title-1-face node-name))) node-name) "\n") (beginning-of-buffer) (center-line 2)) (defun Info-display-node-time-header () "Insert current time and node name as header." ;; `node-name' is free here - bound in `Info-merge-subnodes'. (insert (current-time-string) " " node-name) (beginning-of-buffer) (center-line)) ;; Note: This is not super-clean code (it's kind of a hack job). ;;;###autoload (defun Info-merge-subnodes (&optional recursive-display-p recursive-call-p) "Integrate current node with nodes referred to in its Menu. Displays the current Info node, together with the nodes in its Menu. Buffer `*Info: NODE*' is used for the display, where NODE is the name of the current node. The contents of this node's subnodes (the nodes named in this node's Menu) are included in the buffer, following the contents of the current node. Optional arg RECURSIVE-DISPLAY-P (prefix arg if interactive) governs the way menus of subnodes are treated: If nil, nothing additional happens. Subnode menus are not explored. Only the current node and its immediate subnodes are documented, in the single display buffer `*Info: NODE*'. If non-nil, then the subnodes of a node are treated in the same way as the parent node, recursively: If any of them has, itself, a Menu, then that menu's subnodes are also explored, and so on. If RECURSIVE-DISPLAY-P is zero, then a single display buffer is used for all of the nodes explored. Otherwise, a separate display buffer is used for each subnode that has a Menu (see next). Use this when you want a single, flat compilation of the current node and all of its subnodes. It is less appropriate when the current node has several levels of subnodes: The flattened result can be difficult to read. If RECURSIVE-DISPLAY-P is positive, then the contents of each subnode are displayed twice: once in the parent node's display, and once in the subnode's own display. Use this when the current node has several levels of subnodes and you want each display buffer to be self-contained. If RECURSIVE-DISPLAY-P is negative, then there is no redundancy: A subnode's contents are only displayed in its parent's buffer. The subnode's own display buffer only contains the contents of its own subnodes. Use this when the current node has several levels of subnodes and you want no redundancy between the display buffers. The user option (variable) `Info-subtree-separator' is a string to be inserted by `Info-merge-subnodes' just before the title of each node (preceding its description). By default it is \"\\n* \", producing a node title resembling a menu item. Setting this to \"\\f\\n* \" will cause a page break before each node description. For more on setting this variable, type \\`\\[describe-variable] Info-subtree-separator'. ------ Optional second arg RECURSIVE-CALL-P is only for internal use. It is used to indicate whether (non-nil) or not (nil) this is a recursive \(i.e. not a top-level) call to `Info-merge-subnodes'. Non-nil means that this is a subnode, and that its contents should only be included in the present display if RECURSIVE-DISPLAY-P is also non-nil. For proper operation when RECURSIVE-DISPLAY-P is zero, the non-nil value of RECURSIVE-CALL-P should be the node name of the top-level call to `Info-merge-subnodes'." (interactive "P") (when (interactive-p) (unless (y-or-n-p "Do you really want to integrate this node with its \ subnodes (outside Info)? ") (error (substitute-command-keys "OK. If you are not sure what this command is about, type \ `\\[describe-function] Info-merge-subnodes'.")))) ; Defined in `help.el'. (garbage-collect) (setq recursive-display-p (and recursive-display-p (prefix-numeric-value recursive-display-p))) (let* ((buf (current-buffer)) ; Info buffer (single-buf-p (and recursive-display-p (zerop recursive-display-p))) (node-name (or (and single-buf-p recursive-call-p) Info-current-node)) (rep-buf (get-buffer-create (concat "*Info: " node-name "*"))) ; Merge buffer. (more t) token oldpt strg menu-item-line ind) (when (interactive-p) (message "Processing node `%s' and %ssubnodes..." node-name (if recursive-display-p "all of its " "its immediate "))) (save-window-excursion (goto-char (point-min)) (forward-line 1) (setq strg (buffer-substring (point) (point-max))) ; Node contents. (goto-char (point-min)) (setq more (search-forward "* menu" nil t)) (forward-line 1) ;; Merge buffer: Insert buffer header and main node's contents, if not recursive or ;; do want redundancy. ;; Then insert each subnode (unless this is an Index). (switch-to-buffer-other-window rep-buf) (unless (and recursive-call-p single-buf-p) (erase-buffer) (funcall Info-display-node-header-fn) ; Insert header. (insert (concat "\n\n" (and (or (not recursive-call-p) ; Top-level call. (and recursive-display-p ; Redundancy desired. (> recursive-display-p 0))) strg)))) ; Insert main node's contents. (unless (string-match "\\s-*Index$" node-name) ; Don't recurse down Index menus. ;; Insert menu items and possibly their subnodes. (save-excursion (while more ;; Info buffer: Get menu item token. (set-buffer buf) (end-of-line) (setq oldpt (point)) (setq more (search-forward "\n* " nil t)) ; Possible next menu item. (unless more (goto-char (point-max))) (while (and (not (eobp)) ; Search for a real menu item. (not (setq token (Info-get-token ; File menu item. (point) "\\* " "\\* \\([^:]*\\)::"))) (not (setq token (Info-get-token ; Nonfile menu item. (point) "\\* " "\\* [^:]*:[ \t]+\\([^\t,.\n]+\\)[\t,.\n]")))) (setq more (search-forward "\n* " nil t))) (unless token (setq more nil)) ; No menu item. Done. ;; Treat subnode (menu item). (when more ;; Merge buffer: Insert separator line. (set-buffer rep-buf) (goto-char (point-max)) (insert Info-subtree-separator) ; Ready for next menu item. ;; Info buffer: Go to subnode. (set-buffer buf) (Info-goto-node token) (goto-char (point-min)) (forward-line 1) (setq strg (buffer-substring (point) (point-max))) ; Pick up subnode contents. ;; Go back to parent node and get menu-item line. (if (>= emacs-major-version 22) (Info-history-back) (Info-last)) (let ((inhibit-read-only t)) ; Get untabified menu-item line, so can count (buffer-enable-undo) (undo-start) ; chars to underline. (untabify (point) (save-excursion (forward-line 1) (point))) (setq menu-item-line (buffer-substring-no-properties (save-excursion (beginning-of-line)(forward-char 2) (point)) (save-excursion (forward-line 1) (point)))) (when pending-undo-list (undo-more 1)) ; Only if did something. (buffer-disable-undo)) ;; Merge buffer: Insert menu-item line, underline it, and insert subnode contents. (set-buffer rep-buf) (insert menu-item-line) (setq ind (1+ (length menu-item-line))) (while (> ind 0) (insert "=") (setq ind (1- ind))) ; Underline menu item. (insert "\n") (put-text-property (save-excursion (forward-line -2) (point)) (save-excursion (forward-line 1) (point)) 'face 'info-file) (setq oldpt (point)) (insert strg) ; Insert subnode contents. (indent-rigidly oldpt (point) 2) ;; Recursive call: Insert subnode's subnodes, if there are any. ;; Again, though, don't recurse down Index menus. (when (and recursive-display-p (not (string-match "\\s-*Index$" token))) (save-excursion ;; Info buffer: Go back to subnode. ;; If it has a menu, then treat its subnodes, recursively. (set-buffer buf) (Info-goto-node token) (when (search-forward "* menu" nil t) (forward-line 1) (end-of-line) (when (and (search-forward "\n* " nil t) (or (Info-get-token ; file menu item (point) "\\* " "\\* \\([^:]*\\)::") (Info-get-token ; nonfile menu item (point) "\\* " "\\* [^:]*:[ \t]+\\([^\t,.\n]+\\)[\t,.\n]"))) (Info-merge-subnodes recursive-display-p node-name))) ;; Info buffer: Go back to parent node. (set-buffer buf) (if (>= emacs-major-version 22) (Info-history-back) (Info-last)))) ;; Info buffer (set-buffer buf)))))) ;; Merge buffer (switch-to-buffer-other-window rep-buf) (when (and (one-window-p t) (not (window-minibuffer-p)) (fboundp 'fit-frame) ; Defined in `fit-frame.el'. Info-fit-frame-flag) (fit-frame)) (goto-char (point-min)) (set-buffer-modified-p nil) (use-local-map Info-merged-map) (when (interactive-p) (message "Processing node `%s' and %ssubnodes... done" node-name (if recursive-display-p "all of its " "its immediate "))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; info+.el ends here