]> code.delx.au - gnu-emacs/blobdiff - lisp/info.el
(delete-key-deletes-forward-mode): Treat ms-dos and
[gnu-emacs] / lisp / info.el
index 29d3124efe1b39d664165e859ca231c0f2a9c104..da25668b6846db06a64f09bea506a6ccc64cef1c 100644 (file)
@@ -70,7 +70,7 @@ The Lisp code is executed when the node is selected.")
 (defface info-menu-5
   '((((class color)) (:foreground "red1"))
     (t (:underline t)))
-  "Face for the fifth and tenth `*' in an Info menu."
+  "Face for the fifth and nineth `*' in an Info menu."
   :group 'info)
 
 (defface info-xref
@@ -126,6 +126,19 @@ These directories are not searched for merging the `dir' file."
   :type '(repeat directory)
   :group 'info)
 
+(defcustom Info-scroll-prefer-subnodes t
+  "*If non-nil, \\<Info-mode-map>\\[Info-scroll-up] in a menu visits subnodes.
+If this is non-nil, and you scroll far enough in a node that its menu
+appears on the screen, the next \\<Info-mode-map>\\[Info-scroll-up]
+moves to a subnode indicated by the following menu item.  This means
+that you visit a subnode before getting to the end of the menu.
+
+Setting this option to nil results in behavior similar to the stand-alone
+Info reader program, which visits the first subnode from the menu only
+when you hit the end of the current node."
+  :type 'boolean
+  :group 'info)
+
 (defvar Info-current-file nil
   "Info file that Info is now looking at, or nil.
 This is the name that was specified in Info, not the actual file name.
@@ -161,7 +174,7 @@ Marker points nowhere if file has no tag table.")
   (if (eq system-type 'ms-dos)
       '( (".gz"      . "gunzip")
         (".z"       . "gunzip")
-        (".bz2"     . "bzip2 -dc")
+        (".bz2"     . ("bzip2" "-dc"))
         (".inz"     . "gunzip")
         (".igz"     . "gunzip")
         (".info.Z"  . "gunzip")
@@ -179,29 +192,34 @@ Marker points nowhere if file has no tag table.")
        (".info.Y".    "unyabba")
        (".info.gz".   "gunzip")
        (".info.z".    "gunzip")
-       (".info.bz2" . "bzip2 -dc")
+       (".info.bz2" . ("bzip2" "-dc"))
        (".info".      nil)
        ("-info.Z".   "uncompress")
        ("-info.Y".   "unyabba")
        ("-info.gz".  "gunzip")
-       ("-info.bz2" . "bzip2 -dc")
+       ("-info.bz2" . ("bzip2" "-dc"))
        ("-info.z".   "gunzip")
        ("-info".     nil)
        ("/index.Z".   "uncompress")
        ("/index.Y".   "unyabba")
        ("/index.gz".  "gunzip")
        ("/index.z".   "gunzip")
-       ("/index.bz2". "bzip2 -dc")
+       ("/index.bz2". ("bzip2" "-dc"))
        ("/index".     nil)
        (".Z".         "uncompress")
        (".Y".         "unyabba")
        (".gz".        "gunzip")
        (".z".         "gunzip")
-       (".bz2" .      "bzip2 -dc")
+       (".bz2" .      ("bzip2" "-dc"))
        ("".           nil)))
   "List of file name suffixes and associated decoding commands.
 Each entry should be (SUFFIX . STRING); the file is given to
-the command as standard input.  If STRING is nil, no decoding is done.
+the command as standard input.
+
+STRING may be a list of strings.  In that case, the first element is
+the command name, and the rest are arguments to that command.
+
+If STRING is nil, no decoding is done.
 Because the SUFFIXes are tried in order, the empty string should
 be last in the list.")
 
@@ -271,7 +289,10 @@ Do the right thing if the file has been compressed or zipped."
                (coding-system-for-write 'no-conversion)
                (default-directory (or (file-name-directory fullname)
                                       default-directory)))
-           (call-process-region (point-min) (point-max) decoder t t)))
+           (or (consp decoder)
+               (setq decoder (list decoder)))
+           (apply 'call-process-region (point-min) (point-max)
+                  (car decoder) t t nil (cdr decoder))))
       (insert-file-contents fullname visit))))
 \f
 (defun info-initialize ()
@@ -772,6 +793,8 @@ a case-insensitive match is tried."
            (while (re-search-forward "^\\* Menu:" nil t)
              (let (beg nodename end)
                (forward-line 1)
+               (while (and (eolp) (not (eobp)))
+                 (forward-line 1))
                (setq beg (point))
                (or (search-backward "\n\^_" nil 'move)
                    (looking-at "\^_")
@@ -835,6 +858,7 @@ a case-insensitive match is tried."
       (while buffers
        (kill-buffer (car buffers))
        (setq buffers (cdr buffers)))
+      (if Info-fontify (Info-fontify-menu-headers))
       (goto-char (point-min))
       (if problems
          (message "Composing main Info directory...problems encountered, see `*Messages*'")
@@ -1596,7 +1620,8 @@ N is the digit argument used to invoke this command."
                 ;; so we can scroll back through it.
                 (goto-char (point-max))))
         (recenter -1))
