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