Subject: bug#68246: 30.0.50; Add non-TS mode as extra parent of TS modes

From: João Távora <[email-masked]>
Date: Fri, 5 Jan 2024 11:27:53 +0000

On Fri, Jan 5, 2024 at 7:51 AM Eli Zaretskii <[email-masked]> wrote:
>
> > Cc: [email-masked]
> > From: João Távora <[email-masked]>
> > Date: Thu, 4 Jan 2024 23:48:48 +0000
> >
> > We _don't_ want  x-mode-hook to run when we activate
> > x-ts-mode.  Or do we?
>
> We don't, because FOO-mode-hook usually assumes all kinds of things
> that are generally not true for FOO-ts-mode.

Indeed.

Sorry for the long mail, here's a TL;DR: let's experiment,
but maybe tighten up the docs to state 'define-derived-mode' is
parenting and 'add-derived-mode-parents' is more like adoption.
Possibly add  'remove-derived-mode-parent' for safety and fixing
existing bugs.

Now I've read the patch and the misgivings are back.  It uses
`derived-mode-add-parents`, whereas by "adding the inheritance
ourselves", I was suggesting going to each `define-derived-mode`
of each 'foo-ts-mode' and really putting in 'foo-mode' as a parent.

So this is the multi-file macro-expanded moral equivalent of
the symbol-name hack I was talking about

'd-m-add-parents' is a very new util in our tree, and I suppose
it has been discussed.  It's not really full inheritance as
given by normal parenting, it's more like "adult adoption" :-)

I guess we can try it, and even like it, but can we be sure
of all the semantic impacts?

If you ask me, authors should prioritize getting their hands dirty
and extract commonality for the foo-ts-mode and foo-mode one
by one.  Name such modes foo-base-mode or base-foo-mode maybe.

This is what was done for lisp-data-mode which now parents most
(all?) Lisp modes, so much that the other day I could write a
functional 2 line Clojure-mode based on lisp-data-mode.  The
situation is that camp is much cleaner now, and it wasn't
a very difficult change.

base-foo-mode is a natural place for setup that is common
to both foo-mode and foo-ts-mode to exist.  There is a
good number of things that are independent of the particular
implementation of parsing (lisp-based vs ts-based).

Is it too late for the ts-modes to be looked at like that?
It seems our approach to TS modes often/always looks like
'foo-rewrite-completely-using-ts-while-at-it-mode'.

Maybe for some modes this makes sense IMO, like C and C++ modes.

Inadequate parenting is a real problem.  The lisp-mode example
2-3 years ago, but also recently the parenting the js-json-mode <->
js-mode relation has caused a so-far unsolved problem in Eglot
described in bug#67463.

That bug can also really only be solved by "getting hands
dirty" or by introducing some remove-derived-mode-parent
counterpart to the new derived-mode-add-parents.

If that's how we want to view "derived-mode-p" from now on.
Maybe it is.  But it should be well explained in the docs
of both define-derived-mode and derived-mode-p that you don't
need the former to get the latter and that d-d-mode bakes in
much more powerful relation that add-derived-mode-parents
doesn't fully emulate.  And that remove-derived-mode-parent
can sever that part of the relation (and only that part).

> It should modify our .dir-locals.el and Eglot's database to
> remove special entries for TS modes

As Dmitry mentioned: if that is done just like that it will
break Eglot's support of ts modes in any Emacs which doesn't
have Stefan's patch.

But we could easily add some compatibility code to Eglot that
does the same thing as the patch in ad-hoc fashion, and then
remove that code (much later) on.

Also, I know this mail is long enough, but apropos Eglot's
database, it's getting quite large as you may notice.  Another,
much more natural way to simplify it would be, if major-modes
started setting eglot-server-program (singular) buffer-locally
variable which takes precedence over eglot-server-programs.

João