emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 9d5fc2c7eb: * lisp/minibuffer.el (set-message-functions): New use


From: Juri Linkov
Subject: master 9d5fc2c7eb: * lisp/minibuffer.el (set-message-functions): New user option.
Date: Sun, 13 Nov 2022 13:58:33 -0500 (EST)

branch: master
commit 9d5fc2c7eb3cfc2ae36cdc750a4605b4b08771b8
Author: Juri Linkov <juri@linkov.net>
Commit: Juri Linkov <juri@linkov.net>

    * lisp/minibuffer.el (set-message-functions): New user option.
    
    (set-message-function): Change the default from
    'set-minibuffer-message' to 'set-message-functions'.
    'set-minibuffer-message' is set as the default value
    of the user option 'set-message-functions'.
    (set-message-functions): New function.
    (inhibit-message-regexps): New customizable variable (bug#52314).
    (inhibit-message): New function.
    (multi-message-timeout, multi-message-max): New defcustoms.
    (multi-message-separator, multi-message-list): New variables.
    (set-multi-message): New function.
---
 etc/NEWS           |  9 ++++++
 lisp/minibuffer.el | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/etc/NEWS b/etc/NEWS
index 0b8f4539f9..7cd192b9d3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -712,6 +712,15 @@ part of the buffer.
 +++
 ** 'count-words' will now report sentence count when used interactively.
 
+** New user option 'set-message-functions'.
+It allows selecting more functions for 'set-message-function'
+in addition to the default function that handles messages
+in the active minibuffer.  The most useful are 'inhibit-message'
+that allows specifying a list of messages to inhibit via
+'inhibit-message-regexps', and 'set-multi-message' that
+accumulates recent messages and displays them stacked
+in the echo area.
+
 ---
 ** New user option 'find-library-include-other-files'.
 If set to nil, commands like 'find-library' will only include library
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 4898dfdb98..6bb0fa3ae9 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -850,7 +850,88 @@ via `set-message-function'."
         ;; was handled specially by this function.
         t))))
 
-(setq set-message-function 'set-minibuffer-message)
+(setq set-message-function 'set-message-functions)
+
+(defcustom set-message-functions '(set-minibuffer-message)
+  "List of functions to handle display of echo-area messages.
+Each function is called with one argument that is the text of a message.
+If a function returns nil, a previous message string is given to the
+next function in the list, and if the last function returns nil, the
+last message string is displayed in the echo area.
+If a function returns a string, the returned string is given to the
+next function in the list, and if the last function returns a string,
+it's displayed in the echo area.
+If a function returns any other non-nil value, no more functions are
+called from the list, and no message will be displayed in the echo area."
+  :type '(choice (const :tag "No special message handling" nil)
+                 (repeat
+                  (choice (function-item :tag "Inhibit some messages"
+                                         inhibit-message)
+                          (function-item :tag "Accumulate messages"
+                                         set-multi-message)
+                          (function-item :tag "Handle minibuffer"
+                                         set-minibuffer-message)
+                          (function :tag "Custom function"))))
+  :version "29.1")
+
+(defun set-message-functions (message)
+  (run-hook-wrapped 'set-message-functions
+                    (lambda (fun)
+                      (when (stringp message)
+                        (let ((ret (funcall fun message)))
+                          (when ret (setq message ret))))
+                      nil))
+  message)
+
+(defcustom inhibit-message-regexps nil
+  "List of regexps that inhibit messages by the function `inhibit-message'."
+  :type '(repeat regexp)
+  :version "29.1")
+
+(defun inhibit-message (message)
+  "Don't display MESSAGE when it matches the regexp `inhibit-message-regexps'.
+This function is intended to be added to `set-message-functions'."
+  (or (and (consp inhibit-message-regexps)
+           (string-match-p (mapconcat #'identity inhibit-message-regexps "\\|")
+                           message))
+      message))
+
+(defcustom multi-message-timeout 2
+  "Number of seconds between messages before clearing the accumulated list."
+  :type 'number
+  :version "29.1")
+
+(defcustom multi-message-max 8
+  "Max size of the list of accumulated messages."
+  :type 'number
+  :version "29.1")
+
+(defvar multi-message-separator "\n")
+
+(defvar multi-message-list nil)
+
+(defun set-multi-message (message)
+  "Return recent messages as one string to display in the echo area.
+Note that this feature works best only when `resize-mini-windows'
+is at its default value `grow-only'."
+  (let ((last-message (car multi-message-list)))
+    (unless (and last-message (equal message (aref last-message 1)))
+      (when last-message
+        (cond
+         ((> (float-time) (+ (aref last-message 0) multi-message-timeout))
+          (setq multi-message-list nil))
+         ((or
+           ;; `message-log-max' was nil, potential clutter.
+           (aref last-message 2)
+           ;; Remove old message that is substring of the new message
+           (string-prefix-p (aref last-message 1) message))
+          (setq multi-message-list (cdr multi-message-list)))))
+      (push (vector (float-time) message (not message-log-max)) 
multi-message-list)
+      (when (> (length multi-message-list) multi-message-max)
+        (setf (nthcdr multi-message-max multi-message-list) nil)))
+    (mapconcat (lambda (m) (aref m 1))
+               (reverse multi-message-list)
+               multi-message-separator)))
 
 (defun clear-minibuffer-message ()
   "Clear minibuffer message.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]