2

I regularly use org-tree-to-indirect-buffer to edit an org-mode entry in a separate buffer. I also have org-indirect-buffer-display set to current-window so that org-tree-to-indirect-buffer automatically kills an old indirect buffer before creating a new one.

The problem is that sometimes I would be editing a source-code block using org-edit-src-code, but then forget to press C-c C-c to accept the changes. If I then call org-tree-to-indirect-buffer on another entry, the old indirect buffer is killed and the source buffer that org-edit-src-code created is orphaned. Pressing C-c C-c on that buffer returns "Source buffer disappeared. Aborting". Is there a way to make it so that source code buffers are automatically closed when the original buffer is killed?

TLDR, how can I automatically close Org Src created by org-edit-src-code when the original org buffer is killed?

1
  • You can add an advice to kill-buffer, assuming that is what org uses to kill an old indirect buffer, to check for this case. Mar 9 '20 at 13:34
1

The following Elisp code adds a function org+-kill-orphaned-edit-buffers to the special hook kill-buffer-query-functions buffer-locally in Org buffers.

That function scans the Org buffer for overlays with edit-buffer property and looks whether that buffer is a live org-src-edit buffer. If that is the case it tries to kill the source edit buffer.

The true/false-value of the option org+-query-before-kill-edit-buffer determines whether you should be asked for confirmation if a modified source buffer is going to be killed.

If some modified source buffer is not killed then the original Org buffer is also not killed.

But, if org+-query-before-kill-edit-buffer is nil (the default case) source edit buffers are killed unconditionally. So you only need to confirm killing if the Org buffer itself is modified.

(require 'cl-lib)

(defcustom org+-query-before-kill-edit-buffer nil
  "Query when killing an edited org src buffer."
  :type 'boolean
  :group 'org-src)

(defun org+-kill-orphaned-edit-buffers (&optional b e)
  "Close orphaned source edit buffers in the region from B to E.
B defaults to `point-min' and E defaults to `point-max'.
In interactive calls B and E are the boundaries of the region
if it is active."
  (interactive (when (region-active-p)
                 (list (region-beginning)
                       (region-end))))
  (unless b (setq b (point-min)))
  (unless e (setq e (point-max)))
  (cl-loop with buf
           for ol being the overlays from b to e
           if (and (setq buf (overlay-get ol 'edit-buffer))
                   (org-src-edit-buffer-p buf))
           unless (with-current-buffer buf
                    (when
                        (or (null org+-query-before-kill-edit-buffer)
                            (null (buffer-modified-p))
                            (save-window-excursion
                              (display-buffer (current-buffer))
                              (y-or-n-p (format "Buffer %s modified; kill anyway? " (buffer-name)))))
                      (set-buffer-modified-p nil)
                      (kill-buffer)))
           return nil
           finally return t))

(defun org+-kill-edit-buffers-at-kill-buffer ()
  "Close source edit buffer when the current Org buffer is killed."
  (add-hook 'kill-buffer-query-functions #'org+-kill-orphaned-edit-buffers t t))

(add-hook 'org-mode-hook #'org+-kill-edit-buffers-at-kill-buffer)
6
  • That's really nice, I am still learning elisp and using cl-lib definitely makes things easier! When trying this, I didn't get the confirmation message when org+-query-before-kill-edit-buffer was set to t. It seems that for some reason (at least in my setup), killing a modified source buffer does not prompt for a confirmation when the buffer is modified (this is the case for all temporary buffers in my case). I am not sure how to modify this behavior, so until I figure it out I changed (kill-buffer) to (org-edit-src-exit).
    – Tohiko
    Mar 11 '20 at 9:38
  • Ah, there are some conditions that must be met in order to query the user. I have to work that in. Note, that org-edit-src-exit did also not give the right results for me. I find a query better than silently adopting the changes from the source buffer.
    – Tobias
    Mar 11 '20 at 10:14
  • 1
    @Tohiko I have corrected the query. Could you test again? Thanks in advance.
    – Tobias
    Mar 11 '20 at 10:27
  • Thanks! Yes, I do get the confirmation message now. At the moment, when trying to kill the org buffer, the window switches to a previous buffer (like scratch) and stays there even if I abort the buffer killing. I added a (switch-to-buffer (buffer-name)) next to the y-or-n-p in a progn so that I switch to the source buffer when being prompted to close it. I also changed return nil to do (switch-to-buffer (current-buffer)) and return nil so that I am taken back to the buffer I started with when aborting the buffer-kill.
    – Tohiko
    Mar 11 '20 at 11:23
  • Thanks again, I really think this functionality should be added to org-mode.
    – Tohiko
    Mar 11 '20 at 11:25

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.