I often find I want to close the nearest parent subtree, but don't know of a better way of doing this than navigating to the header first and then pressing tab. I use evil-mode, so properly this should be the effect of zc, but it is not.

  • Having added that answer I now notice that zc does work for me, and is bound to evil-close-fold. Try it by starting emacs with emacs -q, and then only enable the minimum configuration to test that? If that works the problem is with your emacs initialization, and you can start to narrow it down, e.g. using eval-region on your init file. Sep 4 '16 at 0:46
  • @CroadLangshan, sorry, I think my problem was that I expected it to work on plain lists too.
    – Toothrot
    Sep 4 '16 at 7:22
  • @CroadLangshan, does repeated zc close everything for you, if you are in a subsubsubtree?
    – Toothrot
    Sep 4 '16 at 7:33
  • Repeated zc doesn't keep closing parents for me, but it works even if point is inside a list. I'm not sure how to test for tree node visibility in org, so not sure how to make a function that keeps closing parents... Sep 4 '16 at 11:52

I tried implementing the 'keep closing parent' behaviour (please edit the question to say more explicitly what you wanted). I'm quite sure this can be drastically simplified and is likely buggy, but this seems to work for me:

(defun my/org-get-folded-state ()
        ((not (or (org-at-item-p) (org-at-heading-p)))
            (let (eoh eol eos has-children children-skipped struct)
                ;; First, determine end of headline (EOH), end of subtree or item
                ;; (EOS), and if item or heading has children (HAS-CHILDREN).
                    (if (org-at-item-p)
                            (setq struct (org-list-struct))
                            (setq eoh (point-at-eol))
                            (setq eos (org-list-get-item-end-before-blank (point) struct))
                            (setq has-children (org-list-has-child-p (point) struct)))
                        (setq eoh (save-excursion (outline-end-of-heading) (point)))
                        (setq eos (save-excursion (org-end-of-subtree t t)
                                      (when (bolp) (backward-char)) (point)))
                        (setq has-children
                            (or (save-excursion
                                    (let ((level (funcall outline-level)))
                                        (and (org-at-heading-p t)
                                            (> (funcall outline-level) level))))
                                    (org-list-search-forward (org-item-beginning-re) eos t)))))
                    ;; Determine end invisible part of buffer (EOL)
                    (beginning-of-line 2)
                    (while (and (not (eobp)) ;; this is like `next-line'
                               (get-char-property (1- (point)) 'invisible))
                        (goto-char (next-single-char-property-change (point) 'invisible))
                        (and (eolp) (beginning-of-line 2)))
                    (setq eol (point)))
                    ((= eos eoh)
                    ((or (>= eol eos)
                         (not (string-match "\\S-" (buffer-substring eol eos))))

(defun my/org-at-list-root ()
    ;; (org-at-item-p) must be true when you call this
        (let ((old (point)))
            (eq (point) old))))

(defun my/org-jump-to-parent-item ()

(defun my/org-tree-can-fold-p ()
    (not (member (my/org-get-folded-state) (list 'folded 'empty-node))))

(defun my/org-cycle-until-folded ()
    (while (my/org-tree-can-fold-p)

(defun my/org-close-next-parent ()
            (if (my/org-tree-can-fold-p)
                (if (my/org-at-list-root)
            (if (my/org-tree-can-fold-p)
                (if (not (eq (org-outline-level) 1))
                          (call-interactively #'outline-up-heading)
            ;; in heading
  • This doesn't seem to work anymore.
    – Toothrot
    Dec 29 '17 at 16:24

How about something like this?

(defun my/org-cycle-parent-heading ()

I'm using use-package, general and evil-org-mode, so my key binding configuration for that looks like this:

(use-package org
    (:states '(normal) :keymaps 'evil-org-mode-map
         "zc" 'my/org-cycle-parent-heading))

This seems work.

(defun evil*-close-fold () (interactive)
 (if (and (or (org-at-heading-p)
              (invisible-p (point)))
          (invisible-p (point-at-eol))
          (>= (org-current-level) 2))
     (outline-up-heading 1))

(define-key evil-normal-state-map (kbd "zc") 'evil*-close-fold)

The disjunction is necessary because, after evil-close-fold, (org-at-heading-p) will not return t, unless point was at the heading from before.

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.