5

I'm using Outline mode (usually the minor mode, but it shouldn't matter) or Org mode. I have a file that looks like this:

 -*-outline-*- * Chapter 1 ** Section 1.1 *** Subsection 1.1.1 foo *** Subsection 1.1.2 bar ** Section 1.2 baz * Chapter 2 ** Section 2.1 qux ** Section 2.2 wib 

I'm editing subsection 1.1.1 (“foo”). I want to focus on this section, so I run C-c C-o (hide-other). This is what I see:

 -*-outline-*- * Chapter 1 ** Section 1.1 *** Subsection 1.1.1 foo... * Chapter 2... 

In the old days of Emacs 19 (the behavior changed after 19.34 and before 20.7), I saw this:

 -*-outline-*- * Chapter 1 ** Section 1.1 *** Subsection 1.1.1 foo *** Subsection 1.1.2... ** Section 1.2... * Chapter 2... 

The difference is that the headers for Section 1.2 and Subsection 1.1.2 are shown, because they're a sibling of Section 1.1 which contains Subsection 1.1.1 which I'm viewing. I like that. How can I get this behavior in a modern Emacs?

What I'm mainly looking for is a way to make hide-other (or a separate command) show all siblings of all visible headers (if I'm in Subsection 1.1.1, I want to see the headers for Section 1.2 and Subsection 1.1.2, and so on). More generally, I'd like a command outline-show-all-siblings-of-visible-headers. Is there such a thing?

2 Answers 2

2

Since the change was made as part of the Outline rewrite between Emacs 19 and Emacs 20 to use overlays (or close thereto), I had a look at the differences between hide-other from Emacs 19.34 and from Emacs 20.7. The change is easy enough to spot: in the Emacs 20+ definition, the body of the loop that traverses the headings upwards shows the heading it reaches only, while in Emacs 19, it calls show-children. So I tweaked the code of Emacs 23 to call show-children (hot patching with something like flet wouldn't work easily since outline-flag-region is used in many places).

(defun outline-focus () "Hide everything except for the current body and the parent headings. Unlike `hide-other' since Emacs 20, this function shows all siblings of visible headers." (interactive) (hide-sublevels 1) (let (outline-view-change-hook) (save-excursion (outline-back-to-heading t) (show-entry) (while (condition-case nil (progn (outline-up-heading 1 t) (not (bobp))) (error nil)) (show-children)))) (run-hooks 'outline-view-change-hook)) 

In Org mode, org-reveal with a prefix argument (C-u C-x C-r) does what I was looking for: show sibling headers of all headers encountered on the path upwards from the cursor position. Pressing S-tab (org-global-cycle) to get to the “overview” state, or C-u 0 S-tab to get to the “contents” state with minimal depth, followed by C-u C-x C-r gives me the view I wanted.

It's nicer for easy interactive use to mix Outline and Org commands, and call hide-other followed by org-reveal.

(autoload 'org-reveal "org") (defun gilles/outline-focus-entry () (interactive "@") (hide-other) (org-reveal t)) 

This also works in Outline mode, I just need the org-reveal function to be loaded.

1

Here is an modified solution that should reflect the requirements better. Not extensively tested nor optimized.

(defun my-outline-show-near-relatives () "Hides body of all other headings while keeping headers only of siblings and elder relatives." (interactive) (save-excursion (let ((level (progn (outline-back-to-heading) (funcall outline-level)))) (hide-other) (while (> level 1) (outline-up-heading 1) (show-children 1) (setq level (funcall outline-level)))))) 

You can see it in action.

screencast of outlining command

First attempt for posterity sake

Here is an attempt that does what I think you want. Not extensively tested

(defun my-outline-show-all-siblings-of-visible-headers () "Hides body of all other headings while keeping headers of only visible siblings." (interactive) (save-excursion (hide-other) (outline-up-heading 1) (show-children 1))) 

For instance the following layout is outlined as follows depending on where point is.

* Chapter 1 ** Section 1.1 foo ** Section 1.2 bar *** Section 1.2.1 lorem *** Section 1.2.2 ipsum ** Section 1.3 abracadabra *** Section 1.3.1 hocus pocus * Chapter 2 ** Section 2.1 qux ** Section 2.2 wib 

When point ▌is in Section 1.2.2, it becomes

 * Chapter 1 ... ** Section 1.2 ... *** Section 1.2.1... *** Section 1.2.2 ipsum▌... * Chapter 2... 

When point is in Section 1.3, it becomes

* Chapter 1 ** Section 1.1... ** Section 1.2... ** Section 1.3 abracadabra▌ ... * Chapter 2... 
3
  • This doesn't work when the outline level goes up by more than 1 at some heading. You need to call outline-level again at each iteration. I should go and look at the Emacs 19 code. Commented Oct 16, 2014 at 20:03
  • Yeah, I did not consider that. Nice spot. Commented Oct 16, 2014 at 22:48
  • In that case, (outline-up-heading 1) will just echo a message when it reaches the root (before level goes to 1). Not the most robust code, but still gets the job done. Commented Oct 16, 2014 at 23:46

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.