]> git.eshelyaron.com Git - emacs.git/commitdiff
(major-mode-remap(-defaults)): New var and function (bug#69191)
authorStefan Monnier <monnier@iro.umontreal.ca>
Mon, 4 Mar 2024 04:08:16 +0000 (23:08 -0500)
committerEshel Yaron <me@eshelyaron.com>
Tue, 5 Mar 2024 15:29:06 +0000 (16:29 +0100)
While `major-mode-remap-alist` provides a way for users to indicate the
major mode of their choice, we need a similar variable for the
use of packages.

This patch adds a new `major-mode-remap-defaults` and changes various
packages to obey it or make use of it.
I think it nicely cleans the regexp duplication between CC-mode and
`c-ts-mode.el` and also makes it easier/cleaner for users to override
the changes made by `*-ts-mode.el`.

* lisp/files.el (major-mode-remap-defaults): New variable.
(major-mode-remap): New function.
(set-auto-mode-0): Use it.
* doc/lispref/modes.texi (Auto Major Mode): Document them.

* lisp/textmodes/tex-mode.el (tex--redirect-to-submode):
Use `major-mode-remap`.
(major-mode-remap-defaults): Set it to remap AUCTeX modes by default.
* lisp/progmodes/ruby-ts-mode.el (auto-mode-alist): Leave it alone.
(major-mode-remap-defaults): Set this one instead.
* lisp/progmodes/c-ts-mode.el (c-or-c++-ts-mode): Use `major-mode-remap`.
(auto-mode-alist): Leave it alone.
(major-mode-remap-defaults): Set this one instead.
* lisp/org/ox.el (org-export-to-buffer): Modernize docstring accordingly.
* lisp/progmodes/cc-mode.el (c-or-c++-mode):
* lisp/org/ox-latex.el (org-latex-export-as-latex):
* lisp/org/ox-koma-letter.el (org-koma-letter-export-as-latex):
* lisp/org/ox-beamer.el (org-beamer-export-as-latex):
Use `major-mode-remap` when available.

(cherry picked from commit 2b5d43081a30f816dd38a16c7b5bfbad712a779b)

12 files changed:
doc/lispref/modes.texi
etc/NEWS
lisp/files.el
lisp/org/ox-beamer.el
lisp/org/ox-koma-letter.el
lisp/org/ox-latex.el
lisp/org/ox.el
lisp/progmodes/c-ts-mode.el
lisp/progmodes/cc-mode.el
lisp/progmodes/go-ts-mode.el
lisp/progmodes/ruby-ts-mode.el
lisp/textmodes/tex-mode.el

index a2e8f42cf1d919dbc7a4a84b3bf7c3c76907f794..b034fecd77b84d2517c056b938c0ae1d661cd37f 100644 (file)
@@ -791,6 +791,39 @@ init file.)
 @end smallexample
 @end defvar
 
+@defvar major-mode-remap-defaults
+This variable contains an association list indicating which function
+to call to activate a given major mode.  This is used for file formats
+that can be supported by various major modes, where this variable can be
+used to indicate which alternative should be used by default.
+
+For example, a third-party package providing a much improved Pascal
+major mode, can use the following to tell @code{normal-mode} to use
+@code{spiffy-pascal-mode} for all the files that would normally use @code{pascal-mode}:
+
+@smallexample
+@group
+(add-to-list 'major-mode-remap-defaults '(pascal-mode . spiffy-pascal-mode))
+@end group
+@end smallexample
+
+This variable has the same format as @code{major-mode-remap-alist}.
+If both lists match a major mode, the entry in
+@code{major-mode-remap-alist} takes precedence.
+@end defvar
+
+@defun major-mode-remap mode
+This function returns the major mode to use instead of @var{mode}
+according to @code{major-mode-remap-alist} and
+@code{major-mode-remap-defaults}.  It returns @var{mode} if the mode
+is not remapped by those variables.
+
+When a package wants to activate a major mode for a particular file
+format, it should use this function, passing as @code{mode} argument the
+canonical major mode for that file format, to find which specific major
+mode to activate, so as to take into account the user's preferences.
+@end defun
+
 @node Mode Help
 @subsection Getting Help about a Major Mode
 @cindex mode help
index 11e10e110d79d50b7786ececc2f5e1afe7165330..0fb786d38dca1de4607ecf379e69c4abffb1e536 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1733,6 +1733,10 @@ the region and never want to restrict 'undo' to that region, it is
 preferable to use the existing 'undo-inhibit-region' symbol property
 instead of this variable.
 
