Subject: Re: bug#67008: 30.0.50; Multiple major mode parents

From: Ikumi Keita <[email-masked]>
Date: Sat, 11 Nov 2023 21:21:36 +0900

Hi Stefan,

>>>>> Stefan Monnier <[email-masked]> writes:
> I pushed to the branch `feature/derived-mode-add-parents` a bunch of
> patches which add support for such limited form of `multiple
> inheritance`.

I tried the branch with the attached tentative addition to AUCTeX
feature/fix-mode-names-overlap branch. I tested two modes, namely latex
mode and japanese latex mode, with the second attachment to see whether
the directory local variables stored in the .dir-locals.el are reflected
or not.

For latex mode, it works as expected. Thank you, it is promising.

On the contrary, it fails for japanese latex mode with the error:
File mode specification error: (error Cycle in the major mode hierarchy: japanese-LaTeX-mode)
I think the reason is that AUCTeX has
(defalias 'japanese-latex-mode #'japanese-LaTeX-mode)
for backward compatibility.

AUCTeX major modes are divided into two categories.
[a] Modes with former names which are overlapped with built-in tex
modes:
plain-TeX-mode, LaTeX-mode, docTeX-mode, Texinfo-mode
[b] Modes with former names which aren't overlapped with built-in tex
modes:
ConTeXt-mode, AmSTeX-mode, japanese-plain-TeX-mode, japanese-LaTeX-mode

For category [b], AUCTeX feature branch has defalias'es similar to the
above example for compatibility with files which have "%%% mode:" tag
with former mode name such as "japanese-latex".

This new feature of multiple inheritance would work well for category
[a], which retains backward compatibility by `major-mode-remap-alist'
and doesn't use defalias. However, it doesn't work for category [b].

It seems to me very difficult to arrange the proposed feature to cover
category [b], looking at its way to handle mode alias. So I think AUCTeX
feature branch must rely on some very ugly hack to be able to pick up
directory local variable entry with former mode name. :-(
(Or AUCTeX should entirely give up such compatibility with directory
local variables for category [b].)

Best regards,
Ikumi Keita
#StandWithUkraine #StopWarInUkraine

diff --git a/latex.el b/latex.el
index e9b08cc1..0551c320 100644
--- a/latex.el
+++ b/latex.el
@@ -8087,6 +8087,8 @@ Run after mode hooks and file local variables application."
 ;;;###autoload
 (put 'LaTeX-mode 'auctex-function-definition (symbol-function 'LaTeX-mode))
 
+(TeX-derived-mode-add-parents 'LaTeX-mode '(latex-mode))
+
 (with-eval-after-load 'semantic/symref/grep
   (push '(docTeX-mode "*.dtx") semantic-symref-filepattern-alist))
 
diff --git a/tex-jp.el b/tex-jp.el
index ff562e22..36a39ec1 100644
--- a/tex-jp.el
+++ b/tex-jp.el
@@ -471,6 +471,9 @@ Now `japanese-latex-mode-initialization' is no-op.  Don't use it."))
 ;;;###autoload
 (defalias 'japanese-latex-mode #'japanese-LaTeX-mode)
 
+(TeX-derived-mode-add-parents 'japanese-LaTeX-mode
+                              '(japanese-latex-mode latex-mode))
+
 (defun japanese-LaTeX-guess-engine ()
   "Guess Japanese TeX engine and set it to `TeX-engine'.
 Document class and its option are taken into account.  Do not
diff --git a/tex.el b/tex.el
index d4fded73..f67e1e31 100644
--- a/tex.el
+++ b/tex.el
@@ -3875,6 +3875,15 @@ Run after mode hooks and file local variables application."
 ;;;###autoload
 (put 'TeX-mode 'auctex-function-definition (symbol-function 'TeX-mode))
 
+;; COMPATIBILITY for Emacs<30
+(unless (fboundp 'derived-mode-add-parents)
+  (advice-add 'derived-mode-p :after-until #'TeX--compat-derived-mode-p)
+  (defun TeX--compat-derived-mode-p (&rest modes)
+    (let ((extra-parents (get major-mode 'derived-mode-extra-parents)))
+      (and extra-parents
+           (cl-loop for parent in extra-parents
+                    thereis (memq parent modes))))))
+
 ;;; Hilighting
 
 ;; FIXME: It's likely that `hilit-patterns-alist' is much obsolete.
@@ -4828,6 +4837,16 @@ Also see `ignore'.
 This is a compatibility function for Emacs versions prior to v.28."
     t))
 
+;; COMPATIBILITY for Emacs<30
+(if (fboundp 'derived-mode-add-parents)
+    (defalias 'TeX-derived-mode-add-parents #'derived-mode-add-parents)
+  ;; Adapted copy of `derived-mode-add-parents'.
+  (defun TeX-derived-mode-add-parents (mode extra-parents)
+    "Add EXTRA-PARENTS to the parents of MODE.
+Declares the parents of MODE to be its main parent (as defined
+in `define-derived-mode') plus EXTRA-PARENTS."
+    (put mode 'derived-mode-extra-parents extra-parents)))
+
 (defun TeX-match-buffer (n)
   "Return the substring corresponding to the N'th match.
 See `match-data' for details."