branch: elpa/php-mode commit bb5bec31ee927e184c1ddc162d0ddbb92d56d633 Author: USAMI Kenta <tad...@zonu.me> Commit: USAMI Kenta <tad...@zonu.me>
Add php-ide.el --- Cask | 2 + Makefile | 1 + lisp/php-ide.el | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) diff --git a/Cask b/Cask index e090d524d5..0e8d058553 100644 --- a/Cask +++ b/Cask @@ -13,9 +13,11 @@ "lisp/php-project.el" "lisp/php-local-manual.el" "lisp/php-ide-phpactor.el" + "lisp/php-ide.el" "lisp/php-mode-debug.el") (development + ;;(depends-on "lsp-mode") (depends-on "phpactor") (depends-on "pkg-info") (depends-on "projectile") diff --git a/Makefile b/Makefile index c2fc9ffe84..42db81da41 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ ELS += lisp/php-face.el ELS += lisp/php-flymake.el ELS += lisp/php-format.el ELS += lisp/php-ide-phpactor.el +ELS += lisp/php-ide.el ELS += lisp/php-local-manual.el ELS += lisp/php-mode-debug.el ELS += lisp/php-mode.el diff --git a/lisp/php-ide.el b/lisp/php-ide.el new file mode 100644 index 0000000000..e19de0b219 --- /dev/null +++ b/lisp/php-ide.el @@ -0,0 +1,184 @@ +;;; php-ide.el --- IDE-like UI support for PHP development -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Friends of Emacs-PHP development + +;; Author: USAMI Kenta <tad...@zonu.me> +;; Keywords: tools, files +;; URL: https://github.com/emacs-php/php-mode +;; Version: 1.24.0 +;; License: GPL-3.0-or-later + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; PHP Mode integrates LSP Mode (lsp-mode), Phpactor (phpactor.el) and IDE-like tools. +;; +;; **Note**: +;; This feature is under development and experimental. +;; All of these functions, modes and terms are subject to change without notice. +;; +;; ## Motivations +;; +;; There are some IDE-like features / packages for PHP development. +;; PHP-IDE bridges projects and their IDE-like features. +;; +;; ## IDE Features +;; +;; We don't recommend features, but bundle some feature bridges. +;; They are sorted alphabetically except "none." +;; +;; - none +;; Does not launch any IDE features. +;; - eglot +;; https://github.com/joaotavora/eglot +;; - lsp-mode +;; https://emacs-lsp.github.io/lsp-mode/ +;; https://github.com/emacs-lsp/lsp-mode +;; - phpactor +;; https://phpactor.readthedocs.io/ +;; https://github.com/phpactor/phpactor +;; https://github.com/emacs-php/phpactor.el +;; +;; ## Configuration +;; +;; Put follows code into your .emacs (~/.emacs.d/init.el) file: +;; +;; (defun my-php-mode-setup () +;; (add-hook 'hack-local-variables-hook #'php-ide-mode t t)) +;; +;; (with-eval-after-load 'php-ide +;; (custom-set-variables +;; '(php-ide-features . 'eglot) ;; and/or 'none, 'phpactor, 'lsp-mode +;; '(php-ide-eglot-executable "psalm-language-server") ;; or "intelephense", '("php" "vendor/bin/path/to/server") +;; ;; If you want to hide php-ide-mode from the mode line, set an empty string +;; '(php-ide-mode-lighter "")) +;; +;; (add-hook 'php-mode #'my-php-mode-setup)) +;; +;; If you don't enable IDE support by default, set '(php-ide-feature 'none) +;; +;; ### For per project configuration +;; +;; Put follows code into .dir-locals.el in project directory: +;; +;; ((nil (php-project-root . git) +;; (php-ide-features . (lsp-mode)))) +;; +;; If you can't put .dir-locals.el in your project directory, consider the sidecar-locals package. +;; https://melpa.org/#/sidecar-locals +;; https://codeberg.org/ideasman42/emacs-sidecar-locals +;; + +;;; Code: +(require 'php-project) + +(eval-when-compile + (require 'cl-lib) + (require 'php-ide-phpactor) + (defvar eglot-server-programs) + (declare-function eglot-ensure "ext:eglot" ()) + (declare-function eglot--managed-mode-off "ext:eglot" ()) + (declare-function phpactor--find-executable "ext:phpactor" ())) + +(defvar php-ide-feature-alist + '((none :test (lambda () t) + :activate (lambda () t) + :deactivate (lambda () t)) + (phpactor :test (lambda () (and (require 'phpactor nil t) (featurep 'phpactor))) + :activate php-ide-phpactor-activate + :deactivate php-ide-phpactor-activate) + (eglot :test (lambda () (and (require 'eglot nil t) (featurep 'eglot))) + :activate eglot-ensure + :deactivate eglot--managed-mode-off) + (lsp-mode :test (lambda () (and (require 'lsp nil t) (featurep 'lsp))) + :activate lsp + :deactivate lsp-workspace-shutdown))) + +(defvar php-ide-lsp-command-alist + '((intelephense "intelephense" "--stdio") + (phpactor . (lambda () (list (if (fboundp 'phpactor--find-executable) + (phpactor--find-executable) + "phpactor") + "language-server"))))) + +(defgroup php-ide nil + "IDE-like support for PHP developing." + :tag "PHP-IDE" + :prefix "php-ide-" + :group 'php) + +;;;###autoload +(defcustom php-ide-features nil + "A set of PHP-IDE features symbol." + :tag "PHP-IDE Feature" + :group 'php-ide + :type `(set ,@(mapcar (lambda (feature) (list 'const (car feature))) + php-ide-feature-alist) + symbol) + :safe (lambda (v) (cl-loop for feature in (if (listp v) v (list v)) + always (symbolp feature)))) + +(defcustom php-ide-mode-lighter " PHP-IDE" + "A symbol of PHP-IDE feature." + :tag "PHP-IDE Mode Lighter" + :group 'php-ide + :type 'string + :safe #'stringp) + +;;;###autoload +(define-minor-mode php-ide-mode + "Minor mode for integrate IDE-like tools." + :lighter php-ide-mode-lighter + (let ((ide-features php-ide-features)) + (when-let (unavailable-features (cl-loop for feature in ide-features + unless (assq feature php-ide-feature-alist) + collect feature)) + (user-error "%s includes unavailable PHP-IDE features. (available features are: %s)" + ide-features + (mapconcat (lambda (feature) (concat "'" (symbol-name feature))) + (php-ide--avilable-features) ", "))) + (cl-loop for feature in ide-features + for ide-plist = (cdr-safe (assq feature php-ide-feature-alist)) + do (if (null ide-plist) + (message "Please set `php-ide-feature' variable in .dir-locals.el or custom variable") + (if php-ide-mode + (php-ide--activate-buffer feature ide-plist) + (php-ide--deactivate-buffer ide-plist)))))) + +;;;###autoload +(defun php-ide-turn-on () + "Turn on PHP IDE-FEATURES and execute `php-ide-mode'." + (unless php-ide-features + (user-error "No PHP-IDE feature is installed. Install the lsp-mode, eglot or phpactor package")) + (php-ide-mode +1)) + +(defun php-ide--activate-buffer (name ide-plist) + "Activate php-ide implementation by NAME and IDE-PLIST." + (unless (funcall (plist-get ide-plist :test)) + (user-error "PHP-IDE feature `%s' is not available" name)) + (funcall (plist-get ide-plist :activate))) + +(defun php-ide--deactivate-buffer (ide-plist) + "Deactivate php-ide implementation by IDE-PLIST." + (funcall (plist-get ide-plist :deactivate))) + +(defun php-ide--avilable-features () + "Return list of available PHP-IDE features." + (cl-loop for (ide . plist) in php-ide-feature-alist + if (funcall (plist-get plist :test)) + collect ide)) + +(provide 'php-ide) +;;; php-ide.el ends here