]> code.delx.au - gnu-emacs/blobdiff - lisp/man.el
(popup-dialog-box): Don't quote nil and t in docstrings.
[gnu-emacs] / lisp / man.el
index c5a5acd1282e6fa23dc72fb67d3a0b6df2931c9a..0c26ca4deb87da70aca42b22bd5aaf8e7d95c6d6 100644 (file)
@@ -95,6 +95,7 @@
 ;;; Code:
 
 (require 'assoc)
+(require 'button)
 
 ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
 ;; empty defvars (keep the compiler quiet)
@@ -210,6 +211,12 @@ the associated section number."
                       (string :tag "Real Section")))
   :group 'man)
 
+(defcustom Man-header-file-path
+  '("/usr/include" "/usr/local/include")
+  "C Header file search path used in Man."
+  :type '(repeat string)
+  :group 'man)
+
 (defvar manual-program "man"
   "The name of the program that produces man pages.")
 
@@ -249,7 +256,7 @@ the associated section number."
            "(\\(" Man-section-regexp "\\))\\).*\\1"))
   "Regular expression describing the heading of a page.")
 
-(defvar Man-heading-regexp "^\\([A-Z][A-Z ]+\\)$"
+(defvar Man-heading-regexp "^\\([A-Z][A-Z -]+\\)$"
   "Regular expression describing a manpage heading entry.")
 
 (defvar Man-see-also-regexp "SEE ALSO"
@@ -264,6 +271,34 @@ This regular expression should start with a `^' character.")
   (concat "\\(" Man-name-regexp "\\)(\\(" Man-section-regexp "\\))")
   "Regular expression describing a reference to another manpage.")
 
+(defvar Man-synopsis-regexp "SYNOPSIS"
+  "Regular expression for SYNOPSIS heading (or your equivalent).
+This regexp should not start with a `^' character.")
+
+(defvar Man-files-regexp "FILES"
+  "Regular expression for FILES heading (or your equivalent).
+This regexp should not start with a `^' character.")
+
+(defvar Man-include-regexp "#[ \t]*include[ \t]*"
+  "Regular expression describing the #include (directive of cpp).")
+
+(defvar Man-file-name-regexp "[^<>\" \t\n]+"
+  "Regular expression describing <> in #include line (directive of cpp).")
+
+(defvar Man-normal-file-prefix-regexp "[/~$]"
+  "Regular expression describing a file path appeared in FILES section.")
+
+(defvar Man-header-regexp
+  (concat "\\(" Man-include-regexp "\\)"
+          "[<\"]"
+          "\\(" Man-file-name-regexp "\\)"
+          "[>\"]")
+  "Regular expression describing references to header files.")
+
+(defvar Man-normal-file-regexp
+  (concat Man-normal-file-prefix-regexp Man-file-name-regexp)
+  "Regular expression describing references to normal files.")
+
 ;; This includes the section as an optional part to catch hyphenated
 ;; refernces to manpages.
 (defvar Man-hyphenated-reference-regexp
@@ -333,7 +368,7 @@ make -a one of the switches, if your `man' program supports it.")
 
 (if Man-mode-map
     nil
-  (setq Man-mode-map (make-keymap))
+  (setq Man-mode-map (copy-keymap button-buffer-map))
   (suppress-keymap Man-mode-map)
   (define-key Man-mode-map " "    'scroll-up)
   (define-key Man-mode-map "\177" 'scroll-down)
@@ -350,11 +385,32 @@ make -a one of the switches, if your `man' program supports it.")
   (define-key Man-mode-map "k"    'Man-kill)
   (define-key Man-mode-map "q"    'Man-quit)
   (define-key Man-mode-map "m"    'man)
-  (define-key Man-mode-map "\r"   'man-follow)
-  (define-key Man-mode-map [mouse-2]   'man-follow-mouse)
   (define-key Man-mode-map "?"    'describe-mode)
   )
 
+;; buttons
+(define-button-type 'Man-xref-man-page
+  'action (lambda (button) (man-follow (button-label button)))
+  'help-echo "RET, mouse-2: display this man page")
+
+(define-button-type 'Man-xref-header-file
+    'action (lambda (button)
+              (let ((w (button-get button 'Man-target-string)))
+                (unless (Man-view-header-file w)
+                  (error "Cannot find header file: %s" w))))
+    'help-echo "mouse-2: display this header file")
+
+(define-button-type 'Man-xref-normal-file
+  'action (lambda (button)
+           (let ((f (substitute-in-file-name
+                     (button-get button 'Man-target-string))))
+             (if (file-exists-p f)
+                 (if (file-readable-p f)
+                     (view-file f)
+                   (error "Cannot read a file: %s" f))
+               (error "Cannot find a file: %s" f))))
+  'help-echo "mouse-2: mouse-2: display this file")
+
 \f
 ;; ======================================================================
 ;; utilities
@@ -562,13 +618,6 @@ all sections related to a subject, put something appropriate into the
       (error "No item under point")
     (man man-args)))
 
-(defun man-follow-mouse (e)
-  "Get a Un*x manual page of the item under the mouse and put it in a buffer."
-  (interactive "e")
-  (save-excursion
-    (mouse-set-point e)
-    (call-interactively 'man-follow)))
-
 (defun Man-getpage-in-background (topic)
   "Use TOPIC to build and fire off the manpage and cleaning command."
   (let* ((man-args topic)
@@ -593,7 +642,12 @@ all sections related to a subject, put something appropriate into the
             (if default-enable-multibyte-characters
                 locale-coding-system 'raw-text-unix))
            ;; Avoid possible error by using a directory that always exists.
-           (default-directory "/"))
+           (default-directory
+             (if (and (file-directory-p default-directory)
+                      (not (find-file-name-handler default-directory
+                                                   'file-directory-p)))
+                 default-directory
+               "/")))
        ;; Prevent any attempt to use display terminal fanciness.
        (setenv "TERM" "dumb")
        ;; In Debian Woody, at least, we get overlong lines under X
@@ -613,24 +667,24 @@ all sections related to a subject, put something appropriate into the
              ;; the page will actually be displayed, but it seems
              ;; reasonable.
              (setenv "COLUMNS" (number-to-string (frame-width)))))
+       (setenv "GROFF_NO_SGR" "1")
        (if (fboundp 'start-process)
            (set-process-sentinel
             (start-process manual-program buffer "sh" "-c"
                            (format (Man-build-man-command) man-args))
             'Man-bgproc-sentinel)
-         (progn
-           (let ((exit-status
-                  (call-process shell-file-name nil (list buffer nil) nil "-c"
-                                (format (Man-build-man-command) man-args)))
-                 (msg ""))
-             (or (and (numberp exit-status)
-                      (= exit-status 0))
-                 (and (numberp exit-status)
-                      (setq msg
-                            (format "exited abnormally with code %d"
-                                    exit-status)))
-                 (setq msg exit-status))
-             (Man-bgproc-sentinel bufname msg))))))))
+         (let ((exit-status
+                (call-process shell-file-name nil (list buffer nil) nil "-c"
+                              (format (Man-build-man-command) man-args)))
+               (msg ""))
+           (or (and (numberp exit-status)
+                    (= exit-status 0))
+               (and (numberp exit-status)
+                    (setq msg
+                          (format "exited abnormally with code %d"
+                                  exit-status)))
+               (setq msg exit-status))
+           (Man-bgproc-sentinel bufname msg)))))))
 
 (defun Man-notify-when-ready (man-buffer)
   "Notify the user when MAN-BUFFER is ready.
@@ -732,12 +786,41 @@ Same for the ANSI bold and normal escape sequences."
     (put-text-property (1- (point)) (point) 'face 'bold))
   (goto-char (point-min))
   ;; Try to recognize common forms of cross references.
-  (while (re-search-forward "\\w+([0-9].?)" nil t)
-    (put-text-property (match-beginning 0) (match-end 0)
-                      'mouse-face 'highlight))
+  (Man-highlight-references)
   (Man-softhyphen-to-minus)
   (message "%s man page made up" Man-arguments))
 
+(defun Man-highlight-references ()
+  "Highlight the references on mouse-over.
+references include items in the SEE ALSO section,
+header file(#include <foo.h>) and files in FILES"
+  (let ((dummy 0))
+    (Man-highlight-references0
+     Man-see-also-regexp Man-reference-regexp 1 dummy
+     'Man-xref-man-page)
+    (Man-highlight-references0
+     Man-synopsis-regexp Man-header-regexp 0 2
+     'Man-xref-header-file)
+    (Man-highlight-references0
+     Man-files-regexp Man-normal-file-regexp 0 0
+     'Man-xref-normal-file)))
+
+(defun Man-highlight-references0 (start-section regexp button-pos target-pos type)
+  ;; Based on `Man-build-references-alist'
+  (when (Man-find-section start-section)
+    (forward-line 1)
+    (let ((end (save-excursion
+                 (Man-next-section 1)
+                 (point))))
+      (back-to-indentation)
+      (while (re-search-forward regexp end t)
+       (make-text-button
+        (match-beginning button-pos)
+        (match-end button-pos)
+        'type type
+        'Man-target-string (match-string target-pos)
+        )))))
+
 (defun Man-cleanup-manpage ()
   "Remove overstriking and underlining from the current buffer."
   (interactive)
@@ -1115,7 +1198,7 @@ Specify which REFERENCE to use; default is based on word at point."
                            (aheadsym Man-refpages-alist)))
                   chosen
                   (prompt (concat "Refer to: (default " default ") ")))
-             (setq chosen (completing-read prompt Man-refpages-alist nil t))
+             (setq chosen (completing-read prompt Man-refpages-alist))
              (if (or (not chosen)
                      (string= chosen ""))
                  default
@@ -1188,6 +1271,20 @@ Specify which REFERENCE to use; default is based on word at point."
     (if Man-circular-pages-flag
        (Man-goto-page (length Man-page-list))
       (error "You're looking at the first manpage in the buffer"))))
+
+;; Header file support
+(defun Man-view-header-file (file)
+  "View a header file specified by FILE from `Man-header-file-path'."
+  (let ((path Man-header-file-path)
+        complete-path)
+    (while path
+      (setq complete-path (concat (car path) "/" file)
+            path (cdr path))
+      (if (file-readable-p complete-path)
+          (progn (view-file complete-path)
+                 (setq path nil))
+        (setq complete-path nil)))
+    complete-path))
 \f
 ;; Init the man package variables, if not already done.
 (Man-init-defvars)