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
*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.
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*.