Subject: 28.0.50; Prevent duplicate thread titles in Gnus

From: Kévin Le Gouguec <[email-masked]>
Date: Thu, 09 Apr 2020 11:27:15 +0200

Hello,

After tweaking gnus-sum-thread-tree-* options and messing with
gnus-summary-make-false-root before settling for 'dummy, I found a setup
I am mostly satisfied with for displaying loose threads:

(example from bug-gnu-emacs)
                     ┌◈                          bug#40337: 28.0.50; Enable case-fold-search in hi-lock
    02:08            ├► Juri Linkov
    05:33            ╰► Stefan Monnier

Yet sometimes I end up with threads where both the dummy line and the
first article show the title:

(example from emacs-devel)
                     ┌◈                          Re: Emacs's set-frame-size can not work well with gnome-shell?
    10:32            ├► martin rudalics          Re: Emacs's set-frame-size can not work well with gnome-shell?
    16:04            │╰► Eli Zaretskii
    10:33            ├► martin rudalics
    15:19            │╰► Dmitry Gutov
    10:33            ╰► martin rudalics

Ideally, I would like for loose threads to show the subject only once,
on the dummy root line.  IIUC, "%S" in gnus-summary-dummy-line-format
and "%s" in gnus-summary-line-format should get me that; quoting the
latter's docstring:

> %S          Subject (string)
> %s          Subject if it is at the root of a thread, and ""
>             otherwise (string)

I don't know if the duplicate subject I see is due to me misconfiguring
something[1], if this is a corner case that needs to be addressed in
Gnus, or if I am misreading the docstring, i.e. "at the root of a
thread" means "at the non-dummy root of a thread".

In case it's a corner case, here is my stab at fixing it:

>From 5c45214e42322ff84a9f2fa8e28616898e77ea2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= <[email-masked]>
Date: Thu, 9 Apr 2020 11:05:39 +0200
Subject: [PATCH] Simplify dummy root subject before comparing it to the
 current article

* lisp/gnus/gnus-sum.el (gnus-summary-prepare-threads): Simplify both
the dummy root and the following article before comparing them,
otherwise both the former and the latter might display the thread's
subject even when gnus-summary-line-format contains "%s".
---
 lisp/gnus/gnus-sum.el | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index a47e657623..3251ee5974 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -5352,7 +5352,7 @@ gnus-summary-prepare-threads
 	      ;; We remember that we probably want to output a dummy
 	      ;; root.
 	      (setq gnus-tmp-dummy-line gnus-tmp-header)
-	      (setq gnus-tmp-prev-subject gnus-tmp-header))
+	      (setq gnus-tmp-prev-subject (gnus-simplify-subject-fully gnus-tmp-header)))
 	     (t
 	      ;; We do not make a root for the gathered
 	      ;; sub-threads at all.
-- 
2.26.0

AFAIU gnus-tmp-prev-subject is only used for comparison with
simp-subject, which as its name implies is obtained with
gnus-simplify-subject-fully.  So from my naive POV it seems sound to
apply gnus-simplify-subject-fully to gnus-tmp-prev-subject… at least it
seems to get me what I want: only the dummy root shows the subject, in
every situation I could test[2].

WDYT?  Let me know if this report needs more details.  I admit I did not
dig very deep before submitting this patch; it's entirely possible that
there is an issue somewhere else (something in my configuration, some
bug in the thread gathering code…), or, as I said, that it's all normal
and dummy roots should not cause "%s" to elide subsequent subjects
(though I'd prefer if they did, FWIW).

Thank you for your time.

[1] Full .gnus configuration here:

https://gitlab.com/peniblec/dotfiles/raw/master/.gnus

Relevant snippet:

#+begin_src elisp
(setq gnus-select-method
      '(nnimap "gmail"
               (nnimap-address "imap.gmail.com")
               (nnimap-server-port 993)
               (nnmail-expiry-target "nnimap+gmail:[Gmail]/Trash")
               (nnmail-expiry-wait immediate))
      gnus-secondary-select-methods
      '((nntp "archive.lwn.net")
        (nntp "news.gmane.io"))
      gnus-summary-line-format "%*%U%R  %-16,16&user-date; %B%-23,23n  %s\n"
      gnus-summary-dummy-line-format "                     ┌◈                          %S\n"
      gnus-summary-make-false-root 'dummy
      gnus-sum-thread-tree-root "┌◈ "
      gnus-sum-thread-tree-false-root "┄┐ "
      gnus-sum-thread-tree-single-indent " ◈ "
      gnus-sum-thread-tree-indent " "
      gnus-sum-thread-tree-single-leaf "╰► "
      gnus-sum-thread-tree-leaf-with-other "├► "
      gnus-sum-thread-tree-vertical "│"
      gnus-thread-sort-functions
      '(gnus-thread-sort-by-number
        (not gnus-thread-sort-by-most-recent-number))
      gnus-treat-display-smileys nil
      gnus-user-date-format-alist '(((gnus-seconds-today)
                                     . "%H:%M")
                                    ((+ 86400 (gnus-seconds-today))
                                     . "Yesterday %H:%M")
                                    (604800
                                     . "%a %H:%M")
                                    ((gnus-seconds-month)
                                     . "%a %d")
                                    ((gnus-seconds-year)
                                     . "%b %d")
                                    (t
                                     . "%F")))
#+end_src

Relevant history of thread settings:

https://gitlab.com/peniblec/dotfiles/-/commit/d560753f64fc87e9377608bc7e3b1b7c2d2b5aca.patch
https://gitlab.com/peniblec/dotfiles/-/commit/41fecec385e15c3447c1aab4c0840d60a1e2e7af.patch
https://gitlab.com/peniblec/dotfiles/-/commit/0730a1177d43edadf7aa54e46c952fb5a561687a.patch
https://gitlab.com/peniblec/dotfiles/-/commit/ed713fdae47c1207b0efbe0692e2ef74713ba77c.patch
https://gitlab.com/peniblec/dotfiles/-/commit/e1d0940289e061b84876f33b4fb7f8c5a442412a.patch
https://gitlab.com/peniblec/dotfiles/-/commit/3de2177a110e987fa04f6792ad7f9b1d198335be.patch
https://gitlab.com/peniblec/dotfiles/-/commit/d3a52e8c77c588a190714767f5f607ab7270bfec.patch

[2] BTW I'd love to provide a test case for this, as it would make
    reproduction easier for both me and patch reviewers; I have no idea
    how to cook up an ERT test for Gnus though.  The tests under
    test/lisp/gnus do not really cover thread formatting AFAICT; maybe I
    should look into Eric's gnus-mock ELPA package?

    Ideally, I'd like to 1. dump a thread (or all the articles in a
    summary buffer if that's simpler) to some format, then 2. ask Gnus
    to read this dump into a summary buffer.  Afterward crude string
    comparisons would be enough to check whatever needs to be checked.

In GNU Emacs 28.0.50 (build 10, x86_64-pc-linux-gnu, GTK+ Version 3.24.14, cairo version 1.16.0)
 of 2020-03-31 built on my-little-tumbleweed
Repository revision: 05cab7ad06efabae18ee94e3b609ea10ae2f60be
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12007000
System Description: openSUSE Tumbleweed

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

Important settings:
  value of $LC_CTYPE: en_US.UTF-8
  value of $LANG: en_US.UTF-8
  value of $XMODIFIERS: @im=local
  locale-coding-system: utf-8-unix