update packages
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
;;; php-mode.el --- Major mode for editing PHP code
|
||||
;;; php-mode.el --- Major mode for editing PHP code -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2020 Friends of Emacs-PHP development
|
||||
;; Copyright (C) 1999, 2000, 2001, 2003, 2004 Turadg Aleahmad
|
||||
@@ -9,11 +9,11 @@
|
||||
;; Maintainer: USAMI Kenta <tadsan@zonu.me>
|
||||
;; URL: https://github.com/emacs-php/php-mode
|
||||
;; Keywords: languages php
|
||||
;; Version: 1.23.0
|
||||
;; Package-Requires: ((emacs "24.3"))
|
||||
;; Version: 1.24.0
|
||||
;; Package-Requires: ((emacs "25.2"))
|
||||
;; License: GPL-3.0-or-later
|
||||
|
||||
(defconst php-mode-version-number "1.23.0"
|
||||
(defconst php-mode-version-number "1.24.0"
|
||||
"PHP Mode version number.")
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
@@ -56,9 +56,9 @@
|
||||
(require 'php)
|
||||
(require 'php-face)
|
||||
(require 'cc-mode)
|
||||
(require 'cc-langs)
|
||||
|
||||
(eval-when-compile
|
||||
(require 'cc-langs)
|
||||
(require 'cc-fonts))
|
||||
|
||||
;; Boilerplate from other `cc-mode' derived modes. See
|
||||
@@ -69,45 +69,22 @@
|
||||
|
||||
(require 'font-lock)
|
||||
(require 'custom)
|
||||
(require 'etags)
|
||||
(require 'speedbar)
|
||||
(require 'imenu)
|
||||
(require 'nadvice nil t)
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'package)
|
||||
(require 'nadvice)
|
||||
(require 'mode-local)
|
||||
(require 'php-project)
|
||||
|
||||
(eval-when-compile
|
||||
(require 'rx)
|
||||
(require 'cl-lib)
|
||||
(require 'regexp-opt)
|
||||
(defvar add-log-current-defun-header-regexp)
|
||||
(defvar add-log-current-defun-function)
|
||||
(defvar c-vsemi-status-unknown-p)
|
||||
(defvar syntax-propertize-via-font-lock))
|
||||
|
||||
;; Work around emacs bug#18845, cc-mode expects cl to be loaded
|
||||
;; while php-mode only uses cl-lib (without compatibility aliases)
|
||||
(eval-and-compile
|
||||
(when (and (= emacs-major-version 24) (>= emacs-minor-version 4))
|
||||
(require 'cl)))
|
||||
|
||||
;; Work around https://github.com/emacs-php/php-mode/issues/310.
|
||||
;;
|
||||
;; In emacs 24.4 and 24.5, lines after functions with a return type
|
||||
;; are incorrectly analyzed as member-init-cont.
|
||||
;;
|
||||
;; Before emacs 24.4, c member initializers are not supported this
|
||||
;; way. Starting from emacs 25.1, cc-mode only detects member
|
||||
;; initializers when the major mode is c++-mode.
|
||||
(eval-and-compile
|
||||
(if (and (= emacs-major-version 24) (or (= emacs-minor-version 4)
|
||||
(= emacs-minor-version 5)))
|
||||
(defun c-back-over-member-initializers ()
|
||||
;; Override of cc-engine.el, cc-mode in emacs 24.4 and 24.5 are too
|
||||
;; optimistic in recognizing c member initializers. Since we don't
|
||||
;; need it in php-mode, just return nil.
|
||||
nil)))
|
||||
|
||||
(autoload 'php-mode-debug "php-mode-debug"
|
||||
"Display informations useful for debugging PHP Mode." t)
|
||||
|
||||
@@ -191,21 +168,10 @@ enabled."
|
||||
:tag "PHP Mode Do Not Use Semantic Imenu"
|
||||
:type 'boolean)
|
||||
|
||||
(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)
|
||||
|
||||
;;;###autoload
|
||||
(if (version< emacs-version "24.4")
|
||||
(dolist (i '("php" "php5" "php7"))
|
||||
(add-to-list 'interpreter-mode-alist (cons i 'php-mode)))
|
||||
(add-to-list 'interpreter-mode-alist
|
||||
;; Match php, php-3, php5, php7, php5.5, php-7.0.1, etc.
|
||||
(cons "php\\(?:-?[3457]\\(?:\\.[0-9]+\\)*\\)?" 'php-mode)))
|
||||
(add-to-list 'interpreter-mode-alist
|
||||
;; Match php, php-3, php5, php7, php5.5, php-7.0.1, etc.
|
||||
(cons "php\\(?:-?[34578]\\(?:\\.[0-9]+\\)*\\)?" 'php-mode))
|
||||
|
||||
(defcustom php-mode-hook nil
|
||||
"List of functions to be executed on entry to `php-mode'."
|
||||
@@ -417,8 +383,7 @@ In that case set to `NIL'."
|
||||
php "\\s-*\\(<\\?(=\\|\\sw+)\\)")
|
||||
|
||||
(c-lang-defconst c-identifier-ops
|
||||
php '(
|
||||
(left-assoc "\\" "::" "->")
|
||||
php '((left-assoc "\\" "::" "->")
|
||||
(prefix "\\" "::")))
|
||||
|
||||
(c-lang-defconst c-operators
|
||||
@@ -475,25 +440,25 @@ In that case set to `NIL'."
|
||||
|
||||
(c-lang-defconst c-primitive-type-kwds
|
||||
php '("int" "integer" "bool" "boolean" "float" "double" "real"
|
||||
"string" "object" "void" "mixed"))
|
||||
"string" "object" "void" "mixed" "never"))
|
||||
|
||||
(c-lang-defconst c-class-decl-kwds
|
||||
"Keywords introducing declarations where the following block (if any)
|
||||
contains another declaration level that should be considered a class."
|
||||
php '("class" "trait" "interface"))
|
||||
php '("class" "trait" "interface" "enum"))
|
||||
|
||||
(c-lang-defconst c-brace-list-decl-kwds
|
||||
"Keywords introducing declarations where the following block (if
|
||||
any) is a brace list.
|
||||
|
||||
PHP does not have an \"enum\"-like keyword."
|
||||
PHP does not have an C-like \"enum\" keyword."
|
||||
php nil)
|
||||
|
||||
(c-lang-defconst c-typeless-decl-kwds
|
||||
php (append (c-lang-const c-class-decl-kwds) '("function")))
|
||||
|
||||
(c-lang-defconst c-modifier-kwds
|
||||
php '("abstract" "const" "final" "static"))
|
||||
php '("abstract" "const" "final" "static" "case" "readonly"))
|
||||
|
||||
(c-lang-defconst c-protection-kwds
|
||||
"Access protection label keywords in classes."
|
||||
@@ -531,8 +496,7 @@ PHP does not have an \"enum\"-like keyword."
|
||||
(c-lang-defconst c-other-kwds
|
||||
"Keywords not accounted for by any other `*-kwds' language constant."
|
||||
php
|
||||
'(
|
||||
"__halt_compiler"
|
||||
'("__halt_compiler"
|
||||
"and"
|
||||
"array"
|
||||
"as"
|
||||
@@ -649,7 +613,7 @@ but only if the setting is enabled"
|
||||
(beginning-of-line)
|
||||
(if (looking-at-p "\\s-*->") '+ nil))))
|
||||
|
||||
(defun php-c-looking-at-or-maybe-in-bracelist (&optional containing-sexp lim)
|
||||
(defun php-c-looking-at-or-maybe-in-bracelist (&optional _containing-sexp lim)
|
||||
"Replace `c-looking-at-or-maybe-in-bracelist'.
|
||||
|
||||
CONTAINING-SEXP is the position of the brace/paren/bracket enclosing
|
||||
@@ -914,19 +878,18 @@ This is was done due to the problem reported here:
|
||||
(if pos
|
||||
(goto-char pos)
|
||||
(setq pos (point)))
|
||||
(unless (php-in-string-or-comment-p)
|
||||
(or
|
||||
;; Detect PHP8 attribute: <<Attribute()>>
|
||||
(when (and (< 2 pos) (< 2 (- pos (c-point 'bol))))
|
||||
(backward-char 2)
|
||||
(looking-at-p ">>\\s-*\\(?:<<\\|$\\)"))
|
||||
;; Detect HTML/XML tag and PHP tag (<?php, <?=, ?>)
|
||||
(when php-mode-template-compatibility
|
||||
(beginning-of-line)
|
||||
(looking-at-p
|
||||
(eval-when-compile
|
||||
(rx (or (: bol (0+ space) "<" (in "a-z\\?"))
|
||||
(: (0+ not-newline) (in "a-z\\?") ">" (0+ space) eol))))))))))
|
||||
(cond
|
||||
;; Detect PHP8 attribute: #[Attribute()]
|
||||
((and (< 1 pos) (< 1 (- pos (c-point 'bol))))
|
||||
(backward-char 1)
|
||||
(looking-at-p (eval-when-compile (rx "]" (* (syntax whitespace)) (or "#[" line-end)))))
|
||||
;; Detect HTML/XML tag and PHP tag (<?php, <?=, ?>)
|
||||
(php-mode-template-compatibility
|
||||
(beginning-of-line)
|
||||
(looking-at-p
|
||||
(eval-when-compile
|
||||
(rx (or (: bol (0+ space) "<" (in "?a-z"))
|
||||
(: (0+ not-newline) (in "?a-z") ">" (0+ space) eol)))))))))
|
||||
|
||||
(defun php-c-vsemi-status-unknown-p ()
|
||||
"Always return NIL. See `c-vsemi-status-unknown-p'."
|
||||
@@ -970,7 +933,12 @@ this ^ lineup"
|
||||
|
||||
(eval-and-compile
|
||||
(defconst php-heredoc-start-re
|
||||
"<<<\\(?:\\_<.+?\\_>\\|'\\_<.+?\\_>'\\|\"\\_<.+?\\_>\"\\)$"
|
||||
(rx "<<<"
|
||||
(* (syntax whitespace))
|
||||
(or (group (+ (or (syntax word) (syntax symbol))))
|
||||
(: "\"" (group (+ (or (syntax word) (syntax symbol)))) "\"")
|
||||
(: "'" (group (+ (or (syntax word) (syntax symbol)))) "'"))
|
||||
line-end)
|
||||
"Regular expression for the start of a PHP heredoc."))
|
||||
|
||||
(defun php-heredoc-end-re (heredoc-start)
|
||||
@@ -979,27 +947,40 @@ this ^ lineup"
|
||||
(string-match "\\_<.+?\\_>" heredoc-start)
|
||||
(concat "^\\s-*\\(" (match-string 0 heredoc-start) "\\)\\W"))
|
||||
|
||||
(defun php-syntax-propertize-function (start end)
|
||||
"Apply propertize rules from START to END."
|
||||
(goto-char start)
|
||||
(while (and (< (point) end)
|
||||
(re-search-forward php-heredoc-start-re end t))
|
||||
(php-heredoc-syntax))
|
||||
(goto-char start)
|
||||
(while (re-search-forward "['\"]" end t)
|
||||
(when (php-in-comment-p)
|
||||
(c-put-char-property (match-beginning 0)
|
||||
'syntax-table (string-to-syntax "_")))))
|
||||
(eval-and-compile
|
||||
(defconst php-syntax-propertize-rules
|
||||
`((php-heredoc-start-re
|
||||
(0 (ignore (php--syntax-propertize-heredoc
|
||||
(match-beginning 0)
|
||||
(or (match-string 1) (match-string 2) (match-string 3))
|
||||
(null (match-string 3))))))
|
||||
(,(rx "#[")
|
||||
(0 (ignore (php--syntax-propertize-attributes (match-beginning 0)))))
|
||||
(,(rx (or "'" "\"" ))
|
||||
(0 (ignore (php--syntax-propertize-quotes-in-comment (match-beginning 0)))))))
|
||||
|
||||
(defun php-heredoc-syntax ()
|
||||
"Mark the boundaries of searched heredoc."
|
||||
(goto-char (match-beginning 0))
|
||||
(c-put-char-property (point) 'syntax-table (string-to-syntax "|"))
|
||||
(if (re-search-forward (php-heredoc-end-re (match-string 0)) nil t)
|
||||
(goto-char (match-end 1))
|
||||
;; Did not find the delimiter so go to the end of the buffer.
|
||||
(goto-char (point-max)))
|
||||
(c-put-char-property (1- (point)) 'syntax-table (string-to-syntax "|")))
|
||||
(defmacro php-build-propertize-function ()
|
||||
`(byte-compile (syntax-propertize-rules ,@php-syntax-propertize-rules)))
|
||||
|
||||
(defalias 'php-syntax-propertize-function (php-build-propertize-function)))
|
||||
|
||||
(defun php--syntax-propertize-heredoc (start id _is-heredoc)
|
||||
"Apply propertize Heredoc and Nowdoc from START, with ID and IS-HEREDOC."
|
||||
(let ((terminator (rx-to-string `(: line-start (* (syntax whitespace)) ,id word-boundary))))
|
||||
(put-text-property start (1+ start) 'syntax-table (string-to-syntax "|"))
|
||||
(re-search-forward terminator nil t)
|
||||
(when (match-string 0)
|
||||
(put-text-property (1- (point)) (point) 'syntax-table (string-to-syntax "|")))))
|
||||
|
||||
(defun php--syntax-propertize-quotes-in-comment (pos)
|
||||
"Apply propertize quotes (' and \") from POS."
|
||||
(when (php-in-comment-p)
|
||||
(put-text-property pos (1+ pos) 'syntax-table (string-to-syntax "_"))))
|
||||
|
||||
(defun php--syntax-propertize-attributes (start)
|
||||
"Apply propertize PHP8 #[Attributes] (without # comment) from START."
|
||||
(unless (php-in-string-p)
|
||||
(put-text-property start (1+ start) 'syntax-table (string-to-syntax "."))))
|
||||
|
||||
(defvar-local php-mode--propertize-extend-region-current nil
|
||||
"Prevent undesirable recursion in PHP-SYNTAX-PROPERTIZE-EXTEND-REGION")
|
||||
@@ -1013,8 +994,7 @@ this ^ lineup"
|
||||
;; turn call this to be called again.
|
||||
(push pair php-mode--propertize-extend-region-current)
|
||||
(unwind-protect
|
||||
(let ((new-start)
|
||||
(new-end))
|
||||
(let (new-start new-end)
|
||||
(goto-char start)
|
||||
(when (re-search-backward php-heredoc-start-re nil t)
|
||||
(let ((maybe (point)))
|
||||
@@ -1095,11 +1075,10 @@ After setting the stylevars run hooks according to STYLENAME
|
||||
((equal stylename "symfony2") (run-hooks 'php-mode-symfony2-hook))
|
||||
((equal stylename "psr2") (run-hooks 'php-mode-psr2-hook))))
|
||||
|
||||
(defun php-mode--disable-delay-set-style (&rest args)
|
||||
(defun php-mode--disable-delay-set-style (&rest _args)
|
||||
"Disable php-mode-set-style-delay on after hook. `ARGS' be ignore."
|
||||
(setq php-mode--delayed-set-style nil)
|
||||
(when (fboundp 'advice-remove)
|
||||
(advice-remove #'php-mode--disable-delay-set-style #'c-set-style)))
|
||||
(advice-remove #'php-mode--disable-delay-set-style #'c-set-style))
|
||||
|
||||
(defun php-mode-set-style-delay ()
|
||||
"Set the current `php-mode' buffer to use the style by custom or local variables."
|
||||
@@ -1151,7 +1130,7 @@ After setting the stylevars run hooks according to STYLENAME
|
||||
(setq-local comment-start "// ")
|
||||
(setq-local comment-start-skip
|
||||
(eval-when-compile
|
||||
(rx (group (or (: "#")
|
||||
(rx (group (or (: "#" (not (any "[")))
|
||||
(: "/" (+ "/"))
|
||||
(: "/*")))
|
||||
(* (syntax whitespace)))))
|
||||
@@ -1170,7 +1149,9 @@ After setting the stylevars run hooks according to STYLENAME
|
||||
(add-hook 'syntax-propertize-extend-region-functions
|
||||
#'php-syntax-propertize-extend-region t t)
|
||||
|
||||
(setq imenu-generic-expression php-imenu-generic-expression)
|
||||
(setq imenu-generic-expression (if (symbolp php-imenu-generic-expression)
|
||||
(symbol-value php-imenu-generic-expression)
|
||||
php-imenu-generic-expression))
|
||||
|
||||
;; PHP vars are case-sensitive
|
||||
(setq case-fold-search t)
|
||||
@@ -1185,8 +1166,7 @@ After setting the stylevars run hooks according to STYLENAME
|
||||
(progn
|
||||
(add-hook 'hack-local-variables-hook #'php-mode-set-style-delay t t)
|
||||
(setq php-mode--delayed-set-style t)
|
||||
(when (fboundp 'advice-add)
|
||||
(advice-add #'c-set-style :after #'php-mode--disable-delay-set-style '(local))))
|
||||
(advice-add #'c-set-style :after #'php-mode--disable-delay-set-style '(local)))
|
||||
(let ((php-mode-enable-backup-style-variables nil))
|
||||
(php-set-style (symbol-name php-mode-coding-style))))
|
||||
|
||||
@@ -1218,7 +1198,8 @@ After setting the stylevars run hooks according to STYLENAME
|
||||
|
||||
(when (fboundp 'c-looking-at-or-maybe-in-bracelist)
|
||||
(advice-add #'c-looking-at-or-maybe-in-bracelist
|
||||
:override 'php-c-looking-at-or-maybe-in-bracelist))
|
||||
:override 'php-c-looking-at-or-maybe-in-bracelist '(local)))
|
||||
(advice-add #'fixup-whitespace :after #'php-mode--fixup-whitespace-after '(local))
|
||||
|
||||
(when (>= emacs-major-version 25)
|
||||
(with-silent-modifications
|
||||
@@ -1237,10 +1218,7 @@ After setting the stylevars run hooks according to STYLENAME
|
||||
#'semantic-create-imenu-index)
|
||||
"Imenu index function for PHP.")
|
||||
|
||||
|
||||
;; Define function name completion function
|
||||
(defvar php-completion-table nil
|
||||
"Obarray of tag names defined in current tags table and functions known to PHP.")
|
||||
(autoload 'php-local-manual-complete-function "php-local-manual")
|
||||
|
||||
(defun php-complete-function ()
|
||||
"Perform function completion on the text around point.
|
||||
@@ -1249,102 +1227,7 @@ and the standard php functions.
|
||||
The string to complete is chosen in the same way as the default
|
||||
for \\[find-tag] (which see)."
|
||||
(interactive)
|
||||
(let ((pattern (php-get-pattern))
|
||||
beg
|
||||
completion
|
||||
(php-functions (php-completion-table)))
|
||||
(if (not pattern) (message "Nothing to complete")
|
||||
(if (not (search-backward pattern nil t))
|
||||
(message "Can't complete here")
|
||||
(setq beg (point))
|
||||
(forward-char (length pattern))
|
||||
(setq completion (try-completion pattern php-functions nil))
|
||||
(cond ((eq completion t))
|
||||
((null completion)
|
||||
(message "Can't find completion for \"%s\"" pattern)
|
||||
(ding))
|
||||
((not (string= pattern completion))
|
||||
(delete-region beg (point))
|
||||
(insert completion))
|
||||
(t
|
||||
(let ((selected (completing-read
|
||||
"Select completion: "
|
||||
(all-completions pattern php-functions)
|
||||
nil t pattern)))
|
||||
(delete-region beg (point))
|
||||
(insert selected))))))))
|
||||
|
||||
(defun php-completion-table ()
|
||||
"Build variable `php-completion-table' on demand.
|
||||
The table includes the PHP functions and the tags from the
|
||||
current `tags-file-name'."
|
||||
(or (and tags-file-name
|
||||
(save-excursion (tags-verify-table tags-file-name))
|
||||
php-completion-table)
|
||||
(let ((tags-table
|
||||
(when tags-file-name
|
||||
(with-current-buffer (get-file-buffer tags-file-name)
|
||||
(etags-tags-completion-table))))
|
||||
(php-table
|
||||
(cond ((and (not (string= "" php-completion-file))
|
||||
(file-readable-p php-completion-file))
|
||||
(php-build-table-from-file php-completion-file))
|
||||
((and (not (string= "" php-manual-path))
|
||||
(file-directory-p php-manual-path))
|
||||
(php-build-table-from-path php-manual-path))
|
||||
(t nil))))
|
||||
(unless (or php-table tags-table)
|
||||
(error
|
||||
(concat "No TAGS file active nor are "
|
||||
"`php-completion-file' or `php-manual-path' set")))
|
||||
(when tags-table
|
||||
;; Combine the tables.
|
||||
(if (obarrayp tags-table)
|
||||
(mapatoms (lambda (sym) (intern (symbol-name sym) php-table))
|
||||
tags-table)
|
||||
(setq php-table (append tags-table php-table))))
|
||||
(setq php-completion-table php-table))))
|
||||
|
||||
(defun php-build-table-from-file (filename)
|
||||
(let ((table (make-vector 1022 0))
|
||||
(buf (find-file-noselect filename)))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward
|
||||
"^\\([-a-zA-Z0-9_.]+\\)\n"
|
||||
nil t)
|
||||
(intern (buffer-substring (match-beginning 1) (match-end 1))
|
||||
table)))
|
||||
(kill-buffer buf)
|
||||
table))
|
||||
|
||||
(defun php-build-table-from-path (path)
|
||||
"Return list of PHP function name from `PATH' directory."
|
||||
(cl-loop for file in (directory-files path nil "^function\\..+\\.html$")
|
||||
if (string-match "\\.\\([-a-zA-Z_0-9]+\\)\\.html$" file)
|
||||
collect (replace-regexp-in-string
|
||||
"-" "_" (substring file (match-beginning 1) (match-end 1)) t)))
|
||||
|
||||
;; Find the pattern we want to complete
|
||||
;; find-tag-default from GNU Emacs etags.el
|
||||
(defun php-get-pattern ()
|
||||
(save-excursion
|
||||
(while (looking-at "\\sw\\|\\s_")
|
||||
(forward-char 1))
|
||||
(if (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))
|
||||
(progn (goto-char (match-end 0))
|
||||
(buffer-substring-no-properties
|
||||
(point)
|
||||
(progn (forward-sexp -1)
|
||||
(while (looking-at "\\s'")
|
||||
(forward-char 1))
|
||||
(point))))
|
||||
nil)))
|
||||
(php-local-manual-complete-function))
|
||||
|
||||
(defun php-show-arglist ()
|
||||
"Show function arguments at cursor position."
|
||||
@@ -1364,130 +1247,6 @@ current `tags-file-name'."
|
||||
(message "Arglist for %s: %s" tagname arglist)
|
||||
(message "Unknown function: %s" tagname))))
|
||||
|
||||
(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))
|
||||
|
||||
(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)))
|
||||
|
||||
(defvar php-search-local-documentation-types
|
||||
(list "function" "control-structures" "class" "book")
|
||||
;; "intro" and "ref" also look interesting, but for all practical purposes
|
||||
;; their terms are sub-sets of the "book" terms (with the few exceptions
|
||||
;; being very unlikely search terms).
|
||||
"The set (and priority sequence) of documentation file prefixes
|
||||
under which to search for files in the local documentation directory.")
|
||||
|
||||
(defvar php-search-local-documentation-words-cache nil)
|
||||
|
||||
(defun php--search-documentation-read-arg ()
|
||||
"Obtain interactive argument for searching documentation."
|
||||
;; Cache the list of documentation words available for completion,
|
||||
;; based on the defined types-of-interest.
|
||||
(let ((types-list php-search-local-documentation-types)
|
||||
(words-cache php-search-local-documentation-words-cache)
|
||||
(local-manual (and (stringp php-manual-path)
|
||||
(not (string= php-manual-path "")))))
|
||||
(when (and local-manual
|
||||
(not (assq types-list words-cache)))
|
||||
;; Generate the cache on the first run, or if the types changed.
|
||||
;; We read the filenames matching our types list in the local
|
||||
;; documentation directory, and extract the 'middle' component
|
||||
;; of each. e.g. "function.array-map.html" => "array_map".
|
||||
(let* ((types-opt (regexp-opt types-list))
|
||||
(pattern (concat "\\`" types-opt "\\.\\(.+\\)\\.html\\'"))
|
||||
(collection
|
||||
(mapcar (lambda (filename) (subst-char-in-string
|
||||
?- ?_ (replace-regexp-in-string
|
||||
pattern "\\1" filename)))
|
||||
(directory-files php-manual-path nil pattern))))
|
||||
;; Replace the entire cache. If the types changed, we don't need
|
||||
;; to retain the collection for the previous value.
|
||||
(setq words-cache (list (cons types-list collection)))
|
||||
(setq php-search-local-documentation-words-cache words-cache)))
|
||||
;; By default we search for (current-word) immediately, without prompting.
|
||||
;; With a prefix argument, or if there is no (current-word), we perform a
|
||||
;; completing read for a word from the cached collection.
|
||||
(let* ((default (current-word))
|
||||
(prompt (if default
|
||||
(format "Search PHP docs (%s): " default)
|
||||
"Search PHP docs: "))
|
||||
(collection (and local-manual
|
||||
(cdr (assq types-list words-cache))))
|
||||
(word (if (or current-prefix-arg (not default))
|
||||
(completing-read prompt collection nil nil nil nil default)
|
||||
default)))
|
||||
;; Return interactive argument list.
|
||||
(list word))))
|
||||
|
||||
(defun php-search-local-documentation (word)
|
||||
"Search the local PHP documentation (i.e. in `php-manual-path') for
|
||||
the word at point. The function returns t if the requested documentation
|
||||
exists, and nil otherwise.
|
||||
|
||||
With a prefix argument, prompt (with completion) for a word to search for."
|
||||
(interactive (php--search-documentation-read-arg))
|
||||
(let ((file (catch 'found
|
||||
(cl-loop for type in php-search-local-documentation-types do
|
||||
(let* ((doc-html (format "%s.%s.html"
|
||||
type
|
||||
(replace-regexp-in-string
|
||||
"_" "-" (downcase word))))
|
||||
(file (expand-file-name doc-html php-manual-path)))
|
||||
(when (file-exists-p file)
|
||||
(throw 'found file)))))))
|
||||
(when file
|
||||
(let ((file-url (if (string-prefix-p "file://" file)
|
||||
file
|
||||
(concat "file://" file))))
|
||||
(php-browse-documentation-url file-url))
|
||||
t)))
|
||||
|
||||
(defsubst php-search-web-documentation (word)
|
||||
"Return URL to search PHP manual search by `WORD'."
|
||||
(php-browse-documentation-url (concat (or php-search-url php-site-url) word)))
|
||||
|
||||
;; Define function documentation function
|
||||
(defun php-search-documentation (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 (php--search-documentation-read-arg))
|
||||
(if (and (stringp php-manual-path)
|
||||
(not (string= php-manual-path "")))
|
||||
(or (php-search-local-documentation word)
|
||||
(php-search-web-documentation word))
|
||||
(php-search-web-documentation word)))
|
||||
|
||||
;; Define function for browsing manual
|
||||
(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))))
|
||||
|
||||
|
||||
;; Font Lock
|
||||
(defconst php-phpdoc-type-keywords
|
||||
(list "string" "integer" "int" "boolean" "bool" "float"
|
||||
@@ -1680,7 +1439,9 @@ a completion list."
|
||||
|
||||
;; Logical operators (and, or, &&, ...)
|
||||
;; Not operator (!) is defined in "before cc-mode" section above.
|
||||
("\\(&&\\|||\\)" 1 'php-logical-op)))
|
||||
("\\(&&\\|||\\)" 1 'php-logical-op)
|
||||
;; string interpolation ("$var, ${var}, {$var}")
|
||||
(php-mode--string-interpolated-variable-font-lock-find 0 nil)))
|
||||
"Detailed highlighting for PHP Mode.")
|
||||
|
||||
(defvar php-font-lock-keywords php-font-lock-keywords-3
|
||||
@@ -1712,37 +1473,24 @@ The output will appear in the buffer *PHP*."
|
||||
(defconst php-string-interpolated-variable-regexp
|
||||
"{\\$[^}\n\\\\]*\\(?:\\\\.[^}\n\\\\]*\\)*}\\|\\${\\sw+}\\|\\$\\sw+")
|
||||
|
||||
(defun php-string-intepolated-variable-font-lock-find (limit)
|
||||
(while (re-search-forward php-string-interpolated-variable-regexp limit t)
|
||||
(let ((quoted-stuff (nth 3 (syntax-ppss))))
|
||||
(when (and quoted-stuff (member quoted-stuff '(?\" ?`)))
|
||||
(put-text-property (match-beginning 0) (match-end 0)
|
||||
'face 'php-variable-name))))
|
||||
(defun php-mode--string-interpolated-variable-font-lock-find (limit)
|
||||
"Apply text-property to LIMIT for string interpolation by font-lock."
|
||||
(let (quoted-stuff)
|
||||
(while (re-search-forward php-string-interpolated-variable-regexp limit t)
|
||||
(setq quoted-stuff (php-in-string-p))
|
||||
(when (or (eq ?\" quoted-stuff) (eq ?` quoted-stuff))
|
||||
(put-text-property (match-beginning 0) (match-end 0) 'face 'php-variable-name))))
|
||||
nil)
|
||||
|
||||
(eval-after-load 'php-mode
|
||||
'(progn
|
||||
(font-lock-add-keywords
|
||||
'php-mode
|
||||
`((php-string-intepolated-variable-font-lock-find))
|
||||
'append)))
|
||||
|
||||
|
||||
|
||||
;;; Correct the behavior of `delete-indentation' by modifying the
|
||||
;;; logic of `fixup-whitespace'.
|
||||
(defadvice fixup-whitespace (after php-mode-fixup-whitespace)
|
||||
(defun php-mode--fixup-whitespace-after ()
|
||||
"Remove whitespace before certain characters in PHP Mode."
|
||||
(let* ((no-behind-space ";\\|,\\|->\\|::")
|
||||
(no-front-space "->\\|::"))
|
||||
(when (and (eq major-mode 'php-mode)
|
||||
(or (looking-at-p (concat " \\(" no-behind-space "\\)"))
|
||||
(save-excursion
|
||||
(forward-char -2)
|
||||
(looking-at-p no-front-space))))
|
||||
(delete-char 1))))
|
||||
|
||||
(ad-activate 'fixup-whitespace)
|
||||
(when (or (looking-at-p " \\(?:;\\|,\\|->\\|::\\)")
|
||||
(save-excursion
|
||||
(forward-char -2)
|
||||
(looking-at-p "->\\|::")))
|
||||
(delete-char 1)))
|
||||
|
||||
;;;###autoload
|
||||
(progn
|
||||
|
||||
Reference in New Issue
Block a user