From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Yuan Fu Newsgroups: gmane.emacs.devel Subject: Re: Extending define-derived-mode Date: Wed, 31 May 2023 14:31:06 -0700 Message-ID: References: <20F07C52-6B39-4B24-8433-82E2226EADA6@gmail.com> <83zg5mf62s.fsf@gnu.org> Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3731.500.231\)) Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="16206"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Eli Zaretskii , emacs-devel@gnu.org, mickey@masteringemacs.org, theo@thornhill.no, dgutov@yandex.ru To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed May 31 23:32:16 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1q4TQV-0003xU-Eb for ged-emacs-devel@m.gmane-mx.org; Wed, 31 May 2023 23:32:15 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q4TPj-0000Jj-GM; Wed, 31 May 2023 17:31:27 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q4TPf-0000Iz-K2 for emacs-devel@gnu.org; Wed, 31 May 2023 17:31:23 -0400 Original-Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1q4TPd-0005FP-Gi; Wed, 31 May 2023 17:31:23 -0400 Original-Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-64d18d772bdso243005b3a.3; Wed, 31 May 2023 14:31:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20221208; t=1685568679; x=1688160679; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=ti16pMIYo3LOcVAvNZ5XnLZgFHy67TOFTeC15aXJBUY=; b=aeM2YdH0PO+VTwYbJVE/GznJ7Bz7+kqQ62s1tmISQNl484XOllhgJlAslQLNwqLcVH 11PSqTNBAPFnfvfVJ67dGZmDMg8/G6XLpLbbXg9rEcwT27QGhBwBPcxfdVpHkfUbr07w xQHUJOnHbYSmdMfUH/CcVqe6BjEGOR1N2CKzDHRTOB5yuDsbbCukKfffYz1XZarNjzOS kD4tYJJcsUyjK7L2LDajcb8PSRWoFRAwxeab1+vB59eJnxpJG7vO0lvH2hcMFXTGGcQ6 whRulc2mzEuJYfn6ogK0koliVuRCsjrQZVIXRw/WD9DgIBQhzweEsrTsDwYDac1V8EwN YtxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1685568679; x=1688160679; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ti16pMIYo3LOcVAvNZ5XnLZgFHy67TOFTeC15aXJBUY=; b=PaoWe1D4+zmpfNYnX4jV2VoB5qXSDmYI9GcJF40C/MGMqbh4+p9gcwCmU5bomBvSJF g0sJcY68Ox8zDcMNeegEPp3S0R2/YCGEGKDty0wEuwPJTa8wpZW39yZvJkkk21dvgmjy 1sq4yVIo6/433luQ6ro9AkfrKHvAP/R7vh0fGqTpF3xzH908DAAIqbMQN0bZql/47Oft 3u6jW7b8qnc0Ca1tHKRDsGVYs8PU0gT7yQvXrDOQ0OTE87idf0v3nT9chHBcw5KshUXp Fy/xirMMg/yrHdVVjObn4aEYJSjrhgRG1N5nJKHfKj2mN9fP/Dn+Pr4Scau9hV4QfM72 hAJg== X-Gm-Message-State: AC+VfDxx2ipOD88VcYjPI9kq/ABvv64PXzNoWmzyVF3AaghVMNgyrOR9 Si8Y7D0qVv2zfRGioZm0SpE= X-Google-Smtp-Source: ACHHUZ5GKswaij2b/5R+DL0JhhygdlbfDrpGvEyow6moBK7JcDFsAxDfuJ7sfYkTgYgj7p6qYg5nbA== X-Received: by 2002:a05:6a20:1590:b0:110:a7da:b980 with SMTP id h16-20020a056a20159000b00110a7dab980mr8792810pzj.12.1685568679129; Wed, 31 May 2023 14:31:19 -0700 (PDT) Original-Received: from smtpclient.apple (cpe-172-117-161-177.socal.res.rr.com. [172.117.161.177]) by smtp.gmail.com with ESMTPSA id y12-20020a63fa0c000000b0051b36aee4f6sm1740080pgh.83.2023.05.31.14.31.17 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 31 May 2023 14:31:18 -0700 (PDT) In-Reply-To: X-Mailer: Apple Mail (2.3731.500.231) Received-SPF: pass client-ip=2607:f8b0:4864:20::42a; envelope-from=casouri@gmail.com; helo=mail-pf1-x42a.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:306467 Archived-At: > On May 30, 2023, at 7:16 AM, Stefan Monnier = wrote: >=20 >> 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. >=20 > Not quite: within Emacs there's at least pascal.el vs opascal.el and > sgml-mode vs nxml-mode, and depending on how you define it there's = also > postscript-mode vs doc-view-mode, as well as c-mode vs image-mode (for > XPM files). >=20 > And if we consider packages not bundled with Emacs, there are many = more > case:s such as latex-mode vs LaTeX-mode, python.el vs python-mode.el, > js.el vs js2.el vs js3.el, octave-mode vs matlab-mode. >=20 >> 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. >=20 > We don't really have a good answer yet, no. > `major-mode-remap-alist` is aimed at this problem, but brand new so = it's > not clear how useful it will be for that and it's definitely not > a complete solution. >=20 >>> 1. Fallback modes: user enables xxx-ts-mode, but there=E2=80=99s 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. >>=20 >> This fallback must be user-controlled. >=20 > I don't see this as a big problem, actually (there are already several > mechanisms that can do that). The question of how "user enables > xxx-ts-mode" is probably harder. Couldn=E2=80=99t they use major-mode-remap-alist? There are mechanisms to do that, yes, if you are talking about the = advices for latex-mode and bash-ts-mode. But I=E2=80=99d love to see a = standard, cleaner way to do it. >=20 >>> 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). >=20 > As Eli explains, this is not always desirable. And at other times it > *is* desirable: the users's hook function can set/use features that = are > specific to one of the alternative, but they can also set/use features > that are shared between the alternatives :-( For sure, those that aren=E2=80=99t sharable should go into the = not-shared hooks. I=E2=80=99m mainly saying that there should be a = shared hook, so users _can_ share some of the configs. >=20 > Most users use only one of the alternatives, tho, so it's usually not > a big problem (other than introducing incompatibilities when Emacs's > defaults change from one alternative to another). Keep in mind that when people try out tree-sitter modes, they are = unlikely to just throw away their config for the old mode; also since = tree-sitter and grammars aren=E2=80=99t the easiest to install, people = working on multiple machines probably want both tree-sitter and = no-tree-sitter modes configured and ready to go. So I think we=E2=80=99ll = see a lot of people having config for both modes (me included). >=20 > It can be more annoying for `.dir-locals.el` per-mode settings. And in general, any configuration that takes a major-mode symbol as the = key. There are quite a few of them in Emacs. I think this is a big = motivation for having multiple inheritance for derived-mode-p, and = sharing a base mode. >=20 >>> 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. >=20 > `y-ts-mode` can explicitly run `y-mode-hook` (or `x-ts-mode-hook`). >=20 > We may more generally want to extend our notion of "derived" mode to > allow "multiple inheritance". For the actual activation code part, > multiple inheritance is a hard problem that we probably don't want to > tackle, but we can easily run several parent hooks, setup multiple > keymap karents, and make `derived-mode-p` support multiple parents. I agree that we don=E2=80=99t want multiple-inheritance for activation = code. Also, as Juri pointed out, we can encapsulate code into functions = and call functions in major mode body. Multiple-inheritance for hooks = and maps has the potential disadvantage of being confusing. Right now = it=E2=80=99s clear what hooks are run when a major mode turns on, but = with multiple-inheritance it may not be. (I know I brought up the = multiple-inheritance thing in the first place, I=E2=80=99m just writing = whatever comes to my mind :-) How do you setup multiple keymap parents? I thought a keymap can only = have one parent? Here=E2=80=99s another wild idea: we keep single-inheritance for = define-derived-mode; major modes for the same language inherits from the = same base mode; add a feature where xxx-base-mode is automatically = defined when someone defines a major mode with xxx-base-mode as parent, = so we don=E2=80=99t need to pre-define base-modes for every possible = language; separate to major modes, we add a tag/category system, where = modes can adopt multiple tags/categories, and a function like = mode-has-category-p can work similarly to derived-mode-p. >=20 >>> 3. Unrelated to tree-sitter, here=E2=80=99s something I personally = want: >>> it would be nice if every major mode can >>> have a hook that=E2=80=99s not run by its derived modes. Use case: >>> sage-mode inherits python-mode. I have eglot-ensure in >>> python-mode-hook but don=E2=80=99t 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 =3D python-mode. >>=20 >> 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? >=20 > While I tend to agree that it's not a big deal, I also agree that it's > arguably cleaner if parent modes are kept "abstract", so rather than > have `c++-mode` inherit from `c-mode`, you make them both inherit from > a `c-base-mode`. It tends to smell of overkill, tho. Maybe defien-derived-mode can additionally define a function that only = runs the major mode body but doesn=E2=80=99t setup anything that are = autogenerated (eg, keymap, hooks, etc). This way another major mode is = free to reuse other mode=E2=80=99s setup while not inheriting from that = mode. Yuan=