]> code.delx.au - gnu-emacs/blobdiff - lisp/info.el
Use the correct capitalization when making Info-mode and Info-edit-mode
[gnu-emacs] / lisp / info.el
index 80d1c3a05fe83f0651302292684343eb41d8ca3c..841e699cf34184e18f5972b4f1750ec7491b66a2 100644 (file)
@@ -61,7 +61,8 @@ The Lisp code is executed when the node is selected.")
   :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)
@@ -73,7 +74,8 @@ The Lisp code is executed when the node is selected.")
   :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)
@@ -83,18 +85,44 @@ The Lisp code is executed when the node is selected.")
   :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
+  '(;; Because header-lines on tty's are usually reverse-video, the
+    ;; normal info-node colors probably won't look good, so just stick
+    ;; with bold-italic
+    (((type tty) (class color)) (:bold t :italic t))
+    (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.
@@ -576,7 +604,9 @@ a case-insensitive match is tried."
           ;; Search file for a suitable node.
          (let ((guesspos (point-min))
                (regexp (concat "\\(Node:\\|Ref:\\) *\\("
-                               (regexp-quote nodename)
+                               (if (stringp nodename) 
+                                   (regexp-quote nodename)
+                                 "")
                                "\\) *[,\t\n\177]"))
                (nodepos nil))
 
@@ -665,7 +695,10 @@ a case-insensitive match is tried."
       (progn
        (insert Info-dir-contents)
        (goto-char (point-min)))
-    (let ((dirs Info-directory-list)
+    (let ((dirs (if Info-additional-directory-list
+                              (append Info-directory-list
+                                      Info-additional-directory-list)
+                            Info-directory-list))
          ;; Bind this in case the user sets it to nil.
          (case-fold-search t)
          ;; This is set non-nil if we find a problem in some input files.
@@ -862,6 +895,9 @@ a case-insensitive match is tried."
     (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."
@@ -884,6 +920,7 @@ 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
@@ -896,6 +933,9 @@ Bind this in case the user sets it to nil."
                            (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 ()
@@ -908,6 +948,16 @@ Bind this in case the user sets it to nil."
         ") "
         (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.
 
@@ -1090,15 +1140,20 @@ if ERRORNAME is nil, just return nil.
 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
+      (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 ":") nil bound)
            (goto-char (match-end 0))
            (Info-following-node-name))
-       (if (eq errorname t)
-           nil
-         (error "Node has no %s" (capitalize (or errorname 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.
@@ -2023,7 +2078,7 @@ If no reference to follow, moves to the next node, or up if none."
 
 \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.
@@ -2123,7 +2178,7 @@ Advanced commands:
   (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.
@@ -2167,8 +2222,14 @@ Allowed only if variable `Info-enable-edit' is non-nil."
        (message "Tags may have changed.  Use Info-tagify if necessary")))
 \f
 (defvar Info-file-list-for-emacs
-  '("ediff" "forms" "gnus" "info" ("mh" . "mh-e") "sc" "message"
-    ("dired" . "dired-x") ("c" . "ccmode") "viper")
+  '("ediff" "forms" "gnus" ("mh" . "mh-e") "sc" "message"
+    ("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" "cl" "idlwave" "reftex" "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.
@@ -2183,7 +2244,7 @@ The locations are of the format used in `Info-history', i.e.
 \(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)
@@ -2202,22 +2263,30 @@ The locations are of the format used in `Info-history', i.e.
            (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)
@@ -2237,13 +2306,17 @@ the variable `Info-file-list-for-emacs'."
          ;; 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)
@@ -2259,7 +2332,7 @@ Interactively, if the binding is `execute-extended-command', a command is read.
 The command is found by looking up in Emacs manual's Command Index
 or in another manual found via COMMAND's `info-file' property or
 the variable `Info-file-list-for-emacs'."
-  (interactive "kFind documentation for key:")
+  (interactive "kFind documentation for key: ")
   (let ((command (key-binding key)))
     (cond ((null command)
           (message "%s is undefined" (key-description key)))
@@ -2271,17 +2344,17 @@ the variable `Info-file-list-for-emacs'."
           (Info-goto-emacs-command-node command)))))
 \f
 (defface Info-title-1-face
-  '((t (:family "helv" :height 240 :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)))
+  '((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)))
+  '((t (:height 1.2 :weight bold :inherit variable-pitch)))
   "Face for Info titles at level 3."
   :group 'info)
 
@@ -2292,18 +2365,29 @@ the variable `Info-file-list-for-emacs'."
       (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 "Goto 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\\(\\*+\\|=+\\|-+\\)$"
                                nil t)