From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#58075: Mapping file types to major modes Date: Sun, 25 Sep 2022 11:38:28 -0400 Message-ID: Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="2319"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Juri Linkov , Ikumi Keita To: 58075@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Sep 25 17:39:22 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1ocTj0-0000Oc-7c for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 25 Sep 2022 17:39:22 +0200 Original-Received: from localhost ([::1]:55350 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ocTiy-0000vt-UK for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 25 Sep 2022 11:39:20 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:47516) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ocTih-0000W0-T3 for bug-gnu-emacs@gnu.org; Sun, 25 Sep 2022 11:39:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:49292) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ocTih-0008Rc-Lv for bug-gnu-emacs@gnu.org; Sun, 25 Sep 2022 11:39:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ocTif-0002et-Ql; Sun, 25 Sep 2022 11:39:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: juri@linkov.net, ikumi@ikumi.que.jp, bug-gnu-emacs@gnu.org Resent-Date: Sun, 25 Sep 2022 15:39:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 58075 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org X-Debbugs-Original-Xcc: Juri Linkov , Ikumi Keita Original-Received: via spool by submit@debbugs.gnu.org id=B.166412032910198 (code B ref -1); Sun, 25 Sep 2022 15:39:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 25 Sep 2022 15:38:49 +0000 Original-Received: from localhost ([127.0.0.1]:48368 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ocTiT-0002eP-0X for submit@debbugs.gnu.org; Sun, 25 Sep 2022 11:38:49 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:47764) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ocTiP-0002eF-Mj for submit@debbugs.gnu.org; Sun, 25 Sep 2022 11:38:47 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:33428) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ocTiN-0000D7-K2 for bug-gnu-emacs@gnu.org; Sun, 25 Sep 2022 11:38:43 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:47355) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ocTiK-0008Pg-Iw for bug-gnu-emacs@gnu.org; Sun, 25 Sep 2022 11:38:42 -0400 Original-Received: from pmg1.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id 890E2100154; Sun, 25 Sep 2022 11:38:38 -0400 (EDT) Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id BB29110002F; Sun, 25 Sep 2022 11:38:29 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1664120309; bh=IbnjYF7I8aVN2sv8eFFZjPytTBU6I/FO/l+ZDIRQ/hE=; h=From:To:Subject:Date:From; b=P4ZXKdtBOnoeS1gmUY4yxUyocQKyqWQ9DfLNLYLpfqfICuvKcjR+Um/algp6Ybo3D Zlw/51uU04rFDmz5tW8rxD6nk6J9+QAMNFt3/6Cv9XlLXV1TS8xeuGXTKsM+LgTdUe do759APQYItnzPd4Xhe2aFBbkIT4OVvWbjliQdRrrRNekNWs6a1BLUBPC0G6hGXHea 2KFT4pgbWZHq30rDz8U1YqRZu5Zqi70nsuzppOWPsawq9AWLWJkKDhf9P0sSHqt3ao tIm2X2fCGZ/Fd6kaKg/Tem8oVQBGrIbszU9jUgVHXuE5ntZA83vVusgzJVSbNdTnEp tttrwG6zIunJQ== Original-Received: from pastel (65-110-220-202.cpe.pppoe.ca [65.110.220.202]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 97086120623; Sun, 25 Sep 2022 11:38:29 -0400 (EDT) Received-SPF: pass client-ip=132.204.25.50; envelope-from=monnier@iro.umontreal.ca; helo=mailscanner.iro.umontreal.ca X-Spam_score_int: -42 X-Spam_score: -4.3 X-Spam_bar: ---- X-Spam_report: (-4.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:243604 Archived-At: --=-=-= Content-Type: text/plain Tags: patch [ I now see that I had sent this to `emacs-devel` rather than as a bug report, so here is the second try. To make up for it, I include a suggested patch this time. ] Emacs has various facilities to decide which major mode to use for which file based on its name and/or contents. All those facilities specify directly the mode to use. This is usually exactly what we want because there's only ever 1 major mode for that type. But for some file types this is inconvenient because there are various alternative major modes that can be used for that file type. I'm thinking of things like Perl files (`perl-mode` vs `cperl-mode`), LaTeX files (`latex-mode` vs AUCTeX's equivalent (whose name it not clear, sadly)), HTML files (lots of alternatives), ... We have various ways to deal with those different cases, which are variously convenient/successful, but for things like `cperl-mode` vs `perl-mode` or `latex-mode` vs AUCTeX the usual solution is not satisfactory since it looks like: (defalias 'perl-mode #'cperl-mode) or equivalent, which means that the "other" mode becomes unavailable, which is particularly problematic if we want the "fancy/external" mode to be a derived mode of the other. (AUCTeX now does it via advising which at least makes it reversible, but it's still not very satisfactory). The way I tend to think of it is that we'd like to divide the mode choice into two steps: A) recognize the file type (a bit like `/etc/mime.types`). B) choose the mode to use for that type (like `/etc/mailcap`). We don't current have "types" and retro-fitting that might make the common case (where there's only 1 mode) more painful. IOW it would take work and lead to a worse result in the most common case, which doesn't sound very enticing. So instead I suggest consider the current settings as being our implementation of (A), and add (B) as some "mode remapping" layer to decide which major mode to actually for a given "type/mode". So instead of (defalias 'perl-mode #'cperl-mode) We could have (add-to-list 'major-mode-remap-alist '(perl-mode . cperl-mode)) -- Stefan In GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo version 1.16.0, Xaw3d scroll bars) of 2022-09-16 built on pastel Repository revision: c15a53877a7db7aa3205cff3c943321ed81a1412 Repository branch: work Windowing system distributor 'The X.Org Foundation', version 11.0.12011000 System Description: Debian GNU/Linux 11 (bullseye) Configured using: 'configure -C --enable-checking --enable-check-lisp-object-type --with-modules --with-cairo --with-tiff=ifavailable 'CFLAGS=-Wall -g3 -Og -Wno-pointer-sign' PKG_CONFIG_PATH=/home/monnier/lib/pkgconfig' --=-=-= Content-Type: text/patch Content-Disposition: attachment; filename=major-mode-remap.patch diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi index c348130807c..56b779f8de6 100644 --- a/doc/emacs/modes.texi +++ b/doc/emacs/modes.texi @@ -454,6 +454,13 @@ Choosing Modes files, HTML/XML/SGML files, PostScript files, and Unix style Conf files. +@vindex major-mode-remap-alist + Once a major mode is found, Emacs does a final check to see if the +mode has been remapped by @code{major-mode-remap-alist}, in which case +it uses the remapped mode instead. This is used when several +different major modes can be used for the same file type, so you can +specify which mode you prefer. + @findex normal-mode If you have changed the major mode of a buffer, you can return to the major mode Emacs would have chosen automatically, by typing diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index 983dfe2ec59..8e34fdf3640 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -2476,11 +2476,11 @@ Declare Form expander will call @var{expander} with that form as well as with @var{args}@dots{}, and @var{expander} can either return a new expression to use instead of the function call, or it can return just the form unchanged, -to indicate that the function call should be left alone. @var{expander} can -be a symbol, or it can be a form @code{(lambda (@var{arg}) @var{body})} in -which case @var{arg} will hold the original function call expression, and the -(unevaluated) arguments to the function can be accessed using the function's -formal arguments. +to indicate that the function call should be left alone. + +To avoid syntactic redundancy, when @var{expander} is of the form +@code{(lambda (@var{arg}) @var{body})} the function's formal arguments +are automatically added to the lambda's list of arguments. @item (gv-expander @var{expander}) Declare @var{expander} to be the function to handle calls to the macro (or diff --git a/etc/NEWS b/etc/NEWS index 0a5b7bc29c5..02b4ef97583 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -442,6 +442,15 @@ option) and can be set to nil to disable Just-in-time Lock mode. * Changes in Emacs 29.1 ++++ +** New variable 'major-mode-remap-alist' to specify your favorite major modes. +This variable lets you remap the default modes (e.g. 'perl-mode' or +'latex-mode') to your favorite ones (e.g. 'cperl-mode' or +'LaTeX-mode') without having to use 'defalias', which can have +undesirable side effects. +This applies to all modes specified via 'auto-mode-alist', file-local +variables, etc... + --- ** Emacs now supports Unicode Standard version 15.0. diff --git a/lisp/files.el b/lisp/files.el index 1e1ec6127de..939d734a83d 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3331,6 +3331,7 @@ set-auto-mode matches the buffer beginning against `magic-mode-alist', compares the file name against the entries in `auto-mode-alist', then matches the buffer beginning against `magic-fallback-mode-alist'. +It also obeys `major-mode-remap-alist'. If `enable-local-variables' is nil, or if the file name matches `inhibit-local-variables-regexps', this function does not check @@ -3468,6 +3469,17 @@ set-auto-mode (unless done (set-buffer-major-mode (current-buffer))))) +(defvar-local set-auto-mode--last nil + "Remember the mode we have set via `set-auto-mode-0'.") + +(defcustom major-mode-remap-alist nil + "Alist mapping file-specified mode to actual mode. +Every entry is of the form (MODE . FUNCTION) which means that in order +to activate the major mode MODE (specified via something like +`auto-mode-alist', file-local variables, ...) we should actually call +FUNCTION instead." + :type '(alist (symbol) (function))) + ;; When `keep-mode-if-same' is set, we are working on behalf of ;; set-visited-file-name. In that case, if the major mode specified is the ;; same one we already have, don't actually reset it. We don't want to lose @@ -3478,10 +3490,15 @@ set-auto-mode-0 any aliases and compared to current major mode. If they are the same, do nothing and return nil." (unless (and keep-mode-if-same - (eq (indirect-function mode) - (indirect-function major-mode))) + (or (eq (indirect-function mode) + (indirect-function major-mode)) + (and set-auto-mode--last + (eq mode (car set-auto-mode--last)) + (eq major-mode (cdr set-auto-mode--last))))) (when mode - (funcall mode) + (funcall (alist-get mode major-mode-remap-alist mode)) + (unless (eq mode major-mode) + (setq set-auto-mode--last (cons mode major-mode))) mode))) (defvar file-auto-mode-skip "^\\(#!\\|'\\\\\"\\)" @@ -3511,7 +3528,8 @@ set-auto-mode-1 ;; interpreter invocation. The same holds ;; for '\" in man pages (preprocessor ;; magic for the `man' program). - (and (looking-at file-auto-mode-skip) 2)) t) + (and (looking-at file-auto-mode-skip) 2)) + t) (progn (skip-chars-forward " \t") (setq beg (point)) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index fa428642fa4..20a73e238e9 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -632,7 +632,7 @@ cperl-tips If your Emacs does not default to `cperl-mode' on Perl files, and you want it to: put the following into your .emacs file: - (defalias \\='perl-mode \\='cperl-mode) + (add-to-list \\='major-mode-remap-alist \\='(perl-mode . cperl-mode)) Get perl5-info from $CPAN/doc/manual/info/perl5-old/perl5-info.tar.gz --=-=-=--