@ -1,4 +1,4 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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."
@@ -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' . "
@ -318,6 +284,9 @@ In that case set to `NIL'."
@@ -318,6 +284,9 @@ In that case set to `NIL'."
:tag " PHP Mode Enable Project Local Variable "
:type 'boolean )
( defconst php-mode-cc-vertion
( eval-when-compile c-version ) )
( defun php-mode-version ( )
" Display string describing the version of PHP Mode. "
( interactive )
@ -414,8 +383,7 @@ In that case set to `NIL'."
@@ -414,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
@ -472,25 +440,25 @@ In that case set to `NIL'."
@@ -472,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 " ) )
( c-lang-defconst c-protection-kwds
" Access protection label keywords in classes. "
@ -528,8 +496,7 @@ PHP does not have an \"enum\"-like keyword."
@@ -528,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 "
@ -911,19 +878,18 @@ This is was done due to the problem reported here:
@@ -911,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' . "
@ -967,7 +933,12 @@ this ^ lineup"
@@ -967,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 )
@ -976,27 +947,40 @@ this ^ lineup"
@@ -976,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 " _ " ) ) ) ) )
( 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 " | " ) ) )
( 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 ) ) ) ) ) ) )
( defmacro php-build-propertize-function ( )
` ( 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 " )
@ -1010,8 +994,7 @@ this ^ lineup"
@@ -1010,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,8 +1078,7 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1095,8 +1078,7 @@ After setting the stylevars run hooks according to STYLENAME
( 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. "
@ -1131,6 +1113,13 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1131,6 +1113,13 @@ After setting the stylevars run hooks according to STYLENAME
:syntax-table php-mode-syntax-table
;; :after-hook (c-update-modeline)
;; (setq abbrev-mode t)
( unless ( string= php-mode-cc-vertion c-version )
( user-error " CC Mode has been updated. %s "
( if ( package-installed-p 'php-mode )
" Please run ` M-x package-reinstall php-mode' command. "
" Please byte recompile PHP Mode files. " ) ) )
( when php-mode-disable-c-mode-hook
( setq-local c-mode-hook nil )
( setq-local java-mode-hook nil ) )
@ -1141,7 +1130,7 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1141,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 ) ) ) ) )
@ -1160,7 +1149,9 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1160,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 )
@ -1175,8 +1166,7 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1175,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 ) ) ) )
@ -1208,7 +1198,8 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1208,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
@ -1227,10 +1218,7 @@ After setting the stylevars run hooks according to STYLENAME
@@ -1227,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.
@ -1239,102 +1227,7 @@ and the standard php functions.
@@ -1239,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. "
@ -1354,130 +1247,6 @@ current `tags-file-name'."
@@ -1354,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 "
@ -1670,7 +1439,9 @@ a completion list."
@@ -1670,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
@ -1702,37 +1473,24 @@ The output will appear in the buffer *PHP*."
@@ -1702,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