comparison lisp/packages/hyper-apropos.el @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents 8d2a9b52c682
children 6a378aca36af
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
52 ;; Mouse bindings and menus are provided for XEmacs. 52 ;; Mouse bindings and menus are provided for XEmacs.
53 ;; 53 ;;
54 ;; additions by Ben Wing <wing@666.com> July 1995: 54 ;; additions by Ben Wing <wing@666.com> July 1995:
55 ;; added support for function aliases, made programmer's apropos be the 55 ;; added support for function aliases, made programmer's apropos be the
56 ;; default, various other hacking. 56 ;; default, various other hacking.
57 ;; Massive changes by Christoph Wedler <wedler@fmi.uni-passau.de>
58 57
59 ;;; Code: 58 ;;; Code:
60 59
61 (or (fboundp 'pprint) 60 (or (fboundp 'pprint)
62 (progn (autoload 'pp "pp") 61 (progn (autoload 'pp "pp")
66 ;;;###autoload 65 ;;;###autoload
67 (defvar hypropos-show-brief-docs t 66 (defvar hypropos-show-brief-docs t
68 "*If non-nil, `hyper-apropos' will display some documentation in the 67 "*If non-nil, `hyper-apropos' will display some documentation in the
69 \"*Hyper Apropos*\" buffer. Setting this to nil will speed up searches.") 68 \"*Hyper Apropos*\" buffer. Setting this to nil will speed up searches.")
70 69
71 (defvar hypropos-shrink-window nil
72 "*If non-nil, shrink *Hyper Help* buffer if possible.")
73
74 (defvar hypropos-prettyprint-long-values t 70 (defvar hypropos-prettyprint-long-values t
75 "*If non-nil, then try to beautify the printing of very long values.") 71 "*If non-nil, then try to beautify the printing of very long values.")
76 72
77 ;; I changed this to true because I think it's more useful this way. --ben 73 ;; I changed this to true because I think it's more useful this way. --ben
78 74
79 (defvar hypropos-programming-apropos t 75 (defvar hypropos-programming-apropos t
80 "*If non-nil, then `hyper-apropos' takes a bit longer and generates more 76 "*If non-nil, then `hyper-apropos' takes a bit longer and generates more
81 output. If nil, then only functions that are interactive and variables that 77 output. If nil, then only functions that are interactive and variables that
82 are user variables are found by `hyper-apropos'.") 78 are user variables are found by `hyper-apropos'.")
83 79
84 (defvar hypropos-ref-buffer)
85 (defvar hypropos-prev-wconfig) 80 (defvar hypropos-prev-wconfig)
86 81
87 ;; #### - move this to subr.el 82 ;; #### - move this to subr.el
88 (or (fboundp 'event-buffer) 83 (or (fboundp 'event-buffer)
89 (defun event-buffer (event) 84 (defun event-buffer (event)
155 (suppress-keymap map) 150 (suppress-keymap map)
156 (set-keymap-name map 'hypropos-help-map) 151 (set-keymap-name map 'hypropos-help-map)
157 ;; movement 152 ;; movement
158 (define-key map " " 'scroll-up) 153 (define-key map " " 'scroll-up)
159 (define-key map "b" 'scroll-down) 154 (define-key map "b" 'scroll-down)
160 (define-key map [delete] 'scroll-down)
161 (define-key map [backspace] 'scroll-down)
162 (define-key map "/" 'isearch-forward) 155 (define-key map "/" 'isearch-forward)
163 (define-key map "?" 'isearch-backward) 156 (define-key map "?" 'isearch-backward)
164 ;; follow links 157 ;; follow links
165 (define-key map "\r" 'hypropos-get-doc) 158 (define-key map "\r" 'hypropos-get-doc)
166 (define-key map "s" 'hypropos-set-variable) 159 (define-key map "s" 'hypropos-set-variable)
179 "Keybindings for both the *Hyper Help* buffer and the *Hyper Apropos* buffer") 172 "Keybindings for both the *Hyper Help* buffer and the *Hyper Apropos* buffer")
180 173
181 (defvar hypropos-map (let ((map (make-sparse-keymap))) 174 (defvar hypropos-map (let ((map (make-sparse-keymap)))
182 (set-keymap-name map 'hypropos-map) 175 (set-keymap-name map 'hypropos-map)
183 (set-keymap-parents map (list hypropos-help-map)) 176 (set-keymap-parents map (list hypropos-help-map))
184 ;; slightly different scrolling... 177 ;; slightly differrent scrolling...
185 (define-key map " " 'hypropos-scroll-up) 178 (define-key map " " 'hypropos-scroll-up)
186 (define-key map "b" 'hypropos-scroll-down) 179 (define-key map "b" 'hypropos-scroll-down)
187 (define-key map [delete] 'hypropos-scroll-down)
188 (define-key map [backspace] 'hypropos-scroll-down)
189 ;; act on the current line... 180 ;; act on the current line...
190 (define-key map "w" 'hypropos-where-is) 181 (define-key map "w" 'hypropos-where-is)
191 (define-key map "i" 'hypropos-invoke-fn) 182 (define-key map "i" 'hypropos-invoke-fn)
192 (define-key map "s" 'hypropos-set-variable) 183 (define-key map "s" 'hypropos-set-variable)
193 ;; more administrativa... 184 ;; more administrativa...
208 (defconst hypropos-junk-regexp "^Apropos\\|^Functions\\|^Variables\\|^$") 199 (defconst hypropos-junk-regexp "^Apropos\\|^Functions\\|^Variables\\|^$")
209 200
210 (defvar hypropos-currently-showing nil) ; symbol documented in help buffer now 201 (defvar hypropos-currently-showing nil) ; symbol documented in help buffer now
211 (defvar hypropos-help-history nil) ; chain of symbols followed as links in 202 (defvar hypropos-help-history nil) ; chain of symbols followed as links in
212 ; help buffer 203 ; help buffer
213 (defvar hypropos-face-history nil)
214 ;;;(defvar hypropos-variable-history nil)
215 ;;;(defvar hypropos-function-history nil)
216 (defvar hypropos-regexp-history nil)
217 (defvar hypropos-last-regexp nil) ; regex used for last apropos 204 (defvar hypropos-last-regexp nil) ; regex used for last apropos
218 (defconst hypropos-apropos-buf "*Hyper Apropos*") 205 (defconst hypropos-apropos-buf "*Hyper Apropos*")
219 (defconst hypropos-help-buf "*Hyper Help*") 206 (defconst hypropos-help-buf "*Hyper Help*")
220 207
221 ;;;###autoload 208 ;;;###autoload
222 (defun hyper-apropos (regexp toggle-apropos) 209 (defun hyper-apropos (regexp toggle-apropos)
223 "Display lists of functions and variables matching REGEXP 210 "Display lists of functions and variables matching REGEXP
224 in buffer \"*Hyper Apropos*\". If optional prefix arg is given, then the value 211 in buffer \"*Hyper Apropos*\". If optional prefix arg is given, then the value
225 of `hypropos-programming-apropos' is toggled for this search. 212 of `hypropos-programming-apropos' is toggled for this search.
226 See also `hyper-apropos-mode'." 213 See also `hyper-apropos-mode'."
227 (interactive (list (read-from-minibuffer "List symbols matching regexp: " 214 (interactive "sList symbols matching regexp: \nP")
228 nil nil nil 'hypropos-regexp-history)
229 current-prefix-arg))
230 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode)) 215 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode))
231 (setq hypropos-prev-wconfig (current-window-configuration))) 216 (setq hypropos-prev-wconfig (current-window-configuration)))
232 (if (string= "" regexp) 217 (if (string= "" regexp)
233 (if (get-buffer hypropos-apropos-buf) 218 (if (get-buffer hypropos-apropos-buf)
234 (if toggle-apropos 219 (if toggle-apropos
268 (not hypropos-programming-apropos))) 253 (not hypropos-programming-apropos)))
269 (message "Re-running apropos...") 254 (message "Re-running apropos...")
270 (hyper-apropos hypropos-last-regexp nil)) 255 (hyper-apropos hypropos-last-regexp nil))
271 256
272 (defun hypropos-grok-functions (fns) 257 (defun hypropos-grok-functions (fns)
273 (let (fn bind doc type) 258 (let (fn bind type)
274 (while (setq fn (car fns)) 259 (while (setq fn (car fns))
275 (setq bind (symbol-function fn) 260 (setq bind (symbol-function fn)
276 type (cond ((subrp bind) ?i) 261 type (cond ((subrp bind) ?i)
277 ((compiled-function-p bind) ?b) 262 ((compiled-function-p bind) ?b)
278 ((consp bind) (or (cdr 263 ((consp bind) (or (cdr
282 ??)) 267 ??))
283 (t ? ))) 268 (t ? )))
284 (insert type (if (commandp fn) "* " " ")) 269 (insert type (if (commandp fn) "* " " "))
285 (insert-face (format "%-30S" fn) 'hyperlink) 270 (insert-face (format "%-30S" fn) 'hyperlink)
286 (and hypropos-show-brief-docs 271 (and hypropos-show-brief-docs
287 (setq doc (documentation fn)) 272 (if (function-obsolete-p fn)
288 (insert-face (if doc 273 (insert-face " - Obsolete." 'documentation)
289 (concat " - " 274 (let ((doc (documentation fn)))
290 (substring doc 0 (string-match "\n" doc))) 275 (if (not doc)
291 " Not documented.") 276 (insert-face " - Not documented." 'documentation)
292 'documentation)) 277 (insert-face (concat " - "
278 (substring doc 0
279 (string-match "\n" doc)))
280 'documentation)))))
293 (insert ?\n) 281 (insert ?\n)
294 (setq fns (cdr fns)) 282 (setq fns (cdr fns))
295 ))) 283 )))
296 284
297 (defun hypropos-grok-variables (vars) 285 (defun hypropos-grok-variables (vars)
298 (let (var doc userp) 286 (let (var userp)
299 (while (setq var (car vars)) 287 (while (setq var (car vars))
300 (setq userp (user-variable-p var) 288 (setq userp (user-variable-p var)
301 vars (cdr vars)) 289 vars (cdr vars))
302 (insert (if userp " * " " ")) 290 (insert (if userp " * " " "))
303 (insert-face (format "%-30S" var) 'hyperlink) 291 (insert-face (format "%-30S" var) 'hyperlink)
304 (and hypropos-show-brief-docs 292 (and hypropos-show-brief-docs
305 (setq doc (documentation-property var 'variable-documentation)) 293 (if (variable-obsolete-p var)
306 (insert-face (if doc 294 (insert-face " - Obsolete." 'documentation)
307 (concat " - " (substring doc (if userp 1 0) 295 (let ((doc (documentation-property var 'variable-documentation)))
308 (string-match "\n" doc))) 296 (if (not doc)
309 " - Not documented.") 297 (insert-face " - Not documented." 'documentation)
310 'documentation)) 298 (insert-face (concat " - "
299 (substring doc (if userp 1 0)
300 (string-match "\n" doc)))
301 'documentation)))))
311 (insert ?\n) 302 (insert ?\n)
312 ))) 303 )))
313 304
314 ;; ---------------------------------------------------------------------- ;; 305 ;; ---------------------------------------------------------------------- ;;
315 306
343 (setq mode-name "Hyper-Apropos" 334 (setq mode-name "Hyper-Apropos"
344 major-mode 'hyper-apropos-mode 335 major-mode 'hyper-apropos-mode
345 buffer-read-only t 336 buffer-read-only t
346 truncate-lines t 337 truncate-lines t
347 hypropos-last-regexp regexp 338 hypropos-last-regexp regexp
348 modeline-buffer-identification 339 modeline-buffer-identification (concat "Hyper Apropos: "
349 (list (cons modeline-buffer-id-left-extent "Hyper Apropos: ") 340 "\"" regexp "\""))
350 (cons modeline-buffer-id-right-extent (concat "\"" regexp "\""))))
351 (setq mode-motion-hook 'mode-motion-highlight-line) 341 (setq mode-motion-hook 'mode-motion-highlight-line)
352 (use-local-map hypropos-map) 342 (use-local-map hypropos-map)
353 (run-hooks 'hyper-apropos-mode-hook)) 343 (run-hooks 'hyper-apropos-mode-hook))
354 344
355 ;; ---------------------------------------------------------------------- ;; 345 ;; ---------------------------------------------------------------------- ;;
356 346
357 ;; similar to `describe-key-briefly', copied from prim/help.el by CW
358
359 ;;;###autoload 347 ;;;###autoload
360 (defun hyper-describe-key (key) 348 (defun hyper-describe-variable (symbol)
361 (interactive "kDescribe key: ") 349 "Hypertext drop-in replacement for `describe-variable'.
362 (hyper-describe-key-briefly key t))
363
364 ;;;###autoload
365 (defun hyper-describe-key-briefly (key &optional show)
366 (interactive "kDescribe key briefly: \nP")
367 (let (menup defn interm final msg)
368 (setq defn (key-or-menu-binding key 'menup))
369 (if (or (null defn) (integerp defn))
370 (or (numberp show) (message "%s is undefined" (key-description key)))
371 (cond ((stringp defn)
372 (setq interm defn
373 final (key-binding defn)))
374 ((vectorp defn)
375 (setq interm (append defn nil))
376 (while (and interm
377 (member (key-binding (vector (car interm)))
378 '(universal-argument digit-argument)))
379 (setq interm (cdr interm)))
380 (while (and interm
381 (not (setq final (key-binding (vconcat interm)))))
382 (setq interm (butlast interm)))
383 (if final
384 (setq interm (vconcat interm))
385 (setq interm defn
386 final (key-binding defn)))))
387 (setq msg (format
388 "%s runs %s%s%s"
389 ;; This used to say 'This menu item' but it could also
390 ;; be a scrollbar event. We can't distinguish at the
391 ;; moment.
392 (if menup "This item" (key-description key))
393 ;;(if (symbolp defn) defn (key-description defn))
394 (if (symbolp defn) defn (prin1-to-string defn))
395 (if final (concat ", " (key-description interm) " runs ") "")
396 (if final
397 (if (symbolp final) final (prin1-to-string final))
398 "")))
399 (if (numberp show)
400 (or (not (symbolp defn))
401 (memq (symbol-function defn)
402 '(zkey-init-kbd-macro zkey-init-kbd-fn))
403 (progn (princ msg) (princ "\n")))
404 (message "%s" msg)
405 (if final (setq defn final))
406 (if (and (or (symbolp defn) (symbolp (setq defn (car-safe defn))))
407 defn
408 show)
409 (hypropos-get-doc defn t))))))
410
411 ;;;###autoload
412 (defun hyper-describe-face (symbol &optional this-ref-buffer)
413 "Describe face..
414 See also `hyper-apropos' and `hyper-describe-function'." 350 See also `hyper-apropos' and `hyper-describe-function'."
415 ;; #### - perhaps a prefix arg should suppress the prompt... 351 ;; #### - perhaps a prefix arg should suppress the prompt...
416 (interactive 352 (interactive
417 (let (v val) 353 (let* ((v (variable-at-point))
418 (setq v (hypropos-this-symbol)) ; symbol under point 354 (val (let ((enable-recursive-minibuffers t))
419 (or (find-face v)
420 (setq v (variable-at-point)))
421 (setq val (let ((enable-recursive-minibuffers t))
422 (completing-read 355 (completing-read
423 (concat (if (hypropos-follow-ref-buffer current-prefix-arg) 356 (if v
424 "Follow face" 357 (format "Describe variable (default %s): " v)
425 "Describe face") 358 "Describe variable: ")
426 (if v 359 obarray 'boundp t))))
427 (format " (default %s): " v) 360 (list (if (string= val "") v (intern-soft val)))))
428 ": "))
429 (mapcar (function (lambda (x) (list (symbol-name x))))
430 (face-list))
431 nil t nil 'hypropos-face-history)))
432 (list (if (string= val "")
433 (progn (push (symbol-name v) hypropos-face-history) v)
434 (intern-soft val))
435 current-prefix-arg)))
436 (if (null symbol) 361 (if (null symbol)
437 (message "Sorry, nothing to describe.") 362 (message "Sorry, nothing to describe.")
438 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode)) 363 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode))
439 (setq hypropos-prev-wconfig (current-window-configuration))) 364 (setq hypropos-prev-wconfig (current-window-configuration)))
440 (hypropos-get-doc symbol t nil this-ref-buffer))) 365 (hypropos-get-doc symbol t)))
441 366
442 ;;;###autoload 367 ;;;###autoload
443 (defun hyper-describe-variable (symbol &optional this-ref-buffer) 368 (defun hyper-describe-function (symbol)
444 "Hypertext drop-in replacement for `describe-variable'. 369 "Hypertext replacement for `describe-function'. Unlike `describe-function'
445 See also `hyper-apropos' and `hyper-describe-function'." 370 in that the symbol under the cursor is the default if it is a function.
371 See also `hyper-apropos' and `hyper-describe-variable'."
446 ;; #### - perhaps a prefix arg should suppress the prompt... 372 ;; #### - perhaps a prefix arg should suppress the prompt...
447 (interactive (list (hypropos-read-variable-symbol 373 (interactive
448 (if (hypropos-follow-ref-buffer current-prefix-arg) 374 (let (fn val)
449 "Follow variable" 375 (setq fn (hypropos-this-symbol)) ; symbol under point
450 "Describe variable")) 376 (or (fboundp fn)
451 current-prefix-arg)) 377 (setq fn (function-called-at-point)))
378 (setq val (let ((enable-recursive-minibuffers t))
379 (completing-read
380 (if fn
381 (format "Describe function (default %s): " fn)
382 "Describe function: ")
383 obarray 'fboundp t)))
384 (list (if (equal val "") fn (intern-soft val)))))
452 (if (null symbol) 385 (if (null symbol)
453 (message "Sorry, nothing to describe.") 386 (message "Sorry, nothing to describe.")
454 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode)) 387 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode))
455 (setq hypropos-prev-wconfig (current-window-configuration))) 388 (setq hypropos-prev-wconfig (current-window-configuration)))
456 (hypropos-get-doc symbol t nil this-ref-buffer))) 389 (hypropos-get-doc symbol t)))
457
458 (defun hyper-where-is (symbol)
459 "Print message listing key sequences that invoke specified command."
460 (interactive (list (hypropos-read-function-symbol "Where is function")))
461 (if (null symbol)
462 (message "Sorry, nothing to describe.")
463 (where-is symbol)))
464
465 ;;;###autoload
466 (defun hyper-describe-function (symbol &optional this-ref-buffer)
467 "Hypertext replacement for `describe-function'. Unlike `describe-function'
468 in that the symbol under the cursor is the default if it is a function.
469 See also `hyper-apropos' and `hyper-describe-variable'."
470 ;; #### - perhaps a prefix arg should suppress the prompt...
471 (interactive (list (hypropos-read-function-symbol
472 (if (hypropos-follow-ref-buffer current-prefix-arg)
473 "Follow function"
474 "Describe function"))
475 current-prefix-arg))
476 (if (null symbol)
477 (message "Sorry, nothing to describe.")
478 (or (memq major-mode '(hyper-apropos-mode hyper-help-mode))
479 (setq hypropos-prev-wconfig (current-window-configuration)))
480 (hypropos-get-doc symbol t nil this-ref-buffer)))
481
482 ;;;###autoload
483 (defun hypropos-read-variable-symbol (prompt &optional predicate)
484 "Hypertext drop-in replacement for `describe-variable'.
485 See also `hyper-apropos' and `hyper-describe-function'."
486 ;; #### - perhaps a prefix arg should suppress the prompt...
487 (or predicate (setq predicate 'boundp))
488 (let (v val)
489 (setq v (hypropos-this-symbol)) ; symbol under point
490 (or (funcall predicate v)
491 (setq v (variable-at-point)))
492 (or (funcall predicate v)
493 (setq v nil))
494 (setq val (let ((enable-recursive-minibuffers t))
495 (completing-read
496 (concat prompt
497 (if v
498 (format " (default %s): " v)
499 ": "))
500 obarray predicate t nil 'variable-history)))
501 (if (string= val "")
502 (progn (push (symbol-name v) variable-history) v)
503 (intern-soft val))))
504
505 (defun hypropos-read-function-symbol (prompt)
506 "Read function symbol from minibuffer."
507 (let ((fn (hypropos-this-symbol))
508 val)
509 (or (fboundp fn)
510 (setq fn (function-called-at-point)))
511 (setq val (let ((enable-recursive-minibuffers t))
512 (completing-read (if fn
513 (format "%s (default %s): " prompt fn)
514 (format "%s: " prompt))
515 obarray 'fboundp t nil
516 'function-history)))
517 (if (equal val "")
518 (progn (push (symbol-name fn) function-history) fn)
519 (intern-soft val))))
520 390
521 (defun hypropos-last-help (arg) 391 (defun hypropos-last-help (arg)
522 "Go back to the last symbol documented in the *Hyper Help* buffer." 392 "Go back to the last symbol documented in the *Hyper Help* buffer."
523 (interactive "P") 393 (interactive "P")
524 (let ((win (get-buffer-window hypropos-help-buf))) 394 (let ((win (get-buffer-window hypropos-help-buf))
525 (or arg (setq arg (if win 1 0))) 395 (n (prefix-numeric-value arg)))
526 (cond ((= arg 0)) 396 (cond ((and (not win) (not arg))
527 ((<= (length hypropos-help-history) arg) 397 ;; don't alter the help-history, just redisplay
398 )
399 ((<= (length hypropos-help-history) n)
528 ;; go back as far as we can... 400 ;; go back as far as we can...
529 (setcdr (nreverse hypropos-help-history) nil)) 401 (setcdr (nreverse hypropos-help-history) nil))
530 (t 402 (t
531 (setq hypropos-help-history (nthcdr arg hypropos-help-history)))) 403 (setq hypropos-help-history (nthcdr n hypropos-help-history))))
532 (if (or win (> arg 0)) 404 (hypropos-get-doc (car hypropos-help-history) t)))
533 (hypropos-get-doc (car hypropos-help-history) t) 405
534 (display-buffer hypropos-help-buf)))) 406 (defun hypropos-get-doc (&optional symbol force type)
535
536 (defun hypropos-insert-face (string &optional face)
537 "Insert STRING and fontify some parts with face `hyperlink'."
538 (let ((beg (point)) end)
539 (insert-face string (or face 'documentation))
540 (setq end (point))
541 (goto-char beg)
542 (while (re-search-forward
543 "`\\([-a-zA-Z0-9_][-a-zA-Z0-9_][-a-zA-Z0-9_.]+\\)'"
544 end 'limit)
545 (set-extent-face (make-extent (match-beginning 1) (match-end 1))
546 'hyperlink))
547 (goto-char beg)
548 (while (re-search-forward
549 "M-x \\([-a-zA-Z0-9_][-a-zA-Z0-9_][-a-zA-Z0-9_.]+\\)"
550 end 'limit)
551 (set-extent-face (make-extent (match-beginning 1) (match-end 1))
552 'hyperlink))))
553
554 (defun hypropos-insert-keybinding (keys string)
555 (if keys
556 (insert " (" string " bound to \""
557 (mapconcat 'key-description
558 (sort keys #'(lambda (x y)
559 (< (length x) (length y))))
560 "\", \"")
561 "\")\n")))
562
563 (defun hypropos-insert-section-heading (alias-desc &optional desc)
564 (or desc (setq desc alias-desc
565 alias-desc nil))
566 (if alias-desc
567 (setq desc (concat alias-desc
568 (if (memq (aref desc 0)
569 '(?a ?e ?i ?o ?u))
570 ", an " ", a ")
571 desc)))
572 (aset desc 0 (upcase (aref desc 0))) ; capitalize
573 (goto-char (point-max))
574 (newline 3) (delete-blank-lines) (newline 2)
575 (hypropos-insert-face desc 'section-heading))
576
577 (defun hypropos-insert-value (string symbol val)
578 (insert-face string 'heading)
579 (insert (if (symbol-value symbol)
580 (if (or (null val) (eq val t) (integerp val))
581 (prog1
582 (symbol-value symbol)
583 (set symbol nil))
584 "see below")
585 "is void")))
586
587 (defun hypropos-follow-ref-buffer (this-ref-buffer)
588 (and (not this-ref-buffer)
589 (eq major-mode 'hyper-help-mode)
590 hypropos-ref-buffer
591 (buffer-live-p hypropos-ref-buffer)))
592
593 (defun hypropos-get-alias (symbol alias-p next-symbol &optional use)
594 "Return (TERMINAL-SYMBOL . ALIAS-DESC)."
595 (let (aliases)
596 (while (funcall alias-p symbol)
597 (setq aliases (cons (if use (funcall use symbol) symbol) aliases))
598 (setq symbol (funcall next-symbol symbol)))
599 (cons symbol
600 (and aliases
601 (concat "an alias for `"
602 (mapconcat 'symbol-name
603 (nreverse aliases)
604 "',\nwhich is an alias for `")
605 "'")))))
606
607 ;;;###autoload
608 (defun hypropos-get-doc (&optional symbol force type this-ref-buffer)
609 ;; #### - update this docstring 407 ;; #### - update this docstring
610 "Toggle display of documentation for the symbol on the current line." 408 "Toggle display of documentation for the symbol on the current line."
611 ;; SYMBOL is the symbol to document. FORCE, if non-nil, means to 409 ;; SYMBOL is the symbol to document. FORCE, if non-nil, means to
612 ;; regenerate the documentation even if it already seems to be there. And 410 ;; regenerate the documentation even if it already seems to be there. And
613 ;; TYPE, if present, forces the generation of only variable documentation 411 ;; TYPE, if present, forces the generation of only variable documentation
635 ;; record that in the help history. 433 ;; record that in the help history.
636 (cons symbol hypropos-help-history) 434 (cons symbol hypropos-help-history)
637 ;; otherwise clear the history because it's a new search. 435 ;; otherwise clear the history because it's a new search.
638 (list symbol)))) 436 (list symbol))))
639 (save-excursion 437 (save-excursion
640 (if (hypropos-follow-ref-buffer this-ref-buffer) 438 (set-buffer (get-buffer-create hypropos-help-buf))
641 (set-buffer hypropos-ref-buffer) 439 (setq buffer-read-only nil)
642 (setq hypropos-ref-buffer (current-buffer))) 440 (erase-buffer)
643 (let (standard-output 441 (let ((standard-output (current-buffer))
644 ok beg 442 ok beg desc
645 newsym symtype doc obsolete 443 ftype macrop fndef
646 (local mode-name) 444 keys val doc
647 global local-str global-str 445 obsolete aliases alias-desc)
648 font fore back undl 446 (insert-face (format "`%s'\n\n" symbol) 'major-heading)
649 aliases alias-desc desc)
650 (save-excursion
651 (set-buffer (get-buffer-create hypropos-help-buf))
652 ;;(setq standard-output (current-buffer))
653 (setq buffer-read-only nil)
654 (erase-buffer)
655 (insert-face (format "`%s'" symbol) 'major-heading)
656 (insert (format " (buffer: %s, mode: %s)\n"
657 (buffer-name hypropos-ref-buffer)
658 local)))
659 ;; function ----------------------------------------------------------
660 (and (memq 'function type) 447 (and (memq 'function type)
661 (fboundp symbol) 448 (fboundp symbol)
662 (progn 449 (progn
663 (setq ok t) 450 (setq ok t
664 (setq aliases (hypropos-get-alias (symbol-function symbol) 451 fndef (symbol-function symbol))
665 'symbolp 452 (while (symbolp fndef)
666 'symbol-function) 453 (setq aliases (cons fndef aliases))
667 newsym (car aliases) 454 (setq fndef (symbol-function fndef)))
668 alias-desc (cdr aliases)) 455 (if (eq 'macro (car-safe fndef))
669 (if (eq 'macro (car-safe newsym)) 456 (setq macrop t
670 (setq desc "macro" 457 fndef (cdr fndef)))
671 newsym (cdr newsym)) 458 (setq aliases (nreverse aliases))
672 (setq desc "function")) 459 ;; #### - the gods of internationalization shall strike me down!
673 (setq symtype (cond ((subrp newsym) 'subr) 460 (while aliases
674 ((compiled-function-p newsym) 'bytecode) 461 (if alias-desc
675 ((eq (car-safe newsym) 'autoload) 'autoload) 462 (setq alias-desc (concat alias-desc ",\nwhich is ")))
676 ((eq (car-safe newsym) 'lambda) 'lambda)) 463 (setq alias-desc (concat alias-desc
464 (format "an alias for `%s'"
465 (car aliases))))
466 (setq aliases (cdr aliases)))
467 (setq ftype (cond ((subrp fndef) 'subr)
468 ((compiled-function-p fndef) 'bytecode)
469 ((eq (car-safe fndef) 'autoload) 'autoload)
470 ((eq (car-safe fndef) 'lambda) 'lambda))
677 desc (concat (if (commandp symbol) "interactive ") 471 desc (concat (if (commandp symbol) "interactive ")
678 (cdr (assq symtype 472 (cdr (assq ftype
679 '((subr . "built-in ") 473 '((subr . "built-in ")
680 (bytecode . "compiled Lisp ") 474 (bytecode . "compiled Lisp ")
681 (autoload . "autoloaded Lisp ") 475 (autoload . "autoloaded Lisp ")
682 (lambda . "Lisp ")))) 476 (lambda . "Lisp "))))
683 desc) 477 (if macrop "macro" "function")
684 local (current-local-map) 478 ))
685 global (current-global-map) 479 (if alias-desc
686 obsolete (get symbol 'byte-obsolete-info) 480 (setq desc (concat alias-desc
481 (if (memq (aref desc 0)
482 '(?a ?e ?i ?o ?u))
483 ", an " ", a ")
484 desc)))
485 (aset desc 0 (upcase (aref desc 0))) ; capitalize
486 (insert-face desc 'section-heading)
487 (and (eq ftype 'autoload)
488 (insert (format ", (autoloaded from \"%s\")"
489 (nth 1 fndef))))
490 ;; #### - should also show local binding in some other
491 ;; buffer so that this function can be used in place of
492 ;; describe-function and describe-variable.
493 (if (setq keys (where-is-internal symbol (current-global-map)
494 nil nil nil))
495 (insert (format ", (globally bound to %s)"
496 (mapconcat
497 #'(lambda (x)
498 (format "\"%s\""
499 (key-description x)))
500 (sort keys #'(lambda (x y)
501 (< (length x) (length y))))
502 ", "))))
503 (insert ":\n\n")
504 (setq beg (point)
687 doc (or (documentation symbol) "function not documented")) 505 doc (or (documentation symbol) "function not documented"))
688 (save-excursion 506 (insert-face "arguments: " 'heading)
689 (set-buffer hypropos-help-buf) 507 (cond ((eq ftype 'lambda)
690 (goto-char (point-max)) 508 (princ (or (nth 1 fndef) "()")))
691 (setq standard-output (current-buffer)) 509 ((eq ftype 'bytecode)
692 (hypropos-insert-section-heading alias-desc desc) 510 (princ (or (if (fboundp 'compiled-function-arglist)
693 (and (eq symtype 'autoload) 511 (compiled-function-arglist fndef)
694 (insert (format ", (autoloaded from \"%s\")" 512 (aref fndef 0)) "()")))
695 (nth 1 newsym)))) 513 ((and (eq ftype 'subr)
696 (insert ":\n") 514 (string-match
697 (if local 515 "[\n\t ]*\narguments: ?\\((.*)\\)\n?\\'"
698 (hypropos-insert-keybinding 516 doc))
699 (where-is-internal symbol (list local) nil nil nil) 517 (insert (substring doc
700 "locally")) 518 (match-beginning 1)
701 (hypropos-insert-keybinding 519 (match-end 1)))
702 (where-is-internal symbol (list global) nil nil nil) 520 (setq doc (substring doc 0 (match-beginning 0))))
703 "globally") 521 (t (princ "[not available]")))
704 (insert "\n") 522 (insert "\n\n")
705 (if obsolete 523 (let ((new
706 (hypropos-insert-face 524 ;; cookbook from bytecomp.el
707 (format "%s is an obsolete function; %s\n\n" symbol 525 (get symbol 'byte-obsolete-info)))
708 (if (stringp (car obsolete)) 526 (and new
709 (car obsolete) 527 (insert-face
710 (format "use `%s' instead." (car obsolete)))) 528 (format "%s is an obsolete function; %s\n\n" symbol
711 'warning)) 529 (if (stringp (car new))
712 (setq beg (point)) 530 (car new)
713 (insert-face "arguments: " 'heading) 531 (format "use %s instead." (car new))))
714 (cond ((eq symtype 'lambda) 532 'warning)))
715 (princ (or (nth 1 newsym) "()"))) 533 (insert-face doc 'documentation)
716 ((eq symtype 'bytecode) 534 (indent-rigidly beg (point) 1)
717 (princ (or (aref newsym 0) "()"))) 535 (insert"\n\n")
718 ((and (eq symtype 'subr) 536 ))
719 (string-match
720 "[\n\t ]*\narguments: ?\\((.*)\\)\n?\\'"
721 doc))
722 (insert (substring doc
723 (match-beginning 1)
724 (match-end 1)))
725 (setq doc (substring doc 0 (match-beginning 0))))
726 ((and (eq symtype 'subr)
727 (string-match
728 "[\n\t ]*([^\n\t )]+[\t ]*\\([^\n)]+\\)?)\\(:[\t ]*\\|\n?\\'\\)"
729 doc))
730 (insert "("
731 (if (match-end 1)
732 (substring doc
733 (match-beginning 1)
734 (match-end 1)))
735 ")")
736 (setq doc (substring doc (match-end 0))))
737 (t (princ "[not available]")))
738 (insert "\n\n")
739 (hypropos-insert-face doc)
740 (insert "\n")
741 (indent-rigidly beg (point) 2))))
742 ;; variable ----------------------------------------------------------
743 (and (memq 'variable type) 537 (and (memq 'variable type)
744 (or (boundp symbol) (default-boundp symbol)) 538 (boundp symbol)
745 (progn 539 (progn
746 (setq ok t) 540 (setq ok t)
747 (setq aliases (hypropos-get-alias symbol 541 (insert-face (if (user-variable-p symbol)
748 'variable-alias 542 "User variable"
749 'variable-alias 543 "Variable")
750 'variable-alias) 544 'section-heading)
751 newsym (car aliases) 545 (and (local-variable-p symbol nil t)
752 alias-desc (cdr aliases)) 546 (insert ", local when set"))
753 (setq symtype (or (local-variable-p newsym (current-buffer)) 547 (insert ":\n\n")
754 (and (local-variable-p newsym 548 (setq beg (point)
755 (current-buffer) t) 549 val (prin1-to-string (symbol-value symbol))
756 'auto-local)) 550 doc (or (documentation-property
757 desc (concat (if (user-variable-p newsym) 551 symbol 'variable-documentation)
758 "user variable"
759 "variable")
760 (cond ((eq symtype t) ", buffer-local")
761 ((eq symtype 'auto-local)
762 ", local when set")))
763 local (and (boundp newsym)
764 (symbol-value newsym))
765 local-str (and (boundp newsym)
766 (prin1-to-string local))
767 global (and (eq symtype t)
768 (default-boundp newsym)
769 (default-value newsym))
770 global-str (and (eq symtype t)
771 (default-boundp newsym)
772 (prin1-to-string global))
773 obsolete (get symbol 'byte-obsolete-variable)
774 doc (or (documentation-property symbol
775 'variable-documentation)
776 "variable not documented")) 552 "variable not documented"))
777 (save-excursion 553
778 (set-buffer hypropos-help-buf) 554 (let ((ob (get symbol 'byte-obsolete-variable)))
779 (goto-char (point-max)) 555 (setq obsolete
780 (setq standard-output (current-buffer)) 556 (and ob (format "%s is an obsolete variable; %s\n\n"
781 (hypropos-insert-section-heading alias-desc desc) 557 symbol
782 (insert ":\n\n") 558 (if (stringp ob)
783 (setq beg (point)) 559 ob
784 (if obsolete 560 (format "use %s instead." ob))))))
785 (hypropos-insert-face 561 ;; generally, the value of the variable is short and the
786 (format "%s is an obsolete function; %s\n\n" symbol 562 ;; documentation of the variable long, so it's desirable
787 (if (stringp obsolete) 563 ;; to see all of the value and the start of the
788 obsolete 564 ;; documentation. Some variables, though, have huge and
789 (format "use `%s' instead." obsolete))) 565 ;; nearly meaningless values that force you to page
790 'warning)) 566 ;; forward just to find the doc string. That is
791 ;; generally, the value of the variable is short and the 567 ;; undesirable.
792 ;; documentation of the variable long, so it's desirable 568 (if (< (length val) 69) ; 80 cols. docstrings assume this.
793 ;; to see all of the value and the start of the 569 (progn (insert-face "value: " 'heading)
794 ;; documentation. Some variables, though, have huge and 570 (insert (format "%s\n\n" val))
795 ;; nearly meaningless values that force you to page 571 (and obsolete (insert-face obsolete 'warning))
796 ;; forward just to find the doc string. That is 572 (insert-face doc 'documentation))
797 ;; undesirable. 573 (insert "(see below for value)\n\n")
798 (if (and (or (null local-str) (< (length local-str) 69)) 574 (and obsolete (insert-face obsolete 'warning))
799 (or (null global-str) (< (length global-str) 69))) 575 (insert-face doc 'documentation)
800 ; 80 cols. docstrings assume this. 576 (insert "\n\n")
801 (progn (insert-face "value: " 'heading) 577 (insert-face "value: " 'heading)
802 (insert (or local-str "is void")) 578 (if hypropos-prettyprint-long-values
803 (if (eq symtype t) 579 (let ((pp-print-readably nil))
804 (progn 580 (pprint (symbol-value symbol)))
805 (insert "\n") 581 (insert val)))
806 (insert-face "default value: " 'heading) 582 (indent-rigidly beg (point) 2)
807 (insert (or global-str "is void")))) 583 ))
808 (insert "\n\n")
809 (hypropos-insert-face doc))
810 (hypropos-insert-value "value: " 'local-str local)
811 (if (eq symtype t)
812 (progn
813 (insert ", ")
814 (hypropos-insert-value "default-value: "
815 'global-str global)))
816 (insert "\n\n")
817 (hypropos-insert-face doc)
818 (if local-str
819 (progn
820 (newline 3) (delete-blank-lines) (newline 1)
821 (insert-face "value: " 'heading)
822 (if hypropos-prettyprint-long-values
823 (condition-case nil
824 (let ((pp-print-readably nil)) (pprint local))
825 (error (insert local-str)))
826 (insert local-str))))
827 (if global-str
828 (progn
829 (newline 3) (delete-blank-lines) (newline 1)
830 (insert-face "default value: " 'heading)
831 (if hypropos-prettyprint-long-values
832 (condition-case nil
833 (let ((pp-print-readably nil)) (pprint global))
834 (error (insert global-str)))
835 (insert global-str)))))
836 (indent-rigidly beg (point) 2))))
837 ;; face --------------------------------------------------------------
838 (and (memq 'face type) 584 (and (memq 'face type)
839 (find-face symbol) 585 (find-face symbol)
840 (progn 586 (progn
841 (setq ok t) 587 (setq ok t)
842 (copy-face symbol 'hypropos-temp-face 'global)
843 (mapcar (function
844 (lambda (property)
845 (setq symtype (face-property-instance symbol
846 property))
847 (if symtype
848 (set-face-property 'hypropos-temp-face
849 property
850 symtype))))
851 built-in-face-specifiers)
852 (setq font (cons (face-property-instance symbol 'font nil 0 t)
853 (face-property-instance symbol 'font))
854 fore (cons (face-foreground-instance symbol nil 0 t)
855 (face-foreground-instance symbol))
856 back (cons (face-background-instance symbol nil 0 t)
857 (face-background-instance symbol))
858 undl (cons (face-underline-p symbol nil 0 t)
859 (face-underline-p symbol))
860 doc (face-doc-string symbol))
861 ;; #### - add some code here 588 ;; #### - add some code here
862 (save-excursion 589 (insert "Face documentation is \"To be implemented.\"\n\n")
863 (set-buffer hypropos-help-buf) 590 )
864 (setq standard-output (current-buffer)) 591 )
865 (hypropos-insert-section-heading "Face:\n\n ") 592 (or ok (insert-face "symbol is not currently bound" 'heading)))
866 (insert-face "ABCDEFHIJKLMNOPQRSTUVWXYZ abcdefhijklmnopqrstuvwxyz 0123456789"
867 'hypropos-temp-face)
868 (newline 2)
869 (insert-face " Font: " 'heading)
870 (insert (format (if (numberp (car font)) "(%s)\n" "%s\n")
871 (and (cdr font)
872 (font-instance-name (cdr font)))))
873 (insert-face " Foreground: " 'heading)
874 (insert (format (if (numberp (car fore)) "(%s)\n" "%s\n")
875 (and (cdr fore)
876 (color-instance-name (cdr fore)))))
877 (insert-face " Background: " 'heading)
878 (insert (format (if (numberp (car back)) "(%s)\n" "%s\n")
879 (and (cdr back)
880 (color-instance-name (cdr back)))))
881 (insert-face " Underline: " 'heading)
882 (insert (format (if (numberp (car undl)) "(%s)\n" "%s\n")
883 (cdr undl)))
884 (if doc
885 (progn
886 (newline)
887 (setq beg (point))
888 (insert doc)
889 (indent-rigidly beg (point) 2))))))
890 ;; not bound & property list -----------------------------------------
891 (or ok
892 (save-excursion
893 (set-buffer hypropos-help-buf)
894 (hypropos-insert-section-heading
895 "symbol is not currently bound\n")))
896 (if (and (setq symtype (symbol-plist symbol))
897 (or (> (length symtype) 2)
898 (not (memq 'variable-documentation symtype))))
899 (save-excursion
900 (set-buffer hypropos-help-buf)
901 (goto-char (point-max))
902 (setq standard-output (current-buffer))
903 (hypropos-insert-section-heading "property-list:\n\n")
904 (while symtype
905 (if (memq (car symtype)
906 '(variable-documentation byte-obsolete-info))
907 (setq symtype (cdr symtype))
908 (insert-face (concat " " (symbol-name (car symtype))
909 ": ")
910 'heading)
911 (setq symtype (cdr symtype))
912 (indent-to 32)
913 (insert (prin1-to-string (car symtype)) "\n"))
914 (setq symtype (cdr symtype)))))))
915 (save-excursion
916 (set-buffer hypropos-help-buf)
917 (goto-char (point-min)) 593 (goto-char (point-min))
918 ;; pop up window and shrink it if it's wasting space 594 ;; pop up window and shrink it if it's wasting space
919 (if hypropos-shrink-window 595 (shrink-window-if-larger-than-buffer
920 (shrink-window-if-larger-than-buffer 596 (display-buffer (current-buffer)))
921 (display-buffer (current-buffer))) 597 (hyper-help-mode)) )
922 (display-buffer (current-buffer))) 598 (setq hypropos-currently-showing symbol))
923 (hyper-help-mode))
924 (setq hypropos-currently-showing symbol)))
925 599
926 ; ----------------------------------------------------------------------------- 600 ; -----------------------------------------------------------------------------
927 601
928 (defun hyper-help-mode () 602 (defun hyper-help-mode ()
929 "Major mode for hypertext XEmacs help. In this mode, you can quickly 603 "Major mode for hypertext XEmacs help. In this mode, you can quickly
1060 ;; !@(*$^%%# stupid backquote implementation!!! 734 ;; !@(*$^%%# stupid backquote implementation!!!
1061 (skip-chars-forward "`") 735 (skip-chars-forward "`")
1062 (point))) 736 (point)))
1063 (en (progn 737 (en (progn
1064 (skip-syntax-forward "w_") 738 (skip-syntax-forward "w_")
1065 (skip-chars-backward ".':") ; : for Local Variables 739 (skip-chars-backward ".")
1066 (point)))) 740 (point))))
1067 (and (not (eq st en)) 741 (and (not (eq st en))
1068 (intern-soft (buffer-substring st en)))))))) 742 (intern-soft (buffer-substring st en))))))))
1069 743
1070 (defun hypropos-where-is (symbol) 744 (defun hypropos-where-is (symbol)
1078 (cond ((not (fboundp fn)) 752 (cond ((not (fboundp fn))
1079 (error "%S is not a function" fn)) 753 (error "%S is not a function" fn))
1080 (t (call-interactively fn)))) 754 (t (call-interactively fn))))
1081 755
1082 ;;;###autoload 756 ;;;###autoload
1083 (defun hyper-set-variable (var val &optional this-ref-buffer) 757 (defun hypropos-set-variable (var val)
1084 (interactive
1085 (let ((var (hypropos-read-variable-symbol
1086 (if (hypropos-follow-ref-buffer current-prefix-arg)
1087 "In ref buffer, set user option"
1088 "Set user option")
1089 'user-variable-p)))
1090 (list var (hypropos-read-variable-value var) current-prefix-arg)))
1091 (hypropos-set-variable var val this-ref-buffer))
1092
1093 ;;;###autoload
1094 (defun hypropos-set-variable (var val &optional this-ref-buffer)
1095 "Interactively set the variable on the current line." 758 "Interactively set the variable on the current line."
1096 (interactive 759 (interactive
1097 (let ((var (hypropos-this-symbol))) 760 (let ((var (save-excursion
1098 (or (and var (boundp var)) 761 (and (eq major-mode 'hypropos-help-mode)
1099 (and (setq var (and (eq major-mode 'hyper-help-mode) 762 (goto-char (point-min)))
1100 (save-excursion 763 (hypropos-this-symbol))))
1101 (goto-char (point-min)) 764 (or (boundp var)
1102 (hypropos-this-symbol)))) 765 (setq var (completing-read "Set variable: "
1103 (boundp var)) 766 obarray 'boundp t)))
1104 (setq var nil)) 767 (hypropos-get-doc var t)
1105 (list var (hypropos-read-variable-value var)))) 768 (list var
1106 (and var 769 (let ((prop (get var 'variable-interactive))
1107 (boundp var) 770 (print-readably t)
1108 (progn 771 (val (symbol-value var)))
1109 (if (hypropos-follow-ref-buffer this-ref-buffer) 772 (if prop
1110 (save-excursion 773 (call-interactively (list 'lambda '(arg)
1111 (set-buffer hypropos-ref-buffer) 774 (list 'interactive prop)
1112 (set var val)) 775 'arg))
1113 (set var val)) 776 (eval-minibuffer
1114 (hypropos-get-doc var t '(variable) this-ref-buffer)))) 777 (format "Set `%s' to value (evaluated): " var)
1115 778 (format (if (or (consp val)
1116 (defun hypropos-read-variable-value (var &optional this-ref-buffer) 779 (and (symbolp val)
1117 (and var 780 (not (memq val '(t nil)))))
1118 (boundp var) 781 "'%s" "%s")
1119 (let ((prop (get var 'variable-interactive)) 782 (prin1-to-string val))))))
1120 (print-readably t) 783 ))
1121 val str) 784 (set var val)
1122 (hypropos-get-doc var t '(variable) current-prefix-arg) 785 (hypropos-get-doc var t))
1123 (if prop
1124 (call-interactively (list 'lambda '(arg)
1125 (list 'interactive prop)
1126 'arg))
1127 (setq val (if (hypropos-follow-ref-buffer this-ref-buffer)
1128 (save-excursion
1129 (set-buffer hypropos-ref-buffer)
1130 (symbol-value var))
1131 (symbol-value var))
1132 str (prin1-to-string val))
1133 (eval-minibuffer
1134 (format "Set %s `%s' to value (evaluated): "
1135 (if (user-variable-p var) "user option" "Variable")
1136 var)
1137 (condition-case nil
1138 (progn
1139 (read str)
1140 (format (if (or (consp val)
1141 (and (symbolp val)
1142 (not (memq val '(t nil)))))
1143 "'%s" "%s")
1144 str))
1145 (error nil)))))))
1146 786
1147 ;; ---------------------------------------------------------------------- ;; 787 ;; ---------------------------------------------------------------------- ;;
1148 788
1149 (defun hypropos-find-tag (&optional tag-name) 789 (defun hypropos-find-tag (&optional tag-name)
1150 "Find the tag for the symbol on the current line in other window. In 790 "Find the tag for the symbol on the current line in other window. In
1243 (popup-menu hypropos-menu))) 883 (popup-menu hypropos-menu)))
1244 884
1245 (provide 'hyper-apropos) 885 (provide 'hyper-apropos)
1246 886
1247 ;; end of hyper-apropos.el 887 ;; end of hyper-apropos.el
888