Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to follow the end of *Messages* buffer in Emacs?

14 views
Skip to first unread message

Yves Baumes

unread,
Nov 9, 2012, 5:52:00 PM11/9/12
to
I am playing with Elisp, and I find convenient to have the *Messages*
buffer always open in a window in my frame.

I discovered recently that sometimes the buffer stops following the last
lines. If I want to see the last appended lines in this buffer, I need
to go in the buffer and jump to the end manually, with M->. Which is
quite annoying and disruptive.

I am trying to reproduce the "tail -f" command line, in a buffer. Of
course 'auto-revert-tail-mode complains that the *Messages* is not a
visited file... As a consequence, this mode does not want to work. But
it gave me the idea to add a function hook when the buffer is modified.
That function would jump to (point-max) each time that buffer is
modified.

Here is my own attempt, invoked from *Messages* buffer, with M-:
(add-hook
'after-change-functions
(lambda (s e l) (goto-char (point-max)))
nil t)

But it does not work. The (point) remains in the same place while I see
the buffer is growing... The lambda function does not produce any error,
otherwise it would have been removed from the 'after-change-functions
hook and C-h k 'after-change-functions shows it is present.

Any better suggestions?

B. T. Raven

unread,
Nov 10, 2012, 1:39:08 AM11/10/12
to
I don't know if it's better, but this macro works:

