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?

Drew
  • 75,699
  • 9
  • 109
  • 225
Bronze
  • 113
  • 1
  • 6
  • 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 '15 at 01: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 '15 at 01: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 '15 at 02:57

1 Answers1

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

glucas
  • 20,175
  • 1
  • 51
  • 83