5

Q: how do I make source blocks fold automatically when I hide the contents of their entry?

I'd like source code blocks to fold automatically whenever I hide an entry so that they're always out of the way until I specifically want to see them. Out of the box, however, their visibility seems to be independent of their home entry's visibility.

For example, if I have:

* An entry
  #+begin_src R
    x <- 1:10
  #+end_src

Some descriptive text.

I can toggle the visibility of the source block with TAB when point is on the begin_src line. However, when I hide (fold) the entry and then show (unfold) it again, the source block seems to remember it's prior visibility state: if it was visible/open, it will be visible when I show/unfold the entry, and if it was invisible/closed, it will be invisible/closed when I show/unfold the entry.

I want to fold/hide my source blocks automatically whenever I fold/hide the entry that contains them. How do I do that?

PS I'm just now learning how to use source blocks, so I may be missing an obvious solution. Apologies if so.

1 Answer 1

2

In emacs 25.1 there is org-cycle-hook. I've stolen org-cycle-hide-drawers and adapted it to the case of blocks. The resulting code below does exactly what you want in emacs 25.1.

(defun org-cycle-hide-blocks (state &optional exceptions)
  "Re-hide all blocks after a visibility state change.
When non-nil, optional argument EXCEPTIONS is a list of strings
specifying which blocks should not be hidden."
  (when (and (derived-mode-p 'org-mode)
         (not (memq state '(overview folded contents))))
    (save-excursion
      (let* ((globalp (memq state '(contents all)))
             (beg (if globalp (point-min) (point)))
             (end (if globalp (point-max)
            (if (eq state 'children)
            (save-excursion (outline-next-heading) (point))
              (org-end-of-subtree t)))))
    (goto-char beg)
    (while (re-search-forward org-block-regexp (max end (point)) t)
      (unless (member-ignore-case (match-string 1) exceptions)
        (let ((block (org-element-at-point)))
          (when (memq (org-element-type block) '(src-block))
        (org-hide-block-toggle t)
        ;; Make sure to skip block entirely or we might flag
        ;; it another time when matching its ending line with
        ;; `org-block-regexp'.
        (goto-char (org-element-property :end block))))))))))

(add-hook 'org-cycle-hook 'org-cycle-hide-blocks)
5
  • Thank you. It kind of works, but has problems with some of the blocks. For example, it correctly hides blocks with headers such as #+begin_src R, but not those such as #+begin_src R :results silent.
    – Dan
    Commented Feb 18, 2016 at 21:50
  • @Dan Just tried it with #+begin_src R :results silent. Works as expected. Which version of emacs do you have? Could it be that you have some spelling error by accident in the keywords for the source block?
    – Tobias
    Commented Feb 18, 2016 at 22:09
  • Hmm, not sure what's going on. I'm on 24.5 right now.
    – Dan
    Commented Feb 18, 2016 at 22:10
  • That's interesting because the doc of org-cycle-hook says "This variable was introduced, or its default value was changed, in version 25.1 of Emacs. Maybe, it is just the changed default value. Maybe, you should add a complete example (in your question) for the reproduction of the problem. In my opinion it is okay to post it in the question because it is one case that should work.
    – Tobias
    Commented Feb 18, 2016 at 22:12
  • @Dan I have Ubuntu 14.04 LTS with emacs 24.3. Some features such as nadvice do not work with 24.3. So I installed emacs-snapshot and this is 25.1. Maybe, this is an interesting option for you, too?
    – Tobias
    Commented Feb 18, 2016 at 22:21

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.