0

Is there any option or other customization to keep the outline of an org-mode buffer (uncollapsed parts of the tree) after the buffer has been reverted (org-mode 9.0.1, emacs 25.3.2)? In my case only the top headings are displayed after reverting. This is quite annoying and time-consuming in a setup, where one constantly switches between git branches e.g.

  • 1
    Look at org-startup-folded's docstring, which might be the variable you're looking for. – DoMiNeLa10 Jan 18 '18 at 18:38
  • Thanks, but this doesn't help in this case. See below for the correct answer. – Roland Fehrenbacher Jan 20 '18 at 11:28
1

The correct answer was provided on the mailing list:

http://lists.gnu.org/archive/html/emacs-orgmode/2018-01/msg00336.html

Quotation of the relevant part of that message:

Org provides two functions to save and restore visibility (and a macro that does both, but isn't useful in your case): org-outline-overlay-data and org-set-outline-overlay-data.

You may want to use them within before-revert-hook and after-revert-hook.

The following is useful for implementing it:

https://stackoverflow.com/questions/6666862/org-mode-go-back-from-sparse-tree-to-previous-visibility/44158824#44158824


Note that the functions org-outline-overlay-data and org-set-outline-overlay-data do not exist anymore in Orgmode 9.2.

Citation of the incompatible changes of Orgmode 9.2:

Removed commands and functions

org-outline-overlay-data

Use org-save-outline-visibility instead.

org-set-outline-overlay-data

Use org-save-outline-visibility instead.

Possible Implementation

There follows Elisp code that preserves the outline state of headings over revert-buffer. It includes the definitions of org-outline-overlay-data and org-set-outline-overlay-data that have been deleted from Orgmode 9.2.

(defun org-outline-overlay-data (&optional use-markers)
  "Return a list of the locations of all outline overlays.
These are overlays with the `invisible' property value `outline'.
The return value is a list of cons cells, with start and stop
positions for each overlay.
If USE-MARKERS is set, return the positions as markers."
  (let (beg end)
    (org-with-wide-buffer
     (delq nil
       (mapcar (lambda (o)
             (when (eq (overlay-get o 'invisible) 'outline)
               (setq beg (overlay-start o)
                 end (overlay-end o))
               (and beg end (> end beg)
                (if use-markers
                (cons (copy-marker beg)
                      (copy-marker end t))
                  (cons beg end)))))
           (overlays-in (point-min) (point-max)))))))

(defun org-set-outline-overlay-data (data)
  "Create visibility overlays for all positions in DATA.
DATA should have been made by `org-outline-overlay-data'."
  (org-with-wide-buffer
   (org-show-all)
   (dolist (c data) (org-flag-region (car c) (cdr c) t 'outline))))

(defvar-local my-org-outline-state nil
  "Place for saving org outline state before reverting the buffer.")

(put 'my-org-outline-state 'permanent-local t)

(defun my-org-save-outline-state ()
  "Save org outline state in `my-org-outline-state'.
It can be recovered afterwards with `my-org-recover-outline-state'."
  (setq my-org-outline-state (org-outline-overlay-data t)))

(defun my-org-restore-outline-state ()
  "Save org outline state in `my-org-outline-state'.
It can be recovered afterwards with `my-org-recover-outline-state'."
  (when my-org-outline-state
    (org-set-outline-overlay-data my-org-outline-state)
    (setq my-org-outline-state nil)))

(defun my-org-install-save-outline-state ()
  "Configure org to preserve the outline state at revert-buffer."
  (add-hook 'before-revert-hook #'my-org-save-outline-state nil t)
  (add-hook 'after-revert-hook #'my-org-restore-outline-state nil t))

(add-hook 'org-mode-hook #'my-org-install-save-outline-state)

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.