Skip to content

Commit 82ab795

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 a357bc8 commit 82ab795

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
@@ -646,10 +646,17 @@ indentation."
646646

647647
;;;###autoload
648648
(defun php-mode-maybe ()
649-
"Select PHP mode or other major mode."
649+
"Select PHP mode or other major mode.
650+
651+
The selected mode is resolved through `major-mode-remap-alist' the way
652+
`set-auto-mode' would have done had `auto-mode-alist' named it directly,
653+
so that a remapping the user asked for still applies. Emacs's built-in
654+
`php-ts-mode' registers (php-mode . php-ts-mode) for exactly this
655+
purpose, and `treesit-enabled-modes' installs it when the user opts in."
650656
(interactive)
651657
(run-hooks php-mode-maybe-hook)
652-
(funcall (php-derivation-major-mode)))
658+
(let ((mode (php-derivation-major-mode)))
659+
(funcall (if (fboundp 'major-mode-remap) (major-mode-remap mode) mode))))
653660

654661
;;;###autoload
655662
(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)