3

I have the following setup, created through a function I've defined in this reddit post, which states in relevant part:

(defun hd/weekly-review ()
  "Organize a series of windows for weekly reviews"
  ;; Define Keyboard Macro to narrow to weekly review checklist
  (fset 'hd-km/narrow-weekly-review-list
   [?\M-< ?\C-s ?w ?e ?e ?k ?l ?y return ?\C-x ?n ?s])

  (interactive)
  (delete-other-windows)

  ;; Start with org-agenda
  (org-agenda nil "R")
  (set-window-dedicated-p (selected-window) 1)
  (delete-other-windows)

  ;; Create a window for follow-mode (and blank it out with *scratch* so it's less distracting)
  (split-window-horizontally)
  (display-buffer "*scratch*" t)

  ;; Create the third window for the maintenance.org
  (other-window 1)
  (split-window-vertically (floor (* 0.78 (window-height))))
  (other-window 1)
  (find-file "~/org-docs/org-system/maintenance.org")
  (set-window-dedicated-p (selected-window) 1)
  (execute-kbd-macro (symbol-function 'hd-km/narrow-weekly-review-list))
  (show-all)
  (other-window -2)

  ;; Add to registers config for quick switch back within this session
  (window-configuration-to-register ?w))

To summarise, two windows are dedicated to buffers, and one is left undedicated:

-------------------------------------------------
|                 |                             |
|                 |      2a: agenda 'follow'    |
|                 |        (not dedicated)      |
|                 |                             |
|  1a: org-agenda |-----------------------------|
|   (dedicated)   |                             |
|                 |                             |
|                 |   2b: reference .org file   |
|                 |          (dedicated)        |
|                 |                             |
|                 |                             |
-------------------------------------------------

If I perform an action in 2a which creates a pop-up window (e.g. C-c C-t on a org file heading which brings up org todo), emacs creates a new frame to display the contents of the pop-up (which steals focus & remains even after the action associated with the pop-up is completed).

After alot of reading it seems that this problem could be avoided by adding a custom entry to display-buffer-alist.

However, this post suggests that approach will not work since emacs essentially ignores display-buffer-alist for the org todo keywords buffer. The solution proposed is to amend the buffer switching functionality of org-fast-todo-selection. Whilst the change is trivial, I'm reluctant to do so for forwards compatibility reasons.

Is there a better way to achieve what I want here?

xeijin
  • 101
  • 8
  • 1
    File a bug for Org. It's clearly erroneous behaviour to bind `display-buffer-alist` because this stops people from customizing buffer popups, so it's Org's responsibility to undo this, even if it means the default behaviour will change. – wasamasa Oct 04 '15 at 08:58
  • Thanks, I've filed a report. In the mean-time, is there perhaps a way to advise `org-fast-todo-selection` to use the original emacs buffer switching logic rather than org's custom one? I'm still new to elisp and have had a bit of trouble figuring this out. – xeijin Oct 04 '15 at 09:52
  • Use something along the lines of `(eval-after-load 'org '(defun org-fast-todo-selection () ...))` in your init file. The definition is up to you, but could be taken as is from your linked post. – wasamasa Oct 04 '15 at 10:05
  • Have a look at `org-switch-to-buffer-other-window` and `org-no-popups` -- `org-fast-todo-selection` calls the former, which in turn calls the latter. – lawlist Oct 04 '15 at 16:15

2 Answers2

2

I just posted an answer to the question you linked to that advises org-fast-todo-selection. Depending on exactly what behavior you want to achieve, you may be able to modify that code to do what you want (or even take it as-is).

Aaron Harris
  • 2,664
  • 17
  • 22
1

Aaron's solution provided the answer, which I then modified as suggested to fit my purposes. For anyone interested in the modification see below:

; Macro which creates advice 'template'
(defmacro my/with-advice (adlist &rest body)
  "Execute BODY with temporary advice in ADLIST.

Each element of ADLIST should be a list of the form
  (SYMBOL WHERE FUNCTION [PROPS])
suitable for passing to `advice-add'.  The BODY is wrapped in an
`unwind-protect' form, so the advice will be removed even in the
event of an error or nonlocal exit."
  (declare (debug ((&rest (&rest form)) body))
           (indent 1))
  `(progn
     ,@(mapcar (lambda (adform)
                 (cons 'advice-add adform))
               adlist)
     (unwind-protect (progn ,@body)
       ,@(mapcar (lambda (adform)
                   `(advice-remove ,(car adform) ,(nth 2 adform)))
                 adlist))))

;;Function which replaces org-switch-to-buffer-other-window with emacs' original switch-to-buffer-other-window
(defun hd/org-todo-same-window (orig-fn)
  "Advice to fix window placement in `org-fast-todo-selection'."
  (let  ((override
      '("\\*Org todo\\*|\\*Org Note\\*"
        (display-buffer-use-some-window)
        (inhibit-same-window . nil)))) ;locally sets variable "override" as key-value pair for display-buffer-alist entry
    (add-to-list 'display-buffer-alist override) ;adds the contents of the above defined variable to display-buffer-alist
    (my/with-advice
        ((#'org-switch-to-buffer-other-window :override #'switch-to-buffer-other-window))
      (unwind-protect (funcall orig-fn)
        (setq display-buffer-alist
              (delete override display-buffer-alist))))))

; Injecting the relevant advice into the org-fast-todo-selection function
(advice-add #'org-fast-todo-selection :around #'hd/org-todo-same-window)
xeijin
  • 101
  • 8