diff --git a/modules/lang/php/README.org b/modules/lang/php/README.org index 321ce8177..24f7c1f31 100644 --- a/modules/lang/php/README.org +++ b/modules/lang/php/README.org @@ -36,7 +36,7 @@ This module adds support for PHP 5.3+ (including PHP8) to Doom Emacs. langserver (supports [[https://emacs-lsp.github.io/lsp-mode/page/lsp-phpactor/][phpactor]], [[https://emacs-lsp.github.io/lsp-mode/page/lsp-intelephense/][intelephense]], [[https://emacs-lsp.github.io/lsp-mode/page/lsp-serenata/][serenata]], [[https://emacs-lsp.github.io/lsp-mode/page/lsp-php/][php-language-server]]). - +tree-sitter :: Leverages tree-sitter for better syntax highlighting and structural text - editing. Requires [[doom-module::tools tree-sitter]]. + editing. Requires [[doom-module::tools tree-sitter]] and Emacs 30.1+. ** Packages - [[doom-package:async]] diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index 62b1c405e..fe7460e0f 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -1,7 +1,7 @@ ;;; lang/php/config.el -*- lexical-binding: t; -*- (defvar +php--company-backends nil - "List of company backends to use in `php-mode'.") + "List of company backends to use in `php-mode' and `php-ts-mode'.") (defvar +php-default-docker-container "php-fpm" "The default docker container to run commands in.") @@ -20,18 +20,11 @@ ;; ;;; Packages -(use-package! php-mode - :mode "\\.inc\\'" - :hook (php-mode . rainbow-delimiters-mode) - :config - ;; Disable HTML compatibility in php-mode. `web-mode' has superior support for - ;; php+html. Use the .phtml extension instead. - (setq php-mode-template-compatibility nil) - - (set-docsets! 'php-mode "PHP" "PHPUnit" "Laravel" "CakePHP" "CodeIgniter" "Doctrine_ORM") - (set-repl-handler! 'php-mode #'+php/open-repl) - (set-lookup-handlers! 'php-mode :documentation #'php-search-documentation) - (set-ligatures! 'php-mode +(defun +php-common-config (mode) + (set-docsets! mode "PHP" "PHPUnit" "Laravel" "CakePHP" "CodeIgniter" "Doctrine_ORM") + (set-repl-handler! mode #'+php/open-repl) + (set-lookup-handlers! mode :documentation #'php-search-documentation) + (set-ligatures! mode ;; Functional :lambda "function()" :lambda "fn" :def "function" @@ -49,37 +42,63 @@ :return "return" :yield "use") - (if (modulep! -lsp) - ;; `+php-company-backend' uses `php-extras-company' or - ;; `company-dabbrev-code', in that order. - (when +php--company-backends - (set-company-backend! 'php-mode - (cons :separate +php--company-backends) - 'company-dabbrev-code)) - (when (executable-find "php-language-server.php") - (setq lsp-clients-php-server-command "php-language-server.php")) - (add-hook 'php-mode-local-vars-hook #'lsp! 'append)) + (let ((mode-hook (intern (format "%s-hook" mode))) + (mode-vars-hook (intern (format "%s-local-vars-hook" mode))) + (mode-map (symbol-value (intern (format "%s-map" mode))))) + (sp-with-modes (ensure-list mode) + (sp-local-pair "" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p"))) + (sp-local-pair "" :post-handlers '(("| " "SPC") ("||\n[i]" "RET")))) - (when (modulep! +tree-sitter) - (add-hook 'php-mode-local-vars-hook #'tree-sitter! 'append)) + (if (modulep! -lsp) + ;; `+php-company-backend' uses `php-extras-company' or + ;; `company-dabbrev-code', in that order. + (when +php--company-backends + (set-company-backend! mode + (cons :separate +php--company-backends) + 'company-dabbrev-code)) + (when (executable-find "php-language-server.php") + (setq lsp-clients-php-server-command "php-language-server.php")) + (add-hook mode-vars-hook #'lsp! 'append)) - ;; Use the smallest `sp-max-pair-length' for optimum `smartparens' performance - (setq-hook! 'php-mode-hook sp-max-pair-length 5) + (map! :localleader + :map ,mode-map + :prefix ("t" . "test") + "r" #'phpunit-current-project + "a" #'phpunit-current-class + "s" #'phpunit-current-test))) - (sp-with-modes '(php-mode) - (sp-local-pair "" :post-handlers '(("| " "SPC" "=") ("||\n[i]" "RET") ("[d2]" "p"))) - (sp-local-pair "" :post-handlers '(("| " "SPC") ("||\n[i]" "RET")))) - (map! :localleader - :map php-mode-map - :prefix ("t" . "test") - "r" #'phpunit-current-project - "a" #'phpunit-current-class - "s" #'phpunit-current-test)) +(use-package! php-mode + :hook (php-mode . rainbow-delimiters-mode) + :config + (+php-common-config 'php-mode) + + ;; Disable HTML compatibility in php-mode. `web-mode' has superior support for + ;; php+html. Use the .phtml extension instead. + (setq php-mode-template-compatibility nil)) + + +(use-package! php-ts-mode + :when (modulep! +tree-sitter) + :when (fboundp 'php-ts-mode) ; 30.1+ only + :defer t + :init + (set-tree-sitter! 'php-mode 'php-ts-mode + '((php :url "https://github.com/tree-sitter/tree-sitter-php" + :rev "v0.23.11" + :source-dir "php/src") + (phpdoc :url "https://github.com/claytonrcarter/tree-sitter-phpdoc"))) + :config + ;; HACK: Rely on `major-mode-remap-defaults'. + (cl-callf2 rassq-delete-all 'php-ts-mode auto-mode-alist) + (cl-callf2 rassq-delete-all 'php-ts-mode interpreter-mode-alist) + + (+php-common-config 'php-ts-mode)) (use-package! php-refactor-mode :hook php-mode + :hook php-ts-mode :config (map! :localleader :map php-refactor-mode-map @@ -91,7 +110,7 @@ (use-package! php-extras - :after php-mode + :after (:or php-mode php-ts-mode) :preface (setq php-extras-eldoc-functions-file (concat doom-profile-cache-dir "php-extras-eldoc-functions")) @@ -124,10 +143,9 @@ (use-package! composer :defer t :init - (map! :after php-mode - :localleader - :map php-mode-map - :prefix ("c" . "composer") + (setq composer-directory-to-managed-file (file-name-concat doom-etc-dir "composer/")) + (defvar +php-common-mode-map (make-sparse-keymap)) + (map! :map +php-common-mode-map "c" #'composer "i" #'composer-install "r" #'composer-require @@ -136,23 +154,29 @@ "s" #'composer-run-script "v" #'composer-run-vendor-bin-command "o" #'composer-find-json-file - "l" #'composer-view-lock-file)) + "l" #'composer-view-lock-file) + (map! :after php-mode + :map php-mode-map + :desc "composer" "c" +php-common-mode-map) + (map! :after php-ts-mode + :map php-ts-mode-map + :desc "composer" "c" +php-common-mode-map)) ;; ;; Projects (def-project-mode! +php-laravel-mode - :modes '(php-mode yaml-mode web-mode nxml-mode js2-mode scss-mode) + :modes '(php-mode php-ts-mode yaml-mode web-mode nxml-mode js2-mode scss-mode) :files (and "artisan" "server.php")) (def-project-mode! +php-composer-mode - :modes '(web-mode php-mode) + :modes '(web-mode php-mode php-ts-mode) :files ("composer.json")) (def-project-mode! +phpunit-docker-compose-mode :when +php-run-tests-in-docker - :modes '(php-mode docker-compose-mode) + :modes '(php-mode php-ts-mode docker-compose-mode) :files (and "phpunit.xml" (or +php-default-docker-compose "docker-compose.yml")) :on-enter (setq phpunit-args `("exec" ,+php-default-docker-container "php" "vendor/bin/phpunit") diff --git a/modules/lang/php/doctor.el b/modules/lang/php/doctor.el index 6094a4c75..426927e54 100644 --- a/modules/lang/php/doctor.el +++ b/modules/lang/php/doctor.el @@ -9,6 +9,10 @@ (modulep! :tools tree-sitter)) "This module requires (:tools tree-sitter)") +(assert! (or (not (modulep! +tree-sitter)) + (fboundp 'php-ts-mode)) + "Can't find `php-ts-mode'; Emacs 30.1+ is required") + (unless (executable-find "php") (warn! "Couldn't find php in your PATH"))