|
|
;;; php.el --- PHP support for friends -*- lexical-binding: t; -*- |
|
|
|
|
|
;; Copyright (C) 2020 Friends of Emacs-PHP development |
|
|
|
|
|
;; Author: USAMI Kenta <tadsan@zonu.me> |
|
|
;; Created: 5 Dec 2018 |
|
|
;; Version: 1.24.0 |
|
|
;; Keywords: languages, php |
|
|
;; Homepage: https://github.com/emacs-php/php-mode |
|
|
;; 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: |
|
|
|
|
|
;; This file provides common variable and functions for PHP packages. |
|
|
|
|
|
;;; Code: |
|
|
(eval-when-compile |
|
|
(require 'cl-lib)) |
|
|
(require 'flymake) |
|
|
(require 'php-project) |
|
|
(require 'rx) |
|
|
|
|
|
;;;###autoload |
|
|
(defgroup php nil |
|
|
"Language support for PHP." |
|
|
:tag "PHP" |
|
|
:group 'languages |
|
|
:link '(url-link :tag "Official Site" "https://github.com/emacs-php/php-mode") |
|
|
:link '(url-link :tag "PHP Mode Wiki" "https://github.com/emacs-php/php-mode/wiki")) |
|
|
|
|
|
(defcustom php-executable (or (executable-find "php") "/usr/bin/php") |
|
|
"The location of the PHP executable." |
|
|
:group 'php |
|
|
:tag "PHP Executable" |
|
|
:type 'string) |
|
|
|
|
|
(defcustom php-site-url "https://www.php.net/" |
|
|
"Default PHP.net site URL. |
|
|
|
|
|
The URL to use open PHP manual and search word." |
|
|
:group 'php |
|
|
:tag "PHP Site URL" |
|
|
:type 'string) |
|
|
|
|
|
(defcustom php-manual-url 'en |
|
|
"URL at which to find PHP manual. |
|
|
You can replace \"en\" with your ISO language code." |
|
|
:group 'php |
|
|
:tag "PHP Manual URL" |
|
|
:type '(choice (const :tag "English" 'en) |
|
|
(const :tag "Brazilian Portuguese" 'pt_BR) |
|
|
(const :tag "Chinese (Simplified)" 'zh) |
|
|
(const :tag "French" 'fr) |
|
|
(const :tag "German" 'de) |
|
|
(const :tag "Japanese" 'ja) |
|
|
(const :tag "Romanian" 'ro) |
|
|
(const :tag "Russian" 'ru) |
|
|
(const :tag "Spanish" 'es) |
|
|
(const :tag "Turkish" 'tr) |
|
|
(string :tag "PHP manual URL"))) |
|
|
|
|
|
(defcustom php-search-url nil |
|
|
"URL at which to search for documentation on a word." |
|
|
:group 'php |
|
|
:tag "PHP Search URL" |
|
|
:type '(choice (string :tag "URL to search PHP documentation") |
|
|
(const :tag "Use `php-site-url' variable" nil))) |
|
|
|
|
|
(defcustom php-completion-file "" |
|
|
"Path to the file which contains the function names known to PHP." |
|
|
:type 'string) |
|
|
|
|
|
(defcustom php-manual-path "" |
|
|
"Path to the directory which contains the PHP manual." |
|
|
:type 'string) |
|
|
|
|
|
(defcustom php-search-documentation-function #'php-search-web-documentation |
|
|
"Function to search PHP Manual at cursor position." |
|
|
:group 'php |
|
|
:tag "PHP Search Documentation Function" |
|
|
:type '(choice (const :tag "Use online documentation" #'php-search-web-documentation) |
|
|
(const :tag "Use local documentation" #'php-local-manual-search) |
|
|
(function :tag "Use other function"))) |
|
|
|
|
|
(defcustom php-search-documentation-browser-function nil |
|
|
"Function to display PHP documentation in a WWW browser. |
|
|
|
|
|
If non-nil, this shadows the value of `browse-url-browser-function' when |
|
|
calling `php-search-documentation' or `php-search-local-documentation'." |
|
|
:group 'php |
|
|
:tag "PHP Search Documentation Browser Function" |
|
|
:type '(choice (const :tag "default" nil) function) |
|
|
:link '(variable-link browse-url-browser-function)) |
|
|
|
|
|
;; Define function for browsing manual |
|
|
(defun php-browse-documentation-url (url) |
|
|
"Browse a documentation URL using the configured browser function. |
|
|
|
|
|
See `php-search-documentation-browser-function'." |
|
|
(let ((browse-url-browser-function |
|
|
(or php-search-documentation-browser-function |
|
|
browse-url-browser-function))) |
|
|
(browse-url url))) |
|
|
|
|
|
(defun php-browse-manual () |
|
|
"Bring up manual for PHP." |
|
|
(interactive) |
|
|
(browse-url (if (stringp php-manual-url) |
|
|
php-manual-url |
|
|
(format "%smanual/%s/" php-site-url php-manual-url)))) |
|
|
|
|
|
(defun php-search-web-documentation (word) |
|
|
"Return URL to search PHP manual search by `WORD'." |
|
|
(interactive (list (current-word))) |
|
|
(php-browse-documentation-url (concat (or php-search-url php-site-url) word))) |
|
|
|
|
|
(defun php-search-documentation (&optional word) |
|
|
"Search PHP documentation for the `WORD' at point. |
|
|
|
|
|
If `php-manual-path' has a non-empty string value then the command |
|
|
will first try searching the local documentation. If the requested |
|
|
documentation does not exist it will fallback to searching the PHP |
|
|
website. |
|
|
|
|
|
With a prefix argument, prompt for a documentation word to search |
|
|
for. If the local documentation is available, it is used to build |
|
|
a completion list." |
|
|
(interactive) |
|
|
(if (called-interactively-p 'interactive) |
|
|
(call-interactively php-search-documentation-function) |
|
|
(funcall php-search-documentation-function word))) |
|
|
|
|
|
(defcustom php-class-suffix-when-insert "::" |
|
|
"Suffix for inserted class." |
|
|
:group 'php |
|
|
:type 'string) |
|
|
|
|
|
(defcustom php-namespace-suffix-when-insert "\\" |
|
|
"Suffix for inserted namespace." |
|
|
:group 'php |
|
|
:type 'string) |
|
|
|
|
|
(defcustom php-default-major-mode 'php-mode |
|
|
"Major mode for editing PHP script." |
|
|
:group 'php |
|
|
:tag "PHP Default Major Mode" |
|
|
:type 'function) |
|
|
|
|
|
(defcustom php-html-template-major-mode 'web-mode |
|
|
"Major mode for editing PHP-HTML template." |
|
|
:group 'php |
|
|
:tag "PHP-HTML Template Major Mode" |
|
|
:type 'function) |
|
|
|
|
|
(defcustom php-blade-template-major-mode 'web-mode |
|
|
"Major mode for editing Blade template." |
|
|
:group 'php |
|
|
:tag "PHP Blade Template Major Mode" |
|
|
:type 'function) |
|
|
|
|
|
(defcustom php-template-mode-alist |
|
|
`(("\\.blade" . ,php-blade-template-major-mode) |
|
|
("\\.phpt\\'" . ,(if (fboundp 'phpt-mode) 'phpt-mode php-default-major-mode)) |
|
|
("\\.phtml\\'" . ,php-html-template-major-mode)) |
|
|
"Automatically use another MAJOR-MODE when open template file." |
|
|
:group 'php |
|
|
:tag "PHP Template Mode Alist" |
|
|
:type '(alist :key-type regexp :value-type function) |
|
|
:link '(url-link :tag "web-mode" "http://web-mode.org/") |
|
|
:link '(url-link :tag "phpt-mode" "https://github.com/emacs-php/phpt-mode")) |
|
|
|
|
|
(defcustom php-mode-maybe-hook nil |
|
|
"List of functions to be executed on entry to `php-mode-maybe'." |
|
|
:group 'php |
|
|
:tag "PHP Mode Maybe Hook" |
|
|
:type 'hook) |
|
|
|
|
|
(defcustom php-default-builtin-web-server-port 3939 |
|
|
"Port number of PHP Built-in HTTP server (php -S)." |
|
|
:group 'php |
|
|
:tag "PHP Default Built-in Web Server Port" |
|
|
:type 'integer |
|
|
:link '(url-link :tag "Built-in web server" |
|
|
"https://www.php.net/manual/features.commandline.webserver.php")) |
|
|
|
|
|
;;; PHP Keywords |
|
|
(defconst php-magical-constants |
|
|
(list "__LINE__" "__FILE__" "__FUNCTION__" "__CLASS__" "__TRAIT__" "__METHOD__" "__NAMESPACE__") |
|
|
"Magical keyword that is expanded at compile time. |
|
|
|
|
|
These are different from \"constants\" in strict terms. |
|
|
see https://www.php.net/manual/language.constants.predefined.php") |
|
|
|
|
|
;;; Utillity for locate language construction |
|
|
(defsubst php-in-string-p () |
|
|
"Return non-nil if inside a string. |
|
|
it is the character that will terminate the string, or t if the string should be terminated by a generic string delimiter." |
|
|
(nth 3 (syntax-ppss))) |
|
|
|
|
|
(defsubst php-in-comment-p () |
|
|
"Return nil if outside a comment, t if inside a non-nestable comment, else an integer (the current comment nesting)." |
|
|
(nth 4 (syntax-ppss))) |
|
|
|
|
|
(defsubst php-in-string-or-comment-p () |
|
|
"Return character address of start of comment or string; nil if not in one." |
|
|
(nth 8 (syntax-ppss))) |
|
|
|
|
|
(defsubst php-in-poly-php-html-mode () |
|
|
"Return T if current buffer is in `poly-html-mode'." |
|
|
(and (boundp 'poly-php-html-mode) |
|
|
(symbol-value 'poly-php-html-mode))) |
|
|
|
|
|
(defconst php-beginning-of-defun-regexp |
|
|
"^\\s-*\\(?:\\(?:abstract\\|final\\|private\\|protected\\|public\\|static\\)\\s-+\\)*function\\s-+&?\\(\\(\\sw\\|\\s_\\)+\\)\\s-*(" |
|
|
"Regular expression for a PHP function.") |
|
|
|
|
|
(eval-when-compile |
|
|
(cl-defun php-create-regexp-for-method (&optional visibility &key include-args) |
|
|
"Make a regular expression for methods with the given VISIBILITY. |
|
|
|
|
|
VISIBILITY must be a string that names the visibility for a PHP |
|
|
method, e.g. 'public'. The parameter VISIBILITY can itself also |
|
|
be a regular expression. |
|
|
|
|
|
The regular expression this function returns will check for other |
|
|
keywords that can appear in method signatures, e.g. 'final' and |
|
|
'static'. The regular expression will have one capture group |
|
|
which will be the name of the method." |
|
|
(when (stringp visibility) |
|
|
(setq visibility (list visibility))) |
|
|
(rx-to-string `(: line-start |
|
|
(* (syntax whitespace)) |
|
|
(group |
|
|
,@(if visibility |
|
|
`((* (or "abstract" "final" "static") |
|
|
(+ (syntax whitespace))) |
|
|
(or ,@visibility) |
|
|
(+ (syntax whitespace)) |
|
|
(* (or "abstract" "final" "static") |
|
|
(+ (syntax whitespace)))) |
|
|
'((* (* (or "abstract" "final" "static" |
|
|
"private" "protected" "public") |
|
|
(+ (syntax whitespace)))))) |
|
|
"function" |
|
|
(+ (syntax whitespace)) |
|
|
(? "&" (* (syntax whitespace))) |
|
|
(group (+ (or (syntax word) (syntax symbol)))) |
|
|
(* (syntax whitespace)) |
|
|
"(" |
|
|
,@(when include-args |
|
|
'((* any) line-end)))))) |
|
|
|
|
|
(defun php-create-regexp-for-classlike (type) |
|
|
"Accepts a `TYPE' of a 'classlike' object as a string, such as |
|
|
'class' or 'interface', and returns a regexp as a string which |
|
|
can be used to match against definitions for that classlike." |
|
|
(concat |
|
|
;; First see if 'abstract' or 'final' appear, although really these |
|
|
;; are not valid for all values of `type' that the function |
|
|
;; accepts. |
|
|
"^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?" |
|
|
;; The classlike type |
|
|
type |
|
|
;; Its name, which is the first captured group in the regexp. We |
|
|
;; allow backslashes in the name to handle namespaces, but again |
|
|
;; this is not necessarily correct for all values of `type'. |
|
|
"\\s-+\\(\\(?:\\sw\\|\\\\\\|\\s_\\)+\\)"))) |
|
|
|
|
|
(defconst php-imenu-generic-expression-default |
|
|
(eval-when-compile |
|
|
`(("Methods" |
|
|
,(php-create-regexp-for-method nil :include-args t) 1) |
|
|
("Properties" |
|
|
,(rx line-start |
|
|
(* (syntax whitespace)) |
|
|
(group |
|
|
(+ (or "public" "protected" "private" "static" "var") |
|
|
(+ (syntax whitespace))) |
|
|
(* (? (? (or "|" "?")) |
|
|
(or "\\" (syntax word) (syntax symbol)) |
|
|
(+ (syntax whitespace)))) |
|
|
"$" (+ (or (syntax word) (syntax symbol))) |
|
|
word-boundary)) |
|
|
1) |
|
|
("Constants" |
|
|
,(rx line-start |
|
|
(* (syntax whitespace)) |
|
|
(group |
|
|
(* (or "public" "protected" "private") |
|
|
(+ (syntax whitespace))) |
|
|
"const" |
|
|
(+ (syntax whitespace)) |
|
|
(+ (or (syntax word) (syntax symbol))) |
|
|
(* (syntax whitespace)) |
|
|
(? "=" (* (syntax whitespace)) |
|
|
(repeat 0 40 any)))) |
|
|
1) |
|
|
("Functions" |
|
|
,(rx line-start |
|
|
(* (syntax whitespace)) |
|
|
(group |
|
|
"function" |
|
|
(+ (syntax whitespace)) |
|
|
(+ (or (syntax word) (syntax symbol))) |
|
|
(* (syntax whitespace)) |
|
|
"(" |
|
|
(repeat 0 100 any))) |
|
|
1) |
|
|
("Import" |
|
|
,(rx line-start |
|
|
;; (* (syntax whitespace)) |
|
|
(group |
|
|
"use" |
|
|
(+ (syntax whitespace)) |
|
|
(repeat 0 100 any))) |
|
|
1) |
|
|
("Classes" |
|
|
,(php-create-regexp-for-classlike "\\(?:class\\|interface\\|trait\\|enum\\)") 0) |
|
|
("Namespace" |
|
|
,(php-create-regexp-for-classlike "namespace") 1))) |
|
|
"Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") |
|
|
|
|
|
(defconst php-imenu-generic-expression-simple |
|
|
(eval-when-compile |
|
|
`(("Methods" |
|
|
,(php-create-regexp-for-method nil) 2) |
|
|
("Properties" |
|
|
,(rx line-start |
|
|
(* (syntax whitespace)) |
|
|
(+ (or "public" "protected" "private" "static" "var") |
|
|
(+ (syntax whitespace))) |
|
|
(* (? (? (or "|" "?")) |
|
|
(or "\\" (syntax word) (syntax symbol)) |
|
|
(+ (syntax whitespace)))) |
|
|
(group |
|
|
"$" (+ (or (syntax word) (syntax symbol)))) |
|
|
word-boundary) |
|
|
1) |
|
|
("Constants" |
|
|
,(rx line-start |
|
|
(* (syntax whitespace)) |
|
|
(group |
|
|
(* (or "public" "protected" "private") |
|
|
(+ (syntax whitespace))) |
|
|
"const" |
|
|
(+ (syntax whitespace)) |
|
|
(+ (or (syntax word) (syntax symbol))))) |
|
|
1) |
|
|
("Functions" |
|
|
,(rx line-start |
|
|
(* (syntax whitespace)) |
|
|
"function" |
|
|
(+ (syntax whitespace)) |
|
|
(group |
|
|
(+ (or (syntax word) (syntax symbol))))) |
|
|
1) |
|
|
("Classes" |
|
|
,(php-create-regexp-for-classlike "\\(?:class\\|interface\\|trait\\|enum\\)") 1) |
|
|
("Namespace" |
|
|
,(php-create-regexp-for-classlike "namespace") 1))) |
|
|
"Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") |
|
|
|
|
|
(defconst php-imenu-generic-expression-legacy |
|
|
(eval-when-compile |
|
|
`(("Namespaces" |
|
|
,(php-create-regexp-for-classlike "namespace") 1) |
|
|
("Classes" |
|
|
,(php-create-regexp-for-classlike "class") 1) |
|
|
("Interfaces" |
|
|
,(php-create-regexp-for-classlike "interface") 1) |
|
|
("Traits" |
|
|
,(php-create-regexp-for-classlike "trait") 1) |
|
|
("All Methods" |
|
|
,(php-create-regexp-for-method) 1) |
|
|
("Private Methods" |
|
|
,(php-create-regexp-for-method '("private")) 2) |
|
|
("Protected Methods" |
|
|
,(php-create-regexp-for-method '("protected")) 2) |
|
|
("Public Methods" |
|
|
,(php-create-regexp-for-method '("public")) 2) |
|
|
("Anonymous Functions" |
|
|
"\\<\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*=\\s-*f\\(unctio\\)?n\\s-*(" 1) |
|
|
("Named Functions" |
|
|
"^\\s-*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1))) |
|
|
"Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") |
|
|
|
|
|
(defcustom php-imenu-generic-expression 'php-imenu-generic-expression-default |
|
|
"Default Imenu generic expression for PHP Mode. See `imenu-generic-expression'." |
|
|
:type '(choice (alist :key-type string :value-type list) |
|
|
(const 'php-imenu-generic-expression-legacy) |
|
|
(const 'php-imenu-generic-expression-simple) |
|
|
variable) |
|
|
:group 'php) |
|
|
|
|
|
(defconst php--re-namespace-pattern |
|
|
(eval-when-compile |
|
|
(php-create-regexp-for-classlike "namespace"))) |
|
|
|
|
|
(defconst php--re-classlike-pattern |
|
|
(eval-when-compile |
|
|
(php-create-regexp-for-classlike (regexp-opt '("class" "interface" "trait"))))) |
|
|
|
|
|
(defun php-get-current-element (re-pattern) |
|
|
"Return backward matched element by RE-PATTERN." |
|
|
(save-excursion |
|
|
(save-match-data |
|
|
(when (re-search-backward re-pattern nil t) |
|
|
(match-string-no-properties 1))))) |
|
|
|
|
|
(defun php-get-pattern () |
|
|
"Find the pattern we want to complete. |
|
|
`find-tag-default' from GNU Emacs etags.el" |
|
|
(save-excursion |
|
|
(save-match-data |
|
|
(while (looking-at "\\sw\\|\\s_") |
|
|
(forward-char 1)) |
|
|
(when (or (re-search-backward "\\sw\\|\\s_" |
|
|
(save-excursion (beginning-of-line) (point)) |
|
|
t) |
|
|
(re-search-forward "\\(\\sw\\|\\s_\\)+" |
|
|
(save-excursion (end-of-line) (point)) |
|
|
t)) |
|
|
(goto-char (match-end 0)) |
|
|
(buffer-substring-no-properties |
|
|
(point) |
|
|
(progn |
|
|
(forward-sexp -1) |
|
|
(while (looking-at "\\s'") |
|
|
(forward-char 1)) |
|
|
(point))))))) |
|
|
|
|
|
;;; Provide support for Flymake so that users can see warnings and |
|
|
;;; errors in real-time as they write code. |
|
|
(defun php-flymake-php-init () |
|
|
"PHP specific init-cleanup routines. |
|
|
|
|
|
This is an alternative function of `flymake-php-init'. |
|
|
Look at the `php-executable' variable instead of the constant \"php\" command." |
|
|
(let* ((init (funcall (eval-when-compile |
|
|
(if (fboundp 'flymake-proc-php-init) |
|
|
'flymake-proc-php-init |
|
|
'flymake-php-init))))) |
|
|
(list php-executable (cdr init)))) |
|
|
|
|
|
(defconst php-re-detect-html-tag-aggressive |
|
|
(eval-when-compile |
|
|
(rx (or (: string-start (* (in space)) |
|
|
"<!" |
|
|
(or "DOCTYPE" "doctype") |
|
|
(+ (in space)) |
|
|
(or "HTML" "html")) |
|
|
(: (or line-start |
|
|
(: "<" (? "/") |
|
|
(* (in space)) (+ (in alpha "-")) (* (in space)) ">")) |
|
|
(: "<" (* (in space)) (+ (in alpha "-")) (* (in space)) ">")))))) |
|
|
|
|
|
(defconst php-re-detect-html-tag-default |
|
|
(eval-when-compile |
|
|
(rx (or (: string-start (* (in space)) |
|
|
"<!" |
|
|
(or "DOCTYPE" "doctype") |
|
|
(+ (in space)) |
|
|
(or "HTML" "html")) |
|
|
(: line-start |
|
|
(: "<" (* (in space)) (+ (in alpha "-")) (* (in space)) ">")))))) |
|
|
|
|
|
(defcustom php-re-detect-html-tag 'php-re-detect-html-tag-default |
|
|
"Regexp pattern variable-name of HTML detection." |
|
|
:group 'php |
|
|
:tag "PHP Re Detect HTML Tag" |
|
|
:type '(choice (const :tag "Default pattern" 'php-re-detect-html-tag-default) |
|
|
(const :tag "Aggressive pattern" 'php-re-detect-html-tag-aggressive) |
|
|
(variable :tag "Variable name of RegExp pattern"))) |
|
|
|
|
|
(defsubst php-re-detect-html-tag () |
|
|
"Return RegExp pattern for HTML detection." |
|
|
(if (symbolp php-re-detect-html-tag) |
|
|
(symbol-value php-re-detect-html-tag) |
|
|
php-re-detect-html-tag)) |
|
|
|
|
|
(defun php-buffer-has-html-tag () |
|
|
"Return position of HTML tag or NIL in current buffer." |
|
|
(save-excursion |
|
|
(save-restriction |
|
|
(widen) |
|
|
(goto-char (point-min)) |
|
|
(save-match-data |
|
|
(re-search-forward (php-re-detect-html-tag) nil t))))) |
|
|
|
|
|
(defun php-derivation-major-mode () |
|
|
"Return major mode for PHP file by file-name and its content." |
|
|
(let ((mode (assoc-default buffer-file-name |
|
|
php-template-mode-alist |
|
|
#'string-match-p)) |
|
|
type) |
|
|
(when (and (null mode) buffer-file-name |
|
|
php-project-php-file-as-template) |
|
|
(setq type (php-project-get-file-html-template-type buffer-file-name)) |
|
|
(cond |
|
|
((eq t type) (setq mode php-html-template-major-mode)) |
|
|
((eq 'auto type) |
|
|
(when (php-buffer-has-html-tag) |
|
|
(setq mode php-html-template-major-mode))))) |
|
|
(when (and mode (not (fboundp mode))) |
|
|
(if (string-match-p "\\.blade\\." buffer-file-name) |
|
|
(warn "php-mode is NOT support blade template. %s" |
|
|
"Please install `web-mode' package") |
|
|
(setq mode nil))) |
|
|
(or mode php-default-major-mode))) |
|
|
|
|
|
;;;###autoload |
|
|
(defun php-mode-maybe () |
|
|
"Select PHP mode or other major mode." |
|
|
(interactive) |
|
|
(run-hooks php-mode-maybe-hook) |
|
|
(funcall (php-derivation-major-mode))) |
|
|
|
|
|
;;;###autoload |
|
|
(defun php-current-class () |
|
|
"Insert current class name if cursor in class context." |
|
|
(interactive) |
|
|
(let ((matched (php-get-current-element php--re-classlike-pattern))) |
|
|
(when matched |
|
|
(insert (concat matched php-class-suffix-when-insert))))) |
|
|
|
|
|
;;;###autoload |
|
|
(defun php-current-namespace () |
|
|
"Insert current namespace if cursor in namespace context." |
|
|
(interactive) |
|
|
(let ((matched (php-get-current-element php--re-namespace-pattern))) |
|
|
(when matched |
|
|
(insert (concat matched php-namespace-suffix-when-insert))))) |
|
|
|
|
|
;;;###autoload |
|
|
(defun php-copyit-fqsen () |
|
|
"Copy/kill class/method FQSEN." |
|
|
(interactive) |
|
|
(let ((namespace (or (php-get-current-element php--re-namespace-pattern) "")) |
|
|
(class (or (php-get-current-element php--re-classlike-pattern) "")) |
|
|
(namedfunc (php-get-current-element php-beginning-of-defun-regexp))) |
|
|
(kill-new (concat (if (string= namespace "") "" namespace) |
|
|
(if (string= class "") "" (concat "\\" class "::")) |
|
|
(if (string= namedfunc "") "" (concat namedfunc "()")))))) |
|
|
|
|
|
;;;###autoload |
|
|
(defun php-run-builtin-web-server (router-or-dir hostname port &optional document-root) |
|
|
"Run PHP Built-in web server. |
|
|
|
|
|
`ROUTER-OR-DIR': Path to router PHP script or Document root. |
|
|
`HOSTNAME': Hostname or IP address of Built-in web server. |
|
|
`PORT': Port number of Built-in web server. |
|
|
`DOCUMENT-ROOT': Path to Document root. |
|
|
|
|
|
When `DOCUMENT-ROOT' is NIL, the document root is obtained from `ROUTER-OR-DIR'." |
|
|
(interactive |
|
|
(let ((insert-default-directory t) |
|
|
(d-o-r (read-file-name "Document root or Script: " default-directory))) |
|
|
(list |
|
|
(expand-file-name d-o-r) |
|
|
(read-string "Hostname: " "0.0.0.0") |
|
|
(read-number "Port: " php-default-builtin-web-server-port) |
|
|
(if (file-directory-p d-o-r) |
|
|
nil |
|
|
(let ((root-input (read-file-name "Document root: " (directory-file-name d-o-r)))) |
|
|
(file-name-directory |
|
|
(if (file-directory-p root-input) |
|
|
root-input |
|
|
(directory-file-name root-input)))))))) |
|
|
(let* ((default-directory |
|
|
(or document-root |
|
|
(if (file-directory-p router-or-dir) |
|
|
router-or-dir |
|
|
(directory-file-name router-or-dir)))) |
|
|
(short-dirname (abbreviate-file-name default-directory)) |
|
|
(short-filename (abbreviate-file-name router-or-dir)) |
|
|
(buf-name (format "php -S %s:%s -t %s %s" |
|
|
hostname |
|
|
port |
|
|
short-dirname |
|
|
(if document-root short-filename ""))) |
|
|
(args (cl-remove-if |
|
|
#'null |
|
|
(list "-S" |
|
|
(format "%s:%d" hostname port) |
|
|
"-t" |
|
|
default-directory |
|
|
(when document-root router-or-dir))))) |
|
|
(message "Run PHP built-in server: %s" buf-name) |
|
|
(apply #'make-comint buf-name php-executable nil args) |
|
|
(funcall |
|
|
(if (called-interactively-p 'interactive) #'display-buffer #'get-buffer) |
|
|
(format "*%s*" buf-name)))) |
|
|
|
|
|
(defun php-ini () |
|
|
"Get `php --ini' output buffer." |
|
|
(interactive) |
|
|
(let ((buffer (get-buffer-create " *php --ini*"))) |
|
|
(with-current-buffer buffer |
|
|
(view-mode -1) |
|
|
(read-only-mode -1) |
|
|
(erase-buffer) |
|
|
(shell-command (concat php-executable " --ini") buffer) |
|
|
(view-mode +1)) |
|
|
(if (called-interactively-p 'interactive) |
|
|
(pop-to-buffer buffer) |
|
|
buffer))) |
|
|
|
|
|
;;;###autoload |
|
|
(defun php-find-system-php-ini-file (&optional file) |
|
|
"Find php.ini FILE by `php --ini'." |
|
|
(interactive |
|
|
(list |
|
|
(let* ((default-directory (expand-file-name "~")) |
|
|
(buffer (php-ini)) |
|
|
(path (with-current-buffer buffer |
|
|
(goto-char (point-min)) |
|
|
(save-match-data |
|
|
(when (re-search-forward ": \\(.+?\\)$" nil nil) |
|
|
(match-string 1)))))) |
|
|
(when (or (null path) (not (file-directory-p path))) |
|
|
(when (called-interactively-p 'interactive) |
|
|
(pop-to-buffer buffer)) |
|
|
(user-error "Failed get path to PHP ini files directory")) |
|
|
(read-file-name "Find php.ini file: " |
|
|
(concat (expand-file-name path) "/") |
|
|
nil nil nil |
|
|
#'file-exists-p)))) |
|
|
(find-file file)) |
|
|
|
|
|
(provide 'php) |
|
|
;;; php.el ends here
|
|
|
|