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?

4
  • 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
    Commented Oct 4, 2015 at 8: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
    Commented Oct 4, 2015 at 9: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
    Commented Oct 4, 2015 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
    Commented Oct 4, 2015 at 16:15

2 Answers 2

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

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)

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.