0

I currently have my *Org Agenda* opening on startup using the following in my init.el:

(setq inhibit-splash-screen t) ;; no welcome screen

(defun agendafocus()
  "Focus on agenda at Startup"
  (org-agenda-list)
  (delete-other-windows))

(add-hook 'after-init-hook #'agendafocus) ;; agenda on startup

However, I would like this to occur only if no file buffers exist, i.e., if buffer-file-name is nil. How would one get this behaviour?

[EDIT]: The solution suggested by Tobias below almost works: When evaluated manually (M-x (agendamode), it works as expected (i.e. it only opens *Org Agenda* if no other file buffer is present), but does not work as a hook, either as an after-init-hook nor as a emacs-startup-hook.

1

You can use (cl-remove-if-not #'buffer-file-name (buffer-list)) as a predicate for detecting whether there are live file buffers:

(require 'cl-lib)
(setq inhibit-splash-screen t) ;; no welcome screen

(defun agendafocus()
  "Focus on agenda at Startup"
  (unless (cl-remove-if-not #'buffer-file-name (buffer-list))
    (org-agenda-list)
    (delete-other-windows)))

(add-hook 'emacs-startup-hook #'agendafocus t)

Clearly, one can provoke situations where this approach is incomplete.

For instance, if one neglects the APPEND argument t of add-hook in the above code it might be that there is another function hooked into emacs-startup-hook that opens a file.

Even with APPEND argument of add-hook there might be other hook functions added later on that open file buffers.

Other possible pitfalls would be files opened by org-adenda-list or by a timer.

| improve this answer | |
  • @sacul My bad. Please try again. Have swapped when with unless. – Tobias Jan 12 '18 at 15:39
  • That seems to reproduce the behaviour from my original function, agendafocus runs regardless of whether there are other buffers or not... Basically what I'm looking for is something along the lines of (pardon my pseudocode) "if buffer-file-name is nil: run agendafocus, else: do nothing", but I'm not familiar enough with elisp to get that working :$ – sacuL Jan 12 '18 at 15:55
  • @sacul Maybe, you should really use emacs-startup-hook as I suggested in my comment to your question. But, that depends when you generate the other buffers. Your question is not very clear in respect to the additional buffers you expect. Are those file buffers? In that case my solution should be perfect in conjunction with emacs-startup-hook. – Tobias Jan 12 '18 at 15:57
  • yes, those are file buffers (I believe, i.e. buffer-file-name is non-nil). However, even with emacs-startup-hook rather than after-init-hook (which makes much more sense, by the way, thanks for that suggestion, as I didn't know about that hook), it still produces the same behaviour – sacuL Jan 12 '18 at 16:05
  • @sacul FWIW, this approach works for me. – Basil Jan 12 '18 at 16:16
0

See Tobias' answer for the simplest and, in the face of user customisations, more robust solution.

Just for fun, I'd like to share an alternative approach based on an answer of mine to a similar question.

The idea is that, during startup, the only buffers that are usually open, other than standard splash/scratch/etc. buffers, are ones due to unrecognised command-line arguments. For example, emacs -q foo results in a file-visiting buffer named foo being displayed.

This allows us to set the user option initial-buffer-choice to a function which focusses the Org Agenda for the case when there are no unrecognised CLI arguments, and then revert the variable to its original value when unrecognised CLI arguments are detected. See (elisp) Command-Line Arguments for more information on this API.

Without further ado, the required incantations:

(defun my-org-agenda-focus ()
  "Display nothing but the Org Agenda in the selected frame.
Return `current-buffer' for `initial-buffer-choice'."
  (org-agenda-list)
  (delete-other-windows)
  (current-buffer))

(defun my-detect-cli-args ()
  "Inhibit `my-org-agenda-focus' on unrecognised CLI args.
Return nil, i.e. leave arguments unprocessed."
  (ignore (setq initial-buffer-choice nil)))

(add-hook 'command-line-functions #'my-detect-cli-args)

(setq initial-buffer-choice  #'my-org-agenda-focus)
(setq inhibit-startup-screen t)

Note that, starting with Org 9, you can also write

(defun my-org-agenda-focus ()
  "Display nothing but the Org Agenda in the selected frame.
Return `current-buffer' for `initial-buffer-choice'."
  (let ((org-agenda-window-setup 'only-window))
    (org-agenda-list))
  (current-buffer))

The approach of OP and Tobias, when hooked into emacs-startup-hook or window-setup-hook, has the advantage of being simpler and running after most, if not all, buffers, windows and frames have been created.

The CLI arg approach is more beneficial for fine-grained inspection of each argument. For example, you could take different actions depending on whether Emacs was invoked with a special keyword, a directory, a file or a non-existent file argument.

Ultimately you can combine both approaches for the superlative Emacs customisation experience.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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