Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / help.el
index a2e721d..a382113 100644 (file)
@@ -1,7 +1,7 @@
 ;;; help.el --- help commands for Emacs
 
-;; Copyright (C) 1985, 1986, 1993, 1994, 1998, 1999, 2000, 2001, 2002,
-;;   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1986, 1993-1994, 1998-2012
+;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
 ;; Keywords: help, internal
 (add-hook 'temp-buffer-setup-hook 'help-mode-setup)
 (add-hook 'temp-buffer-show-hook 'help-mode-finish)
 
-;; The variable `help-window' below is used by `help-mode-finish' to
-;; communicate the window displaying help (the "help window") to the
-;; macro `with-help-window'.  The latter sets `help-window' to t before
-;; invoking `with-output-to-temp-buffer'.  If and only if `help-window'
-;; is eq to t, `help-mode-finish' (called by `temp-buffer-setup-hook')
-;; sets `help-window' to the window selected by `display-buffer'.
-;; Exiting `with-help-window' and calling `help-print-return-message'
-;; reset `help-window' to nil.
-(defvar help-window nil
-  "Window chosen for displaying help.")
-
 ;; `help-window-point-marker' is a marker you can move to a valid
 ;; position of the buffer shown in the help window in order to override
 ;; the standard positioning mechanism (`point-min') chosen by
@@ -55,7 +44,7 @@
 ;; nowhere before exiting.  Currently used by `view-lossage' to assert
 ;; that the last keystrokes are always visible.
 (defvar help-window-point-marker (make-marker)
-  "Marker to override default `window-point' of `help-window'.")
+  "Marker to override default `window-point' in help windows.")
 
 (defvar help-map
   (let ((map (make-sparse-keymap)))
 (define-key global-map [f1] 'help-command)
 (fset 'help-command help-map)
 
-(autoload 'finder-by-keyword "finder"
-  "Find packages matching a given keyword." t)
-
 ;; insert-button makes the action nil if it is not store somewhere
 (defvar help-button-cache nil)
 
   "What to do to \"exit\" the help buffer.
 This is a list
  (WINDOW . t)              delete the selected window (and possibly its frame,
-                           see `quit-window' and `View-quit'), go to WINDOW.
+                           see `quit-window'), go to WINDOW.
  (WINDOW . quit-window)    do quit-window, then select WINDOW.
  (WINDOW BUF START POINT)  display BUF at START, POINT, then select WINDOW.")
 
@@ -147,8 +133,6 @@ It computes a message, and applies the optional argument FUNCTION to it.
 If FUNCTION is nil, it applies `message', thus displaying the message.
 In addition, this function sets up `help-return-method', which see, that
 specifies what to do when the user exits the help buffer."
-  ;; Reset `help-window' here to avoid confusing `help-mode-finish'.
-  (setq help-window nil)
   (and (not (get-buffer-window standard-output))
        (let ((first-message
              (cond ((or
@@ -418,7 +402,7 @@ With argument, display info only for the selected version."
           (beginning-of-line)
           (point)))))))
 
-(defun view-emacs-todo (&optional arg)
+(defun view-emacs-todo (&optional _arg)
   "Display the Emacs TODO list."
   (interactive "P")
   (view-help-file "TODO"))
@@ -532,7 +516,7 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer."
   (unless definition (error "No command"))
   (let ((func (indirect-function definition))
         (defs nil)
-        (standard-output (if insert (current-buffer) t)))
+        (standard-output (if insert (current-buffer) standard-output)))
     ;; In DEFS, find all symbols that are aliases for DEFINITION.
     (mapatoms (lambda (symbol)
                (and (fboundp symbol)
@@ -630,7 +614,7 @@ temporarily enables it to allow getting help on disabled items and buttons."
                    (aref key 1)
                  (aref key 0)))
         (modifiers (event-modifiers event))
-        (standard-output (if insert (current-buffer) t))
+        (standard-output (if insert (current-buffer) standard-output))
         (mouse-msg (if (or (memq 'click modifiers) (memq 'down modifiers)
                            (memq 'drag modifiers)) " at that spot" ""))
         (defn (key-binding key t))
@@ -874,7 +858,17 @@ whose documentation describes the minor mode."
             (let ((start (point)))
               (insert (format-mode-line mode nil nil buffer))
               (add-text-properties start (point) '(face bold)))))
-       (princ " mode:\n")
+       (princ " mode")
+       (let* ((mode major-mode)
+              (file-name (find-lisp-object-file-name mode nil)))
+         (when file-name
+           (princ (concat " defined in `" (file-name-nondirectory file-name) "'"))
+           ;; Make a hyperlink to the library.
+           (with-current-buffer standard-output
+             (save-excursion
+               (re-search-backward "`\\([^`']+\\)'" nil t)
+               (help-xref-button 1 'help-function-def mode file-name)))))
+       (princ ":\n")
        (princ (documentation major-mode)))))
   ;; For the sake of IELM and maybe others
   nil)
@@ -907,6 +901,7 @@ appeared on the mode-line."
   ;; In order to list up all minor modes, minor-mode-list
   ;; is used here instead of minor-mode-alist.
   (delq nil (mapcar 'symbol-name minor-mode-list)))
+
 (defun describe-minor-mode-from-symbol (symbol)
   "Display documentation of a minor mode given as a symbol, SYMBOL"
   (interactive (list (intern (completing-read
@@ -930,6 +925,7 @@ appeared on the mode-line."
                     (t
                      i))))
                minor-mode-alist)))
+
 (defun describe-minor-mode-from-indicator (indicator)
   "Display documentation of a minor mode specified by INDICATOR.
 If you call this function interactively, you can give indicator which
@@ -965,28 +961,34 @@ is currently activated with completion."
                  minor-modes nil)
          (setq minor-modes (cdr minor-modes)))))
     result))
-
 \f
 ;;; Automatic resizing of temporary buffers.
-
 (defcustom temp-buffer-max-height (lambda (buffer) (/ (- (frame-height) 2) 2))
   "Maximum height of a window displaying a temporary buffer.
 This is effective only when Temp Buffer Resize mode is enabled.
-The value is the maximum height (in lines) which `resize-temp-buffer-window'
-will give to a window displaying a temporary buffer.
-It can also be a function to be called to choose the height for such a buffer.
-It gets one argumemt, the buffer, and should return a positive integer."
+The value is the maximum height (in lines) which
+`resize-temp-buffer-window' will give to a window displaying a
+temporary buffer.  It can also be a function to be called to
+choose the height for such a buffer.  It gets one argument, the
+buffer, and should return a positive integer.  At the time the
+function is called, the window to be resized is selected."
   :type '(choice integer function)
   :group 'help
   :version "20.4")
 
 (define-minor-mode temp-buffer-resize-mode
-  "Toggle the mode which makes windows smaller for temporary buffers.
-With prefix argument ARG, turn the resizing of windows displaying temporary
-buffers on if ARG is positive or off otherwise.
-This makes the window the right height for its contents, but never
-more than `temp-buffer-max-height' nor less than `window-min-height'.
-This applies to `help', `apropos' and `completion' buffers, and some others."
+  "Toggle auto-shrinking temp buffer windows (Temp Buffer Resize mode).
+With a prefix argument ARG, enable Temp Buffer Resize mode if ARG
+is positive, and disable it otherwise.  If called from Lisp,
+enable the mode if ARG is omitted or nil.
+
+When Temp Buffer Resize mode is enabled, the windows in which we
+show a temporary buffer are automatically reduced in height to
+fit the buffer's contents, but never more than
+`temp-buffer-max-height' nor less than `window-min-height'.
+
+This mode is used by `help', `apropos' and `completion' buffers,
+and some others."
   :global t :group 'help
   (if temp-buffer-resize-mode
       ;; `help-make-xrefs' may add a `back' button and thus increase the
@@ -996,29 +998,26 @@ This applies to `help', `apropos' and `completion' buffers, and some others."
 
 (defun resize-temp-buffer-window ()
   "Resize the selected window to fit its contents.
-Will not make it higher than `temp-buffer-max-height' nor smaller than
-`window-min-height'.  Do nothing if it is the only window on its frame, if it
-is not as wide as the frame or if some of the window's contents are scrolled
-out of view."
-  (unless (or (one-window-p 'nomini)
-              (not (pos-visible-in-window-p (point-min)))
-              (not (window-full-width-p)))
+Will not make it higher than `temp-buffer-max-height' nor smaller
+than `window-min-height'.  Do nothing if the selected window is
+not vertically combined or some of its contents are scrolled out
+of view."
+  (when (and (pos-visible-in-window-p (point-min))
+            (window-combined-p))
     (fit-window-to-buffer
-     (selected-window)
+     nil
      (if (functionp temp-buffer-max-height)
-        (funcall temp-buffer-max-height (current-buffer))
+        (funcall temp-buffer-max-height (window-buffer))
        temp-buffer-max-height))))
 
-\f
-;;; help-window
-
+;;; Help windows.
 (defcustom help-window-select 'other
     "Non-nil means select help window for viewing.
 Choices are:
  never (nil) Select help window only if there is no other window
              on its frame.
  other       Select help window unless the selected window is the
-             only other window on its frame.
+             only other window on the help window's frame.
  always (t)  Always select the help window.
 
 This option has effect if and only if the help window was created
@@ -1029,175 +1028,85 @@ by `with-help-window'"
   :group 'help
   :version "23.1")
 
-(defun help-window-display-message (quit-part window &optional other)
+(defun help-window-display-message (quit-part window &optional scroll)
   "Display message telling how to quit and scroll help window.
 QUIT-PART is a string telling how to quit the help window WINDOW.
-Optional argument OTHER non-nil means return text telling how to
-scroll the \"other\" window."
+Optional argument SCROLL non-nil means tell how to scroll WINDOW.
+SCROLL equal `other' means tell how to scroll the \"other\"
+window."
   (let ((scroll-part
         (cond
+         ;; If we don't have QUIT-PART we probably reuse a window
+         ;; showing the same buffer so we don't show any message.
+         ((not quit-part) nil)
          ((pos-visible-in-window-p
            (with-current-buffer (window-buffer window)
-             (point-max)) window)
-          ;; Buffer end is visible.
+             (point-max)) window t)
+          ;; Buffer end is at least partially visible, no need to talk
+          ;; about scrolling.
           ".")
-         (other ", \\[scroll-other-window] to scroll help.")
-         (t ", \\[scroll-up] to scroll help."))))
+         ((eq scroll 'other)
+          ", \\[scroll-other-window] to scroll help.")
+         (scroll ", \\[scroll-up] to scroll help."))))
     (message "%s"
      (substitute-command-keys (concat quit-part scroll-part)))))
 
-(defun help-window-setup-finish (window &optional reuse keep-frame)
-  "Finish setting up help window WINDOW.
-Select WINDOW according to the value of `help-window-select'.
-Display message telling how to scroll and eventually quit WINDOW.
-
-Optional argument REUSE non-nil means WINDOW has been reused by
-`display-buffer'.  Optional argument KEEP-FRAME non-nil means
-that quitting should not delete WINDOW's frame."
-  (let ((number-of-windows
-        (length (window-list (window-frame window) 'no-mini window))))
-    (cond
-     ((eq window (selected-window))
-      ;; The help window is the selected window, probably the
-      ;; `pop-up-windows' nil case.
-      (help-window-display-message
-       (if reuse
-          "Type \"q\" to restore this window"
-        ;; This should not be taken.
-        "Type \"q\" to quit") window))
-     ((= number-of-windows 1)
-      ;; The help window is alone on a frame and not the selected
-      ;; window, could be the `pop-up-frames' t case.
-      (help-window-display-message
-       (cond
-       (keep-frame "Type \"q\" to delete this window")
-       (reuse "Type \"q\" to restore this window")
-       (view-remove-frame-by-deleting "Type \"q\" to delete this frame")
-       (t "Type \"q\" to iconify this frame"))
-       window))
-     ((and (= number-of-windows 2)
-          (eq (window-frame window) (window-frame (selected-window))))
-      ;; There are two windows on the help window's frame and the other
-      ;; window is the selected one.
-      (if (memq help-window-select '(nil other))
-         ;; Do not select the help window.
-         (help-window-display-message
-          (if reuse
-              ;; Offer `display-buffer' for consistency with
-              ;; `help-print-return-message'.  This is hardly TRT when
-              ;; the other window and the selected window display the
-              ;; same buffer but has been handled this way ever since.
-              "Type \\[display-buffer] RET to restore the other window"
-            ;; The classic "two windows" configuration.
-            "Type \\[delete-other-windows] to delete the help window")
-          window t)
-       ;; Select help window and tell how to quit.
-       (select-window window)
-       (help-window-display-message
-        (if reuse
-            "Type \"q\" to restore this window"
-          "Type \"q\" to delete this window") window)))
-     (help-window-select
-      ;; Issuing a message with 3 or more windows on the same frame
-      ;; without selecting the help window doesn't make any sense.
-      (select-window window)
-      (help-window-display-message
-       (if reuse
-          "Type \"q\" to restore this window"
-        "Type \"q\" to delete this window") window)))))
-
-(defun help-window-setup (list-of-frames list-of-window-tuples)
-  "Set up help window.
-LIST-OF-FRAMES and LIST-OF-WINDOW-TUPLES are the lists of frames
-and window quadruples built by `with-help-window'.  The help
-window itself is specified by the variable `help-window'."
-  (let* ((help-buffer (window-buffer help-window))
-        ;; `help-buffer' now denotes the help window's buffer.
-        (view-entry
-         (assq help-window
-               (buffer-local-value 'view-return-to-alist help-buffer)))
-        (help-entry (assq help-window list-of-window-tuples)))
-
-    ;; Handle `help-window-point-marker'.
-    (when (eq (marker-buffer help-window-point-marker) help-buffer)
-      (set-window-point help-window help-window-point-marker)
-      ;; Reset `help-window-point-marker'.
-      (set-marker help-window-point-marker nil))
+(defun help-window-setup (help-window)
+  "Set up help window for `with-help-window'.
+HELP-WINDOW is the window used for displaying the help buffer."
+  (let* ((help-buffer (when (window-live-p help-window)
+                       (window-buffer help-window)))
+        (help-setup (when (window-live-p help-window)
+                      (car (window-parameter help-window 'quit-restore)))))
+    (when help-buffer
+      ;; Handle `help-window-point-marker'.
+      (when (eq (marker-buffer help-window-point-marker) help-buffer)
+       (set-window-point help-window help-window-point-marker)
+       ;; Reset `help-window-point-marker'.
+       (set-marker help-window-point-marker nil))
 
-    (cond
-     (view-entry
-      ;; `view-return-to-alist' has an entry for the help window.
       (cond
-       ((eq help-window (selected-window))
-       ;; The help window is the selected window, probably because the
-       ;; user followed a backward/forward button or a cross reference.
-       ;; In this case just purge stale entries from
-       ;; `view-return-to-alist' but leave the entry alone and don't
-       ;; display a message.
-       (view-return-to-alist-update help-buffer))
-       ((and help-entry (eq (cadr help-entry) help-buffer))
-       ;; The help window was not selected but displayed the help
-       ;; buffer.  In this case reuse existing exit information but try
-       ;; to get back to the selected window when quitting.  Don't
-       ;; display a message since the user must have seen one before.
-       (view-return-to-alist-update
-        help-buffer (cons help-window
-                          (cons (selected-window) (cddr view-entry)))))
-       (help-entry
-       ;; The help window was not selected, did display the help buffer
-       ;; earlier, but displayed another buffer when help was invoked.
-       ;; Set up things so that quitting will show that buffer again.
-       (view-return-to-alist-update
-        help-buffer (cons help-window
-                          (cons (selected-window) (cdr help-entry))))
-       (help-window-setup-finish help-window t))
+       ((or (eq help-window (selected-window))
+           (and (or (eq help-window-select t)
+                    (eq help-setup 'frame)
+                    (and (eq help-window-select 'other)
+                         (eq (window-frame help-window) (selected-frame))
+                         (> (length (window-list nil 'no-mini)) 2)))
+                (select-window help-window)))
+       ;; The help window is or gets selected ...
+       (help-window-display-message
+        (cond
+         ((eq help-setup 'window)
+          ;; ... and is new, ...
+          "Type \"q\" to delete help window")
+         ((eq help-setup 'frame)
+          "Type \"q\" to delete help frame")
+         ((eq help-setup 'other)
+          ;; ... or displayed some other buffer before.
+          "Type \"q\" to restore previous buffer"))
+        help-window t))
+       ((and (eq (window-frame help-window) (selected-frame))
+            (= (length (window-list nil 'no-mini)) 2))
+       ;; There are two windows on the help window's frame and the
+       ;; other one is the selected one.
+       (help-window-display-message
+        (cond
+         ((eq help-setup 'window)
+          "Type \\[delete-other-windows] to delete the help window")
+         ((eq help-setup 'other)
+          "Type \"q\" in help window to restore its previous buffer"))
+        help-window 'other))
        (t
-       ;; The help window is new but `view-return-to-alist' had an
-       ;; entry for it.  This should never happen.
-       (view-return-to-alist-update
-        help-buffer (cons help-window
-                          (cons (selected-window) 'quit-window)))
-       (help-window-setup-finish help-window t))))
-     (help-entry
-      ;; `view-return-to-alist' does not have an entry for help window
-      ;; but `list-of-window-tuples' does.  Hence `display-buffer' must
-      ;; have reused an existing window.
-      (if (eq (cadr help-entry) help-buffer)
-         ;; The help window displayed `help-buffer' before but no
-         ;; `view-return-to-alist' entry was found probably because the
-         ;; user manually switched to the help buffer.  Set up things
-         ;; for `quit-window' although `view-exit-action' should be
-         ;; able to handle this case all by itself.
-         (progn
-           (view-return-to-alist-update
-            help-buffer (cons help-window
-                              (cons (selected-window) 'quit-window)))
-           (help-window-setup-finish help-window t))
-       ;; The help window displayed another buffer before.  Set up
-       ;; things in a way that quitting can orderly show that buffer
-       ;; again.  The window-start and window-point information from
-       ;; `list-of-window-tuples' provide the necessary information.
-       (view-return-to-alist-update
-        help-buffer (cons help-window
-                          (cons (selected-window) (cdr help-entry))))
-       (help-window-setup-finish help-window t)))
-     ((memq (window-frame help-window) list-of-frames)
-      ;; The help window is a new window on an existing frame.  This
-      ;; case must be handled specially by `help-window-setup-finish'
-      ;; and `view-mode-exit' to ascertain that quitting does _not_
-      ;; inadvertently delete the frame.
-      (view-return-to-alist-update
-       help-buffer (cons help-window
-                        (cons (selected-window) 'keep-frame)))
-      (help-window-setup-finish help-window nil t))
-     (t
-      ;; The help window is shown on a new frame.  In this case quitting
-      ;; shall handle both, the help window _and_ its frame.  We changed
-      ;; the default of `view-remove-frame-by-deleting' to t in order to
-      ;; intuitively DTRT here.
-      (view-return-to-alist-update
-       help-buffer (cons help-window (cons (selected-window) t)))
-      (help-window-setup-finish help-window)))))
+       ;; The help window is not selected ...
+       (help-window-display-message
+        (cond
+         ((eq help-setup 'window)
+          ;; ... and is new, ...
+          "Type \"q\" in help window to delete it")
+         ((eq help-setup 'other)
+          ;; ... or displayed some other buffer before.
+          "Type \"q\" in help window to restore previous buffer"))
+        help-window))))))
 
 ;; `with-help-window' is a wrapper for `with-output-to-temp-buffer'
 ;; providing the following additional twists:
@@ -1205,52 +1114,42 @@ window itself is specified by the variable `help-window'."
 ;; (1) Issue more accurate messages telling how to scroll and quit the
 ;; help window.
 
-;; (2) Make `view-mode-exit' DTRT in more cases.
-
-;; (3) An option (customizable via `help-window-select') to select the
+;; (2) An option (customizable via `help-window-select') to select the
 ;; help window automatically.
 
-;; (4) A marker (`help-window-point-marker') to move point in the help
+;; (3) A marker (`help-window-point-marker') to move point in the help
 ;; window to an arbitrary buffer position.
 
 ;; Note: It's usually always wrong to use `help-print-return-message' in
 ;; the body of `with-help-window'.
 (defmacro with-help-window (buffer-name &rest body)
-  "Display buffer BUFFER-NAME in a help window evaluating BODY.
+  "Display buffer with name BUFFER-NAME in a help window evaluating BODY.
 Select help window if the actual value of the user option
 `help-window-select' says so.  Return last value in BODY."
   (declare (indent 1) (debug t))
-  ;; Bind list-of-frames to `frame-list' and list-of-window-tuples to a
-  ;; list of one <window window-buffer window-start window-point> tuple
-  ;; for each live window.
-  `(let ((list-of-frames (frame-list))
-        (list-of-window-tuples
-         (let (list)
-           (walk-windows
-            (lambda (window)
-              (push (list window (window-buffer window)
-                          (window-start window) (window-point window))
-                    list))
-            'no-mini t)
-           list)))
-     ;; Make `help-window' t to trigger `help-mode-finish' to set
-     ;; `help-window' to the actual help window.
-     (setq help-window t)
-     ;; Make `help-window-point-marker' point nowhere (the only place
-     ;; where this should be set to a buffer position is within BODY).
+  `(progn
+     ;; Make `help-window-point-marker' point nowhere.  The only place
+     ;; where this should be set to a buffer position is within BODY.
      (set-marker help-window-point-marker nil)
-     (prog1
-        ;; Return value returned by `with-output-to-temp-buffer'.
-        (with-output-to-temp-buffer ,buffer-name
-          (progn ,@body))
-       (when (windowp help-window)
-        ;; Set up help window.
-        (help-window-setup list-of-frames list-of-window-tuples))
-       ;; Reset `help-window' to nil to avoid confusing future calls of
-       ;; `help-mode-finish' with plain `with-output-to-temp-buffer'.
-       (setq help-window nil))))
+     (let* (help-window
+            (temp-buffer-show-hook
+             (cons (lambda () (setq help-window (selected-window)))
+                   temp-buffer-show-hook)))
+       ;; Return value returned by `with-output-to-temp-buffer'.
+       (prog1
+          (with-output-to-temp-buffer ,buffer-name
+            (progn ,@body))
+        (help-window-setup help-window)))))
+
+;; Called from C, on encountering `help-char' when reading a char.
+;; Don't print to *Help*; that would clobber Help history.
+(defun help-form-show ()
+  "Display the output of a non-nil `help-form'."
+  (let ((msg (eval help-form)))
+    (if (stringp msg)
+       (with-output-to-temp-buffer " *Char Help*"
+         (princ msg)))))
 \f
 (provide 'help)
 
-;; arch-tag: cf427352-27e9-49b7-9a6f-741ebab02423
 ;;; help.el ends here