4

Suppose I type M-! uname -a RET. A message like this is displayed in the echo area:

Linux pergamon 4.15.0-33-generic #36-Ubuntu SMP Wed Aug 15 16:00:05 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

I want to mark some part of this message (like 4.15.0-33-generic) and copy it to the kill ring with M-w.

(This example is for the sake of illustration. In reality I want to do this on some other messages that I get in the echo area.)

But how do I focus the echo area so I can operate on its contents?

Unlike in the “Focus echo area” question, I don’t have a prompt active, just a message.

I can type C-h e to view the *Messages* buffer in another window, but that is less convenient.

  • Note that for your specific example command, supplying a prefix argument causes the output to be inserted into the current buffer rather than displayed as a message. e.g. C-u M-! uname -a RET. This meaning of a prefix argument is common to many of the commands which normally only display a message. – phils Aug 30 '18 at 23:02
  • This is one of the reasons i prefer Emacs in the terminal mode (-nw). At least I can copy the contents of the such ephemeral areas using a mouse. – Jeeves Aug 31 '18 at 9:35
  • 1
    This answer from UNIX SE might be helpful, too. – GergelyPolonkai Sep 5 '18 at 4:41
  • @GergelyPolonkai Something like (read-minibuffer "Dummy: " (current-message)) would be very close to what I want. It doesn’t work for me right away, as (current-message) seems to be nil. If you can post an answer with a working example like that, I would accept it. – Vasiliy Faronov Sep 5 '18 at 15:15
  • As that other answer says, current-message is nil when the message disappears from the echo area. That’s why they created a function that reads from the *Messages* buffer if needed. – GergelyPolonkai Sep 6 '18 at 10:39
4

The echo area is not really a buffer. It is an area of a window. It is used to display messages and to display the minibuffer (which is a buffer). You cannot "visit" the echo area and select text there, as you would a buffer.

You or your code needs instead to visit buffer *Messages*, where messages are logged. (Not everything displayed in the echo area gets logged there, however.)

This is what C-h e does, for reference:

(defun view-echo-area-messages ()
  "View the log of recent echo-area messages: the `*Messages*' buffer.
The number of messages retained in that buffer
is specified by the variable `message-log-max'."
  (interactive)
  (with-current-buffer (messages-buffer)
    (goto-char (point-max))
    (display-buffer (current-buffer))))

From that you can see that you want to visit the buffer that is returned by evaluating (messages-buffer) - this is generally buffer *Messages*.

You want a command something like this (e.g., bind it to a key):

(defun visit-*Messages* ()
  "Visit buffer `*Messages*."
  (interactive)
  (pop-to-buffer (messages-buffer))
  (goto-char (point-max)))

That will put you in the buffer at its end. But you still need to select the text you want, use M-w, and then use C-x 0 to hide the buffer.

If you know the beginning and end positions of the text you want to copy then you can do everything you want in the function. But those need to be positions in buffer *Messages*. In that case, something like this:

(defun copy-from-*Messages* (start end &optional msgp)
  "Copy text from BEG to END in buffer `*Messages* to kill ring."
  (interactive (list (read-number "Start: ") (read-number "End: ") t))
  (with-current-buffer (messages-buffer)
    (copy-region-as-kill start end))
  (when msgp (message "Copied: %S" (car kill-ring)))
  (car kill-ring))

It's unlikely, I think, that you would want to invoke this interactively, as you won't know what the start and end positions are. But you might want to invoke it from Lisp code that knows the positions you're interested in.

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.