1992-05-30 23:54:21 +00:00
;;; ehelp.el --- bindings for electric-help mode
1995-04-07 01:20:53 +00:00
;; Copyright (C) 1986, 1995 Free Software Foundation, Inc.
1992-07-22 04:22:42 +00:00
1992-07-16 21:47:34 +00:00
;; Maintainer: FSF
1992-07-17 08:15:29 +00:00
;; Keywords: help, extensions
1992-07-16 21:47:34 +00:00
1989-10-31 16:00:07 +00:00
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
1992-07-16 21:47:34 +00:00
;; the Free Software Foundation; either version 2, or (at your option)
1989-10-31 16:00:07 +00:00
;; any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
1996-01-14 07:34:30 +00:00
;; 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.
1989-10-31 16:00:07 +00:00
1993-03-22 03:27:18 +00:00
;;; Commentary:
;; This package provides a pre-packaged `Electric Help Mode' for
;; browsing on-line help screens. There is one entry point,
1995-07-18 23:31:41 +00:00
;; `with-electric-help'; all you have to give it is a no-argument
1993-08-08 00:20:22 +00:00
;; function that generates the actual text of the help into the current
1993-03-22 03:27:18 +00:00
;; buffer.
1995-07-30 07:04:58 +00:00
;; 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)
1992-07-16 21:47:34 +00:00
;;; Code:
1989-10-31 16:00:07 +00:00
( require 'electric )
( defvar electric-help-map ( )
1991-02-28 21:40:18 +00:00
" Keymap defining commands available in `electric-help-mode' . " )
1989-10-31 16:00:07 +00:00
1996-02-03 03:18:00 +00:00
( defvar electric-help-form-to-execute nil )
1989-10-31 16:00:07 +00:00
( put 'electric-help-undefined 'suppress-keymap t )
( if electric-help-map
( )
( let ( ( map ( make-keymap ) ) )
1995-10-21 22:23:48 +00:00
;; allow all non-self-inserting keys - search, scroll, etc, but
;; let M-x and C-x exit ehelp mode and retain buffer:
1995-02-14 09:08:40 +00:00
( suppress-keymap map )
1995-10-21 22:23:48 +00:00
( 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 )
1989-10-31 16:00:07 +00:00
( define-key map ( char-to-string help-char ) 'electric-help-help )
( define-key map " ? " 'electric-help-help )
( define-key map " " 'scroll-up )
( define-key map " \^ ? " 'scroll-down )
( define-key map " . " 'beginning-of-buffer )
( define-key map " < " 'beginning-of-buffer )
( define-key map " > " 'end-of-buffer )
;(define-key map "\C-g" 'electric-help-exit)
( define-key map " q " 'electric-help-exit )
( define-key map " Q " 'electric-help-exit )
;;a better key than this?
( define-key map " r " 'electric-help-retain )
1995-02-14 09:08:40 +00:00
( define-key map " R " 'electric-help-retain )
1995-10-21 22:23:48 +00:00
( define-key map " \e x " 'electric-help-execute-extended )
( define-key map " \C -x " 'electric-help-ctrl-x-prefix )
1989-10-31 16:00:07 +00:00
( setq electric-help-map map ) ) )
1995-10-21 22:23:48 +00:00
1989-10-31 16:00:07 +00:00
( defun electric-help-mode ( )
1991-02-28 21:40:18 +00:00
" `with-electric-help' temporarily places its buffer in this mode.
\(On exit from ` with-electric-help ', the buffer is put in ` default-major-mode '. ) "
1989-10-31 16:00:07 +00:00
( setq buffer-read-only t )
( setq mode-name " Help " )
( setq major-mode 'help )
( setq mode-line-buffer-identification ' ( " Help: %b " ) )
( use-local-map electric-help-map )
1995-10-21 22:23:48 +00:00
( setq mouse-leave-buffer-hook ' ( electric-help-retain ) )
1996-02-03 03:18:00 +00:00
( view-mode -1 )
1989-10-31 16:00:07 +00:00
;; this is done below in with-electric-help
;(run-hooks 'electric-help-mode-hook)
)
1995-07-18 23:31:41 +00:00
;;;###autoload
1995-11-02 20:30:38 +00:00
( defun with-electric-help ( thunk &optional buffer noerase minheight )
1995-07-30 07:04:58 +00:00
" Pop up an \" electric \" help buffer.
1995-10-21 22:23:48 +00:00
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
1995-07-30 07:04:58 +00:00
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.
1989-10-31 16:00:07 +00:00
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
1995-10-21 22:23:48 +00:00
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.
1991-02-28 21:40:18 +00:00
When the user exits ( with ` electric-help-exit ', or otherwise ) the help
buffer 's window disappears ( i.e., we use ` save-window-excursion ' )
1995-07-18 23:31:41 +00:00
BUFFER is put into ` default-major-mode ' ( or ` fundamental-mode ' ) when we exit. "
1989-10-31 16:00:07 +00:00
( setq buffer ( get-buffer-create ( or buffer " *Help* " ) ) )
( let ( ( one ( one-window-p t ) )
1991-01-11 19:38:45 +00:00
( config ( current-window-configuration ) )
1995-10-21 22:23:48 +00:00
( bury nil )
1996-02-03 03:18:00 +00:00
( electric-help-form-to-execute nil ) )
1991-01-11 19:38:45 +00:00
( unwind-protect
( save-excursion
( if one ( goto-char ( window-start ( selected-window ) ) ) )
( let ( ( pop-up-windows t ) )
( pop-to-buffer buffer ) )
( save-excursion
( set-buffer buffer )
1995-10-21 22:23:48 +00:00
( if ( and minheight ( < ( window-height ) minheight ) )
( enlarge-window ( - minheight ( window-height ) ) ) )
1991-01-11 19:38:45 +00:00
( electric-help-mode )
1996-02-03 03:18:00 +00:00
( or noerase
( let ( ( inhibit-read-only t ) )
( erase-buffer ) ) ) )
1991-01-11 19:38:45 +00:00
( let ( ( standard-output buffer ) )
( if ( not ( funcall thunk ) )
( progn
( set-buffer buffer )
( set-buffer-modified-p nil )
( goto-char ( point-min ) )
( if one ( shrink-window-if-larger-than-buffer ( selected-window ) ) ) ) ) )
( set-buffer buffer )
( run-hooks 'electric-help-mode-hook )
( if ( eq ( car-safe ( electric-help-command-loop ) )
'retain )
( setq config ( current-window-configuration ) )
( setq bury t ) ) )
( message " " )
( set-buffer buffer )
( setq buffer-read-only nil )
( condition-case ( )
( funcall ( or default-major-mode 'fundamental-mode ) )
( error nil ) )
( set-window-configuration config )
( if bury
( progn
;;>> Perhaps this shouldn't be done.
;; 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
1995-10-21 22:23:48 +00:00
( bury-buffer buffer ) ) )
1996-02-03 03:18:00 +00:00
( eval electric-help-form-to-execute ) ) ) )
1989-10-31 16:00:07 +00:00
( defun electric-help-command-loop ( )
( catch 'exit
( if ( pos-visible-in-window-p ( point-max ) )
1996-01-25 00:53:48 +00:00
( progn ( message " %s " ( substitute-command-keys " <<< Press Space to bury the help buffer, Press \\ [electric-help-retain] to retain it >>> " ) )
1993-06-03 03:50:05 +00:00
( if ( equal ( setq unread-command-events ( list ( read-event ) ) )
' ( ?\ ) )
1993-01-26 01:58:16 +00:00
( progn ( setq unread-command-events nil )
1989-10-31 16:00:07 +00:00
( throw 'exit t ) ) ) ) )
( let ( up down both neither
( standard ( and ( eq ( key-binding " " )
'scroll-up )
( eq ( key-binding " \^ ? " )
'scroll-down )
( eq ( key-binding " q " )
1995-02-14 09:08:40 +00:00
'electric-help-exit )
( eq ( key-binding " r " )
'electric-help-retain ) ) ) )
1989-10-31 16:00:07 +00:00
( Electric-command-loop
'exit
( function ( lambda ( )
1995-10-21 22:23:48 +00:00
( 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.
1989-10-31 16:00:07 +00:00
( let ( ( min ( pos-visible-in-window-p ( point-min ) ) )
( max ( pos-visible-in-window-p ( point-max ) ) ) )
1995-10-21 22:23:48 +00:00
( cond ( isearch-mode 'noprompt )
( ( and min max )
1995-02-14 09:08:40 +00:00
( cond ( standard " Press q to exit, r to retain " )
1989-10-31 16:00:07 +00:00
( neither )
1995-02-14 09:08:40 +00:00
( t ( setq neither ( substitute-command-keys " Press \\ [electric-help-exit] to exit, \\ [electric-help-retain] to retain " ) ) ) ) )
1989-10-31 16:00:07 +00:00
( min
1995-02-14 09:08:40 +00:00
( cond ( standard " Press SPC to scroll, q to exit, r to retain " )
1989-10-31 16:00:07 +00:00
( up )
1995-02-14 09:08:40 +00:00
( t ( setq up ( substitute-command-keys " Press \\ [scroll-up] to scroll, \\ [electric-help-exit] to exit, \\ [electric-help-retain] to retain " ) ) ) ) )
1989-10-31 16:00:07 +00:00
( max
1995-10-21 22:23:48 +00:00
( cond ( standard " Press DEL to scroll back, q to exit, r to retain " )
1989-10-31 16:00:07 +00:00
( down )
1995-02-14 09:08:40 +00:00
( t ( setq down ( substitute-command-keys " Press \\ [scroll-down] to scroll back, \\ [electric-help-exit] to exit, \\ [electric-help-retain] to retain " ) ) ) ) )
1989-10-31 16:00:07 +00:00
( t
1995-10-21 22:23:48 +00:00
( cond ( standard " Press SPC to scroll, DEL to scroll back, q to exit, r to retain " )
1989-10-31 16:00:07 +00:00
( both )
1995-02-14 09:08:40 +00:00
( 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 " ) ) ) ) ) ) ) ) )
1989-10-31 16:00:07 +00:00
t ) ) ) )
;(defun electric-help-scroll-up (arg)
; ">>>Doc"
; (interactive "P")
; (if (and (null arg) (pos-visible-in-window-p (point-max)))
; (electric-help-exit)
; (scroll-up arg)))
( defun electric-help-exit ( )
" >>>Doc "
( interactive )
( throw 'exit t ) )
( defun electric-help-retain ( )
1991-02-28 21:40:18 +00:00
" Exit `electric-help' , retaining the current window/buffer configuration.
1989-10-31 16:00:07 +00:00
\(The *Help* buffer will not be selected, but \\ [ switch-to-buffer-other-window ] RET
will select it. ) "
( interactive )
1995-10-21 22:23:48 +00:00
;; Make sure that we don't throw twice, even if two events cause
;; calling this function:
( if mouse-leave-buffer-hook
( progn
( setq mouse-leave-buffer-hook nil )
( throw 'exit ' ( retain ) ) ) ) )
1989-10-31 16:00:07 +00:00
( defun electric-help-undefined ( )
( interactive )
( error " %s is undefined -- Press %s to exit "
( mapconcat 'single-key-description ( this-command-keys ) " " )
1995-10-21 22:23:48 +00:00
( if ( eq ( key-binding " q " ) 'electric-help-exit )
" q "
1989-10-31 16:00:07 +00:00
( substitute-command-keys " \\ [electric-help-exit] " ) ) ) )
;>>> this needs to be hairified (recursive help, anybody?)
( defun electric-help-help ( )
( interactive )
1995-02-14 09:08:40 +00:00
( if ( and ( eq ( key-binding " q " ) 'electric-help-exit )
1989-10-31 16:00:07 +00:00
( eq ( key-binding " " ) 'scroll-up )
1995-02-14 09:08:40 +00:00
( eq ( key-binding " \^ ? " ) 'scroll-down )
( eq ( key-binding " r " ) 'electric-help-retain ) )
( message " SPC scrolls up, DEL scrolls down, q exits burying help buffer, r exits " )
( message " %s " ( substitute-command-keys " \\ [scroll-up] scrolls up, \\ [scroll-down] scrolls down, \\ [electric-help-exit] exits burying help buffer, \\ [electric-help-retain] exits " ) ) )
1989-10-31 16:00:07 +00:00
( sit-for 2 ) )
1995-07-18 23:31:41 +00:00
;;;###autoload
1989-10-31 16:00:07 +00:00
( defun electric-helpify ( fun )
( let ( ( name " *Help* " ) )
( if ( save-window-excursion
;; kludge-o-rama
( let* ( ( p ( symbol-function 'print-help-return-message ) )
( b ( get-buffer name ) )
( m ( buffer-modified-p b ) ) )
( and b ( not ( get-buffer-window b ) )
( setq b nil ) )
( unwind-protect
( progn
( message " %s... " ( capitalize ( symbol-name fun ) ) )
;; with-output-to-temp-buffer marks the buffer as unmodified.
;; kludging excessively and relying on that as some sort
;; of indication leads to the following abomination...
;;>> This would be doable without such icky kludges if either
;;>> (a) there were a function to read the interactive
;;>> args for a command and return a list of those args.
;;>> (To which one would then just apply the command)
;;>> (The only problem with this is that interactive-p
;;>> would break, but that is such a misfeature in
;;>> any case that I don't care)
;;>> It is easy to do this for emacs-lisp functions;
;;>> the only problem is getting the interactive spec
;;>> for subrs
;;>> (b) there were a function which returned a
;;>> modification-tick for a buffer. One could tell
;;>> whether a buffer had changed by whether the
;;>> modification-tick were different.
;;>> (Presumably there would have to be a way to either
;;>> restore the tick to some previous value, or to
;;>> suspend updating of the tick in order to allow
;;>> things like momentary-string-display)
( and b
( save-excursion
( set-buffer b )
( set-buffer-modified-p t ) ) )
( fset 'print-help-return-message 'ignore )
( call-interactively fun )
( and ( get-buffer name )
( get-buffer-window ( get-buffer name ) )
( or ( not b )
( not ( eq b ( get-buffer name ) ) )
( not ( buffer-modified-p b ) ) ) ) )
( fset 'print-help-return-message p )
( and b ( buffer-name b )
( save-excursion
( set-buffer b )
( set-buffer-modified-p m ) ) ) ) ) )
( with-electric-help 'ignore name t ) ) ) )
1995-10-21 22:23:48 +00:00
;; 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 " )
1996-02-03 03:18:00 +00:00
( setq electric-help-form-to-execute ' ( execute-extended-command nil ) )
1995-10-21 22:23:48 +00:00
( 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 " )
1996-02-03 03:18:00 +00:00
( setq electric-help-form-to-execute ' ( progn ( message nil ) ( setq unread-command-char ?\C -x ) ) )
1995-10-21 22:23:48 +00:00
( electric-help-retain ) )
1989-10-31 16:00:07 +00:00
( defun electric-describe-key ( )
( interactive )
( electric-helpify 'describe-key ) )
( defun electric-describe-mode ( )
( interactive )
( electric-helpify 'describe-mode ) )
( defun electric-view-lossage ( )
( interactive )
( electric-helpify 'view-lossage ) )
;(defun electric-help-for-help ()
; "See help-for-help"
; (interactive)
; )
( defun electric-describe-function ( )
( interactive )
( electric-helpify 'describe-function ) )
( defun electric-describe-variable ( )
( interactive )
( electric-helpify 'describe-variable ) )
( defun electric-describe-bindings ( )
( interactive )
( electric-helpify 'describe-bindings ) )
( defun electric-describe-syntax ( )
( interactive )
( electric-helpify 'describe-syntax ) )
( defun electric-command-apropos ( )
( interactive )
( electric-helpify 'command-apropos ) )
;(define-key help-map "a" 'electric-command-apropos)
1995-02-14 09:08:40 +00:00
( defun electric-apropos ( )
( interactive )
( electric-helpify 'apropos ) )
1989-10-31 16:00:07 +00:00
;;;; ehelp-map
( defvar ehelp-map ( ) )
( if ehelp-map
nil
( let ( ( map ( copy-keymap help-map ) ) )
1995-10-21 22:23:48 +00:00
( substitute-key-definition 'apropos 'electric-apropos map )
1995-02-14 09:08:40 +00:00
( substitute-key-definition 'command-apropos 'electric-command-apropos map )
1989-10-31 16:00:07 +00:00
( substitute-key-definition 'describe-key 'electric-describe-key map )
( substitute-key-definition 'describe-mode 'electric-describe-mode map )
( substitute-key-definition 'view-lossage 'electric-view-lossage map )
( substitute-key-definition 'describe-function 'electric-describe-function map )
( substitute-key-definition 'describe-variable 'electric-describe-variable map )
( substitute-key-definition 'describe-bindings 'electric-describe-bindings map )
( substitute-key-definition 'describe-syntax 'electric-describe-syntax map )
( setq ehelp-map map )
( fset 'ehelp-command map ) ) )
1992-03-16 20:39:07 +00:00
( provide 'ehelp )
1992-05-30 23:54:21 +00:00
;;; ehelp.el ends here