Skip to content

Commit 63422d6

Browse files
committed
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).
1 parent 22e5c80 commit 63422d6

2 files changed

Lines changed: 44 additions & 2 deletions

File tree

lisp/php.el

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,10 +663,17 @@ Currently there are `php-mode' and `php-ts-mode'."
663663

664664
;;;###autoload
665665
(defun php-mode-maybe ()
666-
"Select PHP mode or other major mode."
666+
"Select PHP mode or other major mode.
667+
668+
The selected mode is resolved through `major-mode-remap-alist' the way
669+
`set-auto-mode' would have done had `auto-mode-alist' named it directly,
670+
so that a remapping the user asked for still applies. Emacs's built-in
671+
`php-ts-mode' registers (php-mode . php-ts-mode) for exactly this
672+
purpose, and `treesit-enabled-modes' installs it when the user opts in."
667673
(interactive)
668674
(run-hooks php-mode-maybe-hook)
669-
(funcall (php-derivation-major-mode)))
675+
(let ((mode (php-derivation-major-mode)))
676+
(funcall (if (fboundp 'major-mode-remap) (major-mode-remap mode) mode))))
670677

671678
;;;###autoload
672679
(defun php-current-class ()

tests/php-mode-test.el

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,41 @@ than depending on `poly-php', because that package pulls in a released
699699
(set-buffer-modified-p nil)
700700
(setq buffer-file-name nil)))))
701701

702+
(define-derived-mode php-mode-test--stub-ts-mode prog-mode "PHP/stub-ts"
703+
"Stand-in for `php-ts-mode' in `php-mode-test-mode-remap'.
704+
Using a stub keeps the test independent of whether the PHP tree-sitter
705+
grammar is installed.")
706+
707+
(ert-deftest php-mode-test-mode-remap ()
708+
"`php-mode-maybe' must honor `major-mode-remap-alist'.
709+
710+
Emacs's built-in `php-ts-mode' registers (php-mode . php-ts-mode) in
711+
`treesit-major-mode-remap-alist' so that users can toggle between this
712+
package and the core tree-sitter mode; `treesit-enabled-modes' copies
713+
that entry into `major-mode-remap-alist' when they opt in.
714+
715+
`set-auto-mode' applies the remapping to whatever `auto-mode-alist'
716+
names, so file patterns pointing straight at `php-mode' honored it while
717+
those going through `php-mode-maybe' did not: the same buffer became
718+
`php-mode' for \".php\" but the remapped mode for \".stub\"."
719+
(skip-unless (fboundp 'major-mode-remap))
720+
(dolist (probe '((((php-mode . php-mode-test--stub-ts-mode))
721+
. php-mode-test--stub-ts-mode)
722+
;; Without a remapping the derived mode is used as-is.
723+
(nil . php-mode)))
724+
(let ((major-mode-remap-alist (car probe)))
725+
(with-temp-buffer
726+
;; `php-derivation-major-mode' consults `buffer-file-name'.
727+
(setq buffer-file-name (expand-file-name "remap.php" temporary-file-directory))
728+
(unwind-protect
729+
(progn
730+
(insert "<?php\necho 'hi';\n")
731+
(php-mode-maybe)
732+
(should (equal (cons (car probe) (cdr probe))
733+
(cons (car probe) major-mode))))
734+
(set-buffer-modified-p nil)
735+
(setq buffer-file-name nil))))))
736+
702737
(ert-deftest php-mode-test-php74 ()
703738
"Test highlighting language constructs added in PHP 7.4."
704739
(with-php-mode-test ("7.4/arrow-function.php" :faces t))

0 commit comments

Comments
 (0)