Subject: bug#77446: ELPA diminish: support minor modes without lighters

From: Michael Mauger <[email-masked]>
Date: Tue, 01 Apr 2025 23:39:45 +0000

As I cleaned up my `init.el' using `use-package' I discovered some edge cases in `diminish' that can be easily addressed. 

1. Although the stated purpose from `diminish' is to shorten existing minor mode lighters, there can be the case made for adding a lighter when none is supplied by default. The patch to the `diminish' function creates a dummy empty string lighter when it is called without an existing lighter.

2. The patch to `diminish-undo' detects when a mode was not previously diminished and properly restores the original lighter.

3. The patch to `diminished-modes' corrects and simplifies the logic by calling the `format-mode-line' function to generate the lighter from the minor mode specifications. This eliminates kludgy code for simulating symbol evaluation but also handles other mode-line format specifications not previously handled.

I have signed copyright papers so there shouldn't be any concern there.  I have tried to not use anything not present in Emacs 24.3 and updated the version number to 0.50 to reflect that there is a significant change since version 0.46; please correct either if necessary.  The patch is attached.

--
[email-masked] // FSF and SFConservancy member // GNU Emacs sql.el maintainer

diff --git a/diminish.el b/diminish.el
index 0aa3acb5c2..676ee790ae 100644
--- a/diminish.el
+++ b/diminish.el
@@ -6,7 +6,7 @@
 ;; Maintainer: Martin Yrjölä <[email-masked]>
 ;; URL: https://github.com/myrjola/diminish.el
 ;; Created: Th 19 Feb 98
-;; Version: 0.46
+;; Version: 0.50
 ;; Package-Requires: ((emacs "24.3"))
 ;; Keywords: extensions, diminish, minor, codeprose
 
@@ -36,7 +36,10 @@
 ;; A diminished mode is a minor mode that has had its mode line
 ;; display diminished, usually to nothing, although diminishing to a
 ;; shorter word or a single letter is also supported.  This package
-;; implements diminished modes.
+;; implements diminished modes.  There is also support for adding a
+;; minor mode lighter to the mode line even if no lighter is currently
+;; established.  The replacement specified by diminish must satisfy
+;; mode line formatting specifications (`mode-line-format').
 
 ;; You can use this package either interactively or from your .emacs file.
 ;; In either case, first you'll need to copy this file to a directory that
@@ -174,16 +177,19 @@ to TO-WHAT if it's > 1 char long & doesn't already begin with a space."
                      (read-from-minibuffer
                       "To what mode-line display: "
                       nil nil nil 'diminish-history-names)))
+  (cl-callf or to-what "")
+  (when (and (stringp to-what)
+             (> (length to-what) 1))
+    (or (= (string-to-char to-what) ?\ )
+        (cl-callf2 concat " " to-what)))
   (let ((minor (assq mode minor-mode-alist)))
-    (when minor
-        (progn (cl-callf or to-what "")
-               (when (and (stringp to-what)
-                          (> (length to-what) 1))
-                 (or (= (string-to-char to-what) ?\ )
-                     (cl-callf2 concat " " to-what)))
-               (or (assq mode diminished-mode-alist)
-                   (push (copy-sequence minor) diminished-mode-alist))
-               (setcdr minor (list to-what))))))
+    (unless minor
+      (or (memq mode minor-mode-list)
+          (error "%S is not currently registered as a minor mode" mode))
+      (push (setq minor (list mode "")) minor-mode-alist))
+    (or (assq mode diminished-mode-alist)
+        (push (copy-sequence minor) diminished-mode-alist))
+    (setcdr minor (list to-what))))
 
 ;; But an image comes to me, vivid in its unreality, of a loon alone on his
 ;; forest lake, shrieking his soul out into a canopy of stars.  Alone this
@@ -225,10 +231,13 @@ the arg must be quoted as a symbol, as in (diminish-undo \\='diminished-modes)."
           (cl-callf cdr diminished-modes)))
     (let ((minor      (assq mode      minor-mode-alist))
           (diminished (assq mode diminished-mode-alist)))
-      (or minor
-          (error "%S is not currently registered as a minor mode" mode))
-      (when diminished
-        (setcdr minor (cdr diminished))))))
+      (or diminished
+          (error "%S was not previously diminished" mode))
+      (if minor
+          (setcdr minor (cdr diminished))
+        (or (memq mode minor-mode-list)
+            (error "%S is not currently registered as a minor mode" mode))
+        (push (list mode (cdr diminished)) minor-mode-alist)))))
 
 ;; Plumber Bob was not from Seattle, my grey city, for rainy Seattle is a
 ;; city of interiors, a city of the self-diminished.  When I moved here one
@@ -256,13 +265,7 @@ what diminished modes would be on the mode-line if they were still minor."
                (mode (car mode-pair))
                (minor-pair (or (assq mode diminished-mode-alist) mode-pair))
                (minor-name (cadr minor-pair)))
-          (when (symbolp minor-name)
-            ;; This minor mode uses symbol indirection in the cdr
-            (let ((symbols-seen (list minor-name)))
-              (while (and (symbolp (cl-callf symbol-value minor-name))
-                          (not (memq minor-name symbols-seen)))
-                (push minor-name symbols-seen))))
-          (push minor-name message)))
+          (push (format-mode-line minor-name) message)))
       (cl-callf cdr minor-modes))
     (setq message (mapconcat 'identity (nreverse message) ""))
     (when (= (string-to-char message) ?\ )