6

I need to make a function that will choose an org mode file if emacs was called with no arguments, and basically go about its way otherwise.

So far I have

  (defun personaltodo ()
   (if (= 1 (length command-line-args))
      (find-file "~/personalorg")
   )
  )

This works only if I'm calling emacs plainly. If I call it like

emacs testfile

Or through another program like Mutt, it doesn't open it and I'm forced to switch with

C-x b

Anyone have any ideas?

3
  • If you set 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.
    – glucas
    Aug 27, 2015 at 1:12
  • 1
    @glucas Maybe this isn't emacs' fault. Perhaps this a use-case issue that I could solve by simply aliasing a command to it, like alias emacsp=`emacs ~/personalorg` and training myself to type that instead of just emacs
    – Bronze
    Aug 27, 2015 at 1:31
  • Yeah, I don't see a good solution. This might be worth a bug report... During startup Emacs builds a list of possible buffers to display from the command-line files and then prepends whatever initial-buffer-choice returns. It would be nice if you could safely return nil from initial-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 custom initial-buffer-choice function could know whether some displayable buffers had already been identified.
    – glucas
    Aug 27, 2015 at 2:57

1 Answer 1

6

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.