comparison lisp/packages/hyper-apropos.el @ 30:ec9a17fef872 r19-15b98

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