+** New var 'major-mode-remap-defaults' and function 'major-mode-remap'.
+The first is like Emacs-29's 'major-mode-remap-alist' but to be set by
+packages (instead of users).  The second looks up those two variables.
+
 +++
 ** Pcase's functions (in 'pred' and 'app') can specify the argument position.
 For example, instead of '(pred (< 5))' you can write '(pred (> _ 5))'.
index ba3f0349aec6dc5a8abd88a9bacc1dc8c433d07e..02c9241541429a45d192bf5b7f766abf9d3ac878 100644 (file)
@@ -3436,7 +3436,7 @@ checks if it uses an interpreter listed in `interpreter-mode-alist',
 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'.
+It also obeys `major-mode-remap-alist' and `major-mode-remap-defaults'.
 
 If `enable-local-variables' is nil, or if the file name matches
 `inhibit-local-variables-regexps', this function does not check
@@ -3582,9 +3582,22 @@ we don't actually set it to the same mode the buffer already has."
 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."
+FUNCTION instead.
+FUNCTION can be nil to hide other entries (either in this var or in
+`major-mode-remap-defaults') and means that we should call MODE."
   :type '(alist (symbol) (function)))
 
+(defvar major-mode-remap-defaults nil
+  "Alist mapping file-specified mode to actual mode.
+This works like `major-mode-remap-alist' except it has lower priority
+and it is meant to be modified by packages rather than users.")
+
+(defun major-mode-remap (mode)
+  "Return the function to use to enable MODE."
+  (or (cdr (or (assq mode major-mode-remap-alist)
+               (assq mode major-mode-remap-defaults)))
+      mode))
+
 ;; 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
@@ -3601,7 +3614,7 @@ same, do nothing and return nil."
                        (eq mode (car set-auto-mode--last))
                        (eq major-mode (cdr set-auto-mode--last)))))
     (when mode
-      (funcall (alist-get mode major-mode-remap-alist mode))
+      (funcall (major-mode-remap mode))
       (unless (eq mode major-mode)
         (setq set-auto-mode--last (cons mode major-mode)))
       mode)))
