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

From: Phil Sainty <[email-masked]>
Date: Tue, 10 Jul 2018 02:47:35 +1200

Hi Alan,

On 09/07/18 08:08, Alan Mackenzie wrote:
> Just as an aside, something in the email chain between you and
> me has irritatingly formatted your (and my) text ... with every
> second line containing just one (or two) words.

I've not observed that myself, but I'll refill the text to 65
cols and see if that helps.

> On Thu, Jul 05, 2018 at 09:13:38 +1200, Phil Sainty wrote:
>> I believe the original problem was the same as the problem I'm
>> aiming to fix, which is that `c-update-modeline' imposes a
>> non-standard restriction upon `mode-name' that it be a simple
>> string (as opposed to containing arbitrary mode line
>> constructs, as it should be able to do).

> That's unnecessarily harsh.

Ignorance on my part, I'm afraid -- I'd neither realised that the
ability for mode-name to contain non-string values was a change
that post-dated the CC mode code in question, nor understood that
maintaining compatibility with such old emacsen was important for
these libraries.  No offence intended, regardless.

> The problem is that the definition of mode-name was changed
> incompatibly some while back.  This seems a foolish change -
> the name of a mode is essentially a string, and changing this
> has led to problems.  The current code in CC Mode conforms to
> the original definition of mode-name.

>>          ;; FIXME: Derived modes might want to use something
>>          ;; else than a string for `mode-name'.

> Why should anybody want to do that?  (Not a rhetorical
> question).

I believe it is a genuinely useful thing to be able to do,
particularly for end-user customisation purposes.  I can give a
few examples.

The first thing is that it's useful for *precisely* the same
reason that CC mode contains the code we're discussing -- because
including some kind of dynamic state information in the mode name
in the mode line is a really handy thing to do (and, backwards-
compatibility complications notwithstanding, I'd argue that the
implementation of the CC mode flags using that approach is quite
elegant).  End-users could even choose to implement their own
custom set of CC mode flags with relative ease, using this
technique.

More generally, mode line constructs make it easy for end-users
to implement similar custom displays for any mode at all.  For
example I use the following custom mode-name for
`emacs-lisp-mode':

'("Elisp" (lexical-binding ":Lex" ":Dyn"))

This means that all my elisp buffers show me the state of
`lexical-binding' with either "Elisp:Lex" or "Elisp:Dyn" as the
displayed mode name (which is very useful).

That isn't the *best* example, as one doesn't expect the value of
`lexical-binding' to vary dynamically within any given buffer,
but the point is that it is quite trivial to add dynamic state
information using this technique.

A more dynamic example from my own config is for `re-builder',
which allows the user to dynamically switch between four
different regexp syntaxes (read, string, rx, and sregexp), but
only has two different mode line states: "RE Builder" (for read
and string), and "RE Builder Lisp" (for rx and sregex), which is
on account of it using a separate major mode for each of those
two groups.  In my config I set the following mode-name for each
of those modes:

'("Regexp[" (:eval (symbol-name reb-re-syntax)) "]")

Which then provides me with the details which were lacking:

"Regexp[read]"
"Regexp[string]"
"Regexp[rx]"
"Regexp[sregex]"

Unlike my previous example, this one does vary dynamically, and
is particularly useful for checking whether 'read' or 'string'
syntax is active.

And of course we've already seen an example in `antlr-mode',
where the author had originally wanted to make mode-name react
dynamically to the value of the `antlr-language' variable.

You'll also observe that in my examples I've changed the main
text of the mode name to something shorter ("Elisp" instead of
"Emacs-Lisp", and "Regexp" instead of "RE Builder").  Reducing
the characters used by major and minor modes in the mode line is
a rather common desire (with split windows one quickly runs out
of room to see all the information available), and some people
take this to the extreme of using single characters for many of
their commonly-used modes.  An example might be using the HOT
BEVERAGE character "☕" as the mode-name for `java-mode'.

I mention this because I became aware of this bug in the first
place for related reasons, as my delight.el library was written
to make such customisations easy to configure (see
https://www.emacswiki.org/emacs/DelightedModes ), and I learned
recently that it was incompatible with CC Mode modes:
https://www.reddit.com/r/emacs/comments/8v8de4/change_modename_for_major_mode/

The reason for the incompatibility is that delight.el wants to
display the custom version of the mode in the mode line, but
still display the *original* name in other contexts (such as in
the `describe-mode' output when the user types C-h m), and it
does this by generating a mode line construct which displays one
or the other based on a conditional variable.  Hence my config
for elisp is actually more like:

(delight 'emacs-lisp-mode
         '("Elisp" (lexical-binding ":Lex" ":Dyn"))
         :major)

Resulting in this mode-name:

'(inhibit-mode-name-delight
  "Emacs-Lisp"
  ("Elisp" (lexical-binding ":Lex" ":Dyn")))

And one could use:

(delight 'java-mode
         (char-to-string (char-from-name "HOT BEVERAGE"))
         :major)

Resulting in, in my case:

'(inhibit-mode-name-delight "Java//l" "☕")

which of course then triggers the error in `c-update-modeline'
which I've been seeking to avoid.

Hopefully these various examples answer the question of "Why
should anybody want to do that?"

I believe I can update my patch to retain the previous behaviour
for old emacsen whilst implementing the improvement for newer
ones.  Offhand I think it would be a matter of making
`c-update-modeline' run either the new code or the old code
depending upon the Emacs version, and then I would restore the
calls to `c-update-modeline' that I removed from the various
minor mode toggle functions, etc.  Comments can indicate which
code is for compatibility with Emacs 22 and earlier, to make it
easy to remove if support for those versions is ever dropped in
future.  I am not sure which variant is needed for xemacs (or any
particular versions thereof), as I do not use it, so I would need
help with an appropriate test for that.

I'm happy to review and revise the patch along these lines, if
I've managed to convince you that it's a useful thing to support?

-Phil