:group 'info)
(defface info-node
- '((((class color)) (:foreground "brown" :bold t :italic t))
+ '((((class color) (background light)) (:foreground "brown" :bold t :italic t))
+ (((class color) (background dark)) (:foreground "white" :bold t :italic t))
(t (:bold t :italic t)))
"Face for Info node names."
:group 'info)
:group 'info)
(defface info-xref
- '((((class color)) (:foreground "magenta4" :bold t))
+ '((((class color) (background light)) (:foreground "magenta4" :bold t))
+ (((class color) (background dark)) (:foreground "cyan" :bold t))
(t (:bold t)))
"Face for Info cross-references."
:group 'info)
:type 'integer
:group 'info)
+(defcustom Info-use-header-line t
+ "*Non-nil means to put the beginning-of-node links in an emacs header-line.
+A header-line does not scroll with the rest of the buffer."
+ :type 'boolean
+ :group 'info)
+
+(defface info-header-xref
+ '((t (:inherit info-xref)))
+ "Face for Info cross-references in a node header."
+ :group 'info)
+
+(defface info-header-node
+ '((t (:inherit info-node)))
+ "Face for Info nodes in a node header."
+ :group 'info)
+
(defvar Info-directory-list nil
"List of directories to search for Info documentation files.
nil means not yet initialized. In this case, Info uses the environment
variable INFOPATH to initialize it, or `Info-default-directory-list'
if there is no INFOPATH variable in the environment.
-The last element of `Info-default-directory-list' is the directory
-where Emacs installs the Info files that come with it.
+
+When `Info-directory-list' is initialized from the value of
+`Info-default-directory-list', the first element of the resulting
+list is the directory where Emacs installs the Info files that
+come with it. This is so that Emacs's own manual, which suits the
+version of Emacs you are using, will always be found first. (If
+you want to override that, set INFOPATH in the environment.)
If you run the Emacs executable from the `src' directory in the Emacs
-source tree, the `info' directory in the source tree is used as the last
-element, in place of the installation Info directory. This is useful
-when you run a version of Emacs without installing it.")
+source tree, and INFOPATH is not defined, the `info' directory in the
+source tree is used as the first element of `Info-directory-list', in
+place of the installation Info directory. This is useful when you run
+a version of Emacs without installing it.")
(defcustom Info-additional-directory-list nil
"List of additional directories to search for Info documentation files.
(save-buffers-kill-emacs)))
(info)))
\f
-;; See if the the accessible portion of the buffer begins with a node
+;; See if the accessible portion of the buffer begins with a node
;; delimiter, and the node header line which follows matches REGEXP.
;; Typically, this test will be followed by a loop that examines the
;; rest of the buffer with (search-forward "\n\^_"), and it's a pity
;; want to use the results of re-search-backward.
;; The return value is the value of point at the beginning of matching
-;; REGERXP, if the function succeeds, nil otherwise.
+;; REGEXP, if the function succeeds, nil otherwise.
(defun Info-node-at-bob-matching (regexp)
(and (bobp) ; are we at beginning of buffer?
(looking-at "\^_") ; does it begin with node delimiter?
(if (numberp nodepos)
(+ (- nodepos lastfilepos) (point)))))
+(defvar Info-header-line nil
+ "If the info node header is hidden, the text of the header.")
+
(defun Info-select-node ()
"Select the info node that point is in.
Bind this in case the user sets it to nil."
;; Find the end of it, and narrow.
(beginning-of-line)
(let (active-expression)
+ ;; Narrow to the node contents
(narrow-to-region (point)
(if (re-search-forward "\n[\^_\f]" nil t)
(prog1
(point-max)))
(if Info-enable-active-nodes (eval active-expression))
(if Info-fontify (Info-fontify-node))
+ (if Info-use-header-line
+ (Info-setup-header-line)
+ (setq Info-header-line nil))
(run-hooks 'Info-selection-hook)))))
(defun Info-set-mode-line ()
(setq mode-line-buffer-identification
- (concat
- " *Info* ("
- (file-name-nondirectory (if (stringp Info-current-file)
- Info-current-file
- (or buffer-file-name "")))
- ") "
- (or Info-current-node ""))))
+ (nconc (propertized-buffer-identification "%b")
+ (list
+ (concat " ("
+ (file-name-nondirectory
+ (if (stringp Info-current-file)
+ Info-current-file
+ (or buffer-file-name "")))
+ ") "
+ (or Info-current-node ""))))))
+\f
+;; Skip the node header and make it into a header-line. This function
+;; should be called when the node is already narrowed.
+(defun Info-setup-header-line ()
+ (goto-char (point-min))
+ (forward-line 1)
+ (set (make-local-variable 'Info-header-line)
+ (buffer-substring (point-min) (1- (point))))
+ (setq header-line-format 'Info-header-line)
+ (narrow-to-region (point) (point-max)))
\f
;; Go to an info node specified with a filename-and-nodename string
;; of the sort that is found in pointers in nodes.
(defun Info-goto-node (nodename &optional fork)
"Go to info node named NAME. Give just NODENAME or (FILENAME)NODENAME.
-If FORK is non-nil, show the node in a new info buffer.
+If FORK is non-nil (interactively with a prefix arg), show the node in
+a new info buffer.
If FORK is a string, it is the name to use for the new buffer."
- (interactive (list (Info-read-node-name "Goto node: ") current-prefix-arg))
+ (interactive (list (Info-read-node-name "Go to node: ") current-prefix-arg))
(info-initialize)
(if fork
(set-buffer
Bind this in case the user sets it to nil."
(let ((case-fold-search t))
(save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (if (re-search-backward (concat name ":") nil t)
- (progn
- (goto-char (match-end 0))
- (Info-following-node-name))
- (if (eq errorname t)
- nil
- (error "Node has no %s" (capitalize (or errorname name))))))))
+ (save-restriction
+ (goto-char (point-min))
+ (when Info-header-line
+ ;; expose the header line in the buffer
+ (widen)
+ (forward-line -1))
+ (let ((bound (point)))
+ (forward-line 1)
+ (cond ((re-search-backward (concat name ":") bound t)
+ (goto-char (match-end 0))
+ (Info-following-node-name))
+ ((not (eq errorname t))
+ (error "Node has no %s"
+ (capitalize (or errorname name))))))))))
(defun Info-following-node-name (&optional allowedchars)
"Return the node name in the buffer following point.
(defun Info-menu (menu-item &optional fork)
"Go to node for menu item named (or abbreviated) NAME.
-Completion is allowed, and the menu item point is on is the default."
+Completion is allowed, and the menu item point is on is the default.
+If FORK is non-nil (interactively with a prefix arg), show the node in
+a new info buffer. If FORK is a string, it is the name to use for the
+new buffer."
(interactive
(let ((completions '())
;; If point is within a menu item, use that item as the default
(progn
(goto-char (point-min))
(while (re-search-forward pattern nil t)
- (setq matches
- (cons (list (match-string-no-properties 1)
- (match-string-no-properties 2)
- Info-current-node
- (string-to-int (concat "0"
- (match-string 3))))
- matches)))
+ (push (list (match-string-no-properties 1)
+ (match-string-no-properties 2)
+ Info-current-node
+ (string-to-int (concat "0"
+ (match-string 3))))
+ matches))
(and (setq node (Info-extract-pointer "next" t))
(string-match "\\<Index\\>" node)))
(Info-goto-node node))
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."
(interactive "e")
- (let* ((start (event-start click))
- (window (car start))
- (pos (car (cdr start))))
- (select-window window)
- (goto-char pos))
+ (mouse-set-point click)
(and (not (Info-try-follow-nearest-node))
(save-excursion (forward-line 1) (eobp))
(Info-next-preorder)))
:help "Go backward one node, considering all as a sequence"]
["Forward" Info-forward-node
:help "Go forward one node, considering all as a sequence"]
+ ["Beginning" beginning-of-buffer
+ :help "Go to beginning of this node"]
["Top" Info-top-node
:help "Go to top node of file"]
["Final Node" Info-final-node
("Reference" ["You should never see this" report-emacs-bug t])
["Search..." Info-search
:help "Search for regular expression in this Info file"]
- ["Goto Node..." Info-goto-node
+ ["Go to Node..." Info-goto-node
:help "Go to a named node"]
- ["Last" Info-last Info-history
+ ["Last" Info-last :active Info-history
:help "Go to the last node you were at"]
("Index..."
["Lookup a String" Info-index
:help "Look for a string in the index items"]
["Next Matching Item" Info-index-next
:help "Look for another occurrence of previous item"])
- ["Exit" Info-exit t]))
+ ["Edit" Info-edit :help "Edit contents of this node"
+ :active Info-enable-edit]
+ ["Exit" Info-exit :help "Stop reading Info"]))
+
+
+(defvar info-tool-bar-map
+ (if (display-graphic-p)
+ (let ((tool-bar-map (make-sparse-keymap)))
+ (tool-bar-add-item-from-menu 'Info-exit "close" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-prev "left_arrow" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-next "right_arrow" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-up "up_arrow" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-last "undo" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-top-node "home" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-index "index" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-goto-node "jump_to" Info-mode-map)
+ (tool-bar-add-item-from-menu 'Info-search "search" Info-mode-map)
+ tool-bar-map)))
(defvar Info-menu-last-node nil)
;; Last node the menu was created for.
\f
;; Info mode is suitable only for specially formatted data.
-(put 'info-mode 'mode-class 'special)
+(put 'Info-mode 'mode-class 'special)
(defun Info-mode ()
"Info mode provides commands for browsing through the Info documentation tree.
(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)
(with-current-buffer Info-tag-table-buffer
(copy-marker (marker-position m))))))))
-(defvar Info-edit-map nil
+(defvar Info-edit-map (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map text-mode-map)
+ (define-key map "\C-c\C-c" 'Info-cease-edit)
+ map)
"Local keymap used within `e' command of Info.")
-(if Info-edit-map
- nil
- (setq Info-edit-map (nconc (make-sparse-keymap) text-mode-map))
- (define-key Info-edit-map "\C-c\C-c" 'Info-cease-edit))
;; Info-edit mode is suitable only for specially formatted data.
-(put 'info-edit-mode 'mode-class 'special)
+(put 'Info-edit-mode 'mode-class 'special)
(defun Info-edit-mode ()
"Major mode for editing the contents of an Info node.
\f
(defvar Info-file-list-for-emacs
'("ediff" "forms" "gnus" ("mh" . "mh-e") "sc" "message"
- ("dired" . "dired-x") ("c" . "ccmode") "viper")
+ ("dired" . "dired-x") ("c" . "ccmode") "viper" "vip"
+ ("skeleton" . "autotype") ("auto-insert" . "autotype")
+ ("copyright" . "autotype") ("executable" . "autotype")
+ ("time-stamp" . "autotype") ("quickurl" . "autotype")
+ ("tempo" . "autotype") ("hippie-expand" . "autotype")
+ ("cvs" . "pcl-cvs")
+ "ebrowse" "eshell" "cl" "idlwave" "reftex" "speedbar" "widget" "woman")
"List of Info files that describe Emacs commands.
An element can be a file name, or a list of the form (PREFIX . FILE)
where PREFIX is a name prefix and FILE is the file to look in.
\(FILENAME NODENAME BUFFERPOS\)."
(let ((where '())
(cmd-desc (concat "^\\* +" (regexp-quote (symbol-name command))
- ":\\s *\\(.*\\)\\.$"))
+ "\\( <[0-9]+>\\)?:\\s *\\(.*\\)\\.$"))
(info-file "emacs")) ;default
;; Determine which info file this command is documented in.
(if (get command 'info-file)
(if (string-match regexp (symbol-name command))
(setq info-file file file-list nil))
(setq file-list (cdr file-list))))))
- (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
- (Info-find-node info-file "Index")))
- ;; 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
- (match-string-no-properties 1)
+ (Info-find-node info-file "Top")
+ (or (and (search-forward "\n* menu:" nil t)
+ (re-search-forward "\n\\* \\(.*\\<Index\\>\\)" nil t))
+ (error "Info file `%s' appears to lack an index" info-file))
+ (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)))
- where)))
+ (and (setq node (Info-extract-pointer "next" t))
+ (string-match "\\<Index\\>" node)))
+ (Info-goto-node node)))
+ where))
;;;###autoload
(defun Info-goto-emacs-command-node (command)
;; FIXME It would be cool if this could use a buffer other
;; than *info*.
(pop-to-buffer "*info*")
- (Info-find-node (car (car where))
- (car (cdr (car where))))
+ ;; 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-find-node (car (car where))
+ (car (cdr (car where)))))
(if (> num-matches 1)
(progn
- ;; Info-find-node already pushed (car where) onto
- ;; Info-history. Put the other nodes that were found on
- ;; the history.
+ ;; (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))
(message "Found %d other entr%s. Use %s to see %s."
(1- num-matches)
(Info-goto-emacs-command-node command)))))
\f
(defface Info-title-1-face
- '((t (:family "helv" :height 240 :weight bold)))
+ '((((type tty pc) (class color)) (:foreground "yellow" :weight bold))
+ (t (:height 1.2 :inherit Info-title-2-face)))
"Face for Info titles at level 1."
:group 'info)
(defface Info-title-2-face
- '((t (:family "helv" :height 180 :weight bold)))
+ '((((type tty pc) (class color)) (:foreground "lightblue" :weight bold))
+ (t (:height 1.2 :inherit Info-title-3-face)))
"Face for Info titles at level 2."
:group 'info)
(defface Info-title-3-face
- '((t (:family "helv" :height 160 :weight bold)))
+ '((((type tty pc) (class color)) (:weight bold))
+ (t (:height 1.2 :inherit Info-title-4-face)))
"Face for Info titles at level 3."
:group 'info)
+(defface Info-title-4-face
+ '((((type tty pc) (class color)) (:weight bold))
+ (t (:weight bold :inherit variable-pitch)))
+ "Face for Info titles at level 4."
+ :group 'info)
+
(defun Info-fontify-node ()
(save-excursion
(let ((buffer-read-only nil)
(goto-char (point-min))
(when (looking-at "^File: [^,: \t]+,?[ \t]+")
(goto-char (match-end 0))
- (while
- (looking-at "[ \t]*\\([^:, \t\n]+\\):[ \t]+\\([^:,\t\n]+\\),?")
+ (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))))
+ (let* ((nbeg (match-beginning 2))
+ (nend (match-end 2))
+ (tbeg (match-beginning 1))
+ (tag (buffer-substring tbeg (match-end 1))))
+ (if (string-equal tag "Node")
+ (put-text-property nbeg nend 'face 'info-header-node)
+ (put-text-property nbeg nend 'face 'info-header-xref)
+ (put-text-property nbeg nend 'mouse-face 'highlight)
+ (put-text-property tbeg nend
+ 'help-echo
+ (concat "Go to node "
+ (buffer-substring nbeg nend)))
+ (let ((fun (cdr (assoc tag '(("Prev" . Info-prev)
+ ("Next" . Info-next)
+ ("Up" . Info-up))))))
+ (when fun
+ (let ((keymap (make-sparse-keymap)))
+ (define-key keymap [header-line mouse-1] fun)
+ (define-key keymap [header-line mouse-2] fun)
+ (put-text-property tbeg nend 'local-map keymap))))
+ ))))
(goto-char (point-min))
- (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\)$"
+ (while (re-search-forward "\n\\([^ \t\n].+\\)\n\\(\\*+\\|=+\\|-+\\|\\.+\\)$"
nil t)
(let ((c (preceding-char))
face)
(cond ((= c ?*) (setq face 'Info-title-1-face))
((= c ?=) (setq face 'Info-title-2-face))
- (t (setq face 'Info-title-3-face)))
+ ((= c ?-) (setq face 'Info-title-3-face))
+ (t (setq face 'Info-title-4-face)))
(put-text-property (match-beginning 1) (match-end 1)
'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.
- (if (memq (framep (selected-frame)) '(x pc w32))
+ (if (memq (framep (selected-frame)) '(x pc w32 mac))
(add-text-properties (match-end 1) (match-end 2)
'(invisible t intangible t))))
(goto-char (point-min))
(while (re-search-forward "\\*Note[ \n\t]+\\([^:]*\\):" nil t)
(if (= (char-after (1- (match-beginning 0))) ?\") ; hack
nil
- (put-text-property (match-beginning 1) (match-end 1)
- 'face 'info-xref)
- (put-text-property (match-beginning 1) (match-end 1)
- 'mouse-face 'highlight)))
+ (add-text-properties (match-beginning 1) (match-end 1)
+ '(face info-xref
+ mouse-face highlight
+ help-echo "mouse-2: go to this node"))))
(goto-char (point-min))
(if (and (search-forward "\n* Menu:" nil t)
(not (string-match "\\<Index\\>" Info-current-node))
(put-text-property (match-beginning 0)
(1+ (match-beginning 0))
'face 'info-menu-5))
- (put-text-property (match-beginning 1) (match-end 1)
- 'face 'info-xref)
- (put-text-property (match-beginning 1) (match-end 1)
- 'mouse-face 'highlight))))
+ (add-text-properties (match-beginning 1) (match-end 1)
+ '(face info-xref
+ mouse-face highlight
+ help-echo "mouse-2: go to this node")))))
(set-buffer-modified-p nil))))
\f
(speedbar-change-initial-expansion-list "Info")
)
+(eval-when-compile (defvar speedbar-attached-frame))
+
(defun Info-speedbar-hierarchy-buttons (directory depth &optional node)
"Display an Info directory hierarchy in speedbar.
DIRECTORY is the current directory in the attached frame.
nil))))
(defun Info-speedbar-goto-node (text node indent)
- "When user clicks on TEXT, goto an info NODE.
+ "When user clicks on TEXT, go to an info NODE.
The INDENT level is ignored."
(select-frame speedbar-attached-frame)
(let* ((buff (or (get-buffer "*info*")