unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Eli Zaretskii <eliz@gnu.org>
To: Yuan Fu <casouri@gmail.com>, Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org, mickey@masteringemacs.org,
	theo@thornhill.no, dgutov@yandex.ru
Subject: Re: Extending define-derived-mode
Date: Tue, 30 May 2023 13:48:27 +0300	[thread overview]
Message-ID: <83zg5mf62s.fsf@gnu.org> (raw)
In-Reply-To: <20F07C52-6B39-4B24-8433-82E2226EADA6@gmail.com> (message from Yuan Fu on Mon, 29 May 2023 22:16:49 -0700)

> From: Yuan Fu <casouri@gmail.com>
> Date: Mon, 29 May 2023 22:16:49 -0700
> Cc: Mickey Petersen <mickey@masteringemacs.org>,
>  Theodor Thornhill <theo@thornhill.no>, Dmitry Gutov <dgutov@yandex.ru>
> 
> When we were adding tree-sitter modes a couple of month ago, it was
> clear that the current major mode model needs some upgrade, I’d like
> to discuss the things we need and how can we address them.

You are basically talking about different modes that support the same
programming language or file format.  We never had this in Emacs, with
(AFAIK) the single exception of perl-mode vs cperl-mode, which never
played well.  I think some thought was invested in trying to reconcile
them (Stefan, am I right?), but we never came up with a good solution.
Not sure if that is a general problem or not.

> 1. Fallback modes: user enables xxx-ts-mode, but there’s no
>    tree-sitter grammar for xxx, so Emacs falls back to xxx-mode
>    instead. This feature is also desirable for some non-tree-sitter
>    modes, like TeX modes. Ideally the dispatch should happen before
>    major mode does anything.

This fallback must be user-controlled.  At the very least, users
should be able to say whether they want the fallback, and if they do,
whether the fallback should be silent or vociferous.

> 2. Inheritance:
> 
> 2.1 For xxx-mode and xxx-ts-mode, there should be shared hook. More
>     generally, we want to be able to have a shared hook for similar
>     modes (same language, similar language, etc).
> 
> 2.2 For xxx-mode and xxx-ts-mode, they should be able to share some
>     setup, and diverge on some other.
> 
> 2.3 Right now we have a little inconsistency regarding hook
>     inheritance. js-json-mode inherits from js-mode, json-ts-mode
>     inherits from js-ts-mode. So there isn’t a shared hook that runs
>     in both js-json-mode and json-ts-mode.
> 
>     More generally, if there is a language X and a derived language Y,
>     and we have x-mode, x-ts-mode, y-mode, y-ts-mode, how should
>     inheritance of code and hooks works among them? y-mode probably
>     wants to inherit from x-mode, and y-ts-mode probably wants to
>     inherit hook (but not necessarily code [1]) from x-ts-mode.

This is not simple in practice.  Ask yourself why don't the
FOO-ts-mode's simply run the (existing) hooks of FOO-mode?  Look at
the code, and you will understand: the stuff people put in these hooks
usually customizes aspects that are very different in each of the
modes: font-lock, indentation, syntax tables, supporting "electric"
sub-modes, styles of comments and other things, etc.  The few places
where the new TS modes tried to run the same hooks and share most of
the initialization code (for example, bash-ts-mode and sh-mode,
python-ts-mode and python-mode) introduced subtle bugs which were only
recently fixed.  One problem with inheriting from the same base mode
is that doing initialization there could be problematic because the
mode stuff that gets automatically instantiated and initialized by
define-derived-mode, such as the mode's map and variable, is not yet
set up when the base mode's initialization runs, so you cannot do some
of the things we are used to do there, like setting up the menu-bar
menus.

So it would seem that, for efficient and convenient facilities of this
kind, we need some way of defining stuff in the base mode, which will
be actually run later, when the child mode is set up.

> 3. Unrelated to tree-sitter, here’s something I personally want:
>    it would be nice if every major mode can
>    have a hook that’s not run by its derived modes. Use case:
>    sage-mode inherits python-mode. I have eglot-ensure in
>    python-mode-hook but don’t want it when using sage-mode. Right now
>    I have to wrap eglot-ensure with a lambda function so that it only
>    runs when major-mode = python-mode.

What is wrong with that solution?  Except for the maybe minor
inconvenience of having to use a lambda-function, what different way
of doing this would you envision except telling define-derived-mode to
run some hook only under this-and-that condition?

> 1. Shouldn’t be hard to add some facility to define-derived-mode that
>    runs before everything and dispatches to different major modes.
>    Maybe define-derive-mode can have a :dispatch keyword which takes a
>    arbitrary function; and if the function returns nil, rest of the
>    major mode setup are skipped.

What kind of code would run before the dispatch?  I suggest to take a
couple of examples of related modes, and examine their common parts,
so you have a clear idea of the potential issues.

> 3. Like 1., shouldn’t be hard to modify define-derived-mode to add a
>    hook that’s not run by its derived modes.

If this is a frequent need, then yes, adding that would be easy.



  parent reply	other threads:[~2023-05-30 10:48 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-30  5:16 Extending define-derived-mode Yuan Fu
2023-05-30  5:51 ` Theodor Thornhill
2023-05-31 20:35   ` Yuan Fu
2023-06-01  5:43     ` Theodor Thornhill
2023-05-30 10:48 ` Eli Zaretskii [this message]
2023-05-30 14:16   ` Stefan Monnier
2023-05-31 21:31     ` Yuan Fu
2023-06-01  4:06       ` Stefan Monnier
2023-06-01  6:39         ` Eli Zaretskii
2023-06-02  7:50           ` Yuan Fu
2023-06-02 11:54             ` Eli Zaretskii
2023-06-05  7:31               ` Yuan Fu
2023-06-05 11:33                 ` Eli Zaretskii
2023-06-08  7:25                   ` Yuan Fu
2023-06-02  7:44         ` Yuan Fu
2023-06-02 16:46           ` Stefan Monnier
2023-06-05  7:39             ` Yuan Fu
2023-06-05 15:17               ` Stefan Monnier
2023-05-31 20:48   ` Yuan Fu
2023-06-01  5:47     ` Eli Zaretskii
2023-06-02  7:45       ` Yuan Fu
2023-06-02 11:51         ` Eli Zaretskii
2023-05-30 17:24 ` Juri Linkov
2023-06-05  8:30 ` Philip Kaludercic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=83zg5mf62s.fsf@gnu.org \
    --to=eliz@gnu.org \
    --cc=casouri@gmail.com \
    --cc=dgutov@yandex.ru \
    --cc=emacs-devel@gnu.org \
    --cc=mickey@masteringemacs.org \
    --cc=monnier@iro.umontreal.ca \
    --cc=theo@thornhill.no \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).