comparison lisp/electric/ehelp.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents b82b59fe008d
children b9518feda344
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
1 ;;; ehelp.el --- bindings for electric-help mode 1 ;;; ehelp.el --- bindings for electric-help mode
2 2
3 ;; Copyright (C) 1986, 1995 Free Software Foundation, Inc. 3 ;; Copyright (C) 1986, 1995 Free Software Foundation, Inc.
4 4
5 ;; Author: Richard Mlynarik <mly@ai.mit.edu> 5 ;; Author: Richard Mlynarik <mly@ai.mit.edu>
6
6 ;; Maintainer: FSF 7 ;; Maintainer: FSF
7 ;; Keywords: help, extensions 8 ;; Keywords: help, extensions
8 9
9 ;; This file is part of XEmacs. 10 ;; This file is part of XEmacs.
10 11
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ;; General Public License for more details. 20 ;; General Public License for more details.
20 21
21 ;; You should have received a copy of the GNU General Public License 22 ;; You should have received a copy of the GNU General Public License
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free 23 ;; along with XEmacs; see the file COPYING. If not, write to the Free
23 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 24 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 ;; 02111-1307, USA. 25
25 26 ;;; Synched up with: FSF 19.30.
26 ;;; Synched up with: FSF 19.34.
27 27
28 ;;; Commentary: 28 ;;; Commentary:
29 29
30 ;; This package provides a pre-packaged `Electric Help Mode' for 30 ;; This package provides a pre-packaged `Electric Help Mode' for
31 ;; browsing on-line help screens. There is one entry point, 31 ;; browsing on-line help screens. There is one entry point,
40 ;; (define-key global-map [f1] 'ehelp-command) 40 ;; (define-key global-map [f1] 'ehelp-command)
41 41
42 ;;; Code: 42 ;;; Code:
43 43
44 (require 'electric) 44 (require 'electric)
45 (defvar electric-help-map () 45
46 (defvar electric-help-map nil
46 "Keymap defining commands available in `electric-help-mode'.") 47 "Keymap defining commands available in `electric-help-mode'.")
47
48 (defvar electric-help-form-to-execute nil)
49 48
50 (put 'electric-help-undefined 'suppress-keymap t) 49 (put 'electric-help-undefined 'suppress-keymap t)
51 (if electric-help-map 50 (if electric-help-map
52 () 51 ()
53 (let ((map (make-keymap))) 52 (let ((map (make-keymap)))
53 (set-keymap-name map 'electric-help-map)
54 ;; allow all non-self-inserting keys - search, scroll, etc, but 54 ;; allow all non-self-inserting keys - search, scroll, etc, but
55 ;; let M-x and C-x exit ehelp mode and retain buffer: 55 ;; let M-x and C-x exit ehelp mode and retain buffer:
56 (suppress-keymap map) 56 (suppress-keymap map)
57 (define-key map "\C-u" 'electric-help-undefined) 57 (define-key map "\C-u" 'electric-help-undefined)
58 (define-key map [(control ?0)] 'electric-help-undefined) 58 (define-key map [(control ?0)] 'electric-help-undefined)
65 (define-key map [(control ?7)] 'electric-help-undefined) 65 (define-key map [(control ?7)] 'electric-help-undefined)
66 (define-key map [(control ?8)] 'electric-help-undefined) 66 (define-key map [(control ?8)] 'electric-help-undefined)
67 (define-key map [(control ?9)] 'electric-help-undefined) 67 (define-key map [(control ?9)] 'electric-help-undefined)
68 (define-key map (char-to-string help-char) 'electric-help-help) 68 (define-key map (char-to-string help-char) 'electric-help-help)
69 (define-key map "?" 'electric-help-help) 69 (define-key map "?" 'electric-help-help)
70 ;; XEmacs addition
71 (define-key map 'help 'electric-help-help) 70 (define-key map 'help 'electric-help-help)
72 (define-key map " " 'scroll-up) 71 (define-key map " " 'scroll-up)
73 (define-key map "\^?" 'scroll-down) 72 (define-key map "\^?" 'scroll-down)
74 (define-key map "." 'beginning-of-buffer) 73 (define-key map "." 'beginning-of-buffer)
75 (define-key map "<" 'beginning-of-buffer) 74 (define-key map "<" 'beginning-of-buffer)
85 84
86 (setq electric-help-map map))) 85 (setq electric-help-map map)))
87 86
88 (defun electric-help-mode () 87 (defun electric-help-mode ()
89 "`with-electric-help' temporarily places its buffer in this mode. 88 "`with-electric-help' temporarily places its buffer in this mode.
90 \(On exit from `with-electric-help', the buffer is put in `default-major-mode'.)" 89 \(On exit from `with-electric-help', the buffer is put in `default-major-mode'.\)"
91 (setq buffer-read-only t) 90 (setq buffer-read-only t)
92 (setq mode-name "Help") 91 (setq mode-name "Help")
93 (setq major-mode 'help) 92 (setq major-mode 'help)
94 (setq modeline-buffer-identification '(" Help: %b")) 93 (setq modeline-buffer-identification '(" Help: %b"))
95 (use-local-map electric-help-map) 94 (use-local-map electric-help-map)
96 (add-hook 'mouse-leave-buffer-hook 'electric-help-retain) 95 (setq mouse-leave-buffer-hook '(electric-help-retain))
97 (view-mode -1)
98 ;; this is done below in with-electric-help 96 ;; this is done below in with-electric-help
99 ;(run-hooks 'electric-help-mode-hook) 97 ;(run-hooks 'electric-help-mode-hook)
100 ) 98 )
101 99
102 ;;;###autoload 100 ;;;###autoload
126 BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit." 124 BUFFER is put into `default-major-mode' (or `fundamental-mode') when we exit."
127 (setq buffer (get-buffer-create (or buffer "*Help*"))) 125 (setq buffer (get-buffer-create (or buffer "*Help*")))
128 (let ((one (one-window-p t)) 126 (let ((one (one-window-p t))
129 (config (current-window-configuration)) 127 (config (current-window-configuration))
130 (bury nil) 128 (bury nil)
131 (electric-help-form-to-execute nil)) 129 (to-be-executed nil))
132 (unwind-protect 130 (unwind-protect
133 (save-excursion 131 (save-excursion
134 (if one (goto-char (window-start (selected-window)))) 132 (if one (goto-char (window-start (selected-window))))
135 (let ((pop-up-windows t)) 133 (let ((pop-up-windows t))
136 (pop-to-buffer buffer)) 134 (pop-to-buffer buffer))
138 (set-buffer buffer) 136 (set-buffer buffer)
139 (if (and minheight (< (window-height) minheight)) 137 (if (and minheight (< (window-height) minheight))
140 (enlarge-window (- minheight (window-height)))) 138 (enlarge-window (- minheight (window-height))))
141 (electric-help-mode) 139 (electric-help-mode)
142 (setq buffer-read-only nil) 140 (setq buffer-read-only nil)
143 (or noerase 141 (or noerase (erase-buffer)))
144 (erase-buffer)))
145 (let ((standard-output buffer)) 142 (let ((standard-output buffer))
146 (if (not (funcall thunk)) 143 (if (not (funcall thunk))
147 (progn 144 (progn
148 (set-buffer buffer) 145 (set-buffer buffer)
149 (set-buffer-modified-p nil) 146 (set-buffer-modified-p nil)
150 (goto-char (point-min)) 147 (goto-char (point-min))
151 (if one (shrink-window-if-larger-than-buffer (selected-window)))))) 148 (if one (shrink-window-if-larger-than-buffer (selected-window))))))
152 (set-buffer buffer) 149 (set-buffer buffer)
153 (run-hooks 'electric-help-mode-hook) 150 (run-hooks 'electric-help-mode-hook)
154 (setq buffer-read-only t)
155 (if (eq (car-safe 151 (if (eq (car-safe
156 ;; XEmacs: Don't be screwed by minor-modes (view-minor-mode) 152 ;; Don't be screwed by minor-modes (view-minor-mode)
157 (let ((overriding-local-map electric-help-map)) 153 (let ((overriding-local-map electric-help-map))
158 (electric-help-command-loop))) 154 (electric-help-command-loop)))
159 'retain) 155 'retain)
160 (setq config (current-window-configuration)) 156 (setq config (current-window-configuration))
161 (setq bury t))) 157 (setq bury t)))
162 (message "") 158 (message nil)
163 (set-buffer buffer) 159 (set-buffer buffer)
164 (setq buffer-read-only nil) 160 (setq buffer-read-only nil)
165 (condition-case () 161 (condition-case ()
166 (funcall (or default-major-mode 'fundamental-mode)) 162 (funcall (or default-major-mode 'fundamental-mode))
167 (error nil)) 163 (error nil))
171 ;;>> Perhaps this shouldn't be done. 167 ;;>> Perhaps this shouldn't be done.
172 ;; so that when we say "Press space to bury" we mean it 168 ;; so that when we say "Press space to bury" we mean it
173 (replace-buffer-in-windows buffer) 169 (replace-buffer-in-windows buffer)
174 ;; must do this outside of save-window-excursion 170 ;; must do this outside of save-window-excursion
175 (bury-buffer buffer))) 171 (bury-buffer buffer)))
176 (eval electric-help-form-to-execute)))) 172 (eval to-be-executed))))
177 173
178 (defun electric-help-command-loop () 174 (defun electric-help-command-loop ()
179 (catch 'exit 175 (catch 'exit
180 (if (pos-visible-in-window-p (point-max)) 176 (if (pos-visible-in-window-p (point-max))
181 (progn (message "%s" (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>")) 177 (progn (message (substitute-command-keys "<<< Press Space to bury the help buffer, Press \\[electric-help-retain] to retain it >>>"))
182 ;; XEmacs change
183 (if (equal (setq unread-command-events 178 (if (equal (setq unread-command-events
184 (list (next-command-event))) 179 (list (next-command-event)))
185 '(?\ )) 180 '(?\ ))
186 (progn (setq unread-command-events nil) 181 (progn (setq unread-command-events nil)
187 (throw 'exit t))))) 182 (throw 'exit t)))))
222 t)))) 217 t))))
223 218
224 219
225 220
226 ;(defun electric-help-scroll-up (arg) 221 ;(defun electric-help-scroll-up (arg)
227 ; ">>>Doc" 222 ; "####Doc"
228 ; (interactive "P") 223 ; (interactive "P")
229 ; (if (and (null arg) (pos-visible-in-window-p (point-max))) 224 ; (if (and (null arg) (pos-visible-in-window-p (point-max)))
230 ; (electric-help-exit) 225 ; (electric-help-exit)
231 ; (scroll-up arg))) 226 ; (scroll-up arg)))
232 227
233 (defun electric-help-exit () 228 (defun electric-help-exit ()
234 ">>>Doc" 229 "####Doc"
235 (interactive) 230 (interactive)
236 (throw 'exit t)) 231 (throw 'exit t))
237 232
238 (defun electric-help-retain () 233 (defun electric-help-retain ()
239 "Exit `electric-help', retaining the current window/buffer configuration. 234 "Exit `electric-help', retaining the current window/buffer configuration.
240 \(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET 235 \(The *Help* buffer will not be selected, but \\[switch-to-buffer-other-window] RET
241 will select it.)" 236 will select it.)"
242 (interactive) 237 (interactive)
243 ;; Make sure that we don't throw twice, even if two events cause 238 ;; Make sure that we don't throw twice, even if two events cause
244 ;; calling this function: 239 ;; calling this function:
245 (if (memq 'electric-help-retain mouse-leave-buffer-hook) 240 (if mouse-leave-buffer-hook
246 (progn 241 (progn
247 (remove-hook 'mouse-leave-buffer-hook 'electric-help-retain) 242 (setq mouse-leave-buffer-hook nil)
248 (throw 'exit '(retain))))) 243 (throw 'exit '(retain)))))
249 244
245
246 ;(defun electric-help-undefined ()
247 ; (interactive)
248 ; (let* ((keys (this-command-keys))
249 ; (n (length keys)))
250 ; (if (or (= n 1)
251 ; (and (= n 2)
252 ; meta-flag
253 ; (eq (aref keys 0) meta-prefix-char)))
254 ; (setq unread-command-char last-input-char
255 ; current-prefix-arg prefix-arg)
256 ; ;;#### I don't care.
257 ; ;;#### The emacs command-loop is too much pure pain to
258 ; ;;#### duplicate
259 ; ))
260 ; (throw 'exit t))
250 261
251 (defun electric-help-undefined () 262 (defun electric-help-undefined ()
252 (interactive) 263 (interactive)
253 (error "%s is undefined -- Press %s to exit" 264 (error "%s is undefined -- Press %s to exit"
254 (mapconcat 'single-key-description (this-command-keys) " ") 265 (mapconcat 'single-key-description (this-command-keys) " ")
255 (if (eq (key-binding "q") 'electric-help-exit) 266 (if (eq (key-binding "q") 'electric-help-exit)
256 "q" 267 "q"
257 (substitute-command-keys "\\[electric-help-exit]")))) 268 (substitute-command-keys "\\[electric-help-exit]"))))
258 269
259 270
260 ;>>> this needs to be hairified (recursive help, anybody?) 271 ;#### this needs to be hairified (recursive help, anybody?)
261 (defun electric-help-help () 272 (defun electric-help-help ()
262 (interactive) 273 (interactive)
263 (if (and (eq (key-binding "q") 'electric-help-exit) 274 (if (and (eq (key-binding "q") 'electric-help-exit)
264 (eq (key-binding " ") 'scroll-up) 275 (eq (key-binding " ") 'scroll-up)
265 (eq (key-binding "\^?") 'scroll-down) 276 (eq (key-binding "\^?") 'scroll-down)
268 (message "%s" (substitute-command-keys "\\[scroll-up] scrolls up, \\[scroll-down] scrolls down, \\[electric-help-exit] exits burying help buffer, \\[electric-help-retain] exits"))) 279 (message "%s" (substitute-command-keys "\\[scroll-up] scrolls up, \\[scroll-down] scrolls down, \\[electric-help-exit] exits burying help buffer, \\[electric-help-retain] exits")))
269 (sit-for 2)) 280 (sit-for 2))
270 281
271 282
272 ;;;###autoload 283 ;;;###autoload
273 (defun electric-helpify (fun &optional name) 284 (defun electric-helpify (fun &optional buffer-name)
274 (let ((name (or name "*Help*"))) 285 (or buffer-name (setq buffer-name "*Help*"))
275 (if (save-window-excursion 286 (let* ((p (symbol-function 'print-help-return-message))
276 ;; kludge-o-rama 287 (b (get-buffer buffer-name))
277 (let* ((p (symbol-function 'print-help-return-message)) 288 (tick (and b (buffer-modified-tick b))))
278 (b (get-buffer name)) 289 (and b (not (get-buffer-window b))
279 (m (buffer-modified-p b))) 290 (setq b nil))
280 (and b (not (get-buffer-window b)) 291 (if (unwind-protect
281 (setq b nil)) 292 (save-window-excursion
282 (unwind-protect 293 (message "%s..." (capitalize (symbol-name fun)))
283 (progn 294 ;; kludge-o-rama
284 (message "%s..." (capitalize (symbol-name fun))) 295 (fset 'print-help-return-message 'ignore)
285 ;; with-output-to-temp-buffer marks the buffer as unmodified. 296 (let ((a (call-interactively fun 'lambda)))
286 ;; kludging excessively and relying on that as some sort 297 (let ((temp-buffer-show-function 'ignore))
287 ;; of indication leads to the following abomination... 298 (apply fun a)))
288 ;;>> This would be doable without such icky kludges if either 299 (message nil)
289 ;;>> (a) there were a function to read the interactive 300 ;; Was a non-empty help buffer created/modified?
290 ;;>> args for a command and return a list of those args. 301 (let ((r (get-buffer buffer-name)))
291 ;;>> (To which one would then just apply the command) 302 (and r
292 ;;>> (The only problem with this is that interactive-p 303 ;(get-buffer-window r)
293 ;;>> would break, but that is such a misfeature in 304 (or (not b)
294 ;;>> any case that I don't care) 305 (not (eq b r))
295 ;;>> It is easy to do this for emacs-lisp functions; 306 (not (eql tick (buffer-modified-tick b))))
296 ;;>> the only problem is getting the interactive spec 307 (save-excursion
297 ;;>> for subrs 308 (set-buffer r)
298 ;;>> (b) there were a function which returned a 309 (> (buffer-size) 0)))))
299 ;;>> modification-tick for a buffer. One could tell 310 (fset 'print-help-return-message p)
300 ;;>> whether a buffer had changed by whether the 311 )
301 ;;>> modification-tick were different. 312 (with-electric-help 'ignore buffer-name t))))
302 ;;>> (Presumably there would have to be a way to either
303 ;;>> restore the tick to some previous value, or to
304 ;;>> suspend updating of the tick in order to allow
305 ;;>> things like momentary-string-display)
306 (and b
307 (save-excursion
308 (set-buffer b)
309 (set-buffer-modified-p t)))
310 (fset 'print-help-return-message 'ignore)
311 (call-interactively fun)
312 (and (get-buffer name)
313 (get-buffer-window (get-buffer name))
314 (or (not b)
315 (not (eq b (get-buffer name)))
316 (not (buffer-modified-p b)))))
317 (fset 'print-help-return-message p)
318 (and b (buffer-name b)
319 (save-excursion
320 (set-buffer b)
321 (set-buffer-modified-p m))))))
322 (with-electric-help 'ignore name t))))
323 313
324 314
325 315
326 ;; This is to be bound to M-x in ehelp mode. Retains ehelp buffer and then 316 ;; This is to be bound to M-x in ehelp mode. Retains ehelp buffer and then
327 ;; continues with execute-extended-command. 317 ;; continues with execute-extended-command.
328 (defun electric-help-execute-extended (prefixarg) 318 (defun electric-help-execute-extended (prefixarg)
329 (interactive "p") 319 (interactive "p")
330 (setq electric-help-form-to-execute '(execute-extended-command nil)) 320 (setq to-be-executed '(execute-extended-command nil))
331 (electric-help-retain)) 321 (electric-help-retain))
332 322
333 ;; This is to be buond to C-x in ehelp mode. Retains ehelp buffer and then 323 ;; This is to be buond to C-x in ehelp mode. Retains ehelp buffer and then
334 ;; continues with ctrl-x prefix. 324 ;; continues with ctrl-x prefix.
335 (defun electric-help-ctrl-x-prefix (prefixarg) 325 (defun electric-help-ctrl-x-prefix (prefixarg)
336 (interactive "p") 326 (interactive "p")
337 (setq electric-help-form-to-execute '(progn (message nil) (setq unread-command-char ?\C-x))) 327 (setq to-be-executed '(progn (message nil) (setq unread-command-char ?\C-x)))
338 (electric-help-retain)) 328 (electric-help-retain))
339 329
340 330
341 (defun electric-describe-key () 331 (defun electric-describe-key ()
342 (interactive) 332 (interactive)
371 (interactive) 361 (interactive)
372 (electric-helpify 'describe-syntax)) 362 (electric-helpify 'describe-syntax))
373 363
374 (defun electric-command-apropos () 364 (defun electric-command-apropos ()
375 (interactive) 365 (interactive)
376 (electric-helpify 'command-apropos "*Apropos*")) 366 (electric-helpify 'command-apropos))
377 367
378 ;(define-key help-map "a" 'electric-command-apropos) 368 ;(define-key help-map "a" 'electric-command-apropos)
379 369
380 (defun electric-apropos () 370 (defun electric-apropos ()
381 (interactive) 371 (interactive)
382 (electric-helpify 'apropos)) 372 (electric-helpify 'apropos))
373
383 374
384 375
385 ;;;; ehelp-map 376 ;;;; ehelp-map
386 377
387 (defvar ehelp-map ()) 378 (defvar ehelp-map nil)
388 (if ehelp-map 379 (if ehelp-map
389 nil 380 nil
390 ;; #### WTF? Why don't we just use substitute-key-definition 381 ;; #### WTF? Why don't we just use substitute-key-definition
391 ;; like FSF does? 382 ;; like FSF does?
392 (let ((shadow '((apropos . electric-apropos) 383 (let ((shadow '((apropos . electric-apropos)