From aa6722130316cd9460a5276bd07486887411799a Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Fri, 20 Dec 2019 12:02:17 +0100 Subject: Upgrade all modes --- .emacs | 6 +- .emacs.d/lisp/lua-mode.el | 259 ++++++++++++++++++++++----------------- .emacs.d/lisp/php-face.el | 47 ++++++- .emacs.d/lisp/php-mode.el | 154 ++++++++++++++++++----- .emacs.d/lisp/php-project.el | 35 +++++- .emacs.d/lisp/php-util-buffer.el | 135 ++++++++++++++++++++ .emacs.d/lisp/php.el | 211 ++++++++++++++++++++++--------- .emacs.d/lisp/yaml-mode.el | 6 +- .emacs.d/lisp/yasnippet.el | 14 ++- 9 files changed, 647 insertions(+), 220 deletions(-) create mode 100644 .emacs.d/lisp/php-util-buffer.el diff --git a/.emacs b/.emacs index 0b5d15e..6aa5873 100644 --- a/.emacs +++ b/.emacs @@ -82,8 +82,8 @@ (add-to-list 'load-path "~/.emacs.d/lisp/") ;; PHP -(autoload 'php-mode "php-mode" "Mode for editing PHP source files") -(add-to-list 'auto-mode-alist '("\\.\\(inc\\|php[s34]?\\)" . php-mode)) +;;(autoload 'php-mode "php-mode" "Mode for editing PHP source files") +;;(add-to-list 'auto-mode-alist '("\\.\\(inc\\|php[s34]?\\)" . php-mode)) ;; Lua (autoload 'lua-mode "lua-mode" "Lua editing mode." t) @@ -99,7 +99,7 @@ (add-hook 'python-mode-hook (lambda () (progn - (setq whitespace-line-column 80) + (setq whitespace-line-column 79) (setq whitespace-style '(face empty tabs lines-tail trailing)) (whitespace-mode)))) diff --git a/.emacs.d/lisp/lua-mode.el b/.emacs.d/lisp/lua-mode.el index af94a13..640e490 100644 --- a/.emacs.d/lisp/lua-mode.el +++ b/.emacs.d/lisp/lua-mode.el @@ -1,4 +1,4 @@ -;;; lua-mode.el --- a major-mode for editing Lua scripts +;;; lua-mode.el --- a major-mode for editing Lua scripts -*- lexical-binding: t -*- ;; Author: 2011-2013 immerrr ;; 2010-2011 Reuben Thomas @@ -13,6 +13,7 @@ ;; ;; URL: http://immerrr.github.com/lua-mode ;; Version: 20151025 +;; Package-Requires: ((emacs "24.3")) ;; ;; This file is NOT part of Emacs. ;; @@ -40,7 +41,7 @@ ;;; Commentary: -;; lua-mode provides support for editing Lua, including automatical +;; lua-mode provides support for editing Lua, including automatic ;; indentation, syntactical font-locking, running interactive shell, ;; interacting with `hs-minor-mode' and online documentation lookup. @@ -86,7 +87,7 @@ ;;; Code: (eval-when-compile - (require 'cl)) + (require 'cl-lib)) (require 'comint) (require 'newcomment) @@ -101,80 +102,120 @@ (require 'compile)) (eval-and-compile - (defvar lua-rx-constituents) - (defvar rx-parent) - - (defun lua-rx-to-string (form &optional no-group) - "Lua-specific replacement for `rx-to-string'. + (if (fboundp #'rx-let) + (progn + ;; Emacs 27+ way of customizing rx + (defvar lua--rx-bindings) + + (setq + lua--rx-bindings + '((symbol (&rest x) (seq symbol-start (or x) symbol-end)) + (ws (* (any " \t"))) + (ws+ (+ (any " \t"))) + + (lua-name (symbol (seq (+ (any alpha "_")) (* (any alnum "_"))))) + (lua-funcname (seq lua-name (* ws "." ws lua-name) + (opt ws ":" ws lua-name))) + (lua-funcheader + ;; Outer (seq ...) is here to shy-group the definition + (seq (or (seq (symbol "function") ws (group-n 1 lua-funcname)) + (seq (group-n 1 lua-funcname) ws "=" ws + (symbol "function"))))) + (lua-number + (seq (or (seq (+ digit) (opt ".") (* digit)) + (seq (* digit) (opt ".") (+ digit))) + (opt (regexp "[eE][+-]?[0-9]+")))) + (lua-assignment-op (seq "=" (or buffer-end (not (any "="))))) + (lua-token (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<" + ">" "=" ";" ":" "," "." ".." "...")) + (lua-keyword + (symbol "and" "break" "do" "else" "elseif" "end" "for" "function" + "goto" "if" "in" "local" "not" "or" "repeat" "return" + "then" "until" "while")))) + + (defmacro lua-rx (&rest regexps) + (eval `(rx-let ,lua--rx-bindings + (rx ,@regexps)))) + + (defun lua-rx-to-string (form &optional no-group) + (rx-let-eval lua--rx-bindings + (rx-to-string form no-group)))) + (progn + ;; Pre-Emacs 27 way of customizing rx + (defvar lua-rx-constituents) + (defvar rx-parent) + + (defun lua-rx-to-string (form &optional no-group) + "Lua-specific replacement for `rx-to-string'. See `rx-to-string' documentation for more information FORM and NO-GROUP arguments." - (let ((rx-constituents lua-rx-constituents)) - (rx-to-string form no-group))) + (let ((rx-constituents lua-rx-constituents)) + (rx-to-string form no-group))) - (defmacro lua-rx (&rest regexps) - "Lua-specific replacement for `rx'. + (defmacro lua-rx (&rest regexps) + "Lua-specific replacement for `rx'. See `rx' documentation for more information about REGEXPS param." - (cond ((null regexps) - (error "No regexp")) - ((cdr regexps) - (lua-rx-to-string `(and ,@regexps) t)) - (t - (lua-rx-to-string (car regexps) t)))) + (cond ((null regexps) + (error "No regexp")) + ((cdr regexps) + (lua-rx-to-string `(and ,@regexps) t)) + (t + (lua-rx-to-string (car regexps) t)))) - (defun lua--new-rx-form (form) - "Add FORM definition to `lua-rx' macro. + (defun lua--new-rx-form (form) + "Add FORM definition to `lua-rx' macro. FORM is a cons (NAME . DEFN), see more in `rx-constituents' doc. This function enables specifying new definitions using old ones: if DEFN is a list that starts with `:rx' symbol its second element is itself expanded with `lua-rx-to-string'. " - (let ((name (car form)) - (form-definition (cdr form))) - (when (and (listp form-definition) (eq ':rx (car form-definition))) - (setcdr form (lua-rx-to-string (cadr form-definition) 'nogroup))) - (push form lua-rx-constituents))) - - (defun lua--rx-symbol (form) - ;; form is a list (symbol XXX ...) - ;; Skip initial 'symbol - (setq form (cdr form)) - ;; If there's only one element, take it from the list, otherwise wrap the - ;; whole list into `(or XXX ...)' form. - (setq form (if (eq 1 (length form)) - (car form) - (append '(or) form))) - (rx-form `(seq symbol-start ,form symbol-end) rx-parent)) - - (setq lua-rx-constituents (copy-sequence rx-constituents)) - - (mapc #'lua--new-rx-form - `((symbol lua--rx-symbol 1 nil) - (ws . "[ \t]*") (ws+ . "[ \t]+") - (lua-name :rx (symbol (regexp "[[:alpha:]_]+[[:alnum:]_]*"))) - (lua-funcname - :rx (seq lua-name (* ws "." ws lua-name) - (opt ws ":" ws lua-name))) - (lua-funcheader - ;; Outer (seq ...) is here to shy-group the definition - :rx (seq (or (seq (symbol "function") ws (group-n 1 lua-funcname)) - (seq (group-n 1 lua-funcname) ws "=" ws - (symbol "function"))))) - (lua-number - :rx (seq (or (seq (+ digit) (opt ".") (* digit)) - (seq (* digit) (opt ".") (+ digit))) - (opt (regexp "[eE][+-]?[0-9]+")))) - (lua-assignment-op - :rx (seq "=" (or buffer-end (not (any "="))))) - (lua-token - :rx (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<" - ">" "=" ";" ":" "," "." ".." "...")) - (lua-keyword - :rx (symbol "and" "break" "do" "else" "elseif" "end" "for" "function" - "goto" "if" "in" "local" "not" "or" "repeat" "return" - "then" "until" "while"))) - )) + (let ((form-definition (cdr form))) + (when (and (listp form-definition) (eq ':rx (car form-definition))) + (setcdr form (lua-rx-to-string (cadr form-definition) 'nogroup))) + (push form lua-rx-constituents))) + + (defun lua--rx-symbol (form) + ;; form is a list (symbol XXX ...) + ;; Skip initial 'symbol + (setq form (cdr form)) + ;; If there's only one element, take it from the list, otherwise wrap the + ;; whole list into `(or XXX ...)' form. + (setq form (if (eq 1 (length form)) + (car form) + (append '(or) form))) + (and (fboundp 'rx-form) ; Silence Emacs 27's byte-compiler. + (rx-form `(seq symbol-start ,form symbol-end) rx-parent))) + + (setq lua-rx-constituents (copy-sequence rx-constituents)) + + (mapc 'lua--new-rx-form + `((symbol lua--rx-symbol 1 nil) + (ws . "[ \t]*") (ws+ . "[ \t]+") + (lua-name :rx (symbol (regexp "[[:alpha:]_]+[[:alnum:]_]*"))) + (lua-funcname + :rx (seq lua-name (* ws "." ws lua-name) + (opt ws ":" ws lua-name))) + (lua-funcheader + ;; Outer (seq ...) is here to shy-group the definition + :rx (seq (or (seq (symbol "function") ws (group-n 1 lua-funcname)) + (seq (group-n 1 lua-funcname) ws "=" ws + (symbol "function"))))) + (lua-number + :rx (seq (or (seq (+ digit) (opt ".") (* digit)) + (seq (* digit) (opt ".") (+ digit))) + (opt (regexp "[eE][+-]?[0-9]+")))) + (lua-assignment-op + :rx (seq "=" (or buffer-end (not (any "="))))) + (lua-token + :rx (or "+" "-" "*" "/" "%" "^" "#" "==" "~=" "<=" ">=" "<" + ">" "=" ";" ":" "," "." ".." "...")) + (lua-keyword + :rx (symbol "and" "break" "do" "else" "elseif" "end" "for" "function" + "goto" "if" "in" "local" "not" "or" "repeat" "return" + "then" "until" "while"))) + )))) ;; Local variables @@ -277,8 +318,7 @@ If the latter is nil, the keymap translates into `lua-mode-map' verbatim.") (defvar lua-mode-map - (let ((result-map (make-sparse-keymap)) - prefix-key) + (let ((result-map (make-sparse-keymap))) (unless (boundp 'electric-indent-chars) (mapc (lambda (electric-char) (define-key result-map @@ -488,7 +528,7 @@ groups set according to next matched token: Blanks & comments between tokens are silently skipped. Groups 6-9 can be used in any of argument regexps." - (lexical-let* + (let* ((delimited-matcher-re-template "\\=\\(?2:.*?\\)\\(?:\\(?%s:\\(?4:%s\\)\\|\\(?5:%s\\)\\)\\|\\(?%s:\\(?1:%s\\)\\)\\)") ;; There's some magic to this regexp. It works as follows: @@ -515,7 +555,6 @@ Groups 6-9 can be used in any of argument regexps." (lambda (end) (let* ((prev-elt-p (match-beginning 1)) - (prev-sep-p (match-beginning 4)) (prev-end-p (match-beginning 5)) (regexp (if prev-elt-p sep-or-end-expected-re elt-expected-re)) @@ -567,7 +606,7 @@ Groups 6-9 can be used in any of argument regexps." (,(lua-rx "::" ws lua-name ws "::") . font-lock-constant-face) - ;; Hightlights the name of the label in the "goto" statement like + ;; Highlights the name of the label in the "goto" statement like ;; "goto label" (,(lua-rx (symbol (seq "goto" ws+ (group-n 1 lua-name)))) (1 font-lock-constant-face)) @@ -669,9 +708,6 @@ Groups 6-9 can be used in any of argument regexps." :abbrev-table lua-mode-abbrev-table :syntax-table lua-mode-syntax-table :group 'lua - (setq comint-prompt-regexp lua-prompt-regexp) - - (setq-local font-lock-defaults '(lua-font-lock-keywords ;; keywords nil ;; keywords-only nil ;; case-fold @@ -900,7 +936,7 @@ Return the amount the indentation changed by." (back-to-indentation) (if (lua-comment-or-string-p) (setq indent (lua-calculate-string-or-comment-indentation)) ;; just restore point position - (setq indent (max 0 (lua-calculate-indentation nil)))) + (setq indent (max 0 (lua-calculate-indentation)))) (when (not (equal indent (current-column))) (delete-region (line-beginning-position) (point)) @@ -981,8 +1017,8 @@ ignored, nil otherwise." Each token information entry is of the form: KEYWORD FORWARD-MATCH-REGEXP BACKWARDS-MATCH-REGEXP TOKEN-TYPE KEYWORD is the token. -FORWARD-MATCH-REGEXP is a regexp that matches all possble tokens when going forward. -BACKWARDS-MATCH-REGEXP is a regexp that matches all possble tokens when going backwards. +FORWARD-MATCH-REGEXP is a regexp that matches all possible tokens when going forward. +BACKWARDS-MATCH-REGEXP is a regexp that matches all possible tokens when going backwards. TOKEN-TYPE determines where the token occurs on a statement. open indicates that the token appears at start, close indicates that it appears at end, middle indicates that it is a middle type token, and middle-or-open indicates that it can appear both as a middle or an open type.") (defconst lua-indentation-modifier-regexp @@ -1009,12 +1045,12 @@ TOKEN-TYPE determines where the token occurs on a statement. open indicates that "Returns the relevant match regexp from token info" (cond ((eq direction 'forward) (cadr token-info)) - ((eq direction 'backward) (caddr token-info)) + ((eq direction 'backward) (nth 2 token-info)) (t nil))) (defun lua-get-token-type (token-info) "Returns the relevant match regexp from token info" - (cadddr token-info)) + (nth 3 token-info)) (defun lua-backwards-to-block-begin-or-end () "Move backwards to nearest block begin or end. Returns nil if not successful." @@ -1101,8 +1137,11 @@ DIRECTION has to be either 'forward or 'backward." (defun lua-goto-matching-block-token (&optional parse-start direction) "Find block begion/end token matching the one at the point. This function moves the point to the token that matches the one -at the current point. Returns the point position of the first character of -the matching token if successful, nil otherwise." +at the current point. Returns the point position of the first character of +the matching token if successful, nil otherwise. + +Optional PARSE-START is a position to which the point should be moved first. +DIRECTION has to be 'forward or 'backward ('forward by default)." (if parse-start (goto-char parse-start)) (let ((case-fold-search nil)) (if (looking-at lua-indentation-modifier-regexp) @@ -1114,7 +1153,10 @@ the matching token if successful, nil otherwise." (defun lua-goto-matching-block (&optional noreport) "Go to the keyword balancing the one under the point. If the point is on a keyword/brace that starts a block, go to the -matching keyword that ends the block, and vice versa." +matching keyword that ends the block, and vice versa. + +If optional NOREPORT is non-nil, it won't flag an error if there +is no block open/close open." (interactive) ;; search backward to the beginning of the keyword if necessary (if (eq (char-syntax (following-char)) ?w) @@ -1129,7 +1171,7 @@ matching keyword that ends the block, and vice versa." "Move 1 line forward (back if BACK is non-nil) skipping blank lines. Moves point 1 line forward (or backward) skipping lines that contain -no Lua code besides comments. The point is put to the beginning of +no Lua code besides comments. The point is put to the beginning of the line. Returns final value of point as integer or nil if operation failed." @@ -1160,7 +1202,7 @@ Returns final value of point as integer or nil if operation failed." t) "\\)" "\\s *\\=")) - "Regexp that matches the ending of a line that needs continuation + "Regexp that matches the ending of a line that needs continuation. This regexp starts from eol and looks for a binary operator or an unclosed block intro (i.e. 'for' without 'do' or 'if' without 'then') followed by @@ -1179,15 +1221,15 @@ an optional whitespace till the end of the line.") t) "\\($\\|[^" lua-operator-class "]\\)" "\\)")) - "Regexp that matches a line that continues previous one + "Regexp that matches a line that continues previous one. This regexp means, starting from point there is an optional whitespace followed -by Lua binary operator. Lua is very liberal when it comes to continuation line, +by Lua binary operator. Lua is very liberal when it comes to continuation line, so we're safe to assume that every line that starts with a binop continues previous one even though it looked like an end-of-statement.") (defun lua-last-token-continues-p () - "Returns true if the last token on this line is a continuation token." + "Return non-nil if the last token on this line is a continuation token." (let ((line-begin (line-beginning-position)) (line-end (line-end-position))) (save-excursion @@ -1201,7 +1243,7 @@ previous one even though it looked like an end-of-statement.") (re-search-backward lua-cont-eol-regexp line-begin t)))) (defun lua-first-token-continues-p () - "Returns true if the first token on this line is a continuation token." + "Return non-nil if the first token on this line is a continuation token." (let ((line-end (line-end-position))) (save-excursion (beginning-of-line) @@ -1219,14 +1261,15 @@ previous one even though it looked like an end-of-statement.") "\\_>\\)"))) (defun lua-first-token-starts-block-p () - "Returns true if the first token on this line is a block starter token." + "Return non-nil if the first token on this line is a block starter token." (let ((line-end (line-end-position))) (save-excursion (beginning-of-line) (re-search-forward (concat "\\s *" lua-block-starter-regexp) line-end t)))) (defun lua-is-continuing-statement-p (&optional parse-start) - "Return non-nil if the line continues a statement. + "Return non-nil if the line at PARSE-START continues a statement. + More specifically, return the point in the line that is continued. The criteria for a continuing statement are: @@ -1246,8 +1289,10 @@ The criteria for a continuing statement are: (lua-last-token-continues-p))))))) (defun lua-make-indentation-info-pair (found-token found-pos) - "This is a helper function to lua-calculate-indentation-info. Don't -use standalone." + "Create a pair from FOUND-TOKEN and FOUND-POS for indentation calculation. + +This is a helper function to lua-calculate-indentation-info. +Don't use standalone." (cond ;; function is a bit tricky to indent right. They can appear in a lot ot ;; different contexts. Until I find a shortcut, I'll leave it with a simple @@ -1321,17 +1366,17 @@ use standalone." (- lua-indent-level)))))) (defun lua-add-indentation-info-pair (pair info) - "Add the given indentation info pair to the list of indentation information. + "Add the given indentation info PAIR to the list of indentation INFO. This function has special case handling for two tokens: remove-matching, -and replace-matching. These two tokens are cleanup tokens that remove or +and replace-matching. These two tokens are cleanup tokens that remove or alter the effect of a previously recorded indentation info. When a remove-matching token is encountered, the last recorded info, i.e. -the car of the list is removed. This is used to roll-back an indentation of a +the car of the list is removed. This is used to roll-back an indentation of a block opening statement when it is closed. When a replace-matching token is seen, the last recorded info is removed, -and the cdr of the replace-matching info is added in its place. This is used +and the cdr of the replace-matching info is added in its place. This is used when a middle-of the block (the only case is 'else') is seen on the same line the block is opened." (cond @@ -1354,9 +1399,7 @@ Return list of indentation modifiers from point to BOUND." (while (lua-find-regexp 'forward lua-indentation-modifier-regexp bound) (let ((found-token (match-string 0)) - (found-pos (match-beginning 0)) - (found-end (match-end 0)) - (data (match-data))) + (found-pos (match-beginning 0))) (setq indentation-info (lua-add-indentation-info-pair (lua-make-indentation-info-pair found-token found-pos) @@ -1370,8 +1413,7 @@ The effect of each token can be either a shift relative to the current indentation level, or indentation to some absolute column. This information is collected in a list of indentation info pairs, which denote absolute and relative each, and the shift/column to indent to." - (let ((combined-line-end (line-end-position)) - indentation-info) + (let (indentation-info) (while (lua-is-continuing-statement-p) (lua-forward-line-skip-blanks 'back)) @@ -1541,11 +1583,10 @@ If not, return nil." (current-indentation) (current-column))))))) -(defun lua-calculate-indentation (&optional parse-start) +(defun lua-calculate-indentation () "Return appropriate indentation for current line as Lua code." (save-excursion - (let ((continuing-p (lua-is-continuing-statement-p)) - (cur-line-begin-pos (line-beginning-position))) + (let ((cur-line-begin-pos (line-beginning-position))) (or ;; when calculating indentation, do the following: ;; 1. check, if the line starts with indentation-modifier (open/close brace) @@ -1689,7 +1730,8 @@ When called interactively, switch to the process buffer." (setq compilation-error-regexp-alist (cons (list lua-traceback-line-re 1 2) compilation-error-regexp-alist)) - (compilation-shell-minor-mode 1)) + (compilation-shell-minor-mode 1) + (setq-local comint-prompt-regexp lua-prompt-regexp)) ;; when called interactively, switch to process buffer (if (called-interactively-p 'any) @@ -1856,13 +1898,10 @@ left out." "Forward to block end" (interactive "p") ;; negative offsets not supported - (assert (or (not count) (>= count 0))) + (cl-assert (or (not count) (>= count 0))) (save-match-data - (let* ((count (or count 1)) - (block-start (mapcar 'car lua-sexp-alist)) - (block-end (mapcar 'cdr lua-sexp-alist)) - (block-regex (regexp-opt (append block-start block-end) 'words)) - current-exp) + (let ((count (or count 1)) + (block-start (mapcar 'car lua-sexp-alist))) (while (> count 0) ;; skip whitespace (skip-chars-forward " \t\n") diff --git a/.emacs.d/lisp/php-face.el b/.emacs.d/lisp/php-face.el index 4230bae..5f40257 100644 --- a/.emacs.d/lisp/php-face.el +++ b/.emacs.d/lisp/php-face.el @@ -4,7 +4,7 @@ ;; Author: USAMI Kenta ;; Created: 5 May 2019 -;; Version: 1.21.4 +;; Version: 1.22.1 ;; Keywords: faces, php ;; Homepage: https://github.com/emacs-php/php-mode ;; Package-Requires: ((emacs "24.3")) @@ -56,7 +56,7 @@ :group 'php-faces :tag "PHP Function Name") -(defface php-function-call '((t (:inherit default))) +(defface php-function-call '((t ())) "PHP Mode face used to highlight function names in calles." :group 'php-faces :tag "PHP Function Call") @@ -81,17 +81,52 @@ :group 'php-faces :tag "PHP Property Name") -(defface php-variable-sigil '((t (:inherit default))) +(defface php-variable-sigil '((t ())) "PHP Mode face used to highlight variable sigils ($)." :group 'php-faces :tag "PHP Variable Sigil") -(defface php-object-op '((t (:inherit default))) +(defface php-operator '((t ())) + "PHP Mode face used to operators." + :group 'php-faces + :tag "PHP Operator") + +(defface php-assignment-op '((t (:inherit php-operator))) + "PHP Mode face used to assignment operators (=, +=, ...)." + :group 'php-faces + :tag "PHP Object Op") + +(defface php-comparison-op '((t (:inherit php-operator))) + "PHP Mode face used to comparison operators (==, !=, ===, ...)." + :group 'php-faces + :tag "PHP Comparison Op") + +(defface php-logical-op '((t (:inherit php-operator))) + "PHP Mode face used to logical operators (&&, ||, ?:)." + :group 'php-faces + :tag "PHP Logical Op") + +(defface php-arithmetic-op '((t (:inherit php-operator))) + "PHP Mode face used to arithmetic operators (+, -, %, ...)." + :group 'php-faces + :tag "PHP Arithmetic Op") + +(defface php-inc-dec-op '((t (:inherit php-operator))) + "PHP Mode face used to increment and decremt operators (--, ++)." + :group 'php-faces + :tag "PHP Increment/Decrement Op") + +(defface php-string-op '((t (:inherit php-operator))) + "PHP Mode face used to logical operators (.)." + :group 'php-faces + :tag "PHP String Op") + +(defface php-object-op '((t (:inherit php-operator))) "PHP Mode face used to object operators (->)." :group 'php-faces :tag "PHP Object Op") -(defface php-paamayim-nekudotayim '((t (:inherit default))) +(defface php-paamayim-nekudotayim '((t ())) "PHP Mode face used to highlight \"Paamayim Nekudotayim\" scope resolution operators (::)." :group 'php-faces :tag "PHP Paamayim Nekudotayim") @@ -131,7 +166,7 @@ :group 'php-faces :tag "PHP $this Sigil") -(defface php-errorcontrol-op '((t (:inherit font-lock-type-face))) +(defface php-errorcontrol-op '((t (:inherit font-lock-type-face))) "PHP Mode face used to highlight errorcontrol operators (@).." :group 'php-faces :tag "PHP ErrorControl Op") diff --git a/.emacs.d/lisp/php-mode.el b/.emacs.d/lisp/php-mode.el index 9be3b55..faf2ec5 100644 --- a/.emacs.d/lisp/php-mode.el +++ b/.emacs.d/lisp/php-mode.el @@ -9,16 +9,13 @@ ;; Maintainer: USAMI Kenta ;; URL: https://github.com/emacs-php/php-mode ;; Keywords: languages php -;; Version: 1.21.4 -;; Package-Requires: ((emacs "24.3") (cl-lib "0.5")) +;; Version: 1.22.1 +;; Package-Requires: ((emacs "24.3")) ;; License: GPL-3.0-or-later -(defconst php-mode-version-number "1.21.4" +(defconst php-mode-version-number "1.22.1" "PHP Mode version number.") -(defconst php-mode-modified "2019-05-29" - "PHP Mode build date.") - ;; 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 @@ -195,7 +192,10 @@ of constants when set." :type 'boolean) (defcustom php-mode-page-delimiter - (eval-when-compile (rx symbol-start (or "namespace" "function" "class" "trait" "interface") symbol-end)) + (eval-when-compile + (rx symbol-start + (or "namespace" "function" "class" "trait" "interface") + symbol-end)) "Regexp describing line-beginnings that PHP declaration statements." :group 'php-mode :tag "PHP Mode Page Delimiter" @@ -307,7 +307,7 @@ This variable can take one of the following symbol values: `PSR-2' - use coding styles preferred for working with projects using PSR-2 standards." :group 'php-mode :tag "PHP Mode Coding Style" - :type '(choice (const :tag "Default" default) + :type '(choice (const :tag "Default" php) (const :tag "PEAR" pear) (const :tag "Drupal" drupal) (const :tag "WordPress" wordpress) @@ -340,15 +340,27 @@ In that case set to `NIL'." "When set to `T', do not run hooks of parent modes (`java-mode', `c-mode')." :group 'php-mode :tag "PHP Mode Disable C Mode Hook" - :type 'boolean - :group 'php-mode) + :type 'boolean) + +(defcustom php-mode-enable-project-local-variable t + "When set to `T', apply project local variable to buffer local variable." + :group 'php-mode + :tag "PHP Mode Enable Project Local Variable" + :type 'boolean) (defun php-mode-version () "Display string describing the version of PHP Mode." (interactive) - (funcall - (if (called-interactively-p 'interactive) #'message #'format) - "PHP Mode %s of %s" php-mode-version-number php-mode-modified)) + (let ((fmt + (eval-when-compile + (let ((id "$Id$")) + (concat "PHP Mode %s" + (if (string= id (concat [?$ ?I ?d ?$])) + "" + (concat " " id))))))) + (funcall + (if (called-interactively-p 'interactive) #'message #'format) + fmt php-mode-version-number))) ;;;###autoload (define-obsolete-variable-alias 'php-available-project-root-files 'php-project-available-root-files "1.19.0") @@ -633,10 +645,37 @@ might be to handle switch and goto labels differently." (c-lang-defconst c-opt-<>-sexp-key php nil) +(defconst php-mode--re-return-typed-closure + (eval-when-compile + (rx symbol-start "function" symbol-end + (* (syntax whitespace)) + "(" (* (not (any "("))) ")" + (* (syntax whitespace)) + (? symbol-start "use" symbol-end + (* (syntax whitespace)) + "(" (* (not (any "("))) ")" + (* (syntax whitespace))) + ":" (+ (not (any "{}"))) + (group "{")))) + +(defun php-c-lineup-arglist (langelem) + "Line up the current argument line under the first argument using `c-lineup-arglist' LANGELEM." + (let (in-return-typed-closure) + (when (and (consp langelem) + (eq 'arglist-cont-nonempty (car langelem))) + (save-excursion + (save-match-data + (when (re-search-backward php-mode--re-return-typed-closure (cdr langelem) t) + (goto-char (match-beginning 1)) + (when (not (php-in-string-or-comment-p)) + (setq in-return-typed-closure t)))))) + (unless in-return-typed-closure + (c-lineup-arglist langelem)))) + (defun php-lineup-cascaded-calls (langelem) "Line up chained methods using `c-lineup-cascaded-calls', but only if the setting is enabled" - (if php-lineup-cascaded-calls + (when php-mode-lineup-cascaded-calls (c-lineup-cascaded-calls langelem))) (c-add-style @@ -644,11 +683,12 @@ but only if the setting is enabled" `((c-basic-offset . 4) (c-offsets-alist . ((arglist-close . php-lineup-arglist-close) (arglist-cont . (first php-lineup-cascaded-calls 0)) - (arglist-cont-nonempty . (first php-lineup-cascaded-calls c-lineup-arglist)) + (arglist-cont-nonempty . (first php-lineup-cascaded-calls php-c-lineup-arglist)) (arglist-intro . php-lineup-arglist-intro) (case-label . +) (class-open . 0) (comment-intro . 0) + (inexpr-class . 0) (inlambda . 0) (inline-open . 0) (namespace-open . 0) @@ -661,6 +701,7 @@ but only if the setting is enabled" (tab-width . ,(default-value 'tab-width)) (fill-column . ,(default-value 'fill-column)) (show-trailing-whitespace . ,(default-value 'show-trailing-whitespace)) + (php-mode-lineup-cascaded-calls . t) (php-style-delete-trailing-whitespace . nil))) (defun php-enable-default-coding-style () @@ -687,6 +728,7 @@ but only if the setting is enabled" (tab-width . 2) (fill-column . 78) (show-trailing-whitespace . t) + (php-mode-lineup-cascaded-calls . nil) (php-style-delete-trailing-whitespace . t))) (defun php-enable-drupal-coding-style () @@ -713,6 +755,7 @@ but only if the setting is enabled" '("php" (c-offsets-alist . ((statement-cont . php-lineup-hanging-semicolon))) (c-indent-comments-syntactically-p . t) + (php-mode-lineup-cascaded-calls . nil) (fill-column . 78))) (defun php-enable-symfony2-coding-style () @@ -721,12 +764,13 @@ but only if the setting is enabled" (php-set-style "symfony2")) (c-add-style - "psr2" + "psr2" ; PSR-2 / PSR-12 '("php" (c-offsets-alist . ((statement-cont . +))) (c-indent-comments-syntactically-p . t) (fill-column . 78) (show-trailing-whitespace . t) + (php-mode-lineup-cascaded-calls . nil) (php-style-delete-trailing-whitespace . t))) (defun php-enable-psr2-coding-style () @@ -734,10 +778,6 @@ but only if the setting is enabled" (interactive) (php-set-style "psr2")) -(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.") - (defun php-beginning-of-defun (&optional arg) "Move to the beginning of the ARGth PHP function from point. Implements PHP version of `beginning-of-defun-function'." @@ -1009,6 +1049,14 @@ this ^ lineup" (easy-menu-define php-mode-menu php-mode-map "PHP Mode Commands" (cons "PHP" (c-lang-const c-mode-menu php))) +(defun php-mode-get-style-alist () + "Return an alist consisting of `php' style and styles that inherit it." + (cl-loop for l in c-style-alist + if (or (string= (car l) "php") + (equal (cadr l) "php")) + collect l)) + +(defvar php-mode-set-style-history nil) (defvar-local php-mode--delayed-set-style nil) (defvar-local php-style-delete-trailing-whitespace nil) @@ -1027,7 +1075,15 @@ After setting the stylevars run hooks according to STYLENAME \"wordpress\" `php-mode-wordpress-hook' \"symfony2\" `php-mode-symfony2-hook' \"psr2\" `php-mode-psr2-hook'" - (interactive) + (interactive + (list (let ((completion-ignore-case t) + (prompt (format "Which %s indentation style? " + mode-name))) + (completing-read prompt + (php-mode-get-style-alist) + nil t nil + 'php-mode-set-style-history + c-indentation-style)))) (php-mode--disable-delay-set-style) ;; Back up manually set variables @@ -1046,13 +1102,11 @@ After setting the stylevars run hooks according to STYLENAME (if (eq (symbol-value 'php-style-delete-trailing-whitespace) t) (add-hook 'before-save-hook 'delete-trailing-whitespace nil t) (remove-hook 'before-save-hook 'delete-trailing-whitespace t)) - (cond ((eq stylename "pear") (run-hooks 'php-mode-pear-hook)) - ((eq stylename "drupal") (run-hooks 'php-mode-drupal-hook)) - ((eq stylename "wordpress") (run-hooks 'php-mode-wordpress-hook)) - ((eq stylename "symfony2") (run-hooks 'php-mode-symfony2-hook)) - ((eq stylename "psr2") (run-hooks 'php-mode-psr2-hook)))) - -(put 'php-set-style 'interactive-form (interactive-form 'c-set-style)) + (cond ((equal stylename "pear") (run-hooks 'php-mode-pear-hook)) + ((equal stylename "drupal") (run-hooks 'php-mode-drupal-hook)) + ((equal stylename "wordpress") (run-hooks 'php-mode-wordpress-hook)) + ((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) "Disable php-mode-set-style-delay on after hook. `ARGS' be ignore." @@ -1069,6 +1123,11 @@ After setting the stylevars run hooks according to STYLENAME (php-set-style (symbol-name coding-style))) (remove-hook 'hack-local-variables-hook #'php-mode-set-style-delay))))) +(defun php-mode-set-local-variable-delay () + "Set local variable from php-project." + (php-project-apply-local-variables) + (remove-hook 'hack-local-variables-hook #'php-mode-set-local-variable-delay)) + (defvar php-mode-syntax-table (let ((table (make-syntax-table))) (c-populate-syntax-table table) @@ -1077,7 +1136,7 @@ After setting the stylevars run hooks according to STYLENAME (modify-syntax-entry ?\" "\"" table) (modify-syntax-entry ?# "< b" table) (modify-syntax-entry ?\n "> b" table) - (modify-syntax-entry ?$ "'" table) + (modify-syntax-entry ?$ "_" table) table)) ;;;###autoload @@ -1122,6 +1181,9 @@ After setting the stylevars run hooks according to STYLENAME ;; PHP vars are case-sensitive (setq case-fold-search t) + (when php-mode-enable-project-local-variable + (add-hook 'hack-local-variables-hook #'php-mode-set-local-variable-delay t t)) + ;; When php-mode-enable-project-coding-style is set, it is delayed by hook. ;; Since it depends on the timing at which the file local variable is set. ;; File local variables are set after initialization of major mode except `run-hook' is complete. @@ -1440,7 +1502,7 @@ a completion list." "return" "throws" "var")) (defconst php-phpdoc-font-lock-doc-comments - `(("{@[-[:alpha:]]+\\s-\\([^}]*\\)}" ; "{@foo ...}" markup. + `(("{@[-[:alpha:]]+\\s-*\\([^}]*\\)}" ; "{@foo ...}" markup. (0 'php-doc-annotation-tag prepend nil) (1 'php-string prepend nil)) (,(rx (group "$") (group (in "A-Za-z_") (* (in "0-9A-Za-z_")))) @@ -1482,6 +1544,9 @@ a completion list." ("\\(->\\)\\(\\sw+\\)\\s-*(" (1 'php-object-op) (2 'php-method-call)) ("\\<\\(const\\)\\s-+\\(\\_<.+?\\_>\\)" (1 'php-keyword) (2 'php-constant-assign)) + ;; Logical operator (!) + ("\\(![^=]\\)" 1 'php-logical-op) + ;; Highlight special variables ("\\(\\$\\)\\(this\\)\\>" (1 'php-$this-sigil) (2 'php-$this)) ("\\(\\$+\\)\\(\\sw+\\)" (1 'php-variable-sigil) (2 'php-variable-name)) @@ -1517,7 +1582,14 @@ a completion list." ;; Highlight static method calls as such. This is necessary for method ;; names which are identical to keywords to be highlighted correctly. ("\\sw+::\\(\\sw+\\)(" 1 'php-static-method-call) - + ;; Multiple catch (FooException | BarException $e) + (,(rx symbol-start "catch" symbol-end + (* (syntax whitespace)) "(" (* (syntax whitespace)) + (group (+ (or (syntax word) (syntax symbol))))) + (1 font-lock-type-face) + (,(rx (* (syntax whitespace)) "|" (* (syntax whitespace)) + (group (+ (or (syntax word) (syntax symbol))) symbol-end)) + nil nil (1 font-lock-type-face))) ;; While c-opt-cpp-* highlights the \\)\\s-*(" 1 'php-function-call) ;; Highlight all upper-cased symbols as constant ("\\<\\([A-Z_][A-Z0-9_]+\\)\\>" 1 'php-constant) @@ -1581,7 +1655,23 @@ a completion list." ("\\?\\(\\(:?\\sw\\|\\s_\\)+\\)\\s-+\\$" 1 font-lock-type-face) ("function.+:\\s-*\\??\\(\\(?:\\sw\\|\\s_\\)+\\)" 1 font-lock-type-face) (")\\s-*:\\s-*\\??\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*\\(?:\{\\|;\\)" 1 font-lock-type-face) - )) + + ;; Assignment operators (=, +=, ...) + ("\\([^=]+?\\([\-+./%]?=\\)[^=]+?\\)" 2 'php-assignment-op) + + ;; Comparison operators (==, ===, >=, ...) + ("\\([!=]=\\{1,2\\}[>]?\\|[<>]=?\\)" 1 'php-comparison-op) + + ;; Arithmetic operators (+, -, *, **, /, %) + ("\\(?:[A-Za-z0-9[:blank:]]\\)\\([\-+*/%]\\*?\\)\\(?:[A-Za-z0-9[:blank:]]\\)" 1 'php-arithmetic-op) + + ;; Increment and Decrement operators (++, --) + ("\\(\-\-\\|\+\+\\)\$\\w+" 1 'php-inc-dec-op) ;; pre inc/dec + ("\$\\w+\\(\-\-\\|\+\+\\)" 1 'php-inc-dec-op) ;; post inc/dec + + ;; Logical operators (and, or, &&, ...) + ;; Not operator (!) is defined in "before cc-mode" section above. + ("\\(&&\\|||\\)" 1 'php-logical-op))) "Detailed highlighting for PHP Mode.") (defvar php-font-lock-keywords php-font-lock-keywords-3 diff --git a/.emacs.d/lisp/php-project.el b/.emacs.d/lisp/php-project.el index eb9a50e..18115cc 100644 --- a/.emacs.d/lisp/php-project.el +++ b/.emacs.d/lisp/php-project.el @@ -5,8 +5,8 @@ ;; Author: USAMI Kenta ;; Keywords: tools, files ;; URL: https://github.com/emacs-php/php-mode -;; Version: 1.21.4 -;; Package-Requires: ((emacs "24.3") (cl-lib "0.5")) +;; Version: 1.22.1 +;; Package-Requires: ((emacs "24.3")) ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify @@ -72,6 +72,19 @@ ;; Constants (defconst php-project-composer-autoloader "vendor/autoload.php") +;; Custom variables +(defgroup php-project nil + "Major mode for editing PHP code." + :tag "PHP Project" + :prefix "php-project-" + :group 'php) + +(defcustom php-project-auto-detect-etags-file nil + "If `T', automatically detect etags file when file is opened." + :tag "PHP Project Auto Detect Etags File" + :group 'php-project + :type 'boolean) + ;; Variables (defvar php-project-available-root-files '((projectile ".projectile") @@ -104,6 +117,12 @@ STRING (put 'php-project-root 'safe-local-variable #'(lambda (v) (or (stringp v) (assq v php-project-available-root-files)))) + (defvar-local php-project-etags-file nil) + (put 'php-project-etags-file 'safe-local-variable + #'(lambda (v) (or (functionp v) + (eq v t) + (php-project--eval-bootstrap-scripts v)))) + (defvar-local php-project-bootstrap-scripts nil "List of path to bootstrap php script file. @@ -172,7 +191,6 @@ Typically it is `pear', `drupal', `wordpress', `symfony2' and `psr2'.") (put 'php-project-server-start 'safe-local-variable #'(lambda (v) (or (functionp v) (php-project--eval-bootstrap-scripts v))))) - ;; Functions (defun php-project--validate-php-file-as-template (val) @@ -229,6 +247,17 @@ Typically it is `pear', `drupal', `wordpress', `symfony2' and `psr2'.") (t (prog1 nil (warn "php-project-php-file-as-template is unexpected format"))))) +(defun php-project-apply-local-variables () + "Apply php-project variables to local variables." + (when (null tags-file-name) + (when (or (and php-project-auto-detect-etags-file + (null php-project-etags-file)) + (eq php-project-etags-file t)) + (let ((tags-file (expand-file-name "TAGS" (php-project-get-root-dir)))) + (when (file-exists-p tags-file) + (setq-local php-project-etags-file tags-file)))) + (when php-project-etags-file + (setq-local tags-file-name (php-project--eval-bootstrap-scripts php-project-etags-file))))) ;;;###autoload (defun php-project-get-bootstrap-scripts () "Return list of bootstrap script." diff --git a/.emacs.d/lisp/php-util-buffer.el b/.emacs.d/lisp/php-util-buffer.el new file mode 100644 index 0000000..70836a0 --- /dev/null +++ b/.emacs.d/lisp/php-util-buffer.el @@ -0,0 +1,135 @@ +;;; php-util-buffer.el --- Utility function for buffer manipulation -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2019 Friends of Emacs-PHP development +;; Copyright 2013 The go-mode Authors. All rights reserved. + +;; Author: Dominik Honnef +;; Maintainer: USAMI Kenta +;; URL: https://github.com/emacs-php/php-mode +;; Keywords: lisp + +;; 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 . + +;;; Commentary: + +;; Functions for patching buffer. + +;;; Original License: + +;; Copyright (c) 2014 The go-mode Authors. All rights reserved. + +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions are +;; met: + +;; * Redistributions of source code must retain the above copyright +;; notice, this list of conditions and the following disclaimer. +;; * Redistributions in binary form must reproduce the above +;; copyright notice, this list of conditions and the following disclaimer +;; in the documentation and/or other materials provided with the +;; distribution. +;; * Neither the name of the copyright holder nor the names of its +;; contributors may be used to endorse or promote products derived from +;; this software without specific prior written permission. + +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +;; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;; Code: + +;; gofmt apply-rcs-patch Function +;; These functions are copied by go-mode(gofmt). +(defun php-util-buffer--delete-whole-line (&optional arg) + "Delete the current line without putting it in the `kill-ring'. +Derived from function `kill-whole-line'. ARG is defined as for that +function." + (setq arg (or arg 1)) + (if (and (> arg 0) + (eobp) + (save-excursion (forward-visible-line 0) (eobp))) + (signal 'end-of-buffer nil)) + (if (and (< arg 0) + (bobp) + (save-excursion (end-of-visible-line) (bobp))) + (signal 'beginning-of-buffer nil)) + (cond ((zerop arg) + (delete-region (progn (forward-visible-line 0) (point)) + (progn (end-of-visible-line) (point)))) + ((< arg 0) + (delete-region (progn (end-of-visible-line) (point)) + (progn (forward-visible-line (1+ arg)) + (unless (bobp) + (backward-char)) + (point)))) + (t + (delete-region (progn (forward-visible-line 0) (point)) + (progn (forward-visible-line arg) (point)))))) + +(defun php-util-buffer-apply-rcs-patch (target-buffer patch-buffer) + "Apply an RCS-formatted diff from `PATCH-BUFFER' to the `TARGET-BUFFER'." + (let ( + ;; Relative offset between buffer line numbers and line numbers + ;; in patch. + ;; + ;; Line numbers in the patch are based on the source file, so + ;; we have to keep an offset when making changes to the + ;; buffer. + ;; + ;; Appending lines decrements the offset (possibly making it + ;; negative), deleting lines increments it. This order + ;; simplifies the forward-line invocations. + (line-offset 0) + (column (current-column))) + (save-excursion + (with-current-buffer patch-buffer + (goto-char (point-min)) + (while (not (eobp)) + (unless (looking-at "^\\([ad]\\)\\([0-9]+\\) \\([0-9]+\\)") + (error "Invalid rcs patch or internal error in php-util-buffer-apply-rcs-patch")) + (forward-line) + (let ((action (match-string 1)) + (from (string-to-number (match-string 2))) + (len (string-to-number (match-string 3)))) + (cond + ((equal action "a") + (let ((start (point))) + (forward-line len) + (let ((text (buffer-substring start (point)))) + (with-current-buffer target-buffer + (cl-decf line-offset len) + (goto-char (point-min)) + (forward-line (- from len line-offset)) + (insert text))))) + ((equal action "d") + (with-current-buffer target-buffer + (goto-char (point-min)) + (forward-line (1- (- from line-offset))) + (cl-incf line-offset len) + (php-util-buffer--delete-whole-line len))) + (t + (error "Invalid rcs patch or internal error in php-util-buffer--apply-rcs-patch"))))))) + (move-to-column column))) +;; Copy of go-mode.el ends here + +(provide 'php-util-buffer) +;;; php-util-buffer.el ends here diff --git a/.emacs.d/lisp/php.el b/.emacs.d/lisp/php.el index 2bf117b..663559a 100644 --- a/.emacs.d/lisp/php.el +++ b/.emacs.d/lisp/php.el @@ -4,10 +4,10 @@ ;; Author: USAMI Kenta ;; Created: 5 Dec 2018 -;; Version: 1.21.4 +;; Version: 1.22.1 ;; Keywords: languages, php ;; Homepage: https://github.com/emacs-php/php-mode -;; Package-Requires: ((emacs "24.3") (cl-lib "0.5")) +;; Package-Requires: ((emacs "24.3")) ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify @@ -159,8 +159,13 @@ it is the character that will terminate the string, or t if the string should be (and (boundp 'poly-php-html-mode) (symbol-value 'poly-php-html-mode))) -(defun php-create-regexp-for-method (visibility) - "Make a regular expression for methods with the given VISIBILITY. +(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 + (defun php-create-regexp-for-method (&optional visibility) + "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 @@ -170,67 +175,81 @@ 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." - (concat - ;; Initial space with possible 'abstract' or 'final' keywords - "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?" - ;; 'static' keyword may come either before or after visibility - "\\(?:" visibility "\\(?:\\s-+static\\)?\\|\\(?:static\\s-+\\)?" visibility "\\)\\s-+" - ;; Make sure 'function' comes next with some space after - "function\\s-+" - ;; Capture the name as the first group and the regexp and make sure - ;; by the end we see the opening parenthesis for the parameters. - "\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(")) - -(defun php-create-regexp-for-classlike (type) - "Accepts a `TYPE' of a 'classlike' object as a string, such as + (when (stringp visibility) + (setq visibility (list visibility))) + (rx-to-string `(: line-start + (* (syntax whitespace)) + ,@(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)) + "("))) + + (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_\\)+\\)")) - -(defvar php-imenu-generic-expression - `(("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 "\\(?:\\sw\\|\\s_\\)+") 1) - ("Private Methods" - ,(php-create-regexp-for-method "private") 1) - ("Protected Methods" - ,(php-create-regexp-for-method "protected") 1) - ("Public Methods" - ,(php-create-regexp-for-method "public") 1) - ("Anonymous Functions" - "\\<\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*=\\s-*function\\s-*(" 1) - ("Named Functions" - "^\\s-*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1)) + (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 + (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")) 1) + ("Protected Methods" + ,(php-create-regexp-for-method '("protected")) 1) + ("Public Methods" + ,(php-create-regexp-for-method '("public")) 1) + ("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'.") -(defvar php--re-namespace-pattern - (php-create-regexp-for-classlike "namespace")) +(defconst php--re-namespace-pattern + (eval-when-compile + (php-create-regexp-for-classlike "namespace"))) -(defvar php--re-classlike-pattern - (php-create-regexp-for-classlike (regexp-opt '("class" "interface" "trait")))) +(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 - (when (re-search-backward re-pattern nil t) - (match-string-no-properties 1)))) + (save-match-data + (when (re-search-backward re-pattern nil t) + (match-string-no-properties 1))))) ;;; Provide support for Flymake so that users can see warnings and ;;; errors in real-time as they write code. @@ -245,7 +264,7 @@ Look at the `php-executable' variable instead of the constant \"php\" command." 'flymake-php-init))))) (list php-executable (cdr init)))) -(defconst php-re-detect-html-tag +(defconst php-re-detect-html-tag-aggressive (eval-when-compile (rx (or (: string-start (* (in space)) "")) (: "<" (* (in space)) (+ (in alpha "-")) (* (in space)) ">")))))) +(defconst php-re-detect-html-tag-default + (eval-when-compile + (rx (or (: string-start (* (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)) - (re-search-forward php-re-detect-html-tag nil t)))) + (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." @@ -309,6 +353,17 @@ Look at the `php-executable' variable instead of the constant \"php\" command." (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. @@ -338,9 +393,8 @@ When `DOCUMENT-ROOT' is NIL, the document root is obtained from `ROUTER-OR-DIR'. (if (file-directory-p router-or-dir) router-or-dir (directory-file-name router-or-dir)))) - (pattern (rx-form `(: bos ,(getenv "HOME")))) - (short-dirname (replace-regexp-in-string pattern "~" default-directory)) - (short-filename (replace-regexp-in-string pattern "~" 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 @@ -359,5 +413,40 @@ When `DOCUMENT-ROOT' is NIL, the document root is obtained from `ROUTER-OR-DIR'. (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))) + +(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 diff --git a/.emacs.d/lisp/yaml-mode.el b/.emacs.d/lisp/yaml-mode.el index 9f76c38..7adb17f 100644 --- a/.emacs.d/lisp/yaml-mode.el +++ b/.emacs.d/lisp/yaml-mode.el @@ -7,7 +7,7 @@ ;; Maintainer: Vasilij Schneidermann ;; Package-Requires: ((emacs "24.1")) ;; Keywords: data yaml -;; Version: 0.0.13 +;; Version: 0.0.14 ;; This file is not part of Emacs @@ -117,7 +117,7 @@ that key is pressed to begin a block literal." ;; Constants -(defconst yaml-mode-version "0.0.13" "Version of `yaml-mode'.") +(defconst yaml-mode-version "0.0.14" "Version of `yaml-mode'.") (defconst yaml-blank-line-re "^ *$" "Regexp matching a line containing only (valid) whitespace.") @@ -286,7 +286,7 @@ line in the match data, as consumed by `font-lock-keywords' matcher functions. The function begins by searching backwards to determine whether or not the current line is within a block literal. This could be time-consuming in large buffers, so the number of lines searched is -artificially limitted to the value of +artificially limited to the value of `yaml-block-literal-search-lines'." (if (eolp) (goto-char (1+ (point)))) (unless (or (eobp) (>= (point) bound)) diff --git a/.emacs.d/lisp/yasnippet.el b/.emacs.d/lisp/yasnippet.el index 3bbb94d..bfd904e 100644 --- a/.emacs.d/lisp/yasnippet.el +++ b/.emacs.d/lisp/yasnippet.el @@ -386,7 +386,7 @@ It must be set to nil before loading yasnippet to take effect." ;; Only two faces, and one of them shouldn't even be used... ;; (defface yas-field-highlight-face - '((t (:inherit 'region))) + '((t (:inherit region))) "The face used to highlight the currently active field of a snippet") (defface yas--field-debug-face @@ -1399,6 +1399,9 @@ conditions to filter out potential expansions." (push (cons name template) acc)) namehash)) (yas--table-hash table)) + (maphash #'(lambda (uuid template) + (push (cons uuid template) acc)) + (yas--table-uuidhash table)) (yas--filter-templates-by-condition acc)))) (defun yas--templates-for-key-at-point () @@ -4727,7 +4730,14 @@ When multiple expressions are found, only the last one counts." ;; (save-excursion (while (re-search-forward yas--field-regexp nil t) - (let* ((real-match-end-0 (yas--scan-sexps (1+ (match-beginning 0)) 1)) + (let* ((brace-scan (yas--scan-sexps (1+ (match-beginning 0)) 1)) + ;; if the `brace-scan' didn't reach a brace, we have a + ;; snippet with invalid escaping, probably a closing + ;; brace escaped with two backslashes (github#979). But + ;; be lenient, because we can. + (real-match-end-0 (if (eq ?} (char-before brace-scan)) + brace-scan + (point))) (number (and (match-string-no-properties 1) (string-to-number (match-string-no-properties 1)))) (brand-new-field (and real-match-end-0 -- cgit v1.3