How can I set up a dynamic TOC with an org subtree on a new window? (TOC on the left, org heading and contents on the right.) The following functions by @blujay from

How can I get an org-mode outline in a 2nd buffer as a dynamic table of contents?

gets me most of the way there. Adding (org-narrow-to-element) or (org-narrow-to-subtree) to the second function (my/jump-to-point-and-show) opens the narrowed heading, but as I click through the headings in the TOC, subsequent headings don't open as expected. Also only the heading shows, but the contents stay collapsed unless I press TAB.

Here's the function from the StackExchange page linked above:

 (defun my/open-tree-view ()
  "Open a clone of the current buffer to the left, resize it to 30 columns, and bind <mouse-1> to jump to the same position in the base buffer."
  (let ((new-buffer-name (concat "<tree>" (buffer-name))))
    ;; Create tree buffer
    (split-window-right 30)
    (if (get-buffer new-buffer-name)
        (switch-to-buffer new-buffer-name)  ; Use existing tree buffer
      ;; Make new tree buffer
      (progn  (clone-indirect-buffer new-buffer-name nil t)
              (switch-to-buffer new-buffer-name)

              ;; Do this twice in case the point is in a hidden line
              (dotimes (_ 2 (forward-line 0)))

              ;; Map keys
              (use-local-map (copy-keymap outline-mode-map))
              (local-set-key (kbd "q") 'delete-window)
              (mapc (lambda (key) (local-set-key (kbd key) 'my/jump-to-point-and-show))
                    '("<mouse-1>" "RET"))))))

(defun my/jump-to-point-and-show ()
  "Switch to a cloned buffer's base buffer and move point to the cursor position in the clone."
  (let ((buf (buffer-base-buffer)))
    (unless buf
      (error "You need to be in a cloned buffer!"))
    (let ((pos (point))
          (win (car (get-buffer-window-list buf))))
      (if win
          (select-window win)
        (other-window 1)
        (switch-to-buffer buf))
      (goto-char pos)
      (when (invisible-p (point))

(I would also like to thank @blujay for the code snippets.)

1 Answer 1


I forgot to first widen the narrowed org element before applying the second function again. Adding widen, olivetti-mode, org-narrow-to-element, and org-show-chidren does the job. Changes made to the second function:

      (goto-char pos)  
      (olivetti-mode 1)

Once again, many thanks to @blujay. As a non-programmer, I had been struggling to get this right for a while.

Comments: (org-narrow-to-element) messes up the next heading in the TOC. I suggest using (org-narrow-to-subtree) instead. I'm leaving the above code unchanged to highlight this (i.e., my) mistake.

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.