]> code.delx.au - gnu-emacs/blobdiff - lisp/info.el
(goto-address-mail-regexp): Allow = in username.
[gnu-emacs] / lisp / info.el
index b779bb41ca6b915aee45778db3955de5b3b6ccd7..750f302d4227ee28b024f8388b38591b77ebd688 100644 (file)
@@ -79,14 +79,14 @@ The Lisp code is executed when the node is selected.")
   :group 'info)
 
 (defface info-xref
-  '((((class color) (background light)) :foreground "blue")
-    (((class color) (background dark)) :foreground "cyan")
+  '((((class color) (background light)) :foreground "blue" :underline t)
+    (((class color) (background dark)) :foreground "cyan" :underline t)
     (t :underline t))
   "Face for Info cross-references."
   :group 'info)
 
 (defface info-xref-visited
-  '((t :inherit info-xref)
+  '((default :inherit info-xref)
     (((class color) (background light)) :foreground "magenta4")
     (((class color) (background dark)) :foreground "magenta3")) ;"violet"?
   "Face for visited Info cross-references."
@@ -188,7 +188,7 @@ file, so be prepared for a few surprises if you enable this feature."
   :type 'boolean
   :group 'info)
 
-(defcustom Info-search-whitespace-regexp "\\(?:\\s-+\\)"
+(defcustom Info-search-whitespace-regexp "\\s-+"
   "*If non-nil, regular expression to match a sequence of whitespace chars.
 This applies to Info search for regular expressions.
 You might want to use something like \"[ \\t\\r\\n]+\" instead.
@@ -455,6 +455,7 @@ Do the right thing if the file has been compressed or zipped."
 
 ;;;###autoload (add-hook 'same-window-regexps "\\*info\\*\\(\\|<[0-9]+>\\)")
 
+;;;###autoload (put 'info 'info-file "emacs")
 ;;;###autoload
 (defun info (&optional file buffer)
   "Enter Info, the documentation browser.
@@ -656,10 +657,10 @@ is preserved, if possible."
             (equal old-nodename Info-current-node))
        (progn
          ;; note goto-line is no good, we want to measure from point-min
-         (beginning-of-buffer)
+         (goto-char (point-min))
          (forward-line wline)
          (set-window-start (selected-window) (point))
-         (beginning-of-buffer)
+         (goto-char (point-min))
          (forward-line pline)
          (move-to-column pcolumn))
       ;; only add to the history when coming from a different file+node
@@ -1467,31 +1468,45 @@ If DIRECTION is `backward', search in the reverse direction."
          (opoint-max (point-max))
          (ostart (window-start))
          (osubfile Info-current-subfile))
-      (when Info-search-whitespace-regexp
-        (setq regexp
-              (mapconcat 'identity (split-string regexp "[ \t\n]+")
-                         Info-search-whitespace-regexp)))
       (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)
-                     (or (null found)
-                         (if backward
-                              (isearch-range-invisible found beg-found)
-                            (isearch-range-invisible beg-found found))))
-           (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)))))
+                     (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 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))))))
       ;; If no subfiles, give error now.
       (if give-up
          (if (null Info-current-subfile)
-             (if backward
-                  (re-search-backward regexp)
-                (re-search-forward regexp))
+             (let ((search-spaces-regexp Info-search-whitespace-regexp))
+               (if backward
+                   (re-search-backward regexp)
+                 (re-search-forward regexp)))
            (setq found nil)))
 
       (unless (or found bound)
@@ -1530,20 +1545,37 @@ If DIRECTION is `backward', search in the reverse direction."
              (while list
                (message "Searching subfile %s..." (cdr (car list)))
                (Info-read-subfile (car (car list)))
-                (if backward (goto-char (point-max)))
+               (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)
-                           (or (null found)
-                               (if backward
-                                    (isearch-range-invisible found beg-found)
-                                  (isearch-range-invisible beg-found found))))
-                 (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)))
+                           (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 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
@@ -1729,7 +1761,7 @@ If SAME-FILE is non-nil, do not move to a different Info file."
       (let ((inhibit-read-only t))
         (erase-buffer)
         (goto-char (point-min))
-        (insert "\n\^_\nFile: history Node: Top, Up: (dir)\n\n")
+        (insert "\n\^_\nFile: history,  Node: Top,  Up: (dir)\n\n")
         (insert "Recently Visited Nodes\n**********************\n\n")
         (insert "* Menu:\n\n")
         (let ((hl (delete '("history" "Top") Info-history-list)))
@@ -1749,26 +1781,31 @@ If SAME-FILE is non-nil, do not move to a different Info file."
   "Go to a node with table of contents of the current Info file.
 Table of contents is created from the tree structure of menus."
   (interactive)
-  (let ((curr-file Info-current-file)
-        (curr-node Info-current-node)
+  (let ((curr-file (substring-no-properties Info-current-file))
+        (curr-node (substring-no-properties Info-current-node))
         p)
     (with-current-buffer (get-buffer-create " *info-toc*")
       (let ((inhibit-read-only t)
             (node-list (Info-build-toc curr-file)))
         (erase-buffer)
         (goto-char (point-min))
-        (insert "\n\^_\nFile: toc Node: Top, Up: (dir)\n\n")
+        (insert "\n\^_\nFile: toc,  Node: Top,  Up: (dir)\n\n")
         (insert "Table of Contents\n*****************\n\n")
-        (insert "*Note Top::\n")
+        (insert "*Note Top: (" curr-file ")Top.\n")
         (Info-insert-toc
          (nth 2 (assoc "Top" node-list)) ; get Top nodes
-         node-list 0 (substring-no-properties curr-file)))
+         node-list 0 curr-file))
       (if (not (bobp))
           (let ((Info-hide-note-references 'hide)
                 (Info-fontify-visited-nodes nil))
             (Info-mode)
             (setq Info-current-file "toc" Info-current-node "Top")
-            (Info-fontify-node)))
+            (goto-char (point-min))
+            (narrow-to-region (or (re-search-forward "\n[\^_\f]\n" nil t)
+                                  (point-min))
+                              (point-max))
+            (Info-fontify-node)
+            (widen)))
       (goto-char (point-min))
       (if (setq p (search-forward (concat "*Note " curr-node ":") nil t))
           (setq p (- p (length curr-node) 2))))
@@ -1789,14 +1826,12 @@ Table of contents is created from the tree structure of menus."
 
 (defun Info-build-toc (file)
   "Build table of contents from menus of Info FILE and its subfiles."
-  (if (equal file "dir")
-      (error "Table of contents for Info directory is not supported yet"))
   (with-temp-buffer
-    (let* ((default-directory (or (and (stringp file)
-                                       (file-name-directory
-                                        (setq file (Info-find-file file))))
+    (let* ((file (and (stringp file) (Info-find-file file)))
+           (default-directory (or (and (stringp file)
+                                       (file-name-directory file))
                                   default-directory))
-           (main-file file)
+           (main-file (and (stringp file) file))
            (sections '(("Top" "Top")))
            nodes subfiles)
       (while (or main-file subfiles)
@@ -1976,7 +2011,7 @@ Because of ambiguities, this should be concatenated with something like
               (if (match-beginning 5)
                   (string-to-number (match-string 5))
                 (buffer-substring (match-beginning 0) (1- (match-beginning 1)))))
-;;; Comment out the next line to use names of cross-references:
+;;; Uncomment next line to use names of cross-references in non-index nodes:
 ;;;       (setq Info-point-loc
 ;;;             (buffer-substring (match-beginning 0) (1- (match-beginning 1))))
       )
@@ -2799,8 +2834,7 @@ if point is in a menu item description, follow that menu item."
   "Follow a node reference near point.  Return non-nil if successful."
   (let (node)
     (cond
-     ((and (Info-get-token (point) "[hf]t?tp://" "[hf]t?tp://\\([^ \t\n\"`({<>})']+\\)")
-           (or (featurep 'browse-url) (require 'browse-url nil t)))
+     ((Info-get-token (point) "[hf]t?tp://" "[hf]t?tp://\\([^ \t\n\"`({<>})']+\\)")
       (setq node t)
       (browse-url (browse-url-url-at-point)))
      ((setq node (Info-get-token (point) "\\*note[ \n\t]+"
@@ -3210,7 +3244,7 @@ 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" "eudc" "forms" "gnus" "info" ("mh" . "mh-e")
+  '("ediff" "eudc" "forms" "gnus" "info" ("Info" . "info") ("mh" . "mh-e")
     "sc" "message" ("dired" . "dired-x") "viper" "vip" "idlwave"
     ("c" . "ccmode") ("c++" . "ccmode") ("objc" . "ccmode")
     ("java" . "ccmode") ("idl" . "ccmode") ("pike" . "ccmode")
@@ -3241,10 +3275,13 @@ 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 `Info-history', i.e.
-\(FILENAME NODENAME BUFFERPOS\)."
-  (let ((where '())
+\(FILENAME NODENAME BUFFERPOS\), where BUFFERPOS is the line number
+in the first element of the returned list (which is treated specially in
+`Info-goto-emacs-command-node'), and 0 for the rest elements of a list."
+  (let ((where '()) line-number
        (cmd-desc (concat "^\\* +" (regexp-quote (symbol-name command))
-                         "\\( <[0-9]+>\\)?:\\s *\\(.*\\)\\.$"))
+                         "\\( <[0-9]+>\\)?:\\s *\\(.*\\)\\."
+                         "\\(?:[ \t\n]+(line +\\([0-9]+\\))\\)?"))
        (info-file "emacs"))            ;default
     ;; Determine which info file this command is documented in.
     (if (get command 'info-file)
@@ -3258,6 +3295,7 @@ The locations are of the format used in `Info-history', i.e.
                           (car elt)
                         elt))
                 (file (if (consp elt) (cdr elt) elt))
+                (case-fold-search nil)
                 (regexp (concat "\\`" (regexp-quote name)
                                 "\\(\\'\\|-\\)")))
            (if (string-match regexp (symbol-name command))
@@ -3282,11 +3320,17 @@ The locations are of the format used in `Info-history', i.e.
                    (cons (list Info-current-file
                                (match-string-no-properties 2)
                                0)
-                         where)))
+                         where))
+             (setq line-number (and (match-beginning 3)
+                                    (string-to-number (match-string 3)))))
            (and (setq nodes (cdr nodes) node (car nodes))))
        (Info-goto-node node)))
-    where))
+    (if (and line-number where)
+       (cons (list (nth 0 (car where)) (nth 1 (car where)) line-number)
+             (cdr where))
+      where)))
 
+;;;###autoload (put 'Info-goto-emacs-command-node 'info-file "emacs")
 ;;;###autoload
 (defun Info-goto-emacs-command-node (command)
   "Go to the Info node in the Emacs manual for command COMMAND.
@@ -3310,9 +3354,11 @@ COMMAND must be a symbol or string."
          ;; 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)))))
+         (let ((Info-history nil) (Info-history-list nil)
+               (line-number (nth 2 (car where))))
+           (Info-find-node (nth 0 (car where)) (nth 1 (car where)))
+           (if (and (integerp line-number) (> line-number 0))
+               (forward-line (1- line-number))))
          (if (> num-matches 1)
              (progn
                ;; (car where) will be pushed onto Info-history
@@ -3326,6 +3372,7 @@ COMMAND must be a symbol or string."
                         (if (> num-matches 2) "them" "it")))))
       (error "Couldn't find documentation for %s" command))))
 
+;;;###autoload (put 'Info-goto-emacs-key-command-node 'info-file "emacs")
 ;;;###autoload
 (defun Info-goto-emacs-key-command-node (key)
   "Go to the node in the Emacs manual which describes the command bound to KEY.
@@ -3440,7 +3487,8 @@ Preserve text properties."
            (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))))
+                 (< (- (point-max) (point-min)) Info-fontify-maximum-menu-size)))
+           rbeg rend)
 
       ;; Fontify header line
       (goto-char (point-min))
@@ -3565,39 +3613,48 @@ Preserve text properties."
                              "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))))
+              (setq rbeg (match-beginning 2)
+                    rend (match-end 2))
+              (put-text-property
+               rbeg rend
+               '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))
+              ;; For multiline ref, unfontify newline and surrounding whitespace
+              (save-excursion
+                (goto-char rbeg)
+                (save-match-data
+                  (while (re-search-forward "\\s-*\n\\s-*" rend t nil)
+                    (remove-text-properties (match-beginning 0)
+                                            (match-end 0)
+                                            '(font-lock-face t))))))
             (when not-fontified-p
               (when (memq Info-hide-note-references '(t hide))
                 (add-text-properties (match-beginning 3) (match-end 3)