diff options
| author | Basil L. Contovounesios | 2019-09-27 00:04:33 +0100 |
|---|---|---|
| committer | Basil L. Contovounesios | 2019-10-03 23:05:14 +0100 |
| commit | 0fc8177414801e428ca184e8a9ba8b79a291c15a (patch) | |
| tree | 7ed7df57104eee1e0beaa6074efba73670adf3b0 | |
| parent | 660d509acd9da23d9795b5aaa12a5453e6c61bbd (diff) | |
| download | emacs-0fc8177414801e428ca184e8a9ba8b79a291c15a.tar.gz emacs-0fc8177414801e428ca184e8a9ba8b79a291c15a.zip | |
Further improve button.el support for help-echo
The last change to forward-button added support for help-echo values
that are functions. This patch fixes the arguments passed to such
functions and further adds support for help-echo values that are
forms (bug#37515).
* doc/lispref/display.texi (Button Properties): Fix description of
help-echo button property.
* lisp/button.el (button--help-echo): New function.
(forward-button): Use it.
(backward-button): Clarify help-echo reference in docstring.
* test/lisp/button-tests.el (button--help-echo-string)
(button--help-echo-form, button--help-echo-function): New tests.
| -rw-r--r-- | doc/lispref/display.texi | 19 | ||||
| -rw-r--r-- | lisp/button.el | 26 | ||||
| -rw-r--r-- | test/lisp/button-tests.el | 56 |
3 files changed, 86 insertions, 15 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 494bf0d3f7e..61bd4ce8830 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi | |||
| @@ -6607,14 +6607,23 @@ in the variable @code{button-map}, which defines @key{RET} and | |||
| 6607 | The button type. @xref{Button Types}. | 6607 | The button type. @xref{Button Types}. |
| 6608 | 6608 | ||
| 6609 | @item help-echo | 6609 | @item help-echo |
| 6610 | @kindex help-index @r{(button property)} | 6610 | @kindex help-echo @r{(button property)} |
| 6611 | A string displayed by the Emacs tool-tip help system; by default, | 6611 | A string displayed by the Emacs tooltip help system; by default, |
| 6612 | @code{"mouse-2, RET: Push this button"}. | 6612 | @code{"mouse-2, RET: Push this button"}. Alternatively, a function |
| 6613 | that returns, or a form that evaluates to, a string to be displayed or | ||
| 6614 | @code{nil}. For details see @ref{Text help-echo}. | ||
| 6615 | |||
| 6616 | The function is called with three arguments, @var{window}, | ||
| 6617 | @var{object}, and @var{pos}. The second argument, @var{object}, is | ||
| 6618 | either the overlay that had the property (for overlay buttons), or the | ||
| 6619 | buffer containing the button (for text property buttons). The other | ||
| 6620 | arguments have the same meaning as for the special text property | ||
| 6621 | @code{help-echo}. | ||
| 6613 | 6622 | ||
| 6614 | @item follow-link | 6623 | @item follow-link |
| 6615 | @kindex follow-link @r{(button property)} | 6624 | @kindex follow-link @r{(button property)} |
| 6616 | The follow-link property, defining how a @key{mouse-1} click behaves | 6625 | The @code{follow-link} property, defining how a @key{mouse-1} click |
| 6617 | on this button, @xref{Clickable Text}. | 6626 | behaves on this button, @xref{Clickable Text}. |
| 6618 | 6627 | ||
| 6619 | @item button | 6628 | @item button |
| 6620 | @kindex button @r{(button property)} | 6629 | @kindex button @r{(button property)} |
diff --git a/lisp/button.el b/lisp/button.el index 32efc2f95be..04e77ca904f 100644 --- a/lisp/button.el +++ b/lisp/button.el | |||
| @@ -467,13 +467,22 @@ return t." | |||
| 467 | (button-activate button use-mouse-action) | 467 | (button-activate button use-mouse-action) |
| 468 | t)))) | 468 | t)))) |
| 469 | 469 | ||
| 470 | (defun button--help-echo (button) | ||
| 471 | "Evaluate BUTTON's `help-echo' property and return its value." | ||
| 472 | (let ((help (button-get button 'help-echo))) | ||
| 473 | (if (functionp help) | ||
| 474 | (let ((obj (if (overlayp button) button (current-buffer)))) | ||
| 475 | (funcall help (selected-window) obj (button-start button))) | ||
| 476 | (eval help lexical-binding)))) | ||
| 477 | |||
| 470 | (defun forward-button (n &optional wrap display-message no-error) | 478 | (defun forward-button (n &optional wrap display-message no-error) |
| 471 | "Move to the Nth next button, or Nth previous button if N is negative. | 479 | "Move to the Nth next button, or Nth previous button if N is negative. |
| 472 | If N is 0, move to the start of any button at point. | 480 | If N is 0, move to the start of any button at point. |
| 473 | If WRAP is non-nil, moving past either end of the buffer continues from the | 481 | If WRAP is non-nil, moving past either end of the buffer continues from the |
| 474 | other end. | 482 | other end. |
| 475 | If DISPLAY-MESSAGE is non-nil, the button's help-echo string is displayed. | 483 | If DISPLAY-MESSAGE is non-nil, the button's `help-echo' property |
| 476 | Any button with a non-nil `skip' property is skipped over. | 484 | is displayed. Any button with a non-nil `skip' property is |
| 485 | skipped over. | ||
| 477 | 486 | ||
| 478 | If NO-ERROR, return nil if no further buttons could be found | 487 | If NO-ERROR, return nil if no further buttons could be found |
| 479 | instead of erroring out. | 488 | instead of erroring out. |
| @@ -506,13 +515,9 @@ Returns the button found." | |||
| 506 | (unless (button-get button 'skip) | 515 | (unless (button-get button 'skip) |
| 507 | (setq n (1- n))))))) | 516 | (setq n (1- n))))))) |
| 508 | (if (null button) | 517 | (if (null button) |
| 509 | (if no-error | 518 | (unless no-error |
| 510 | nil | ||
| 511 | (user-error (if wrap "No buttons!" "No more buttons"))) | 519 | (user-error (if wrap "No buttons!" "No more buttons"))) |
| 512 | (let ((msg (and display-message (button-get button 'help-echo)))) | 520 | (let ((msg (and display-message (button--help-echo button)))) |
| 513 | (when (functionp msg) | ||
| 514 | (setq msg (funcall msg (selected-window) (current-buffer) | ||
| 515 | (button-start button)))) | ||
| 516 | (when msg | 521 | (when msg |
| 517 | (message "%s" msg))) | 522 | (message "%s" msg))) |
| 518 | button))) | 523 | button))) |
| @@ -522,8 +527,9 @@ Returns the button found." | |||
| 522 | If N is 0, move to the start of any button at point. | 527 | If N is 0, move to the start of any button at point. |
| 523 | If WRAP is non-nil, moving past either end of the buffer continues from the | 528 | If WRAP is non-nil, moving past either end of the buffer continues from the |
| 524 | other end. | 529 | other end. |
| 525 | If DISPLAY-MESSAGE is non-nil, the button's help-echo string is displayed. | 530 | If DISPLAY-MESSAGE is non-nil, the button's `help-echo' property |
| 526 | Any button with a non-nil `skip' property is skipped over. | 531 | is displayed. Any button with a non-nil `skip' property is |
| 532 | skipped over. | ||
| 527 | 533 | ||
| 528 | If NO-ERROR, return nil if no further buttons could be found | 534 | If NO-ERROR, return nil if no further buttons could be found |
| 529 | instead of erroring out. | 535 | instead of erroring out. |
diff --git a/test/lisp/button-tests.el b/test/lisp/button-tests.el index d54a992ab89..44a7ea6f6e5 100644 --- a/test/lisp/button-tests.el +++ b/test/lisp/button-tests.el | |||
| @@ -37,4 +37,60 @@ | |||
| 37 | (widget-create 'link "link widget") | 37 | (widget-create 'link "link widget") |
| 38 | (should-not (button-at (1- (point)))))) | 38 | (should-not (button-at (1- (point)))))) |
| 39 | 39 | ||
| 40 | (ert-deftest button--help-echo-string () | ||
| 41 | "Test `button--help-echo' with strings." | ||
| 42 | (with-temp-buffer | ||
| 43 | ;; Text property buttons. | ||
| 44 | (let ((button (insert-text-button "text" 'help-echo "text help"))) | ||
| 45 | (should (equal (button--help-echo button) "text help"))) | ||
| 46 | ;; Overlay buttons. | ||
| 47 | (let ((button (insert-button "overlay" 'help-echo "overlay help"))) | ||
| 48 | (should (equal (button--help-echo button) "overlay help"))))) | ||
| 49 | |||
| 50 | (ert-deftest button--help-echo-form () | ||
| 51 | "Test `button--help-echo' with forms." | ||
| 52 | (with-temp-buffer | ||
| 53 | ;; Test text property buttons with dynamic scoping. | ||
| 54 | (let* ((help (make-symbol "help")) | ||
| 55 | (form `(funcall (let ((,help "lexical form")) | ||
| 56 | (lambda () ,help)))) | ||
| 57 | (button (insert-text-button "text" 'help-echo form))) | ||
| 58 | (set help "dynamic form") | ||
| 59 | (should (equal (button--help-echo button) "dynamic form"))) | ||
| 60 | ;; Test overlay buttons with lexical scoping. | ||
| 61 | (setq lexical-binding t) | ||
| 62 | (let* ((help (make-symbol "help")) | ||
| 63 | (form `(funcall (let ((,help "lexical form")) | ||
| 64 | (lambda () ,help)))) | ||
| 65 | (button (insert-button "overlay" 'help-echo form))) | ||
| 66 | (set help "dynamic form") | ||
| 67 | (should (equal (button--help-echo button) "lexical form"))))) | ||
| 68 | |||
| 69 | (ert-deftest button--help-echo-function () | ||
| 70 | "Test `button--help-echo' with functions." | ||
| 71 | (with-temp-buffer | ||
| 72 | ;; Text property buttons. | ||
| 73 | (let* ((owin (selected-window)) | ||
| 74 | (obuf (current-buffer)) | ||
| 75 | (opos (point)) | ||
| 76 | (help (lambda (win obj pos) | ||
| 77 | (should (eq win owin)) | ||
| 78 | (should (eq obj obuf)) | ||
| 79 | (should (= pos opos)) | ||
| 80 | "text function")) | ||
| 81 | (button (insert-text-button "text" 'help-echo help))) | ||
| 82 | (should (equal (button--help-echo button) "text function")) | ||
| 83 | ;; Overlay buttons. | ||
| 84 | (setq help (lambda (win obj pos) | ||
| 85 | (should (eq win owin)) | ||
| 86 | (should (overlayp obj)) | ||
| 87 | (should (eq obj button)) | ||
| 88 | (should (eq (overlay-buffer obj) obuf)) | ||
| 89 | (should (= (overlay-start obj) opos)) | ||
| 90 | (should (= pos opos)) | ||
| 91 | "overlay function")) | ||
| 92 | (setq opos (point)) | ||
| 93 | (setq button (insert-button "overlay" 'help-echo help)) | ||
| 94 | (should (equal (button--help-echo button) "overlay function"))))) | ||
| 95 | |||
| 40 | ;;; button-tests.el ends here | 96 | ;;; button-tests.el ends here |