branch: elpa/php-mode
commit 82ab795ed6c45ce5f45e7a37f23c9129fde37639
Author: USAMI Kenta <[email protected]>
Commit: USAMI Kenta <[email protected]>
Honor major-mode-remap-alist in php-mode-maybe
Emacs's built-in php-ts-mode registers
(add-to-list 'treesit-major-mode-remap-alist '(php-mode . php-ts-mode))
with the comment "To be able to toggle between an external package and
core ts-mode", and `treesit-enabled-modes' copies that entry into
`major-mode-remap-alist' when the user opts in. So a user who installs
this package and enables php-ts-mode is asking for php-ts-mode.
They did not get it for .php files. `set-auto-mode' applies the
remapping to whatever `auto-mode-alist' names, so entries pointing
straight at `php-mode' honored it, but ".php"/".phtml" go through
`php-mode-maybe', which is not itself a remap target and called the
derived mode directly. The same buffer therefore opened in different
modes depending on the extension:
a.stub auto-mode-alist=php-mode -> php-ts-mode (remapped)
a.php auto-mode-alist=php-mode-maybe -> php-mode (not remapped)
Resolve the derived mode through `major-mode-remap' so `php-mode-maybe'
behaves as if `auto-mode-alist' had named the mode directly. The
function is Emacs 30 or later, hence the `fboundp' guard; on older
Emacs the mode is used unchanged, as before.
Note that no adjustment is needed for `php-base-mode': php-ts-mode
declares `php-mode' as an extra parent via `derived-mode-add-parents',
and `php-mode' derives from `php-base-mode', so once this package is
loaded `derived-mode-all-parents' of php-ts-mode already resolves to
(php-ts-mode php-mode php-base-mode prog-mode).
---
lisp/php.el | 11 +++++++++--
tests/php-mode-test.el | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/lisp/php.el b/lisp/php.el
index 671ff1c7cd..2e072376f2 100644
--- a/lisp/php.el
+++ b/lisp/php.el
@@ -646,10 +646,17 @@ indentation."
;;;###autoload
(defun php-mode-maybe ()
- "Select PHP mode or other major mode."
+ "Select PHP mode or other major mode.
+
+The selected mode is resolved through `major-mode-remap-alist' the way
+`set-auto-mode' would have done had `auto-mode-alist' named it directly,
+so that a remapping the user asked for still applies. Emacs's built-in
+`php-ts-mode' registers (php-mode . php-ts-mode) for exactly this
+purpose, and `treesit-enabled-modes' installs it when the user opts in."
(interactive)
(run-hooks php-mode-maybe-hook)
- (funcall (php-derivation-major-mode)))
+ (let ((mode (php-derivation-major-mode)))
+ (funcall (if (fboundp 'major-mode-remap) (major-mode-remap mode) mode))))
;;;###autoload
(defun php-current-class ()
diff --git a/tests/php-mode-test.el b/tests/php-mode-test.el
index 8985c2d6ce..da662856b1 100644
--- a/tests/php-mode-test.el
+++ b/tests/php-mode-test.el
@@ -699,6 +699,41 @@ than depending on `poly-php', because that package pulls
in a released
(set-buffer-modified-p nil)
(setq buffer-file-name nil)))))
+(define-derived-mode php-mode-test--stub-ts-mode prog-mode "PHP/stub-ts"
+ "Stand-in for `php-ts-mode' in `php-mode-test-mode-remap'.
+Using a stub keeps the test independent of whether the PHP tree-sitter
+grammar is installed.")
+
+(ert-deftest php-mode-test-mode-remap ()
+ "`php-mode-maybe' must honor `major-mode-remap-alist'.
+
+Emacs's built-in `php-ts-mode' registers (php-mode . php-ts-mode) in
+`treesit-major-mode-remap-alist' so that users can toggle between this
+package and the core tree-sitter mode; `treesit-enabled-modes' copies
+that entry into `major-mode-remap-alist' when they opt in.
+
+`set-auto-mode' applies the remapping to whatever `auto-mode-alist'
+names, so file patterns pointing straight at `php-mode' honored it while
+those going through `php-mode-maybe' did not: the same buffer became
+`php-mode' for \".php\" but the remapped mode for \".stub\"."
+ (skip-unless (fboundp 'major-mode-remap))
+ (dolist (probe '((((php-mode . php-mode-test--stub-ts-mode))
+ . php-mode-test--stub-ts-mode)
+ ;; Without a remapping the derived mode is used as-is.
+ (nil . php-mode)))
+ (let ((major-mode-remap-alist (car probe)))
+ (with-temp-buffer
+ ;; `php-derivation-major-mode' consults `buffer-file-name'.
+ (setq buffer-file-name (expand-file-name "remap.php"
temporary-file-directory))
+ (unwind-protect
+ (progn
+ (insert "<?php\necho 'hi';\n")
+ (php-mode-maybe)
+ (should (equal (cons (car probe) (cdr probe))
+ (cons (car probe) major-mode))))
+ (set-buffer-modified-p nil)
+ (setq buffer-file-name nil))))))
+
(ert-deftest php-mode-test-php74 ()
"Test highlighting language constructs added in PHP 7.4."
(with-php-mode-test ("7.4/arrow-function.php" :faces t))