-       ((and (not (equal (Info-extract-pointer "up")
+       ((and (Info-no-error (Info-extract-pointer "prev"))
+             (not (equal (Info-extract-pointer "up")
                          (Info-extract-pointer "prev"))))
         (Info-no-error (Info-prev))
         (goto-char (point-max))
@@ -1616,13 +1641,16 @@ N is the digit argument used to invoke this command."
 (defun Info-scroll-up ()
   "Scroll one screenful forward in Info, considering all nodes as one sequence.
 Once you scroll far enough in a node that its menu appears on the screen
-but after point, the next scroll moves into its first subnode.
+but after point, the next scroll moves into its first subnode, unless
+`Info-scroll-prefer-subnodes' is nil.
 
-When you scroll past the end of a node, that goes to the next node; if
-this node has no successor, it moves to the parent node's successor,
-and so on.  If point is inside the menu of a node, it moves to
-subnode indicated by the following menu item.  (That case won't
-normally result from this command, but can happen in other ways.)"
+When you scroll past the end of a node, that goes to the next node if
+`Info-scroll-prefer-subnodes' is non-nil and to the first subnode otherwise;
+if this node has no successor, it moves to the parent node's successor,
+and so on.  If `Info-scroll-prefer-subnodes' is non-nil and point is inside
+the menu of a node, it moves to subnode indicated by the following menu
+item.  (That case won't normally result from this command, but can happen
+in other ways.)"
 
   (interactive)
   (if (or (< (window-start) (point-min))
@@ -1631,32 +1659,39 @@ normally result from this command, but can happen in other ways.)"
   (let* ((case-fold-search t)
         (virtual-end (save-excursion
                        (goto-char (point-min))
-                       (if (search-forward "\n* Menu:" nil t)
+                       (if (and Info-scroll-prefer-subnodes
+                                (search-forward "\n* Menu:" nil t))
                            (point)
                          (point-max)))))
     (if (or (< virtual-end (window-start))
            (pos-visible-in-window-p virtual-end))
-       (Info-next-preorder)
+       (cond
+        (Info-scroll-prefer-subnodes (Info-next-preorder))
+        ((Info-no-error (Info-goto-node (Info-extract-menu-counting 1))))
+        (t (Info-next-preorder)))
       (scroll-up))))
 
 (defun Info-scroll-down ()
   "Scroll one screenful back in Info, considering all nodes as one sequence.
-Within the menu of a node, this goes to its last subnode.
-When you scroll past the beginning of a node, that goes to the
-previous node or back up to the parent node."
+If point is within the menu of a node, and `Info-scroll-prefer-subnodes'
+is non-nil, this goes to its last subnode.  When you scroll past the
+beginning of a node, that goes to the previous node or back up to the
+parent node."
   (interactive)
   (if (or (< (window-start) (point-min))
          (> (window-start) (point-max)))
       (set-window-start (selected-window) (point)))
   (let* ((case-fold-search t)
         (current-point (point))
-        (virtual-end (save-excursion
-                       (beginning-of-line)
-                       (setq current-point (point))
-                       (goto-char (point-min))
-                       (search-forward "\n* Menu:"
-                                       current-point
-                                       t))))
+        (virtual-end
+         (and Info-scroll-prefer-subnodes
+              (save-excursion
+                (beginning-of-line)
+                (setq current-point (point))
+                (goto-char (point-min))
+                (search-forward "\n* Menu:"
+                                current-point
+                                t)))))
     (if (or virtual-end (pos-visible-in-window-p (point-min)))
        (Info-last-preorder)
       (scroll-down))))
@@ -2154,7 +2189,6 @@ Advanced commands:
   (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)
@@ -2173,7 +2207,7 @@ Advanced commands:
   ;; 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 (make-local-hook 'clone-buffer-hook) 'Info-clone-buffer-hook nil t)
+  (add-hook 'clone-buffer-hook 'Info-clone-buffer-hook nil t)
   (Info-set-mode-line)
   (run-hooks 'Info-mode-hook))
 
@@ -2245,7 +2279,7 @@ Allowed only if variable `Info-enable-edit' is non-nil."
     ("time-stamp" . "autotype") ("quickurl" . "autotype")
     ("tempo" . "autotype") ("hippie-expand" . "autotype")
     ("cvs" . "pcl-cvs")
-    "ebrowse" "cl" "idlwave" "reftex" "speedbar" "widget" "woman")
+    "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.
@@ -2383,6 +2417,27 @@ the variable `Info-file-list-for-emacs'."
   "Face for Info titles at level 4."
   :group 'info)
 
+(defface info-menu-header
+  '((((type tty pc))
+     :underline t
+     :weight bold)
+    (t
+     :inherit variable-pitch
+     :weight bold))
+  "Face for headers in Info menus."
+  :group 'info)
+
+(defun Info-fontify-menu-headers ()
+  "Add the face `info-menu-header' to any header before a menu entry."
+  (save-excursion
+    (goto-char (point-min))
+    (when (re-search-forward "\\* Menu:" nil t)
+      (put-text-property (match-beginning 0) (match-end 0)
+                        'face 'info-menu-header)
+      (while (re-search-forward "\n\n\\([^*\n ].*\\)\n\n?[*]" nil t)
+       (put-text-property (match-beginning 1) (match-end 1)
+                          'face 'info-menu-header)))))
+
 (defun Info-fontify-node ()
   (save-excursion
     (let ((buffer-read-only nil)
@@ -2427,7 +2482,7 @@ the variable `Info-file-list-for-emacs'."
        ;; 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))
@@ -2450,10 +2505,11 @@ the variable `Info-file-list-for-emacs'."
                  (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")))))
+      (Info-fontify-menu-headers)
       (set-buffer-modified-p nil))))
 \f