[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 485b423: New variable set-message-function to show message at the
From: |
Juri Linkov |
Subject: |
master 485b423: New variable set-message-function to show message at the end of the minibuffer |
Date: |
Sat, 21 Dec 2019 17:02:18 -0500 (EST) |
branch: master
commit 485b423e8f0df2711a850be7f254665f64ab0bdb
Author: Juri Linkov <address@hidden>
Commit: Juri Linkov <address@hidden>
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).
---
doc/lispref/display.texi | 29 ++++++++++++++++++++
etc/NEWS | 8 ++++++
lisp/minibuffer.el | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
src/keyboard.c | 2 ++
src/xdisp.c | 55 ++++++++++++++++++++++++++++++++++---
5 files changed, 160 insertions(+), 4 deletions(-)
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 42b049e..0085f3b 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -306,6 +306,35 @@ reformatted, with undesirable results. Instead, use
@code{(message
"%s" @var{string})}.
@end defun
+@defvar set-message-function
+When this variable is non-@code{nil}, @code{message} and related functions
+call it as a function with one argument that is the message to show.
+
+When this function returns @code{nil}, the message is displayed in the
+echo area as usual. When the function returns a string, the returned
+string is displayed in the echo area. When this function returns
+other non-@code{nil} values, this means that the message was handled
+specially, so the same message is not displayed in the echo area.
+See also @code{clear-message-function} that can be used to clear the
+message displayed by this function.
+
+The default value is the function that displays the message at the end
+of the minibuffer when the minibuffer is active.
+@end defvar
+
+@defvar clear-message-function
+When this variable is non-@code{nil}, @code{message} and related functions
+call it without arguments when their message is @code{nil} or the empty string.
+
+Usually this function is called when the next input event arrives.
+The function is called without arguments. It is expected to clear the
+message displayed by its counterpart function specified by
+@code{set-message-function}.
+
+The default value is the function that clears the message displayed at
+the end of the minibuffer when the minibuffer is active.
+@end defvar
+
@defvar inhibit-message
When this variable is non-@code{nil}, @code{message} and related functions
will not use the Echo Area to display messages.
diff --git a/etc/NEWS b/etc/NEWS
index 678139e..cd835f3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -781,6 +781,10 @@ been introduced to allow controlling how the 'M-<' command
works in
the minibuffer. If non-nil, point will move to the end of the prompt
(if point is after the end of the prompt).
++++
+*** When the minibuffer is active, messages are displayed at the end of
+the minibuffer instead of overwriting the minibuffer by the echo area.
+
---
*** Minibuffer now uses 'minibuffer-message' to display error messages
at the end of the active minibuffer.
@@ -2723,6 +2727,10 @@ This function works like 'read-char', but uses
'read-from-minibuffer'
to read a character, so it maintains a history that can be navigated
via usual minibuffer keystrokes 'M-p'/'M-n'.
+** New variables 'set-message-function' and 'clear-message-function'
+can be used to specify functions to show and clear messages that
+normally are displayed in the echo area.
+
** 'setq-local' can now set an arbitrary number of variables, which
makes the syntax more like 'setq'.
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 76d8ca4..5dc753f 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -746,6 +746,76 @@ If ARGS are provided, then pass MESSAGE through
`format-message'."
(sit-for (or minibuffer-message-timeout 1000000)))
(delete-overlay ol)))))
+(defcustom minibuffer-message-clear-timeout nil
+ "How long to display an echo-area message when the minibuffer is active.
+If the value is a number, it should be specified in seconds.
+If the value is not a number, such messages never time out,
+and the text is displayed until the next input event arrives.
+Unlike `minibuffer-message-timeout' used by `minibuffer-message',
+this option affects the pair of functions `set-minibuffer-message'
+and `clear-minibuffer-message' called automatically via
+`set-message-function' and `clear-message-function'."
+ :type '(choice (const :tag "Never time out" nil)
+ (integer :tag "Wait for the number of seconds" 2))
+ :version "27.1")
+
+(defvar minibuffer-message-timer nil)
+(defvar minibuffer-message-overlay nil)
+
+(defun set-minibuffer-message (message)
+ "Temporarily display MESSAGE at the end of the minibuffer.
+The text is displayed for `minibuffer-message-clear-timeout' seconds
+(if the value is a number), or until the next input event arrives,
+whichever comes first.
+Unlike `minibuffer-message', this function is called automatically
+via `set-message-function'."
+ (when (and (not noninteractive)
+ (window-live-p (active-minibuffer-window)))
+ (with-current-buffer (window-buffer (active-minibuffer-window))
+ (setq message (if (string-match-p "\\` *\\[.+\\]\\'" message)
+ ;; Make sure we can put-text-property.
+ (copy-sequence message)
+ (concat " [" message "]")))
+ (unless (or (null minibuffer-message-properties)
+ ;; Don't overwrite the face properties the caller has set
+ (text-properties-at 0 message))
+ (setq message (apply #'propertize message
minibuffer-message-properties)))
+
+ (clear-minibuffer-message)
+
+ (setq minibuffer-message-overlay
+ (make-overlay (point-max) (point-max) nil t t))
+ (unless (zerop (length message))
+ ;; The current C cursor code doesn't know to use the overlay's
+ ;; marker's stickiness to figure out whether to place the cursor
+ ;; before or after the string, so let's spoon-feed it the pos.
+ (put-text-property 0 1 'cursor t message))
+ (overlay-put minibuffer-message-overlay 'after-string message)
+
+ (when (numberp minibuffer-message-clear-timeout)
+ (setq minibuffer-message-timer
+ (run-with-timer minibuffer-message-clear-timeout nil
+ #'clear-minibuffer-message)))
+
+ ;; Return `t' telling the caller that the message
+ ;; was handled specially by this function.
+ t)))
+
+(setq set-message-function 'set-minibuffer-message)
+
+(defun clear-minibuffer-message ()
+ "Clear minibuffer message.
+Intended to be called via `clear-message-function'."
+ (when (not noninteractive)
+ (when (timerp minibuffer-message-timer)
+ (cancel-timer minibuffer-message-timer)
+ (setq minibuffer-message-timer nil))
+ (when (overlayp minibuffer-message-overlay)
+ (delete-overlay minibuffer-message-overlay)
+ (setq minibuffer-message-overlay nil))))
+
+(setq clear-message-function 'clear-minibuffer-message)
+
(defun minibuffer-completion-contents ()
"Return the user input in a minibuffer before point as a string.
In Emacs 22, that was what completion commands operated on.
diff --git a/src/keyboard.c b/src/keyboard.c
index 5135fd0..4cf1f64 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2990,6 +2990,8 @@ read_char (int commandflag, Lisp_Object map,
safe_run_hooks (Qecho_area_clear_hook);
clear_message (1, 0);
}
+ else if (FUNCTIONP (Vclear_message_function))
+ clear_message (1, 0);
}
reread_for_input_method:
diff --git a/src/xdisp.c b/src/xdisp.c
index 08c6927..8cba5c5 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -11706,13 +11706,32 @@ truncate_message_1 (ptrdiff_t nchars, Lisp_Object a2)
static void
set_message (Lisp_Object string)
{
+ Lisp_Object message = Qnil;
+
eassert (STRINGP (string));
- message_enable_multibyte = STRING_MULTIBYTE (string);
+ if (FUNCTIONP (Vset_message_function))
+ {
+ ptrdiff_t count = SPECPDL_INDEX ();
+ specbind (Qinhibit_quit, Qt);
+ message = safe_call1 (Vset_message_function, string);
+ unbind_to (count, Qnil);
- with_echo_area_buffer (0, -1, set_message_1, 0, string);
- message_buf_print = false;
- help_echo_showing_p = false;
+ if (STRINGP (message))
+ {
+ string = message;
+ message = Qnil;
+ }
+ }
+
+ if (NILP (message))
+ {
+ message_enable_multibyte = STRING_MULTIBYTE (string);
+
+ with_echo_area_buffer (0, -1, set_message_1, 0, string);
+ message_buf_print = false;
+ help_echo_showing_p = false;
+ }
if (STRINGP (Vdebug_on_message)
&& STRINGP (string)
@@ -11768,6 +11787,14 @@ clear_message (bool current_p, bool last_displayed_p)
{
echo_area_buffer[0] = Qnil;
message_cleared_p = true;
+
+ if (FUNCTIONP (Vclear_message_function))
+ {
+ ptrdiff_t count = SPECPDL_INDEX ();
+ specbind (Qinhibit_quit, Qt);
+ safe_call (1, Vclear_message_function);
+ unbind_to (count, Qnil);
+ }
}
if (last_displayed_p)
@@ -34940,6 +34967,26 @@ display table takes effect; in this case, Emacs does
not consult
doc: /* If non-nil, debug if a message matching this regexp is
displayed. */);
Vdebug_on_message = Qnil;
+ DEFVAR_LISP ("set-message-function", Vset_message_function,
+ doc: /* If non-nil, function to show the message.
+The function is called with one argument that is the message.
+When this function returns nil, the message is displayed in the echo
+area as usual. When the function returns a string, the returned
+string is displayed in the echo area. When this function returns
+other non-nil values, this means that the message was handled
+specially, so the same message is not displayed in the echo area.
+See also `clear-message-function' that can be used to clear the
+message displayed by this function. */);
+ Vset_message_function = Qnil;
+
+ DEFVAR_LISP ("clear-message-function", Vclear_message_function,
+ doc: /* If non-nil, function to clear message.
+Usually this function is called when the next input event arrives.
+The function is called without arguments. It is expected to clear the
+message displayed by its counterpart function specified by
+`set-message-function'. */);
+ Vclear_message_function = Qnil;
+
DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
doc: /* */);
Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 485b423: New variable set-message-function to show message at the end of the minibuffer,
Juri Linkov <=