1

Is it possible to place the current buffer at the end of the buffer list without switching buffers in the window? I would like to write a wrapper function for ibuffer that modifies the buffer list so that the IBuffer buffer is at the end of the list after calling it. The motivation is for the case when working on say src1.code and then I call ibuffer and use it to select src2.code, then the buffer list looks like (most recent at the top)

src2.code
*Ibuffer*
src1.code
    .
    .
    .

but I would like it to look like

src2.code
src1.code
    .
    .
    .
*Ibuffer*

In the Emacs manual at https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer-List.html, it says that there is a function bury-buffer that places a buffer at the end of the buffer list. So I was hoping to write a function such as follows to achieve the desired result:

(defun ibuffer-bury-buffer ()
  "Calls `ibuffer` and moves the buffer to the end of the buffer 
   list.  Doesn't work!"
  (interactive)
  (ibuffer)
  (bury-buffer))

But it seems that when you call bury-buffer using the current buffer in the window that it also changes the buffer to the next buffer in the buffer list. Is there anything that can be done to prevent that?

  • 1
    In general, you should not mess with the buffer-list because it always changes and there is no way of reliably controlling it and/or counting on it to be the same in the future. There is almost always a better way of handling this; e.g., copying the buffer-list to a variable (let-bound, buffer-local, global, as a custom frame-parameter as does the library frame-bufs, etc.), and modifying the variable and then doing something with the modified list. – lawlist Aug 28 '18 at 0:29
  • So if I am understanding this correctly, in general I should copy the buffer list to a local variable, make the changes to the variable, and then revise the buffer list to match the contents of the local variable? And the point of this is to prevent race conditions between my acting on the buffer list and other potential threads or processes from acting on it? – dpritch Aug 28 '18 at 18:27
  • 1
    To the extent that you seek to change the appearance of how buffers are sorted within *Ibuffer*, there are likely customizable sort options. To the extent you wish to see how the function bury-buffer-internal works, type M-x describe-function or C-h f. Here is something you can use to test: (progn (message "\nbuffer-list (BEFORE): %s" (buffer-list)) (bury-buffer-internal (current-buffer)) (message "\nbuffer-list (AFTER): %s" (buffer-list)) nil). You can place that in a *scratch* buffer and move to the end of the code and type C-x C-e and then switch to *Messages* buffer. – lawlist Aug 28 '18 at 19:14
  • 1
    In terms of modifying the buffer-list, that is a Pandora's Box that I do not wish to open. Stefan was the lead of the Emacs development team for years, so he is definitely the expert here. Most of the code that I have seen or written/modified over the years calls the function (buffer-list) and then does something with the copied list and does not modify the actual internal buffer-list that Emacs relies upon. Here is a simple first/last of the buffer-list which does not modify the internal buffer-list: (let ((lst (buffer-list))) (cons (first lst) (last lst))) – lawlist Aug 28 '18 at 19:17
  • @lawlist thanks so much for your comments, especially for the debugging tips! I will continue to work on this exercise to hopefully gain some enlightenment and experience with elisp. – dpritch Aug 29 '18 at 14:04
2

Just pass the buffer explicitly to bury-buffer. Notice how its docstring says:

If BUFFER-OR-NAME is nil or omitted, bury the
current buffer.  Also, if BUFFER-OR-NAME is nil or omitted,
remove the current buffer from the selected window if it is
displayed there.

So, you can use (bury-buffer (current-buffer)) if you only want to change the buffer-list without affecting display.

  • Thanks - I've tried this but it doesn't seem to be working for me. When I change the call to bury-buffer in the function as suggested and then call the revised version of ibuffer-bury-buffer, the *Ibuffer* buffer still seems to be at the front of the buffer list after the call, judging from the output obtained by calling buffer-list – dpritch Aug 28 '18 at 15:36
  • 1
    @dpritch: Maybe (current-buffer) is not the Ibuffer when the ibuffer function returns? I suggest you add a (message "Cur buf: %S" (current-buffer)) in there to debug it. – Stefan Aug 29 '18 at 3:27
  • Thanks so much @Stefan for taking the time to answer this. I'll continue to work on the function and hopefully figure out what is going on before accepting this answer. – dpritch Aug 29 '18 at 14:00

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.