summaryrefslogtreecommitdiff
path: root/lisp/button.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/button.el')
-rw-r--r--lisp/button.el74
1 files changed, 66 insertions, 8 deletions
diff --git a/lisp/button.el b/lisp/button.el
index b3afc4eca25..11317605cee 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -78,6 +78,10 @@
"Keymap useful for buffers containing buttons.
Mode-specific keymaps may want to use this as their parent keymap.")
+(define-minor-mode button-mode
+ "A minor mode for navigating to buttons with the TAB key."
+ :keymap button-buffer-map)
+
;; Default properties for buttons.
(put 'default-button 'face 'button)
(put 'default-button 'mouse-face 'highlight)
@@ -341,15 +345,14 @@ If the property `button-data' is present, it will later be used
as the argument for the `action' callback function instead of the
default argument, which is the button itself.
-BEG can also be a string, in which case it is made into a button.
+BEG can also be a string, in which case a copy of it is made into
+a button and returned.
Also see `insert-text-button'."
(let ((object nil)
(type-entry
(or (plist-member properties 'type)
(plist-member properties :type))))
- (when (stringp beg)
- (setq object beg beg 0 end (length object)))
;; Disallow setting the `category' property directly.
(when (plist-get properties 'category)
(error "Button `category' property may not be set directly"))
@@ -362,6 +365,10 @@ Also see `insert-text-button'."
(setcar type-entry 'category)
(setcar (cdr type-entry)
(button-category-symbol (cadr type-entry))))
+ (when (stringp beg)
+ (setq object (copy-sequence beg))
+ (setq beg 0)
+ (setq end (length object)))
;; Now add all the text properties at once.
(add-text-properties beg end
;; Each button should have a non-eq `button'
@@ -461,18 +468,24 @@ see).
POS defaults to point, except when `push-button' is invoked
interactively as the result of a mouse-event, in which case, the
mouse event is used.
+
If there's no button at POS, do nothing and return nil, otherwise
-return t."
+return t.
+
+To get a description of what function will called when pushing a
+butting, use the `button-describe' command."
(interactive
(list (if (integerp last-command-event) (point) last-command-event)))
(if (and (not (integerp pos)) (eventp pos))
;; POS is a mouse event; switch to the proper window/buffer
(let ((posn (event-start pos)))
(with-current-buffer (window-buffer (posn-window posn))
- (if (posn-string posn)
- ;; mode-line, header-line, or display string event.
- (button-activate (posn-string posn) t)
- (push-button (posn-point posn) t))))
+ (let* ((str (posn-string posn))
+ (str-button (and str (get-text-property (cdr str) 'button (car str)))))
+ (if str-button
+ ;; mode-line, header-line, or display string event.
+ (button-activate str t)
+ (push-button (posn-point posn) t)))))
;; POS is just normal position
(let ((button (button-at (or pos (point)))))
(when button
@@ -550,6 +563,51 @@ Returns the button found."
(interactive "p\nd\nd")
(forward-button (- n) wrap display-message no-error))
+(defun button--describe (properties)
+ "Describe a button's PROPERTIES (an alist) in a *Help* buffer.
+This is a helper function for `button-describe', in order to be possible to
+use `help-setup-xref'.
+
+Each element of PROPERTIES should be of the form (PROPERTY . VALUE)."
+ (help-setup-xref (list #'button--describe properties)
+ (called-interactively-p 'interactive))
+ (with-help-window (help-buffer)
+ (with-current-buffer (help-buffer)
+ (insert (format-message "This button's type is `%s'."
+ (alist-get 'type properties)))
+ (dolist (prop '(action mouse-action))
+ (let ((name (symbol-name prop))
+ (val (alist-get prop properties)))
+ (when (functionp val)
+ (insert "\n\n"
+ (propertize (capitalize name) 'face 'bold)
+ "\nThe " name " of this button is")
+ (if (symbolp val)
+ (progn
+ (insert (format-message " `%s',\nwhich is " val))
+ (describe-function-1 val))
+ (insert "\n")
+ (princ val))))))))
+
+(defun button-describe (&optional button-or-pos)
+ "Display a buffer with information about the button at point.
+
+When called from Lisp, pass BUTTON-OR-POS as the button to describe, or a
+buffer position where a button is present. If BUTTON-OR-POS is nil, the
+button at point is the button to describe."
+ (interactive "d")
+ (let* ((button (cond ((integer-or-marker-p button-or-pos)
+ (button-at button-or-pos))
+ ((null button-or-pos) (button-at (point)))
+ ((overlayp button-or-pos) button-or-pos)))
+ (props (and button
+ (mapcar (lambda (prop)
+ (cons prop (button-get button prop)))
+ '(type action mouse-action)))))
+ (when props
+ (button--describe props)
+ t)))
+
(provide 'button)
;;; button.el ends here