Subject: bug#2034: [PATCH] 27.0.50; Support mode line constructs for `mode-name' in c-mode

From: Phil Sainty <[email-masked]>
Date: Tue, 3 Jul 2018 00:40:49 +1200

`c-update-modeline' in cc-cmds.el has a long-standing bug (and FIXME
comment) whereby a `mode-name' which is not a string will trigger
errors, on account of the function using string manipulations to add
the minor mode flags to the original `mode-name'.

This is what bug #2034 was originally about. i.e.:

> c-update-modeline: Wrong type argument: stringp,
> (sgml-xml-mode "XML" "SGML")

This new patch instead uses mode-line constructs to concatenate the
flags, thus eliminating the string manipulation code and this bug.

In the process I've added a user option to allow the user to choose
whether or not these flags should be displayed at all, as this was not
previously configurable.

e.g.: `c-update-modeline' will now convert the mode-name "C++" into
'("C++" (c-modeline-display-flags c-modeline-flags)); and it only
updates the buffer-local value of `c-modeline-flags' which is then
conditionally displayed based on option `c-modeline-display-flags'.

This bug fix also resolves an incompatibility with the `delight'
package in GNU ELPA, which wraps any targeted `mode-name' values
in additional mode line constructs, and consequently triggered the
`c-update-modeline' bug with its assumption of a string, when used
with any of the major modes in question.

In my testing thus far this new approach seems to work nicely.

-Phil
>From 7454e8aca12b47ae36fdb46b869ebf1e2ea7afa4 Mon Sep 17 00:00:00 2001
From: Phil Sainty <[email-masked]>
Date: Mon, 2 Jul 2018 23:58:34 +1200
Subject: [PATCH] Support mode line constructs for `mode-name' in c-mode
 (bug#2034)

Also make the inclusion of minor mode flags in `mode-name' optional.

* cc-cmds.el (c-modeline-flags): New variable.
(c-modeline-display-flags): New user option.
(c-update-modeline): Use them.  Use mode line constructs, rather than
string concatenation, to optionally include minor mode flags in
`mode-name'.
---
 lisp/progmodes/cc-cmds.el | 60 ++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 24 deletions(-)

diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 31cf0b1..131d7d1 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -258,31 +258,43 @@ c-syntactic-information-on-region
 (defvar c-block-comment-flag nil)
 (make-variable-buffer-local 'c-block-comment-flag)
 
+(defcustom c-modeline-display-flags t
+  "If non-nil, `mode-name' includes indicators for certain minor modes.
+
+These flags are set by `c-update-modeline'.
+
+See Info node `(ccmode) Minor Modes'."
+  :type 'boolean
+  :group 'c)
+
+(defvar-local c-modeline-flags ""
+  "Minor mode indicators to be appended to `mode-name'.
+
+Hidden when `c-modeline-display-flags' is nil.
+
+See Info node `(ccmode) Minor Modes'.")
+
 (defun c-update-modeline ()
-  (let ((fmt (format "/%s%s%s%s%s"
-		     (if c-block-comment-flag "*" "/")
-		     (if c-electric-flag "l" "")
-		     (if (and c-electric-flag c-auto-newline)
-			 "a" "")
-		     (if c-hungry-delete-key "h" "")
-		     (if (and
-			  ;; (cc-)subword might not be loaded.
-			  (boundp 'c-subword-mode)
-			  (symbol-value 'c-subword-mode))
-                         ;; FIXME: subword-mode already comes with its
-                         ;; own lighter!
-			 "w"
-		       "")))
-        ;; FIXME: Derived modes might want to use something else
-        ;; than a string for `mode-name'.
-	(bare-mode-name (if (string-match "\\(^[^/]*\\)/" mode-name)
-			    (match-string 1 mode-name)
-			  mode-name)))
-    (setq mode-name
-	  (if (> (length fmt) 1)
-	      (concat bare-mode-name fmt)
-	bare-mode-name))
-    (force-mode-line-update)))
+  "Update `c-modeline-flags' and append to `mode-name'."
+  (when (stringp mode-name)
+    (setq mode-name (list mode-name (list 'c-modeline-display-flags
+                                          'c-modeline-flags))))
+  (setq c-modeline-flags
+        (format "/%s%s%s%s%s"
+                (if c-block-comment-flag "*" "/")
+                (if c-electric-flag "l" "")
+                (if (and c-electric-flag c-auto-newline)
+                    "a" "")
+                (if c-hungry-delete-key "h" "")
+                (if (and
+                     ;; (cc-)subword might not be loaded.
+                     (boundp 'c-subword-mode)
+                     (symbol-value 'c-subword-mode))
+                    ;; FIXME: subword-mode already comes with its
+                    ;; own lighter!
+                    "w"
+                  "")))
+  (force-mode-line-update))
 
 (defun c-toggle-syntactic-indentation (&optional arg)
   "Toggle syntactic indentation.
-- 
2.8.3