aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/button.el45
-rw-r--r--lisp/help-fns.el44
-rw-r--r--lisp/wid-edit.el57
3 files changed, 146 insertions, 0 deletions
diff --git a/lisp/button.el b/lisp/button.el
index d9c36a0375c..941b9fe720a 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -555,6 +555,51 @@ Returns the button found."
555 (interactive "p\nd\nd") 555 (interactive "p\nd\nd")
556 (forward-button (- n) wrap display-message no-error)) 556 (forward-button (- n) wrap display-message no-error))
557 557
558(defun button--describe (properties)
559 "Describe a button's PROPERTIES (an alist) in a *Help* buffer.
560This is a helper function for `button-describe', in order to be possible to
561use `help-setup-xref'.
562
563Each element of PROPERTIES should be of the form (PROPERTY . VALUE)."
564 (help-setup-xref (list #'button--describe properties)
565 (called-interactively-p 'interactive))
566 (with-help-window (help-buffer)
567 (with-current-buffer (help-buffer)
568 (insert (format-message "This button's type is `%s'."
569 (alist-get 'type properties)))
570 (dolist (prop '(action mouse-action))
571 (let ((name (symbol-name prop))
572 (val (alist-get prop properties)))
573 (when (functionp val)
574 (insert "\n\n"
575 (propertize (capitalize name) 'face 'bold)
576 "\nThe " name " of this button is")
577 (if (symbolp val)
578 (progn
579 (insert (format-message " `%s',\nwhich is " val))
580 (describe-function-1 val))
581 (insert "\n")
582 (princ val))))))))
583
584(defun button-describe (&optional button-or-pos)
585 "Display a buffer with information about the button at point.
586
587When called from Lisp, pass BUTTON-OR-POS as the button to describe, or a
588buffer position where a button is present. If BUTTON-OR-POS is nil, the
589button at point is the button to describe."
590 (interactive "d")
591 (let* ((button (cond ((integer-or-marker-p button-or-pos)
592 (button-at button-or-pos))
593 ((null button-or-pos) (button-at (point)))
594 ((overlayp button-or-pos) button-or-pos)))
595 (props (and button
596 (mapcar (lambda (prop)
597 (cons prop (button-get button prop)))
598 '(type action mouse-action)))))
599 (when props
600 (button--describe props)
601 t)))
602
558(provide 'button) 603(provide 'button)
559 604
560;;; button.el ends here 605;;; button.el ends here
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index b9536470631..5a99103f6af 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1769,6 +1769,50 @@ documentation for the major and minor modes of that buffer."
1769 ;; For the sake of IELM and maybe others 1769 ;; For the sake of IELM and maybe others
1770 nil) 1770 nil)
1771 1771
1772;; Widgets.
1773
1774(defvar describe-widget-functions
1775 '(button-describe widget-describe)
1776 "A list of functions for `describe-widget' to call.
1777Each function should take one argument, a buffer position, and return
1778non-nil if it described a widget at that position.")
1779
1780;;;###autoload
1781(defun describe-widget (&optional pos)
1782 "Display a buffer with information about a widget.
1783You can use this command to describe buttons (e.g., the links in a *Help*
1784buffer), editable fields of the customization buffers, etc.
1785
1786Interactively, click on a widget to describe it, or hit RET to describe the
1787widget at point.
1788
1789When called from Lisp, POS may be a buffer position or a mouse position list.
1790
1791Calls each function of the list `describe-widget-functions' in turn, until
1792one of them returns non-nil."
1793 (interactive
1794 (list
1795 (let ((key
1796 (read-key
1797 "Click on a widget, or hit RET to describe the widget at point")))
1798 (cond ((eq key ?\C-m) (point))
1799 ((and (mouse-event-p key)
1800 (eq (event-basic-type key) 'mouse-1)
1801 (equal (event-modifiers key) '(click)))
1802 (event-end key))
1803 ((eq key ?\C-g) (signal 'quit nil))
1804 (t (user-error "You didn't specify a widget"))))))
1805 (let (buf)
1806 ;; Allow describing a widget in a different window.
1807 (when (posnp pos)
1808 (setq buf (window-buffer (posn-window pos))
1809 pos (posn-point pos)))
1810 (with-current-buffer (or buf (current-buffer))
1811 (unless (cl-some (lambda (fun) (when (fboundp fun) (funcall fun pos)))
1812 describe-widget-functions)
1813 (message "No widget found at that position")))))
1814
1815
1772;;; Replacements for old lib-src/ programs. Don't seem especially useful. 1816;;; Replacements for old lib-src/ programs. Don't seem especially useful.
1773 1817
1774;; Replaces lib-src/digest-doc.c. 1818;; Replaces lib-src/digest-doc.c.
diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el
index 284fd1d6cbd..ea7e266e0d0 100644
--- a/lisp/wid-edit.el
+++ b/lisp/wid-edit.el
@@ -577,6 +577,63 @@ respectively."
577 (if (and widget (funcall function widget maparg)) 577 (if (and widget (funcall function widget maparg))
578 (setq overlays nil))))) 578 (setq overlays nil)))))
579 579
580(defun widget-describe (&optional widget-or-pos)
581 "Describe the widget at point.
582Displays a buffer with information about the widget (e.g., its actions) as well
583as a link to browse all the properties of the widget.
584
585This command resolves the indirection of widgets running the action of its
586parents, so the real action executed can be known.
587
588When called from Lisp, pass WIDGET-OR-POS as the widget to describe,
589or a buffer position where a widget is present. If WIDGET-OR-POS is nil,
590the widget at point is the widget to describe."
591 (interactive "d")
592 (require 'wid-browse) ; The widget-browse widget.
593 (let ((widget (if (widgetp widget-or-pos)
594 widget-or-pos
595 (widget-at widget-or-pos)))
596 props)
597 (when widget
598 (help-setup-xref (list #'widget-describe widget)
599 (called-interactively-p 'interactive))
600 (setq props (list (cons 'action (widget--resolve-parent-action widget))
601 (cons 'mouse-down-action
602 (widget-get widget :mouse-down-action))))
603 (with-help-window (help-buffer)
604 (with-current-buffer (help-buffer)
605 (widget-insert "This widget's type is ")
606 (widget-create 'widget-browse :format "%[%v%]\n%d"
607 :doc (get (car widget) 'widget-documentation)
608 :help-echo "Browse this widget's properties"
609 widget)
610 (dolist (action '(action mouse-down-action))
611 (let ((name (symbol-name action))
612 (val (alist-get action props)))
613 (when (functionp val)
614 (widget-insert "\n\n" (propertize (capitalize name) 'face 'bold)
615 "'\nThe " name " of this widget is")
616 (if (symbolp val)
617 (progn (widget-insert " ")
618 (widget-create 'function-link :value val
619 :button-prefix "" :button-suffix ""
620 :help-echo "Describe this function"))
621 (widget-insert "\n")
622 (princ val)))))))
623 (widget-setup)
624 t)))
625
626(defun widget--resolve-parent-action (widget)
627 "Resolve the real action of WIDGET up its inheritance chain.
628Follow the WIDGET's parents, until its :action is no longer
629`widget-parent-action', and return its value."
630 (let ((action (widget-get widget :action))
631 (parent (widget-get widget :parent)))
632 (while (eq action 'widget-parent-action)
633 (setq parent (widget-get parent :parent)
634 action (widget-get parent :action)))
635 action))
636
580;;; Images. 637;;; Images.
581 638
582(defcustom widget-image-directory (file-name-as-directory 639(defcustom widget-image-directory (file-name-as-directory