branch: elpa/php-mode
commit c3cc4c999e5427d7a0ec9fba5531c998707570c1
Author: USAMI Kenta <[email protected]>
Commit: USAMI Kenta <[email protected]>
Add php-pipe-op face for the PHP 8.5 pipe operator
The pipe operator came out half-fontified. No rule matched `|>', so
the comparison-operator matcher -- whose `[<>]=?' alternative claims a
bare `>' -- took the second character and left the first one plain:
'|' -> nil
'>' -> php-comparison-op
Give it a face of its own. php-pipe-op inherits php-operator like the
rest of the operator faces, and its rule sits ahead of the comparison
operators so it wins the `>'.
The rule is deliberately narrow (`|>' only), so nothing else moves:
`||', `>=', `>', `===', `<=>', `=>' and a bare `|' all keep the faces
they had. A test pins that down alongside the pipe itself.
See https://www.php.net/releases/8.5/en.php
---
lisp/php-face.el | 5 +++++
lisp/php-mode.el | 5 +++++
tests/php-mode-test.el | 30 ++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
diff --git a/lisp/php-face.el b/lisp/php-face.el
index 15395fb269..85aa38dd39 100644
--- a/lisp/php-face.el
+++ b/lisp/php-face.el
@@ -126,6 +126,11 @@
"PHP Mode face used to object operators (->)."
:tag "PHP Object Op")
+(defface php-pipe-op '((t (:inherit php-operator)))
+ "PHP Mode face used to the pipe operator (|>).
+The operator was added in PHP 8.5."
+ :tag "PHP Pipe Op")
+
(defface php-paamayim-nekudotayim '((t ()))
"PHP Mode face used to highlight scope resolution operators (::).
The operator is also knows as \"Paamayim Nekudotayim\"."
diff --git a/lisp/php-mode.el b/lisp/php-mode.el
index 4b050d2449..4fd23b2912 100644
--- a/lisp/php-mode.el
+++ b/lisp/php-mode.el
@@ -1518,6 +1518,11 @@ for \\[find-tag] (which see)."
;; Assignment operators (=, +=, ...)
("\\([^=<!>]+?\\([\-+./%]?=\\)[^=<!]+?\\)" 2 'php-assignment-op)
+ ;; Pipe operator (|>) --- PHP 8.5. Must precede the comparison
+ ;; operators, whose `[<>]=?' alternative would otherwise claim the
+ ;; `>' and leave the `|' unfontified.
+ ("\\(|>\\)" 1 'php-pipe-op)
+
;; Comparison operators (==, ===, >=, ...)
("\\([!=]=\\{1,2\\}[>]?\\|[<>]=?\\)" 1 'php-comparison-op)
diff --git a/tests/php-mode-test.el b/tests/php-mode-test.el
index 09a33754f2..1d5ef11ffb 100644
--- a/tests/php-mode-test.el
+++ b/tests/php-mode-test.el
@@ -803,6 +803,36 @@ path; sending those to an HTML mode would take most PHP
files away from
"Test highlighting language constructs added in PHP 8.4."
(with-php-mode-test ("8.4/property-hooks.php" :faces t)))
+(defun php-mode-test--faces-of (code token)
+ "Return the list of faces on TOKEN's characters after fontifying CODE."
+ (with-temp-buffer
+ (insert code)
+ (php-mode)
+ (font-lock-ensure)
+ (goto-char (point-min))
+ (should (search-forward token nil t))
+ (let ((start (- (point) (length token))))
+ (mapcar (lambda (i) (get-text-property (+ start i) 'face))
+ (number-sequence 0 (1- (length token)))))))
+
+(ert-deftest php-mode-test-php85-pipe-op ()
+ "The PHP 8.5 pipe operator is fontified as `php-pipe-op'.
+
+Both characters must get the face. The comparison-operator matcher
+claims a bare `>', so without a rule of its own `|>' came out
+half-fontified: the `|' plain and the `>' as `php-comparison-op'."
+ (should (equal '(php-pipe-op php-pipe-op)
+ (php-mode-test--faces-of "<?php\n$slug = $title |>
trim(...);\n" "|>")))
+ ;; Operators that the new rule must not steal from.
+ (dolist (probe '(("<?php\n$a = $b || $c;\n" "||" (php-logical-op
php-logical-op))
+ ("<?php\n$a = $b >= $c;\n" ">=" (php-comparison-op
php-comparison-op))
+ ("<?php\n$a = $b > $c;\n" ">" (php-comparison-op))
+ ("<?php\n$a = $b <=> $c;\n" "<=>" (php-comparison-op
php-comparison-op php-comparison-op))
+ ("<?php\n$a = $b | $c;\n" "|" (nil))))
+ (cl-destructuring-bind (code token expected) probe
+ (should (equal (cons token expected)
+ (cons token (php-mode-test--faces-of code token)))))))
+
(ert-deftest php-mode-test-lang ()
"Test highlighting for language constructs."
(with-php-mode-test ("lang/class/anonymous-class.php" :indent t :magic t
:faces t))