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*.
initial-buffer-choice
to a custom function, Emacs will try to show that buffer. To get the kind of behavior you want you'll need to return some buffer in the case when there was more than 1 argument -- I don't believe you can tell Emacs to pick whatever buffer it was going to pick by default. Rather you may need to look at(buffer-list)
and pick one.alias emacsp=`emacs ~/personalorg`
and training myself to type that instead of justemacs
initial-buffer-choice
returns. It would be nice if you could safely return nil frominitial-buffer-choice
to mean "don't add anything", which would allow for the conditional initial buffer behavior that you want. Right now returning nil results in an error. It would also be nice if a custominitial-buffer-choice
function could know whether some displayable buffers had already been identified.