From: Juri Linkov Date: Sun, 13 Nov 2022 18:57:50 +0000 (+0200) Subject: * lisp/minibuffer.el (set-message-functions): New user option. X-Git-Tag: emacs-29.0.90~1616^2~166 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=9d5fc2c7eb3cfc2ae36cdc750a4605b4b08771b8;p=emacs.git * 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. --- diff --git a/etc/NEWS b/etc/NEWS index 0b8f4539f9d..7cd192b9d3e 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 4898dfdb983..6bb0fa3ae98 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.