1

I'm using emacs 25.1.

I know that I can send a message to the echo area via (message "Message text"). However, that message disappears whenever buffers are switched or other similar changes take place during my emacs session.

I assume that this is because various internal emacs functions sometimes do the equivalent of (message nil).

Is there a way to send a message to the echo area and have it always persist until I explicitly remove it?

I don't care if the echo area is overwritten when the minibuffer is used. I'm only wanting to keep messages persistent in the echo area for as long as no minibuffer interaction is taking place.

  • 1
    You might like to look at the minibuffer-line package available in GNU ELPA. It might not provide exactly what you want, but its implementation may give you ideas about how to go about it. – Stefan Jun 9 '18 at 23:53
  • Thank you. Yes, minibuffer-line is helpful. It uses a timer to repeatedly put text into the minibuffer. I guess I could do something similar. I'll investigate. – HippoMan Jun 10 '18 at 12:17
2

I tried the following. It seems to work, but I'm not sure about edge cases, and I'm still testing. The following code displays "foo" in the echo area, and then "bar", and then "hippo", and then "oink". The strings "quack" and "potamus" never show up ...

(defvar my-persisting-messages nil
  "*Set if we are persisting messages.")

(defun my-message-function (orig-fun &rest args)
  (unless (current-message)
    (apply orig-fun args)))

(defun my-persist-message (&rest args)
  (my-depersist-messages)
  (apply 'message args)
  (setq my-persisting-messages t)
  (advice-add 'message :around #'my-message-function))

(defun my-depersist-messages ()
  (when my-persisting-messages
    (setq my-persisting-messages nil)
    (advice-remove 'message #'my-message-function)))

(message "foo")
(sleep-for 1)
(my-persist-message "bar")
(sleep-for 1)
(message "quack")
(sleep-for 1)
(my-persist-message "hippo")
(sleep-for 1)
(message "potamus")
(sleep-for 1)
(my-depersist-messages)
(message "oink")
(sleep-for 1)

Using advice is hacky, and I'm still wondering if there might be a better way to do this.

1

ElDoc in scratch buffer does that. It runs a timer that uses a predicate function:

;; Decide whether now is a good time to display a message.
(defun eldoc-display-message-p ()
  "Return non-nil when it is appropriate to display an ElDoc message."
   (and (eldoc-display-message-no-interference-p)
       ;; If this-command is non-nil while running via an idle
       ;; timer, we're still in the middle of executing a command,
       ;; e.g. a query-replace where it would be annoying to
       ;; overwrite the echo area.
       (not this-command)
       (eldoc--message-command-p last-command)))

this-command and last-command are core Emacs variables.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.