The initial-buffer-choice
mechanism in startup.el
makes some assumptions that may not fit your use case.
Here's a quick overview of how Emacs decides what buffer(s) to display at startup:
- Command-line arguments are processed so that any files specified are opened in new buffers. These buffers are added to a list of displayable buffers.
initial-buffer-choice
is evaluated and the resulting buffer is pushed on to the displayable buffer list. If initial-buffer-choice
results in something other than a valid buffer, an error is thrown.
Once all the potentially displayable buffers are identified, Emacs picks which ones to show. If there is one, that's easy. If there are two or more the frame is split so you get two windows. If there are exactly two displayable buffers they are both shown; otherwise, the first one is chosen and a *Buffer List*
is shown in the other window.
As you've found, initial-buffer-choice
can be t
(meaning *scratch*
), a file name, or a function. If you use a function it must return a valid buffer or you'll get an error. In your code above you're returning nil
when there are command-line arguments.
Note that even if you improved your custom function to always return a valid live buffer (e.g. by examining (buffer-list)
and picking one), it may not always behave as you want because of how Emacs splits the frame and picks two buffers -- your function can only add to the list of displayable buffers, it cannot replace it.
I think the behavior you want (which seems like a reasonable feature request to me) would be to allow initial-buffer-choice
to return nil
as a way of indicating that no additional buffers should be added to the displayable buffers list and Emacs should show whatever it would have shown if initial-buffer-choice
had not been set at all. An even better enhancement might be to allow initial-buffer-choice
functions to access the current list of displayable buffers so they can choose to create some other buffer without having to re-examine the command-line arguments directly.
Update
Looks like this behavior is changing. From the 25.1 NEWS (as of 2015-10-05):
When Emacs is given a file as a command line argument and initial-buffer-choice
is non-nil, display both the file and initial-buffer-choice
. When Emacs is given more than one file and initial-buffer-choice
is non-nil, show initial-buffer-choice
and *Buffer List*.