Subject: 29.0.50; emacs-news-view-mode breakage

From: Stephen Berman <[email-masked]>
Date: Tue, 09 Aug 2022 18:18:11 +0200

0. emacs -Q

1. Type `C-h n'
=> The NEWS buffer is displayed without icons on the header lines,
although the value of `outline-minor-mode-use-buttons' is `(derived-mode
. special-mode)'.

2. Type `C-c C-n' to move point to the first NEWS header "* Installation
Changes in Emacs 29.1" and then type TAB
=> Now there is an outline-close icon (emoji) at the beginning of the
header, the header has lost its first-level fontification and the NEWS
buffer is flagged as modified in the mode line. But instead of hiding
the current header line's body as per outline-cycle, there is no other
change in the buffer.

3. Type TAB again
=> forward-button is executed instead of outline-cycle, indicating that
the line with the icon is now not being treated as an outline header
line.  And typing `M-< C-c C-n' now puts point on the first second level
header below the line with the icon.

4. Move point back to the icon and type RET
=> The icon changes to outline-open but there is otherwise no change in
the outline structure, and the message "Before first heading" is
displayed.

5. Type `C-c @ C-q' (outline-hide-sublevels)
=> The outline-close icon is inserted at the start of the second-level
header below the current line and after the icon only "..."  is
displayed, i.e. all remaing text in the buffer has vanished.
Repeatedly typing RET toggles the icon between outline-open and
outline-close and displays the message "Before first heading" but the
text remains hidden.  (Typing `C-c @ C-a' unhides the text.)

The attached patch appears to fix the problems described above, but the
only buffer using outline-minor-mode beside NEWS that I've tested it on
is *Help* showing the output of describe-bindings, and the seems to work
as expected with the patch (and due to the patch is not flagged as
modified, though that isn't important for *Help*.)

In GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.17.6)
 of 2022-08-09 built on strobelfs2
Repository revision: f1f1912658556e2f2a39cdae0da7ea2b8564d861
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101003
System Description: Linux From Scratch r11.0-165

Configured using:
 'configure --with-xinput2 --with-xwidgets 'CFLAGS=-Og -g3'
 PKG_CONFIG_PATH=/opt/qt5/lib/pkgconfig'

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBSYSTEMD LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG RSVG
SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM
XINPUT2 XPM XWIDGETS GTK3 ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

diff --git a/lisp/outline.el b/lisp/outline.el
index 7750f9a75d..35524a79a9 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -435,7 +435,7 @@ outline-minor-mode-highlight-buffer
                          (goto-char (match-beginning 0))
                          (not (get-text-property (point) 'face))))
             (overlay-put overlay 'face (outline-font-lock-face)))
-          (when (outline--use-buttons-p)
+          (when (and (outline--use-buttons-p) (outline-on-heading-p))
             (outline--insert-open-button)))
         (goto-char (match-end 0))))))

@@ -452,11 +452,10 @@ outline-minor-mode
   (if outline-minor-mode
       (progn
         (when outline-minor-mode-highlight
-          (if (and global-font-lock-mode (font-lock-specified-p major-mode))
-              (progn
-                (font-lock-add-keywords nil outline-font-lock-keywords t)
-                (font-lock-flush))
-            (outline-minor-mode-highlight-buffer)))
+          (when (and global-font-lock-mode (font-lock-specified-p major-mode))
+            (font-lock-add-keywords nil outline-font-lock-keywords t)
+            (font-lock-flush))
+          (outline-minor-mode-highlight-buffer))
 	;; Turn off this mode if we change major modes.
 	(add-hook 'change-major-mode-hook
 		  (lambda () (outline-minor-mode -1))
@@ -1011,32 +1010,34 @@ outline--make-button-overlay
     o))

 (defun outline--insert-open-button ()
-  (save-excursion
-    (beginning-of-line)
-    (when (derived-mode-p 'special-mode)
-      (let ((inhibit-read-only t))
-        (insert "  ")
-        (beginning-of-line)))
-    (let ((o (outline--make-button-overlay 'open)))
-      (overlay-put o 'help-echo "Click to hide")
-      (overlay-put o 'keymap
-                   (define-keymap
-                     "RET" #'outline-hide-subtree
-                     "<mouse-2>" #'outline-hide-subtree)))))
+  (with-silent-modifications
+    (save-excursion
+        (beginning-of-line)
+        (when (derived-mode-p 'special-mode)
+          (let ((inhibit-read-only t))
+            (insert "  ")
+            (beginning-of-line)))
+        (let ((o (outline--make-button-overlay 'open)))
+          (overlay-put o 'help-echo "Click to hide")
+          (overlay-put o 'keymap
+                       (define-keymap
+                         "RET" #'outline-hide-subtree
+                         "<mouse-2>" #'outline-hide-subtree))))))

 (defun outline--insert-close-button ()
-  (save-excursion
-    (beginning-of-line)
-    (when (derived-mode-p 'special-mode)
-      (let ((inhibit-read-only t))
-        (insert "  ")
-        (beginning-of-line)))
-    (let ((o (outline--make-button-overlay 'close)))
-      (overlay-put o 'help-echo "Click to show")
-      (overlay-put o 'keymap
-                   (define-keymap
-                     "RET" #'outline-show-subtree
-                     "<mouse-2>" #'outline-show-subtree)))))
+  (with-silent-modifications
+    (save-excursion
+        (beginning-of-line)
+        (when (derived-mode-p 'special-mode)
+          (let ((inhibit-read-only t))
+            (insert "  ")
+            (beginning-of-line)))
+        (let ((o (outline--make-button-overlay 'close)))
+          (overlay-put o 'help-echo "Click to show")
+          (overlay-put o 'keymap
+                       (define-keymap
+                         "RET" #'outline-show-subtree
+                         "<mouse-2>" #'outline-show-subtree))))))

 (defun outline--fix-up-all-buttons (&optional from to)
   (when from
diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el
index c7fa9fa2b2..e6e1f03728 100644
--- a/lisp/textmodes/emacs-news-mode.el
+++ b/lisp/textmodes/emacs-news-mode.el
@@ -69,11 +69,9 @@ emacs-news-mode-font-lock-keywords

 (defun emacs-news--mode-common ()
   (setq-local font-lock-defaults '(emacs-news-mode-font-lock-keywords t))
-  (setq-local outline-regexp "\\*+ "
+  (setq-local outline-regexp "\\(:? +\\)?\\(\\*+\\) "
               outline-minor-mode-cycle t
-              ;; We subtract one from the level, because we have a
-              ;; space after the asterisks.
-              outline-level (lambda () (1- (length (match-string 0))))
+              outline-level (lambda () (length (match-string 2)))
               outline-minor-mode-highlight 'append)
   (outline-minor-mode))