comparison lisp/help.el @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
238 "Exit from help mode, possibly restoring the previous window configuration. 238 "Exit from help mode, possibly restoring the previous window configuration.
239 If the optional argument BURY is non-nil, the help buffer is buried, 239 If the optional argument BURY is non-nil, the help buffer is buried,
240 otherwise it is killed." 240 otherwise it is killed."
241 (interactive) 241 (interactive)
242 (let ((buf (current-buffer))) 242 (let ((buf (current-buffer)))
243 (cond ((frame-property (selected-frame) 'help-window-config) 243 (cond (help-window-config
244 (set-window-configuration 244 (set-window-configuration help-window-config))
245 (frame-property (selected-frame) 'help-window-config))
246 (set-frame-property (selected-frame) 'help-window-config nil))
247 ((not (one-window-p)) 245 ((not (one-window-p))
248 (delete-window))) 246 (delete-window)))
249 (if bury 247 (if bury
250 (bury-buffer buf) 248 (bury-buffer buf)
251 (kill-buffer buf)))) 249 (kill-buffer buf))))
478 ;; #### BEFORE you rush to make this a macro, think about backward 476 ;; #### BEFORE you rush to make this a macro, think about backward
479 ;; compatibility. The right way would be to create a macro with 477 ;; compatibility. The right way would be to create a macro with
480 ;; another name (which is a shame, because w-d-h-b is a perfect name 478 ;; another name (which is a shame, because w-d-h-b is a perfect name
481 ;; for a macro) that uses with-displaying-help-buffer internally. 479 ;; for a macro) that uses with-displaying-help-buffer internally.
482 480
481 (defcustom mode-for-help 'help-mode
482 "*Mode that help buffers are put into.")
483
484 (defvar help-sticky-window nil
485 ;; Window into which help buffers will be displayed, rather than
486 ;; always searching for a new one. This is INTERNAL and liable to
487 ;; change its interface and/or name at any moment. It should be
488 ;; bound, not set.
489 )
490
491 (defvar help-window-config nil)
492
493 (make-variable-buffer-local 'help-window-config)
494 (put 'help-window-config 'permanent-local t)
495
483 (defun with-displaying-help-buffer (thunk &optional name) 496 (defun with-displaying-help-buffer (thunk &optional name)
484 "Form which makes a help buffer with given NAME and evaluates BODY there. 497 "Form which makes a help buffer with given NAME and evaluates BODY there.
485 The actual name of the buffer is generated by the function `help-buffer-name'." 498 The actual name of the buffer is generated by the function `help-buffer-name'."
486 (let* ((winconfig (current-window-configuration)) 499 (let* ((winconfig (current-window-configuration))
487 (was-one-window (one-window-p)) 500 (was-one-window (one-window-p))
490 (not (and (windows-of-buffer buffer-name) ;shortcut 503 (not (and (windows-of-buffer buffer-name) ;shortcut
491 (memq (selected-frame) 504 (memq (selected-frame)
492 (mapcar 'window-frame 505 (mapcar 'window-frame
493 (windows-of-buffer buffer-name))))))) 506 (windows-of-buffer buffer-name)))))))
494 (help-register-and-maybe-prune-excess buffer-name) 507 (help-register-and-maybe-prune-excess buffer-name)
495 (prog1 (with-output-to-temp-buffer buffer-name 508 ;; if help-sticky-window is bogus or deleted, get rid of it.
496 (prog1 (funcall thunk) 509 (if (and help-sticky-window (or (not (windowp help-sticky-window))
497 (save-excursion 510 (not (window-live-p help-sticky-window))))
498 (set-buffer standard-output) 511 (setq help-sticky-window nil))
499 (help-mode)))) 512 (prog1
513 (let ((temp-buffer-show-function
514 (if help-sticky-window
515 #'(lambda (buffer)
516 (set-window-buffer help-sticky-window buffer))
517 temp-buffer-show-function)))
518 (with-output-to-temp-buffer buffer-name
519 (prog1 (funcall thunk)
520 (save-excursion
521 (set-buffer standard-output)
522 (funcall mode-for-help)))))
500 (let ((helpwin (get-buffer-window buffer-name))) 523 (let ((helpwin (get-buffer-window buffer-name)))
501 (when helpwin 524 (when helpwin
502 (with-current-buffer (window-buffer helpwin) 525 ;; If the *Help* buffer is already displayed on this
503 ;; If the *Help* buffer is already displayed on this 526 ;; frame, don't override the previous configuration
504 ;; frame, don't override the previous configuration 527 (when help-not-visible
505 (when help-not-visible 528 (with-current-buffer (window-buffer helpwin)
506 (set-frame-property (selected-frame) 529 (setq help-window-config winconfig)))
507 'help-window-config winconfig)))
508 (when help-selects-help-window 530 (when help-selects-help-window
509 (select-window helpwin)) 531 (select-window helpwin))
510 (cond ((eq helpwin (selected-window)) 532 (cond ((eq helpwin (selected-window))
511 (display-message 'command 533 (display-message 'command
512 (substitute-command-keys "Type \\[help-mode-quit] to remove help window, \\[scroll-up] to scroll the help."))) 534 (substitute-command-keys "Type \\[help-mode-quit] to remove help window, \\[scroll-up] to scroll the help.")))
728 (interactive) 750 (interactive)
729 (if (and (boundp 'Installation-string) 751 (if (and (boundp 'Installation-string)
730 (stringp Installation-string)) 752 (stringp Installation-string))
731 (with-displaying-help-buffer 753 (with-displaying-help-buffer
732 (lambda () 754 (lambda ()
733 (princ Installation-string)) 755 (princ
756 (if (fboundp 'decode-coding-string)
757 (decode-coding-string Installation-string 'automatic-conversion)
758 Installation-string)))
734 "Installation") 759 "Installation")
735 (error "No Installation information available."))) 760 (error "No Installation information available.")))
736 761
737 (defun view-emacs-news () 762 (defun view-emacs-news ()
738 "Display info on recent changes to XEmacs." 763 "Display info on recent changes to XEmacs."
740 (find-file (locate-data-file "NEWS"))) 765 (find-file (locate-data-file "NEWS")))
741 766
742 (defun xemacs-www-page () 767 (defun xemacs-www-page ()
743 "Go to the XEmacs World Wide Web page." 768 "Go to the XEmacs World Wide Web page."
744 (interactive) 769 (interactive)
745 (if (boundp 'browse-url-browser-function) 770 (if (fboundp 'browse-url)
746 (funcall browse-url-browser-function "http://www.xemacs.org/") 771 (browse-url "http://www.xemacs.org/")
747 (error "xemacs-www-page requires browse-url"))) 772 (error "xemacs-www-page requires browse-url")))
748 773
749 (defun xemacs-www-faq () 774 (defun xemacs-www-faq ()
750 "View the latest and greatest XEmacs FAQ using the World Wide Web." 775 "View the latest and greatest XEmacs FAQ using the World Wide Web."
751 (interactive) 776 (interactive)
752 (if (boundp 'browse-url-browser-function) 777 (if (fboundp 'browse-url)
753 (funcall browse-url-browser-function 778 (browse-url "http://www.xemacs.org/faq/index.html")
754 "http://www.xemacs.org/faq/index.html")
755 (error "xemacs-www-faq requires browse-url"))) 779 (error "xemacs-www-faq requires browse-url")))
756 780
757 (defun xemacs-local-faq () 781 (defun xemacs-local-faq ()
758 "View the local copy of the XEmacs FAQ. 782 "View the local copy of the XEmacs FAQ.
759 If you have access to the World Wide Web, you should use `xemacs-www-faq' 783 If you have access to the World Wide Web, you should use `xemacs-www-faq'
917 (forward-char 1) 941 (forward-char 1)
918 (let (obj) 942 (let (obj)
919 (setq obj (read (current-buffer))) 943 (setq obj (read (current-buffer)))
920 (and (symbolp obj) (fboundp obj) obj))))))) 944 (and (symbolp obj) (fboundp obj) obj)))))))
921 945
946 (defun function-at-event (event)
947 "Return the function whose name is around the position of EVENT.
948 EVENT should be a mouse event. When calling from a popup or context menu,
949 use `last-popup-menu-event' to find out where the mouse was clicked.
950 \(You cannot use (interactive \"e\"), unfortunately. This returns a
951 misc-user event.)
952
953 If the event contains no position, or the position is not over text, or
954 there is no function around that point, nil is returned."
955 (if (and event (event-buffer event) (event-point event))
956 (save-excursion
957 (set-buffer (event-buffer event))
958 (goto-char (event-point event))
959 (function-at-point))))
960
922 ;; Default to nil for the non-hackers? Not until we find a way to 961 ;; Default to nil for the non-hackers? Not until we find a way to
923 ;; distinguish hackers from non-hackers automatically! 962 ;; distinguish hackers from non-hackers automatically!
924 (defcustom describe-function-show-arglist t 963 (defcustom describe-function-show-arglist t
925 "*If non-nil, describe-function will show its arglist, 964 "*If non-nil, describe-function will show its arglist,
926 unless the function is autoloaded." 965 unless the function is autoloaded."
1060 (void-function "")))) 1099 (void-function ""))))
1061 (if (and strip-arglist 1100 (if (and strip-arglist
1062 (string-match "[\n\t ]*\narguments: ?(\\(.*\\))\n?\\'" doc)) 1101 (string-match "[\n\t ]*\narguments: ?(\\(.*\\))\n?\\'" doc))
1063 (setq doc (substring doc 0 (match-beginning 0)))) 1102 (setq doc (substring doc 0 (match-beginning 0))))
1064 doc)) 1103 doc))
1104 ; (let ((name-char "[-+a-zA-Z0-9_*]") (sym-char "[-+a-zA-Z0-9_:*]"))
1105 ; (list
1106 ; ;;
1107 ; ;; The symbol itself.
1108 ; (list (concat "\\`\\(" name-char "+\\)\\(:\\)?")
1109 ; '(1 (if (match-beginning 2)
1110 ; 'font-lock-function-name-face
1111 ; 'font-lock-variable-name-face)
1112 ; nil t))
1113 ; ;;
1114 ; ;; Words inside `' which tend to be symbol names.
1115 ; (list (concat "`\\(" sym-char sym-char "+\\)'")
1116 ; 1 '(prog1
1117 ; 'font-lock-reference-face
1118 ; (add-list-mode-item (match-beginning 1)
1119 ; (match-end 1)
1120 ; nil
1121 ; 'help-follow-reference))
1122 ; t)
1123 ; ;;
1124 ; ;; CLisp `:' keywords as references.
1125 ; (list (concat "\\<:" sym-char "+\\>") 0 'font-lock-reference-face t)))
1126
1127 (defvar help-symbol-regexp
1128 (let ((sym-char "[+a-zA-Z0-9_:*]")
1129 (sym-char-no-dash "[-+a-zA-Z0-9_:*]"))
1130 (concat "\\("
1131 ;; a symbol with a - in it.
1132 "\\<\\(" sym-char-no-dash "+\\(-" sym-char-no-dash "+\\)+\\)\\>"
1133 "\\|"
1134 "`\\(" sym-char "+\\)'"
1135 "\\)")))
1136
1137 (defun help-symbol-run-function-1 (ev ex fun)
1138 (let ((help-sticky-window
1139 ;; if we were called from a help buffer, make sure the new help
1140 ;; goes in the same window.
1141 (if (and (event-buffer ev)
1142 (symbol-value-in-buffer 'help-window-config
1143 (event-buffer ev)))
1144 (event-window ev)
1145 help-sticky-window)))
1146 (funcall fun (extent-property ex 'help-symbol))))
1147
1148 (defun help-symbol-run-function (fun)
1149 (let ((ex (extent-at-event last-popup-menu-event 'help-symbol)))
1150 (when ex
1151 (help-symbol-run-function-1 last-popup-menu-event ex fun))))
1152
1153 (defvar help-symbol-function-context-menu
1154 '("---"
1155 ["View %_Documentation" (help-symbol-run-function 'describe-function)]
1156 ["Find %_Function Source" (help-symbol-run-function 'find-function)]
1157 ))
1158
1159 (defvar help-symbol-variable-context-menu
1160 '("---"
1161 ["View %_Documentation" (help-symbol-run-function 'describe-variable)]
1162 ["Find %_Variable Source" (help-symbol-run-function 'find-variable)]
1163 ))
1164
1165 (defvar help-symbol-function-and-variable-context-menu
1166 '("---"
1167 ["View Function %_Documentation" (help-symbol-run-function
1168 'describe-function)]
1169 ["View Variable D%_ocumentation" (help-symbol-run-function
1170 'describe-variable)]
1171 ["Find %_Function Source" (help-symbol-run-function 'find-function)]
1172 ["Find %_Variable Source" (help-symbol-run-function 'find-variable)]
1173 ))
1174
1175 (defun frob-help-extents (buffer)
1176 ;; Look through BUFFER, starting at the buffer's point and continuing
1177 ;; till end of file, and find documented functions and variables.
1178 ;; any such symbol found is tagged with an extent, that sets up these
1179 ;; properties:
1180 ;; 1. mouse-face is 'highlight (so the extent gets highlighted on mouse over)
1181 ;; 2. help-symbol is the name of the symbol.
1182 ;; 3. context-menu is a list of context menu items, specific to whether
1183 ;; the symbol is a function, variable, or both.
1184 ;; 4. activate-function will cause the function or variable to be described,
1185 ;; replacing the existing help contents.
1186 (save-excursion
1187 (set-buffer buffer)
1188 (let (b e name)
1189 (while (re-search-forward help-symbol-regexp nil t)
1190 (setq b (or (match-beginning 2) (match-beginning 4)))
1191 (setq e (or (match-end 2) (match-end 4)))
1192 (setq name (buffer-substring b e))
1193 (let* ((sym (intern-soft name))
1194 (var (and sym (boundp sym)
1195 (documentation-property sym
1196 'variable-documentation t)))
1197 (fun (and sym (fboundp sym)
1198 (documentation sym t))))
1199 (when (or var fun)
1200 (let ((ex (make-extent b e)))
1201 (set-extent-property ex 'mouse-face 'highlight)
1202 (set-extent-property ex 'help-symbol sym)
1203 (set-extent-property
1204 ex 'context-menu
1205 (cond ((and var fun)
1206 help-symbol-function-and-variable-context-menu)
1207 (var help-symbol-variable-context-menu)
1208 (fun help-symbol-function-context-menu)))
1209 (set-extent-property
1210 ex 'activate-function
1211 (if fun
1212 #'(lambda (ev ex)
1213 (help-symbol-run-function-1 ev ex 'describe-function))
1214 #'(lambda (ev ex)
1215 (help-symbol-run-function-1 ev ex 'describe-variable))))
1216 ))))))) ;; 11 parentheses!
1065 1217
1066 (defun describe-function-1 (function &optional nodoc) 1218 (defun describe-function-1 (function &optional nodoc)
1067 "This function does the work for `describe-function'." 1219 "This function does the work for `describe-function'."
1068 (princ (format "`%s' is " function)) 1220 (princ (format "`%s' is " function))
1069 (let* ((def function) 1221 (let* ((def function)
1156 (terpri) 1308 (terpri)
1157 (terpri)) 1309 (terpri))
1158 (unless (and obsolete aliases) 1310 (unless (and obsolete aliases)
1159 (let ((doc (function-documentation function t))) 1311 (let ((doc (function-documentation function t)))
1160 (princ "Documentation:\n") 1312 (princ "Documentation:\n")
1161 (princ doc) 1313 (let ((oldp (point standard-output))
1314 newp)
1315 (princ doc)
1316 (setq newp (point standard-output))
1317 (goto-char oldp standard-output)
1318 (frob-help-extents standard-output)
1319 (goto-char newp standard-output))
1162 (unless (or (equal doc "") 1320 (unless (or (equal doc "")
1163 (eq ?\n (aref doc (1- (length doc))))) 1321 (eq ?\n (aref doc (1- (length doc)))))
1164 (terpri))))))))) 1322 (terpri)))))))))
1165 1323
1166 1324
1169 (defun describe-function-arglist (function) 1327 (defun describe-function-arglist (function)
1170 (interactive (list (or (function-at-point) 1328 (interactive (list (or (function-at-point)
1171 (error "no function call at point")))) 1329 (error "no function call at point"))))
1172 (message nil) 1330 (message nil)
1173 (message (function-arglist function))) 1331 (message (function-arglist function)))
1174
1175 1332
1176 (defun variable-at-point () 1333 (defun variable-at-point ()
1177 (ignore-errors 1334 (ignore-errors
1178 (with-syntax-table emacs-lisp-mode-syntax-table 1335 (with-syntax-table emacs-lisp-mode-syntax-table
1179 (save-excursion 1336 (save-excursion
1182 (eq (char-syntax (char-after (point))) ?_) 1339 (eq (char-syntax (char-after (point))) ?_)
1183 (forward-sexp -1)) 1340 (forward-sexp -1))
1184 (skip-chars-forward "'") 1341 (skip-chars-forward "'")
1185 (let ((obj (read (current-buffer)))) 1342 (let ((obj (read (current-buffer))))
1186 (and (symbolp obj) (boundp obj) obj)))))) 1343 (and (symbolp obj) (boundp obj) obj))))))
1344
1345 (defun variable-at-event (event)
1346 "Return the variable whose name is around the position of EVENT.
1347 EVENT should be a mouse event. When calling from a popup or context menu,
1348 use `last-popup-menu-event' to find out where the mouse was clicked.
1349 \(You cannot use (interactive \"e\"), unfortunately. This returns a
1350 misc-user event.)
1351
1352 If the event contains no position, or the position is not over text, or
1353 there is no variable around that point, nil is returned."
1354 (if (and event (event-buffer event) (event-point event))
1355 (save-excursion
1356 (set-buffer (event-buffer event))
1357 (goto-char (event-point event))
1358 (variable-at-point))))
1187 1359
1188 (defun variable-obsolete-p (variable) 1360 (defun variable-obsolete-p (variable)
1189 "Return non-nil if VARIABLE is obsolete." 1361 "Return non-nil if VARIABLE is obsolete."
1190 (not (null (get variable 'byte-obsolete-variable)))) 1362 (not (null (get variable 'byte-obsolete-variable))))
1191 1363
1311 (terpri)) 1483 (terpri))
1312 ;; don't bother to print anything if variable is obsolete and aliased. 1484 ;; don't bother to print anything if variable is obsolete and aliased.
1313 (when (or (not obsolete) (not aliases)) 1485 (when (or (not obsolete) (not aliases))
1314 (if doc 1486 (if doc
1315 ;; note: documentation-property calls substitute-command-keys. 1487 ;; note: documentation-property calls substitute-command-keys.
1316 (princ doc) 1488 (let ((oldp (point standard-output))
1489 newp)
1490 (princ doc)
1491 (setq newp (point standard-output))
1492 (goto-char oldp standard-output)
1493 (frob-help-extents standard-output)
1494 (goto-char newp standard-output))
1317 (princ "not documented as a variable.")))) 1495 (princ "not documented as a variable."))))
1318 (terpri))) 1496 (terpri)))
1319 (format "variable `%s'" variable))) 1497 (format "variable `%s'" variable)))
1320 1498
1321 (defun sorted-key-descriptions (keys &optional separator) 1499 (defun sorted-key-descriptions (keys &optional separator)
1444 (let ((string (eval form))) 1622 (let ((string (eval form)))
1445 (if (stringp string) 1623 (if (stringp string)
1446 (with-displaying-help-buffer 1624 (with-displaying-help-buffer
1447 (insert string))))) 1625 (insert string)))))
1448 1626
1449
1450 ;;; help.el ends here 1627 ;;; help.el ends here