From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Re: Extending define-derived-mode Date: Tue, 30 May 2023 13:48:27 +0300 Message-ID: <83zg5mf62s.fsf@gnu.org> References: <20F07C52-6B39-4B24-8433-82E2226EADA6@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="29297"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org, mickey@masteringemacs.org, theo@thornhill.no, dgutov@yandex.ru To: Yuan Fu , Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Tue May 30 12:49:10 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 1q3wub-0007OA-MM for ged-emacs-devel@m.gmane-mx.org; Tue, 30 May 2023 12:49:09 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q3wtZ-0002ze-A3; Tue, 30 May 2023 06:48:05 -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 1q3wtJ-0002xb-GM for emacs-devel@gnu.org; Tue, 30 May 2023 06:47:53 -0400 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q3wtH-0001yB-JR; Tue, 30 May 2023 06:47:47 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=QzmDRqD26gBHl6r/CfwhvD4swy7qVvmNlW0hY0gW1E0=; b=dNLo08OyRgtIrcXfEryS 7MX5m7OZs5Hf9tkkSPyyRRWGI/nlSeSYJInbEgDav62XYkjjbYSkgssZNkY+Kx0u21i11cHe5RBFk 1HW3LAYTT3/HV0jnWf0mAYNN4+U3pbQmced8gstV1hwNe0+G/+webzwsr21n3fs42ObpjWbjoOp+A TXlUZ67XVZUh32At0hD+bekqCfcbWXytO0+erw/ZEjvxbvIzF3yqilzPStBM2pkGAymG15OqYlbIL BNFOs69fhllUpCcOsgW0rXfnHFCK2nq0StXcOoVGMqdDdBTrJ1DrwnBx7oQI1NRgWJwP5gnCMVpvD 3Ct+1E/SSdSVdQ==; Original-Received: from [87.69.77.57] (helo=home-c4e4a596f7) by fencepost.gnu.org with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q3wtG-0000lV-Gd; Tue, 30 May 2023 06:47:47 -0400 In-Reply-To: <20F07C52-6B39-4B24-8433-82E2226EADA6@gmail.com> (message from Yuan Fu on Mon, 29 May 2023 22:16:49 -0700) 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:306405 Archived-At: > From: Yuan Fu > Date: Mon, 29 May 2023 22:16:49 -0700 > Cc: Mickey Petersen , > Theodor Thornhill , Dmitry Gutov > > 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.