13

Q: how can I control which window org-deadline uses to display the calendar?

org-deadline temporarily pops up the calendar buffer in a window when setting a deadline, and then closes it again after completing. When there is only one window, it pops a new window at the bottom of the existing frame. When there are multiple windows, it selects one -- I presume with something like get-lru-window -- of the available windows.

The latter is problematic if it takes over one of the other windows that has the information I need in order to set the deadline (date, time, etc.) This is commonly a problem in a window setup such as:

+--------------------+--------------------+
|                    |                    |
|                    |  (B: mu4e header)  |
|                    |                    |
|                    +--------------------+
|  (A: agenda file)  |                    |
|                    |                    |
|                    |                    |
|                    |  (C: mu4e view)    |
|                    |                    |
|                    |                    |
|                    |                    |
+--------------------+--------------------+

When adding a deadline to the agenda file in (A), org-deadline will take over (B) or (C), which contain emails that have the date/time information I need. I'd much prefer that, if I'm calling org-deadline from (A), it would pop a temporary window (D) to contain the calendar buffer as below:

+--------------------+--------------------+
|                    |                    |
|                    |  (B: mu4e header)  |
|                    |                    |
|                    +--------------------+
|  (A: agenda file)  |                    |
|                    |                    |
|                    |                    |
+--------------------+  (C: mu4e view)    |
|                    |                    |
|   (D: calendar)    |                    |
|                    |                    |
+--------------------+--------------------+

So: how would one force org-deadline (and analogous functions) to pop a new, temporary window at the bottom of the active window rather than take over one of the other ones?

PS: I'm aware of dedicated windows, but they don't strike me as the best approach since it's not so much that I want to dedicate buffers to windows as I want to avoid having a function take over one of the "short" ones.

1
  • I really hope somebody comes back with an answer that gives fine control over new, temporary windows. (popwin.el? display-buffer-alist?) But I think there's an additional wrinkle here because org-deadline uses calendar which itself goes way out of its way to control what window to use. c.f. the comments in calendar-basic-setup. Oct 6, 2014 at 14:34

1 Answer 1

10

Following should do what you want.

(defun my-window-displaying-agenda-p (window)
    (equal (with-current-buffer (window-buffer window) major-mode)
        'org-agenda-mode)) 

(defun my-position-calendar-buffer (buffer alist)
  (let ((agenda-window (car (remove-if-not #'my-window-displaying-agenda-p (window-list)))))
    (when agenda-window
      (let ((desired-window (split-window agenda-window nil 'below)))
        (set-window-buffer desired-window  buffer)
        desired-window))))

(add-to-list 'display-buffer-alist (cons "\\*Calendar\\*" (cons #'my-position-calendar-buffer nil)))

Calendar uses the function calendar-basic-setup to display the calendar buffer, calendar-basic-setup in turn uses pop-to-buffer which in turn uses display-buffer to display the calendar buffer. Now display-buffer is highly customizable and allows us to provide functions to display a buffer using certain variables we use one such variable display-buffer-alist here.

Basically we are saying emacs to use the function my-position-calendar-buffer to display a buffer matching the regexp \*Calendar\*. The function my-position-calendar-buffer searches for a window displaying org agenda, if it does not find any such window, it does nothing in which case display-buffer will try some other functions to display the buffer. In case a window displaying org-agenda is found the function splits that window vertically and displays the calendar buffer.

I have not tested this throughly (just tried starting calendar with agenda view and without agenda view), it seems to be working but there might be some bugs.

4
  • 1
    It would be preferable to use something like add-to-list on display-buffer-alist. Using setq overrides other customizations.
    – Malabarba
    Oct 6, 2014 at 21:37
  • @Malabarba thanks for the suggestion, fixed! Oct 7, 2014 at 0:48
  • Just an update for those running into this answer with emas version > 24.X: to use the code above you need to replace remove-if-not with cl-remove-if-not.
    – apc
    Jun 24, 2020 at 14:38
  • Not sure about earlier ones, but at least in emacs 27 and 28, remove-if-not still exists as an alias to cl-remove-if-not. That might elicit a warning, but it is not going to break. But @apc is correct that you should fix the code: the alias might go away eventually. At least for now, though, you don't need to.
    – NickD
    Jul 12, 2021 at 14:28

Your Answer

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

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