Subject: bug#51809: 29.0.50; [PATCH] Support for outline default state in Diff buffers

From: Matthias Meulien <[email-masked]>
Date: Mon, 14 Feb 2022 22:07:32 +0100

Juri Linkov <[email-masked]> writes:

> But the problem with the reported attached file is different:
> in that file outlines are never displayed even outside of Gnus.
> This is because the diff format is slightly different, but
> `outline--show-headings-up-to-level' first hides all outlines,
> but then fails to unhide them back.
>
> Matthias, could you please check what is wrong with the reported diff file
> and why vasibility of its outlines can't be changed?

First note that with the reported attached file `diff-buffer-type' isn't
equal to 'git: There's no "diff --git" header.

If you replace the file first three lines with the following four lines
then there's no outline problem:

diff --git a/woman.el.orig b/woman.el
index 44328a2b28..214f7435d9 100644
--- a/woman.el.orig
+++ b/woman.el

When `diff-buffer-type' is nil, `outline-regexp' is set to
`diff-outline-regex', which default to "\\([*+][*+][*+] [^0-9]\\|@@
...\\|\\*\\*\\* [0-9].\\|--- [0-9]..\\)", and `outline-level' use the
default function which returns the number of characters matched by
‘outline-regexp’

Since the regexp match the first 5 characters of the first line of the
diff ("+++ w") and the first 6 characters of the second line ("@@
-22"), the file has two headings at level 5 and 6!

If you have set `outline-default-state' to be equal to 1 and kept
`outline-default-rules' to its default nil (meaning the subtree starting
at level 1 must be hidden), then the file outlines are logically hidden
by `outline-apply-default-state'.

I suspect that it's what you see.

>From my pov, the problem doesn't come from the "default outline state
machinery" but from wrong defaults for `outline-level' when
`diff-buffer-type' is  nil.

My first impression is that setting `outline-level' to
`diff--outline-level' inconditionnaly should work but since I don't
understand why `diff-outline-regex' hasn't been defined in terms of
`diff-file-header-re' and `diff-hunk-header-re' I guess I am missing
some subtleties.

(Note that there's another minor bug when `diff-buffer-type` isn't equal
to 'git: `diff--font-lock-prettify` should be a no-op since the regexp
written there match only Git generated diffs, confirmed by the FIXME
string "This has only been tested with Git's diff output." written in
the implementation).
-- 
Matthias