X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/732be46569e11c446abb92a0fe9664fff94be875..a2236dc611360edfb8f5f891b4e63d586793f38f:/lisp/ehelp.el diff --git a/lisp/ehelp.el b/lisp/ehelp.el index b5d32ad851..3656521f68 100644 --- a/lisp/ehelp.el +++ b/lisp/ehelp.el @@ -18,29 +18,50 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; This package provides a pre-packaged `Electric Help Mode' for ;; browsing on-line help screens. There is one entry point, -;; `with-electric-help'; All you have to give it is a no-argument +;; `with-electric-help'; all you have to give it is a no-argument ;; function that generates the actual text of the help into the current ;; buffer. +;; To make this the default, you must do +;; (require 'ehelp) +;; (define-key global-map "\C-h" 'ehelp-command) +;; (define-key global-map [help] 'ehelp-command) +;; (define-key global-map [f1] 'ehelp-command) + ;;; Code: (require 'electric) (defvar electric-help-map () "Keymap defining commands available in `electric-help-mode'.") +(defvar electric-help-form-to-execute nil) + (put 'electric-help-undefined 'suppress-keymap t) (if electric-help-map () (let ((map (make-keymap))) - ;; allow all non-self-inserting keys - search, scroll, etc + ;; allow all non-self-inserting keys - search, scroll, etc, but + ;; let M-x and C-x exit ehelp mode and retain buffer: (suppress-keymap map) + (define-key map "\C-u" 'electric-help-undefined) + (define-key map [?\C-0] 'electric-help-undefined) + (define-key map [?\C-1] 'electric-help-undefined) + (define-key map [?\C-2] 'electric-help-undefined) + (define-key map [?\C-3] 'electric-help-undefined) + (define-key map [?\C-4] 'electric-help-undefined) + (define-key map [?\C-5] 'electric-help-undefined) + (define-key map [?\C-6] 'electric-help-undefined) + (define-key map [?\C-7] 'electric-help-undefined) + (define-key map [?\C-8] 'electric-help-undefined) + (define-key map [?\C-9] 'electric-help-undefined) (define-key map (char-to-string help-char) 'electric-help-help) (define-key map "?" 'electric-help-help) (define-key map " " 'scroll-up) @@ -54,9 +75,11 @@ ;;a better key than this? (define-key map "r" 'electric-help-retain) (define-key map "R" 'electric-help-retain) + (define-key map "\ex" 'electric-help-execute-extended) + (define-key map "\C-x" 'electric-help-ctrl-x-prefix) (setq electric-help-map map))) - + (defun electric-help-mode () "`with-electric-help' temporarily places its buffer in this mode. \(On exit from `with-electric-help', the buffer is put in `default-major-mode'.)" @@ -65,27 +88,42 @@ (setq major-mode 'help) (setq mode-line-buffer-identification '(" Help: %b")) (use-local-map electric-help-map) + (add-hook 'mouse-leave-buffer-hook 'electric-help-retain) + (view-mode -1) ;; this is done below in with-electric-help ;(run-hooks 'electric-help-mode-hook) ) -(defun with-electric-help (thunk &optional buffer noerase) - "Arguments are THUNK &optional BUFFER NOERASE. BUFFER defaults to \"*Help*\" -THUNK is a function of no arguments which is called to initialize -the contents of BUFFER. BUFFER will be erased before THUNK is called unless -NOERASE is non-nil. THUNK will be called with `standard-output' bound to -the buffer specified by BUFFER +;;;###autoload +(defun with-electric-help (thunk &optional buffer noerase minheight) + "Pop up an \"electric\" help buffer. +The arguments are THUNK &optional BUFFER NOERASE MINHEIGHT. +THUNK is a function of no arguments which is called to initialize the +contents of BUFFER. BUFFER defaults to `*Help*'. BUFFER will be +erased before THUNK is called unless NOERASE is non-nil. THUNK will +be called while BUFFER is current and with `standard-output' bound to +the buffer specified by BUFFER. + +If THUNK returns nil, we display BUFFER starting at the top, and +shrink the window to fit. If THUNK returns non-nil, we don't do those things. After THUNK has been called, this function \"electrically\" pops up a window in which BUFFER is displayed and allows the user to scroll through that buffer -in electric-help-mode. +in electric-help-mode. The window's height will be at least MINHEIGHT if +this value is non-nil. + +If THUNK returns nil, we display BUFFER starting at the top, and +shrink the window to fit. If THUNK returns non-nil, we don't do those +things. + When the user exits (with `electric-help-exit', or otherwise) the help buffer's window disappears (i.e., we use `save-window-excursion') -BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" +BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit." (setq buffer (get-buffer-create (or buffer "*Help*"))) (let ((one (one-window-p t)) (config (current-window-configuration)) - (bury nil)) + (bury nil) + (electric-help-form-to-execute nil)) (unwind-protect (save-excursion (if one (goto-char (window-start (selected-window)))) @@ -93,9 +131,12 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" (pop-to-buffer buffer)) (save-excursion (set-buffer buffer) + (if (and minheight (< (window-height) minheight)) + (enlarge-window (- minheight (window-height)))) (electric-help-mode) - (setq buffer-read-only nil) - (or noerase (erase-buffer))) + (setq buffer-read-only nil) + (or noerase + (erase-buffer))) (let ((standard-output buffer)) (if (not (funcall thunk)) (progn @@ -105,10 +146,14 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" (if one (shrink-window-if-larger-than-buffer (selected-window)))))) (set-buffer buffer) (run-hooks 'electric-help-mode-hook) + (setq buffer-read-only t) (if (eq (car-safe (electric-help-command-loop)) 'retain) (setq config (current-window-configuration)) - (setq bury t))) + (setq bury t)) + ;; Remove the hook. + (if (memq 'electric-help-retain mouse-leave-buffer-hook) + (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain))) (message "") (set-buffer buffer) (setq buffer-read-only nil) @@ -122,12 +167,13 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" ;; so that when we say "Press space to bury" we mean it (replace-buffer-in-windows buffer) ;; must do this outside of save-window-excursion - (bury-buffer buffer)))))) + (bury-buffer buffer))) + (eval electric-help-form-to-execute)))) (defun electric-help-command-loop () (catch 'exit (if (pos-visible-in-window-p (point-max)) - (progn (message (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>")) + (progn (message "%s" (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>")) (if (equal (setq unread-command-events (list (read-event))) '(?\ )) (progn (setq unread-command-events nil) @@ -144,9 +190,13 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" (Electric-command-loop 'exit (function (lambda () + (sit-for 0) ;necessary if last command was end-of-buffer or + ;beginning-of-buffer - otherwise pos-visible-in-window-p + ;will yield a wrong result. (let ((min (pos-visible-in-window-p (point-min))) (max (pos-visible-in-window-p (point-max)))) - (cond ((and min max) + (cond (isearch-mode 'noprompt) + ((and min max) (cond (standard "Press q to exit, r to retain ") (neither) (t (setq neither (substitute-command-keys "Press \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) @@ -155,11 +205,11 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" (up) (t (setq up (substitute-command-keys "Press \\[scroll-up] to scroll, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) (max - (cond (standard "Press DEL to scroll back, q to exit ") + (cond (standard "Press DEL to scroll back, q to exit, r to retain ") (down) (t (setq down (substitute-command-keys "Press \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))) (t - (cond (standard "Press SPC to scroll, DEL to scroll back, q to exit ") + (cond (standard "Press SPC to scroll, DEL to scroll back, q to exit, r to retain ") (both) (t (setq both (substitute-command-keys "Press \\[scroll-up] to scroll, \\[scroll-down] to scroll back, \\[electric-help-exit] to exit, \\[electric-help-retain] to retain "))))))))) t)))) @@ -174,24 +224,35 @@ BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit" ; (scroll-up arg))) (defun electric-help-exit () - ">>>Doc" + "Exit `electric-help', restoring the previous window/buffer configuration. +\(The *Help* buffer will be buried.)" (interactive) - (throw 'exit t)) + ;; Make sure that we don't throw twice, even if two events cause + ;; calling this function: + (if (memq 'electric-help-retain mouse-leave-buffer-hook) + (progn + (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain) + (throw 'exit t)))) (defun electric-help-retain () "Exit `electric-help', retaining the current window/buffer configuration. \(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET will select it.)" (interactive) - (throw 'exit '(retain))) + ;; Make sure that we don't throw twice, even if two events cause + ;; calling this function: + (if (memq 'electric-help-retain mouse-leave-buffer-hook) + (progn + (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain) + (throw 'exit '(retain))))) (defun electric-help-undefined () (interactive) (error "%s is undefined -- Press %s to exit" (mapconcat 'single-key-description (this-command-keys) " ") - (if (eq (key-binding "Q") 'electric-help-exit) - "Q" + (if (eq (key-binding "q") 'electric-help-exit) + "q" (substitute-command-keys "\\[electric-help-exit]")))) @@ -207,8 +268,9 @@ will select it.)" (sit-for 2)) -(defun electric-helpify (fun) - (let ((name "*Help*")) +;;;###autoload +(defun electric-helpify (fun &optional name) + (let ((name (or name "*Help*"))) (if (save-window-excursion ;; kludge-o-rama (let* ((p (symbol-function 'print-help-return-message)) @@ -258,6 +320,22 @@ will select it.)" (set-buffer-modified-p m)))))) (with-electric-help 'ignore name t)))) + + +;; This is to be bound to M-x in ehelp mode. Retains ehelp buffer and then +;; continues with execute-extended-command. +(defun electric-help-execute-extended (prefixarg) + (interactive "p") + (setq electric-help-form-to-execute '(execute-extended-command nil)) + (electric-help-retain)) + +;; This is to be buond to C-x in ehelp mode. Retains ehelp buffer and then +;; continues with ctrl-x prefix. +(defun electric-help-ctrl-x-prefix (prefixarg) + (interactive "p") + (setq electric-help-form-to-execute '(progn (message nil) (setq unread-command-char ?\C-x))) + (electric-help-retain)) + (defun electric-describe-key () (interactive) @@ -294,7 +372,7 @@ will select it.)" (defun electric-command-apropos () (interactive) - (electric-helpify 'command-apropos)) + (electric-helpify 'command-apropos "*Apropos*")) ;(define-key help-map "a" 'electric-command-apropos) @@ -309,6 +387,7 @@ will select it.)" (if ehelp-map nil (let ((map (copy-keymap help-map))) + (substitute-key-definition 'apropos 'electric-apropos map) (substitute-key-definition 'command-apropos 'electric-command-apropos map) (substitute-key-definition 'describe-key 'electric-describe-key map) (substitute-key-definition 'describe-mode 'electric-describe-mode map) @@ -321,8 +400,6 @@ will select it.)" (setq ehelp-map map) (fset 'ehelp-command map))) -;; Do (define-key global-map "\C-h" 'ehelp-command) if you want to win - (provide 'ehelp) ;;; ehelp.el ends here