aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2019-12-22 00:02:10 +0200
committerJuri Linkov2019-12-22 00:02:10 +0200
commit485b423e8f0df2711a850be7f254665f64ab0bdb (patch)
tree02f294b4daa4ec7718769afe8235a7119b52bcb5
parent678a71ea2d044f19f75e3f45c930c5e3b707e3dc (diff)
downloademacs-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.texi29
-rw-r--r--etc/NEWS8
-rw-r--r--lisp/minibuffer.el70
-rw-r--r--src/keyboard.c2
-rw-r--r--src/xdisp.c55
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
310When this variable is non-@code{nil}, @code{message} and related functions
311call it as a function with one argument that is the message to show.
312
313When this function returns @code{nil}, the message is displayed in the
314echo area as usual. When the function returns a string, the returned
315string is displayed in the echo area. When this function returns
316other non-@code{nil} values, this means that the message was handled
317specially, so the same message is not displayed in the echo area.
318See also @code{clear-message-function} that can be used to clear the
319message displayed by this function.
320
321The default value is the function that displays the message at the end
322of the minibuffer when the minibuffer is active.
323@end defvar
324
325@defvar clear-message-function
326When this variable is non-@code{nil}, @code{message} and related functions
327call it without arguments when their message is @code{nil} or the empty string.
328
329Usually this function is called when the next input event arrives.
330The function is called without arguments. It is expected to clear the
331message displayed by its counterpart function specified by
332@code{set-message-function}.
333
334The default value is the function that clears the message displayed at
335the end of the minibuffer when the minibuffer is active.
336@end defvar
337
309@defvar inhibit-message 338@defvar inhibit-message
310When this variable is non-@code{nil}, @code{message} and related functions 339When this variable is non-@code{nil}, @code{message} and related functions
311will not use the Echo Area to display messages. 340will not use the Echo Area to display messages.
diff --git a/etc/NEWS b/etc/NEWS
index 678139ecbcf..cd835f3d2a9 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -781,6 +781,10 @@ been introduced to allow controlling how the 'M-<' command works in
781the minibuffer. If non-nil, point will move to the end of the prompt 781the 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
786the 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
786at the end of the active minibuffer. 790at the end of the active minibuffer.
@@ -2723,6 +2727,10 @@ This function works like 'read-char', but uses 'read-from-minibuffer'
2723to read a character, so it maintains a history that can be navigated 2727to read a character, so it maintains a history that can be navigated
2724via usual minibuffer keystrokes 'M-p'/'M-n'. 2728via usual minibuffer keystrokes 'M-p'/'M-n'.
2725 2729
2730** New variables 'set-message-function' and 'clear-message-function'
2731can be used to specify functions to show and clear messages that
2732normally 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
2727makes the syntax more like 'setq'. 2735makes 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.
751If the value is a number, it should be specified in seconds.
752If the value is not a number, such messages never time out,
753and the text is displayed until the next input event arrives.
754Unlike `minibuffer-message-timeout' used by `minibuffer-message',
755this option affects the pair of functions `set-minibuffer-message'
756and `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.
767The text is displayed for `minibuffer-message-clear-timeout' seconds
768(if the value is a number), or until the next input event arrives,
769whichever comes first.
770Unlike `minibuffer-message', this function is called automatically
771via `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.
808Intended 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.
751In Emacs 22, that was what completion commands operated on. 821In 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)
11706static void 11706static void
11707set_message (Lisp_Object string) 11707set_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.
34972The function is called with one argument that is the message.
34973When this function returns nil, the message is displayed in the echo
34974area as usual. When the function returns a string, the returned
34975string is displayed in the echo area. When this function returns
34976other non-nil values, this means that the message was handled
34977specially, so the same message is not displayed in the echo area.
34978See also `clear-message-function' that can be used to clear the
34979message 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.
34984Usually this function is called when the next input event arrives.
34985The function is called without arguments. It is expected to clear the
34986message 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);