+;; replacement for `princ' that puts the text in the specified face,
+;; if possible
+(defun Help-princ-face (object face)
+ (cond ((bufferp standard-output)
+ (let ((opoint (point standard-output)))
+ (princ object)
+ (put-nonduplicable-text-property opoint (point standard-output)
+ 'face face standard-output)))
+ ((markerp standard-output)
+ (let ((buf (marker-buffer standard-output))
+ (pos (marker-position standard-output)))
+ (princ object)
+ (put-nonduplicable-text-property
+ pos (marker-position standard-output) 'face face buf)))
+ (t princ object)))
+
+;; replacement for `prin1' that puts the text in the specified face,
+;; if possible
+(defun Help-prin1-face (object face)
+ (cond ((bufferp standard-output)
+ (let ((opoint (point standard-output)))
+ (prin1 object)
+ (put-nonduplicable-text-property opoint (point standard-output)
+ 'face face standard-output)))
+ ((markerp standard-output)
+ (let ((buf (marker-buffer standard-output))
+ (pos (marker-position standard-output)))
+ (prin1 object)
+ (put-nonduplicable-text-property
+ pos (marker-position standard-output) 'face face buf)))
+ (t prin1 object)))
+
+(defvar help-symbol-regexp
+ (let ((sym-char "[+a-zA-Z0-9_:*]")
+ (sym-char-no-dash "[-+a-zA-Z0-9_:*]"))
+ (concat "\\("
+ ;; a symbol with a - in it.
+ "\\<\\(" sym-char-no-dash "+\\(-" sym-char-no-dash "+\\)+\\)\\>"
+ "\\|"
+ "`\\(" sym-char "+\\)'"
+ "\\)")))
+
+(defun help-symbol-run-function-1 (ev ex fun)
+ (let ((help-sticky-window
+ ;; if we were called from a help buffer, make sure the new help
+ ;; goes in the same window.
+ (if (and (event-buffer ev)
+ (symbol-value-in-buffer 'help-window-config
+ (event-buffer ev)))
+ (event-window ev)
+ help-sticky-window)))
+ (funcall fun (extent-property ex 'help-symbol))))
+
+(defun help-symbol-run-function (fun)
+ (let ((ex (extent-at-event last-popup-menu-event 'help-symbol)))
+ (when ex
+ (help-symbol-run-function-1 last-popup-menu-event ex fun))))
+
+(defvar help-symbol-function-context-menu
+ '(["View %_Documentation" (help-symbol-run-function 'describe-function)]
+ ["Find %_Function Source" (help-symbol-run-function 'find-function)]
+ ["Find %_Tag" (help-symbol-run-function 'find-tag)]
+ ))
+
+(defvar help-symbol-variable-context-menu
+ '(["View %_Documentation" (help-symbol-run-function 'describe-variable)]
+ ["Find %_Variable Source" (help-symbol-run-function 'find-variable)]
+ ["Find %_Tag" (help-symbol-run-function 'find-tag)]
+ ))
+
+(defvar help-symbol-function-and-variable-context-menu
+ '(["View Function %_Documentation" (help-symbol-run-function
+ 'describe-function)]
+ ["View Variable D%_ocumentation" (help-symbol-run-function
+ 'describe-variable)]
+ ["Find %_Function Source" (help-symbol-run-function 'find-function)]
+ ["Find %_Variable Source" (help-symbol-run-function 'find-variable)]
+ ["Find %_Tag" (help-symbol-run-function 'find-tag)]
+ ))
+
+(defun frob-help-extents (buffer)
+ ;; Look through BUFFER, starting at the buffer's point and continuing
+ ;; till end of file, and find documented functions and variables.
+ ;; any such symbol found is tagged with an extent, that sets up these
+ ;; properties:
+ ;; 1. mouse-face is 'highlight (so the extent gets highlighted on mouse over)
+ ;; 2. help-symbol is the name of the symbol.
+ ;; 3. face is 'hyper-apropos-hyperlink.
+ ;; 4. context-menu is a list of context menu items, specific to whether
+ ;; the symbol is a function, variable, or both.
+ ;; 5. activate-function will cause the function or variable to be described,
+ ;; replacing the existing help contents.
+ (save-excursion
+ (set-buffer buffer)
+ (let (b e name)
+ (while (re-search-forward help-symbol-regexp nil t)
+ (setq b (or (match-beginning 2) (match-beginning 4)))
+ (setq e (or (match-end 2) (match-end 4)))
+ (setq name (buffer-substring b e))
+ (let* ((sym (intern-soft name))
+ (var (and sym (boundp sym)
+ (documentation-property sym
+ 'variable-documentation t)))
+ (fun (and sym (fboundp sym)
+ (documentation sym t))))
+ (when (or var fun)
+ (let ((ex (make-extent b e)))
+ (set-extent-property ex 'mouse-face 'highlight)
+ (set-extent-property ex 'help-symbol sym)
+ (set-extent-property ex 'face 'hyper-apropos-hyperlink)
+ (set-extent-property
+ ex 'context-menu
+ (cond ((and var fun)
+ help-symbol-function-and-variable-context-menu)
+ (var help-symbol-variable-context-menu)
+ (fun help-symbol-function-context-menu)))
+ (set-extent-property
+ ex 'activate-function
+ (if fun
+ #'(lambda (ev ex)
+ (help-symbol-run-function-1 ev ex 'describe-function))
+ #'(lambda (ev ex)
+ (help-symbol-run-function-1 ev ex 'describe-variable))))
+ ))))))) ;; 11 parentheses!
+