C-x (
C-x 5 b *Messages*
M->
C-u -1
C-x 5 o
C-x )
C-x C-k n bot-mess
(global-set-key [(super a)] 'bot-mess) C-x C-e

Keeping at the bottom of *Messages* this way does require intermittent
manual intervention but it's only one keychord.

Ed


Peter Dyballa

unread,
Nov 10, 2012, 5:07:23 AM11/10/12
to Yves Baumes, help-gn...@gnu.org

Am 09.11.2012 um 23:52 schrieb Yves Baumes:

> I discovered recently that sometimes the buffer stops following the last
> lines. If I want to see the last appended lines in this buffer, I need
> to go in the buffer and jump to the end manually, with M->. Which is
> quite annoying and disruptive.

Manually invoking end-of-buffer-other-window? You need to be in the same frame plus more implications when more than two windows exist in that frame…

--
Greetings

Pete

Well begun is half done.
– Optimist.
Half done is well begun.
– Realist.
Half begun is well done.
– Australian.



martin rudalics

unread,
Nov 10, 2012, 6:56:14 AM11/10/12
to yba...@gmail.com, help-gn...@gnu.org
> I am playing with Elisp, and I find convenient to have the *Messages*
> buffer always open in a window in my frame.
>
> I discovered recently that sometimes the buffer stops following the last
> lines. If I want to see the last appended lines in this buffer, I need
> to go in the buffer and jump to the end manually, with M->. Which is
> quite annoying and disruptive.

Can you please tell us when and how this happens. Here, when I display
*Messages* in a window, I always see the last line but maybe something
about my setup is peculiar.

> I am trying to reproduce the "tail -f" command line, in a buffer. Of
> course 'auto-revert-tail-mode complains that the *Messages* is not a
> visited file... As a consequence, this mode does not want to work. But
> it gave me the idea to add a function hook when the buffer is modified.
> That function would jump to (point-max) each time that buffer is
> modified.
>
> Here is my own attempt, invoked from *Messages* buffer, with M-:
> (add-hook
> 'after-change-functions
> (lambda (s e l) (goto-char (point-max)))
> nil t)
>
> But it does not work. The (point) remains in the same place while I see
> the buffer is growing... The lambda function does not produce any error,
> otherwise it would have been removed from the 'after-change-functions
> hook and C-h k 'after-change-functions shows it is present.

The (goto-char (point-max)) just sets `point' in that buffer. It does
not care whether the buffer is currently displayed in a window. You
have to use something like

(walk-windows
(lambda (w)
(when (eq (window-buffer w) (current-buffer))
(set-window-point w (point-max))))))

within that function.

martin

martin rudalics

unread,
Nov 10, 2012, 1:51:00 PM11/10/12
to Yves Baumes, help-gn...@gnu.org
> After finishing to read the description I want to quit it, because I
> want the *Messages* buffer to come back. For that, I do: C-x o, thus
> switching to the focus to the *Help* buffer, and I just type in 'q' to
> quit it and instantly focus back to the *scratch* buffer.
>
> But: When I look into the *Messages* buffer, the "ghost" cursor is no
> longer at the same place. It has moved in the middle of the buffer. From
> there, the window position relative to the buffer remains the same.
>
> (Hum.. I am being over-descriptive here, but I am trying to compensate
> my low level in english)

If only everyone were as over-descriptive as you. The behavior you see
is due to `quit-window' restoring the previous position of
`window-point' for that window. This clearly backfires for the
*Messages* buffer. Please file a bug report with your description.

As an aside: The problem also happens with `switch-to-prev-buffer' and
`switch-to-next-buffer' and it happens for all sorts of buffers where
text is asynchronously inserted at the end as with shell buffers and the
like.

> Ok, I suppose that, indeed, set-window-point is more appropriate.
>
> I've been able to make the whole stuff work, thanks to the various
> remarks. Since I was trying to automate the whole stuff I decided not to
> go in the macro direction. Here is the code:
>
> (defun tail-f-msgs ()
> "Go to the enf of Messages buffer."
> (let ((msg-window (get-buffer-window "*Messages*")))
> (if msg-window
> (with-current-buffer (window-buffer msg-window)
> (set-window-point msg-window (point-max))))))
>
> ;; Make the Messages buffer stick to the end.
> (add-hook 'post-command-hook 'tail-f-msgs)
>
> Of course with that the *Messages* buffer is no longer editable, or you
> can browse it to see older lines. Next fix: make a variable to the
> follow mode.

This would be tedious. We have to fix this in the window code. More
precisely, we need a buffer local variable which when set and
`window-point' equals `point-max' for that buffer at the time of saving
the buffer's window's `window-point' (in your case that would be the
time when the help buffer is displayed) we would store nil in the
corresponding slot. When restoring the buffer in the window (via
`quit-window' in your case) and we find that that slot contains nil,
we'd use the buffer's `point' as new position of `window-point'.

Thanks in advance for the bug report, martin

Yves Baumes

unread,
Nov 10, 2012, 10:55:37 AM11/10/12
to martin rudalics, help-gn...@gnu.org
martin rudalics <ruda...@gmx.at> writes:

>> I am playing with Elisp, and I find convenient to have the *Messages*
>> buffer always open in a window in my frame.
>>
>> I discovered recently that sometimes the buffer stops following the last
>> lines. If I want to see the last appended lines in this buffer, I need
>> to go in the buffer and jump to the end manually, with M->. Which is
>> quite annoying and disruptive.
>
> Can you please tell us when and how this happens. Here, when I display
> *Messages* in a window, I always see the last line but maybe something
> about my setup is peculiar.

I've tried and I think I've been able to reproduce. Let's split the
frame in two windows only, one for the *scratch* and the other for
*Messages*. From here you have a few lines only in the *Messages*
buffer. And untill now, every new lines introduced because of a command
output is followed. Moreover, I can see the "ghost" cursor at the end of
the buffer and it follows every *Messages* buffer updates.

Then, from the *scratch* buffer, I call the describe-variable key
sequence ( C-h v xxx ). The current buffer being *scratch*, the
*Messages* buffer will be replaced with the *help* buffer.

After finishing to read the description I want to quit it, because I
want the *Messages* buffer to come back. For that, I do: C-x o, thus
switching to the focus to the *Help* buffer, and I just type in 'q' to
quit it and instantly focus back to the *scratch* buffer.

But: When I look into the *Messages* buffer, the "ghost" cursor is no
longer at the same place. It has moved in the middle of the buffer. From
there, the window position relative to the buffer remains the same.

(Hum.. I am being over-descriptive here, but I am trying to compensate
my low level in english)

>> I am trying to reproduce the "tail -f" command line, in a buffer. Of
>> course 'auto-revert-tail-mode complains that the *Messages* is not a
>> visited file... As a consequence, this mode does not want to work.
>> But it gave me the idea to add a function hook when the buffer is
>> modified. That function would jump to (point-max) each time that
>> buffer is modified.
>>
>> Here is my own attempt, invoked from *Messages* buffer, with M-:
>> (add-hook
>> 'after-change-functions
>> (lambda (s e l) (goto-char (point-max)))
>> nil t)
>>
>> But it does not work. The (point) remains in the same place while I see
>> the buffer is growing... The lambda function does not produce any error,
>> otherwise it would have been removed from the 'after-change-functions
>> hook and C-h k 'after-change-functions shows it is present.
>
> The (goto-char (point-max)) just sets `point' in that buffer. It does
> not care whether the buffer is currently displayed in a window. You
> have to use something like
>
> (walk-windows
> (lambda (w)
> (when (eq (window-buffer w) (current-buffer))
> (set-window-point w (point-max))))))

Ok, I suppose that, indeed, set-window-point is more appropriate.

I've been able to make the whole stuff work, thanks to the various
remarks. Since I was trying to automate the whole stuff I decided not to
go in the macro direction. Here is the code:

(defun tail-f-msgs ()
"Go to the enf of Messages buffer."
(let ((msg-window (get-buffer-window "*Messages*")))
(if msg-window
(with-current-buffer (window-buffer msg-window)
(set-window-point msg-window (point-max))))))

;; Make the Messages buffer stick to the end.
(add-hook 'post-command-hook 'tail-f-msgs)

Of course with that the *Messages* buffer is no longer editable, or you
can browse it to see older lines. Next fix: make a variable to the
follow mode.


> within that function.
>
> martin

Yves Baumes

unread,
Nov 10, 2012, 2:56:54 PM11/10/12
to martin rudalics, help-gn...@gnu.org
martin rudalics <ruda...@gmx.at> writes:

> Please file a bug report with your description.

Done. Buf report #12855.

> This would be tedious. We have to fix this in the window code.
Oh, I didn't mean to provide a solution here. I see it it can be quite
complex. Maybe some days! ;-)

> Thanks in advance for the bug report, martin
You're welcome.

Regards
Yves

martin rudalics

unread,
Nov 10, 2012, 4:02:52 PM11/10/12
to Yves Baumes, help-gn...@gnu.org
>> Please file a bug report with your description.
>
> Done. Buf report #12855.

Thank you.

>> This would be tedious. We have to fix this in the window code.
> Oh, I didn't mean to provide a solution here. I see it it can be quite
> complex. Maybe some days! ;-)

For the moment it should be sufficient if you add your function to
`window-configuration-change-hook' instead of `post-command-hook'. This
should allow you to scroll and edit *Messages* without any problems.

martin

Yves Baumes

unread,
Nov 10, 2012, 5:00:49 PM11/10/12
to martin rudalics, help-gn...@gnu.org
martin rudalics <ruda...@gmx.at> writes:

> For the moment it should be sufficient if you add your function to
> `window-configuration-change-hook' instead of `post-command-hook'. This
> should allow you to scroll and edit *Messages* without any problems.

I've just tried and it does not work with that hook, as is. I don't know
whether it is related to mistakes on my side , or whether it is related
to the bug you've highlighted previously. I've added some 'message call
to my function in order to try to understand, and obviously the
'(point-max) gets a lower value from one execution to the other. Since
my *Messages* buffer is not limited in size, it must not happen I
presume. (Something tells me it is related to the bug you were talking
about, but I still need to re-read your email and digest it in order to
get a better picture about what is going on here. :-) )

