diff options
| author | Juri Linkov | 2019-12-22 00:02:10 +0200 |
|---|---|---|
| committer | Juri Linkov | 2019-12-22 00:02:10 +0200 |
| commit | 485b423e8f0df2711a850be7f254665f64ab0bdb (patch) | |
| tree | 02f294b4daa4ec7718769afe8235a7119b52bcb5 | |
| parent | 678a71ea2d044f19f75e3f45c930c5e3b707e3dc (diff) | |
| download | emacs-485b423e8f0df2711a850be7f254665f64ab0bdb.tar.gz emacs-485b423e8f0df2711a850be7f254665f64ab0bdb.zip | |
New variable set-message-function to show message at the end of the minibuffer
* doc/lispref/display.texi (Displaying Messages): Document
set-message-function and clear-message-function.
* lisp/minibuffer.el (minibuffer-message-clear-timeout): New defcustom.
(minibuffer-message-timer, minibuffer-message-overlay): New variables.
(set-minibuffer-message, clear-minibuffer-message): New functions.
(set-message-function, clear-message-function): Set variables to
set-minibuffer-message and clear-minibuffer-message respectively.
* src/keyboard.c (read_char): Call clear_message when
Vclear_message_function is a function.
* src/xdisp.c (set_message): Call Vset_message_function when it's a function.
(clear_message): Call Vclear_message_function when it's a function.
(syms_of_xdisp): New variables set-message-function and clear-message-function
(bug#38457).
| -rw-r--r-- | doc/lispref/display.texi | 29 | ||||
| -rw-r--r-- | etc/NEWS | 8 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 70 | ||||
| -rw-r--r-- | src/keyboard.c | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 55 |
5 files changed, 160 insertions, 4 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 42b049eafde..0085f3b6750 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi | |||
| @@ -306,6 +306,35 @@ reformatted, with undesirable results. Instead, use @code{(message | |||
| 306 | "%s" @var{string})}. | 306 | "%s" @var{string})}. |
| 307 | @end defun | 307 | @end defun |
| 308 | 308 | ||
| 309 | @defvar set-message-function | ||
| 310 | When this variable is non-@code{nil}, @code{message} and related functions | ||
| 311 | call it as a function with one argument that is the message to show. | ||
| 312 | |||
| 313 | When this function returns @code{nil}, the message is displayed in the | ||
| 314 | echo area as usual. When the function returns a string, the returned | ||
| 315 | string is displayed in the echo area. When this function returns | ||
| 316 | other non-@code{nil} values, this means that the message was handled | ||
| 317 | specially, so the same message is not displayed in the echo area. | ||
| 318 | See also @code{clear-message-function} that can be used to clear the | ||
| 319 | message displayed by this function. | ||
| 320 | |||
| 321 | The default value is the function that displays the message at the end | ||
| 322 | of the minibuffer when the minibuffer is active. | ||
| 323 | @end defvar | ||
| 324 | |||
| 325 | @defvar clear-message-function | ||
| 326 | When this variable is non-@code{nil}, @code{message} and related functions | ||
| 327 | call it without arguments when their message is @code{nil} or the empty string. | ||
| 328 | |||
| 329 | Usually this function is called when the next input event arrives. | ||
| 330 | The function is called without arguments. It is expected to clear the | ||
| 331 | message displayed by its counterpart function specified by | ||
| 332 | @code{set-message-function}. | ||
| 333 | |||
| 334 | The default value is the function that clears the message displayed at | ||
| 335 | the end of the minibuffer when the minibuffer is active. | ||
| 336 | @end defvar | ||
| 337 | |||
| 309 | @defvar inhibit-message | 338 | @defvar inhibit-message |
| 310 | When this variable is non-@code{nil}, @code{message} and related functions | 339 | When this variable is non-@code{nil}, @code{message} and related functions |
| 311 | will not use the Echo Area to display messages. | 340 | will not use the Echo Area to display messages. |
| @@ -781,6 +781,10 @@ been introduced to allow controlling how the 'M-<' command works in | |||
| 781 | the minibuffer. If non-nil, point will move to the end of the prompt | 781 | the minibuffer. If non-nil, point will move to the end of the prompt |
| 782 | (if point is after the end of the prompt). | 782 | (if point is after the end of the prompt). |
| 783 | 783 | ||
| 784 | +++ | ||
| 785 | *** When the minibuffer is active, messages are displayed at the end of | ||
| 786 | the minibuffer instead of overwriting the minibuffer by the echo area. | ||
| 787 | |||
| 784 | --- | 788 | --- |
| 785 | *** Minibuffer now uses 'minibuffer-message' to display error messages | 789 | *** Minibuffer now uses 'minibuffer-message' to display error messages |
| 786 | at the end of the active minibuffer. | 790 | at the end of the active minibuffer. |
| @@ -2723,6 +2727,10 @@ This function works like 'read-char', but uses 'read-from-minibuffer' | |||
| 2723 | to read a character, so it maintains a history that can be navigated | 2727 | to read a character, so it maintains a history that can be navigated |
| 2724 | via usual minibuffer keystrokes 'M-p'/'M-n'. | 2728 | via usual minibuffer keystrokes 'M-p'/'M-n'. |
| 2725 | 2729 | ||
| 2730 | ** New variables 'set-message-function' and 'clear-message-function' | ||
| 2731 | can be used to specify functions to show and clear messages that | ||
| 2732 | normally are displayed in the echo area. | ||
| 2733 | |||
| 2726 | ** 'setq-local' can now set an arbitrary number of variables, which | 2734 | ** 'setq-local' can now set an arbitrary number of variables, which |
| 2727 | makes the syntax more like 'setq'. | 2735 | makes the syntax more like 'setq'. |
| 2728 | 2736 | ||
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 76d8ca44757..5dc753ffd5c 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -746,6 +746,76 @@ If ARGS are provided, then pass MESSAGE through `format-message'." | |||
| 746 | (sit-for (or minibuffer-message-timeout 1000000))) | 746 | (sit-for (or minibuffer-message-timeout 1000000))) |
| 747 | (delete-overlay ol))))) | 747 | (delete-overlay ol))))) |
| 748 | 748 | ||
| 749 | (defcustom minibuffer-message-clear-timeout nil | ||
| 750 | "How long to display an echo-area message when the minibuffer is active. | ||
| 751 | If the value is a number, it should be specified in seconds. | ||
| 752 | If the value is not a number, such messages never time out, | ||
| 753 | and the text is displayed until the next input event arrives. | ||
| 754 | Unlike `minibuffer-message-timeout' used by `minibuffer-message', | ||
| 755 | this option affects the pair of functions `set-minibuffer-message' | ||
| 756 | and `clear-minibuffer-message' called automatically via | ||
| 757 | `set-message-function' and `clear-message-function'." | ||
| 758 | :type '(choice (const :tag "Never time out" nil) | ||
| 759 | (integer :tag "Wait for the number of seconds" 2)) | ||
| 760 | :version "27.1") | ||
| 761 | |||
| 762 | (defvar minibuffer-message-timer nil) | ||
| 763 | (defvar minibuffer-message-overlay nil) | ||
| 764 | |||
| 765 | (defun set-minibuffer-message (message) | ||
| 766 | "Temporarily display MESSAGE at the end of the minibuffer. | ||
| 767 | The text is displayed for `minibuffer-message-clear-timeout' seconds | ||
| 768 | (if the value is a number), or until the next input event arrives, | ||
| 769 | whichever comes first. | ||
| 770 | Unlike `minibuffer-message', this function is called automatically | ||
| 771 | via `set-message-function'." | ||
| 772 | (when (and (not noninteractive) | ||
| 773 | (window-live-p (active-minibuffer-window))) | ||
| 774 | (with-current-buffer (window-buffer (active-minibuffer-window)) | ||
| 775 | (setq message (if (string-match-p "\\` *\\[.+\\]\\'" message) | ||
| 776 | ;; Make sure we can put-text-property. | ||
| 777 | (copy-sequence message) | ||
| 778 | (concat " [" message "]"))) | ||
| 779 | (unless (or (null minibuffer-message-properties) | ||
| 780 | ;; Don't overwrite the face properties the caller has set | ||
| 781 | (text-properties-at 0 message)) | ||
| 782 | (setq message (apply #'propertize message minibuffer-message-properties))) | ||
| 783 | |||
| 784 | (clear-minibuffer-message) | ||
| 785 | |||
| 786 | (setq minibuffer-message-overlay | ||
| 787 | (make-overlay (point-max) (point-max) nil t t)) | ||
| 788 | (unless (zerop (length message)) | ||
| 789 | ;; The current C cursor code doesn't know to use the overlay's | ||
| 790 | ;; marker's stickiness to figure out whether to place the cursor | ||
| 791 | ;; before or after the string, so let's spoon-feed it the pos. | ||
| 792 | (put-text-property 0 1 'cursor t message)) | ||
| 793 | (overlay-put minibuffer-message-overlay 'after-string message) | ||
| 794 | |||
| 795 | (when (numberp minibuffer-message-clear-timeout) | ||
| 796 | (setq minibuffer-message-timer | ||
| 797 | (run-with-timer minibuffer-message-clear-timeout nil | ||
| 798 | #'clear-minibuffer-message))) | ||
| 799 | |||
| 800 | ;; Return `t' telling the caller that the message | ||
| 801 | ;; was handled specially by this function. | ||
| 802 | t))) | ||
| 803 | |||
| 804 | (setq set-message-function 'set-minibuffer-message) | ||
| 805 | |||
| 806 | (defun clear-minibuffer-message () | ||
| 807 | "Clear minibuffer message. | ||
| 808 | Intended to be called via `clear-message-function'." | ||
| 809 | (when (not noninteractive) | ||
| 810 | (when (timerp minibuffer-message-timer) | ||
| 811 | (cancel-timer minibuffer-message-timer) | ||
| 812 | (setq minibuffer-message-timer nil)) | ||
| 813 | (when (overlayp minibuffer-message-overlay) | ||
| 814 | (delete-overlay minibuffer-message-overlay) | ||
| 815 | (setq minibuffer-message-overlay nil)))) | ||
| 816 | |||
| 817 | (setq clear-message-function 'clear-minibuffer-message) | ||
| 818 | |||
| 749 | (defun minibuffer-completion-contents () | 819 | (defun minibuffer-completion-contents () |
| 750 | "Return the user input in a minibuffer before point as a string. | 820 | "Return the user input in a minibuffer before point as a string. |
| 751 | In Emacs 22, that was what completion commands operated on. | 821 | In Emacs 22, that was what completion commands operated on. |
diff --git a/src/keyboard.c b/src/keyboard.c index 5135fd0bc84..4cf1f64b487 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -2990,6 +2990,8 @@ read_char (int commandflag, Lisp_Object map, | |||
| 2990 | safe_run_hooks (Qecho_area_clear_hook); | 2990 | safe_run_hooks (Qecho_area_clear_hook); |
| 2991 | clear_message (1, 0); | 2991 | clear_message (1, 0); |
| 2992 | } | 2992 | } |
| 2993 | else if (FUNCTIONP (Vclear_message_function)) | ||
| 2994 | clear_message (1, 0); | ||
| 2993 | } | 2995 | } |
| 2994 | 2996 | ||
| 2995 | reread_for_input_method: | 2997 | reread_for_input_method: |
diff --git a/src/xdisp.c b/src/xdisp.c index 08c6927052c..8cba5c5028d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -11706,13 +11706,32 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2) | |||
| 11706 | static void | 11706 | static void |
| 11707 | set_message (Lisp_Object string) | 11707 | set_message (Lisp_Object string) |
| 11708 | { | 11708 | { |
| 11709 | Lisp_Object message = Qnil; | ||
| 11710 | |||
| 11709 | eassert (STRINGP (string)); | 11711 | eassert (STRINGP (string)); |
| 11710 | 11712 | ||
| 11711 | message_enable_multibyte = STRING_MULTIBYTE (string); | 11713 | if (FUNCTIONP (Vset_message_function)) |
| 11714 | { | ||
| 11715 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 11716 | specbind (Qinhibit_quit, Qt); | ||
| 11717 | message = safe_call1 (Vset_message_function, string); | ||
| 11718 | unbind_to (count, Qnil); | ||
| 11712 | 11719 | ||
| 11713 | with_echo_area_buffer (0, -1, set_message_1, 0, string); | 11720 | if (STRINGP (message)) |
| 11714 | message_buf_print = false; | 11721 | { |
| 11715 | help_echo_showing_p = false; | 11722 | string = message; |
| 11723 | message = Qnil; | ||
| 11724 | } | ||
| 11725 | } | ||
| 11726 | |||
| 11727 | if (NILP (message)) | ||
| 11728 | { | ||
| 11729 | message_enable_multibyte = STRING_MULTIBYTE (string); | ||
| 11730 | |||
| 11731 | with_echo_area_buffer (0, -1, set_message_1, 0, string); | ||
| 11732 | message_buf_print = false; | ||
| 11733 | help_echo_showing_p = false; | ||
| 11734 | } | ||
| 11716 | 11735 | ||
| 11717 | if (STRINGP (Vdebug_on_message) | 11736 | if (STRINGP (Vdebug_on_message) |
| 11718 | && STRINGP (string) | 11737 | && STRINGP (string) |
| @@ -11768,6 +11787,14 @@ clear_message (bool current_p, bool last_displayed_p) | |||
| 11768 | { | 11787 | { |
| 11769 | echo_area_buffer[0] = Qnil; | 11788 | echo_area_buffer[0] = Qnil; |
| 11770 | message_cleared_p = true; | 11789 | message_cleared_p = true; |
| 11790 | |||
| 11791 | if (FUNCTIONP (Vclear_message_function)) | ||
| 11792 | { | ||
| 11793 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 11794 | specbind (Qinhibit_quit, Qt); | ||
| 11795 | safe_call (1, Vclear_message_function); | ||
| 11796 | unbind_to (count, Qnil); | ||
| 11797 | } | ||
| 11771 | } | 11798 | } |
| 11772 | 11799 | ||
| 11773 | if (last_displayed_p) | 11800 | if (last_displayed_p) |
| @@ -34940,6 +34967,26 @@ display table takes effect; in this case, Emacs does not consult | |||
| 34940 | doc: /* If non-nil, debug if a message matching this regexp is displayed. */); | 34967 | doc: /* If non-nil, debug if a message matching this regexp is displayed. */); |
| 34941 | Vdebug_on_message = Qnil; | 34968 | Vdebug_on_message = Qnil; |
| 34942 | 34969 | ||
| 34970 | DEFVAR_LISP ("set-message-function", Vset_message_function, | ||
| 34971 | doc: /* If non-nil, function to show the message. | ||
| 34972 | The function is called with one argument that is the message. | ||
| 34973 | When this function returns nil, the message is displayed in the echo | ||
| 34974 | area as usual. When the function returns a string, the returned | ||
| 34975 | string is displayed in the echo area. When this function returns | ||
| 34976 | other non-nil values, this means that the message was handled | ||
| 34977 | specially, so the same message is not displayed in the echo area. | ||
| 34978 | See also `clear-message-function' that can be used to clear the | ||
| 34979 | message displayed by this function. */); | ||
| 34980 | Vset_message_function = Qnil; | ||
| 34981 | |||
| 34982 | DEFVAR_LISP ("clear-message-function", Vclear_message_function, | ||
| 34983 | doc: /* If non-nil, function to clear message. | ||
| 34984 | Usually this function is called when the next input event arrives. | ||
| 34985 | The function is called without arguments. It is expected to clear the | ||
| 34986 | message displayed by its counterpart function specified by | ||
| 34987 | `set-message-function'. */); | ||
| 34988 | Vclear_message_function = Qnil; | ||
| 34989 | |||
| 34943 | DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause, | 34990 | DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause, |
| 34944 | doc: /* */); | 34991 | doc: /* */); |
| 34945 | Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL); | 34992 | Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL); |