index 3d4d998432d45c575049f015403783f717ee9220..d3a90179d73c1a1dbdf1da8e1d2f4e0f2f9a863a 100644 (file)
@@ -1008,7 +1008,10 @@ will be displayed when `org-export-show-temporary-export-buffer'
 is non-nil."
   (interactive)
   (org-export-to-buffer 'beamer "*Org BEAMER Export*"
-    async subtreep visible-only body-only ext-plist (lambda () (LaTeX-mode))))
+    async subtreep visible-only body-only ext-plist
+    (if (fboundp 'major-mode-remap)
+        (major-mode-remap 'latex-mode)
+      #'LaTeX-mode)))
 
 ;;;###autoload
 (defun org-beamer-export-to-latex
index aef25232c20199b3e4805d7c28bf61f73310c718..38460d1749e48233030fe5079cb4581eec0c2027 100644 (file)
@@ -911,7 +911,9 @@ non-nil."
   (let (org-koma-letter-special-contents)
     (org-export-to-buffer 'koma-letter "*Org KOMA-LETTER Export*"
       async subtreep visible-only body-only ext-plist
-      (lambda () (LaTeX-mode)))))
+      (if (fboundp 'major-mode-remap)
+          (major-mode-remap 'latex-mode)
+        #'LaTeX-mode))))
 
 ;;;###autoload
 (defun org-koma-letter-export-to-latex
index bca387e5935691dd8bba55b1c1efeda961e46c82..98b388081ea59a8119ee7b1ee0daf1bcb4340461 100644 (file)
@@ -4160,7 +4160,10 @@ will be displayed when `org-export-show-temporary-export-buffer'
 is non-nil."
   (interactive)
   (org-export-to-buffer 'latex "*Org LATEX Export*"
-    async subtreep visible-only body-only ext-plist (lambda () (LaTeX-mode))))
+    async subtreep visible-only body-only ext-plist
+    (if (fboundp 'major-mode-remap)
+        (major-mode-remap 'latex-mode)
+      #'LaTeX-mode)))
 
 ;;;###autoload
 (defun org-latex-convert-region-to-latex ()
index 19bf559c9e772c3a1077de79d9f5095f614bdd4d..8e2fdd22acdc20925930f5934bb789210e6ef863 100644 (file)
@@ -6608,7 +6608,7 @@ use it to set a major mode there, e.g.,
     (interactive)
     (org-export-to-buffer \\='latex \"*Org LATEX Export*\"
       async subtreep visible-only body-only ext-plist
-      #\\='LaTeX-mode))
+      (major-mode-remap 'latex-mode)))
 
 When expressed as an anonymous function, using `lambda',
 POST-PROCESS needs to be quoted.
index 4ef17daf8765a16528e3c56ae204297a503aeb8b..315bb68699e07f103048a9d2e6501b9289e4d229 100644 (file)
@@ -1190,7 +1190,6 @@ BEG and END are described in `treesit-range-rules'."
   "C-c C-c" #'comment-region
   "C-c C-k" #'c-ts-mode-toggle-comment-style)
 
-;;;###autoload
 (define-derived-mode c-ts-base-mode prog-mode "C"
   "Major mode for editing C, powered by tree-sitter.
 
@@ -1439,36 +1438,33 @@ should be used.
 This function attempts to use file contents to determine whether
 the code is C or C++ and based on that chooses whether to enable
 `c-ts-mode' or `c++-ts-mode'."
+  (declare (obsolete c-or-c++-mode "30.1"))?
   (interactive)
-  (if (save-excursion
-        (save-restriction
-          (save-match-data ; Why `save-match-data'?
-            (widen)
-            (goto-char (point-min))
-            (re-search-forward c-ts-mode--c-or-c++-regexp nil t))))
-      (c++-ts-mode)
-    (c-ts-mode)))
+  (let ((mode
+         (if (save-excursion
+               (save-restriction
+                 (save-match-data       ; Why `save-match-data'?
+                   (widen)
+                   (goto-char (point-min))
+                   (re-search-forward c-ts-mode--c-or-c++-regexp nil t))))
+             'c++-ts-mode)
+         'c-ts-mode))
+    (funcall (major-mode-remap mode))))
+
 ;; The entries for C++ must come first to prevent *.c files be taken
 ;; as C++ on case-insensitive filesystems, since *.C files are C++,
 ;; not C.
 (if (treesit-ready-p 'cpp)
-    (add-to-list 'auto-mode-alist
-                 '("\\(\\.ii\\|\\.\\(CC?\\|HH?\\)\\|\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\|\\.\\(cc\\|hh\\)\\)\\'"
-                   . c++-ts-mode)))
+    (add-to-list 'major-mode-remap-defaults
+                 '(c++-mode . c++-ts-mode)))
 
 (when (treesit-ready-p 'c)
-  (add-to-list 'auto-mode-alist
-               '("\\(\\.[chi]\\|\\.lex\\|\\.y\\(acc\\)?\\)\\'" . c-ts-mode))
-  (add-to-list 'auto-mode-alist '("\\.x[pb]m\\'" . c-ts-mode))
-  ;; image-mode's association must be before the C mode, otherwise XPM
-  ;; images will be initially visited as C files.  Also note that the
-  ;; regexp must be different from what files.el does, or else
-  ;; add-to-list will not add the association where we want it.
-  (add-to-list 'auto-mode-alist '("\\.x[pb]m\\'" . image-mode)))
-
-(if (and (treesit-ready-p 'cpp)
-         (treesit-ready-p 'c))
-    (add-to-list 'auto-mode-alist '("\\.h\\'" . c-or-c++-ts-mode)))
+  (add-to-list 'major-mode-remap-defaults '(c++-mode . c++-ts-mode))
+  (add-to-list 'major-mode-remap-defaults '(c-mode . c-ts-mode)))
+
+(when (and (treesit-ready-p 'cpp)
+           (treesit-ready-p 'c))
+  (add-to-list 'major-mode-remap-defaults '(c-or-c++-mode . c-or-c++-ts-mode)))
 
 (provide 'c-ts-mode)
 (provide 'c++-ts-mode)
index 64a679eacc771f218112936f8b402974698ee6fb..e46ac2e2178fc0e4af85c2dd9447ee6848a09000 100644 (file)
@@ -2902,15 +2902,19 @@ This function attempts to use file contents to determine whether
 the code is C or C++ and based on that chooses whether to enable
 `c-mode' or `c++-mode'."
   (interactive)
-  (if (save-excursion
-        (save-restriction
-          (save-match-data
-            (widen)
-            (goto-char (point-min))
-            (re-search-forward c-or-c++-mode--regexp
-                               (+ (point) c-guess-region-max) t))))
-      (c++-mode)
-    (c-mode)))
+  (let ((mode
+        (if (save-excursion
+              (save-restriction
+                (save-match-data
+                  (widen)
+                  (goto-char (point-min))
+                  (re-search-forward c-or-c++-mode--regexp
+                                     (+ (point) c-guess-region-max) t))))
+            'c++-mode)
+        'c-mode))
+    (funcall (if (fboundp 'major-mode-remap)
+                (major-mode-remap mode)
+              mode))))
 
 \f
 ;; Support for C++
index 65adc1c55ea35de16eb14be2fd61644ed4a04ccb..296e4d0037df5b74284cecf87ae8e1a05c67d202 100644 (file)
     (treesit-major-mode-setup)))
 
 (if (treesit-ready-p 'go)
+    ;; FIXME: Should we instead put `go-mode' in `auto-mode-alist'
+    ;; and then use `major-mode-remap-defaults' to map it to `go-ts-mode'?
     (add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode)))
 
 (defun go-ts-mode--defun-name (node &optional skip-prefix)
index 0c0f720dc9b79c9a746282b1d97d023938f95621..aa6c5b1b6cc41dbc8eb2ca96c1d92f8a8521336d 100644 (file)
@@ -1220,18 +1220,8 @@ leading double colon is not added."
                                         minimize (car r))))))
 
 (if (treesit-ready-p 'ruby)
-    ;; Copied from ruby-mode.el.
-    (add-to-list 'auto-mode-alist
-                 (cons (concat "\\(?:\\.\\(?:"
-                               "rbw?\\|ru\\|rake\\|thor"
-                               "\\|jbuilder\\|rabl\\|gemspec\\|podspec"
-                               "\\)"
-                               "\\|/"
-                               "\\(?:Gem\\|Rake\\|Cap\\|Thor"
-                               "\\|Puppet\\|Berks\\|Brew"
-                               "\\|Vagrant\\|Guard\\|Pod\\)file"
-                               "\\)\\'")
-                       'ruby-ts-mode)))
+    (add-to-list 'major-mode-remap-defaults
+                 '(ruby-mode . ruby-ts-mode)))
 
 (provide 'ruby-ts-mode)
 
index 616b887109066f8d92fdb4ff68898c556879a6c1..02ee1242c724eefe50d565f344f605a77e3bb3c8 100644 (file)
@@ -1036,14 +1036,20 @@ says which mode to use."
                  ;; `tex--guess-mode' really tries to guess the *type* of file,
                  ;; so we still need to consult `major-mode-remap-alist'
                  ;; to see which mode to use for that type.
-                 (alist-get mode major-mode-remap-alist mode))))))
+                 (major-mode-remap mode))))))
 
-;; The following three autoloaded aliases appear to conflict with
-;; AUCTeX.  We keep those confusing aliases for those users who may
-;; have files annotated with -*- LaTeX -*- (e.g. because they received
+;; Support files annotated with -*- LaTeX -*- (e.g. because they received
 ;; them from someone using AUCTeX).
-;; FIXME: Turn them into autoloads so that AUCTeX can override them
-;; with its own autoloads?  Or maybe rely on `major-mode-remap-alist'?
+;;;###autoload (add-to-list 'major-mode-remap-defaults '(TeX-mode . tex-mode))
+;;;###autoload (add-to-list 'major-mode-remap-defaults '(plain-TeX-mode . plain-tex-mode))
+;;;###autoload (add-to-list 'major-mode-remap-defaults '(LaTeX-mode . latex-mode))
+
+;; FIXME: These aliases conflict with AUCTeX, but we still need them
+;; because of packages out there which call these functions directly.
+;; They should be patched to use `major-mode-remap'.
+;; It would be nice to mark them obsolete somehow to encourage using
+;; something else, but the obsolete declaration would become invalid
+;; and confusing when AUCTeX *is* installed.
 ;;;###autoload (defalias 'TeX-mode #'tex-mode)
 ;;;###autoload (defalias 'plain-TeX-mode #'plain-tex-mode)
 ;;;###autoload (defalias 'LaTeX-mode #'latex-mode)