Yves.

Yves Baumes

unread,
Nov 10, 2012, 5:24:16 PM11/10/12
to martin rudalics, help-gn...@gnu.org
martin rudalics <ruda...@gmx.at> writes:

> For the moment it should be sufficient if you add your function to
> `window-configuration-change-hook' instead of `post-command-hook'. This
> should allow you to scroll and edit *Messages* without any problems.

In order to correct my previous post. 'message-log-max was set to 100.
I've modified it to t - true. As a result (point-max) get higher each
time. But the issue is still there. Every time the *Messages* buffer
comes back in its window, the cursor is not in the right place. I've
tried several attempts and it did not fixed the issue. And it is ok, the
initial puropose was to play with GNU Emacs! :-) And I am getting more
and more fun actually, believe me or not :-)

Regards
Yves

Stefan Monnier

unread,
Nov 11, 2012, 12:25:34 PM11/11/12
to
> This would be tedious. We have to fix this in the window code. More
> precisely, we need a buffer local variable which when set and
> `window-point' equals `point-max' for that buffer at the time of saving
> the buffer's window's `window-point' (in your case that would be the
> time when the help buffer is displayed) we would store nil in the
> corresponding slot. When restoring the buffer in the window (via
> `quit-window' in your case) and we find that that slot contains nil,
> we'd use the buffer's `point' as new position of `window-point'.

IIUC we already have that buffer-local variable (it's called
window-point-insertion-type).


Stefan

martin rudalics

unread,
Nov 12, 2012, 4:57:11 AM11/12/12
to mon...@iro.umontreal.ca, help-gn...@gnu.org
> IIUC we already have that buffer-local variable (it's called
> window-point-insertion-type).

You understand correctly ;-)

martin

martin rudalics

unread,
Nov 12, 2012, 4:56:59 AM11/12/12
to Yves Baumes, help-gn...@gnu.org
>> For the moment it should be sufficient if you add your function to
>> `window-configuration-change-hook' instead of `post-command-hook'. This
>> should allow you to scroll and edit *Messages* without any problems.
>
> I've just tried and it does not work with that hook, as is.

It doesn't, indeed. As a matter of fact, `window-point' is reset by
`quit-window' _after_ running `window-configuration-change-hook'. If
you want to fix this in `window-configuration-change-hook' you have two
possibilites:

(1) In `window-configuration-change-hook' add your function that updates
the positions to `post-command-hook'. In the function itself add
code so the function removes itself from `post-command-hook'. This
means that you run the function only when the *Messages* buffer
reappears on the frame and not when you scroll or modify it.

(2) In the function itself modify the `quit-restore' parameter of the
window to point to `point-max' instead.

Both approaches are tricky so try them only if you want to play around
with Elisp. Otherwise, the patch I posted in reply to your bug report
should take care of this.

martin

0 new messages