1

In Emacs, I am writing a PHP file that mixes both PHP and non-PHP code, which will be in C++ mode. I would like the PHP code to be highlighted with a link-pink background in order to make it stand out visually.

To do this, I use the font-lock setting:

(make-face 'font-lock-special-macro-face)
(set-face-background 'font-lock-special-macro-face "pink")
(defun add-custom-keyw()
  "adds a few special keywords for c and c++ modes"
  ;
  (font-lock-add-keywords nil
   '(
     ("<\\?[^\\?]*\\?>" . 'font-lock-special-macro-face )
     ; more of those would go here
    )
  )
)
(setq font-lock-multiline t)
(add-hook 'c++-mode-hook 'add-custom-keyw)

The regular expression expression matches the typical PHP tags and their enclosed text. However, if there are any string literals in the body of the PHP block, then the highlighting fails. I think this is because the face defined above is clashing with the coloring of string literals, which are by default colored text.

What should I do to fix this issue? I would like to keep both coloring schemes (highlighting and colored string literals) if possible.

Here is an example:

The code <?= $className ?> is highlighted with a pink background.

The code <?= inputs_to_vector($factors, 'factors') ?> does not have a highlighted background and the string literal 'factors' is displayed with red colored text.

This happens regardless of whether the leading PHP tag <? or <?= is used.

Drew
  • 29,895
  • 7
  • 74
  • 104
Jon Claus
  • 2,862
  • 4
  • 22
  • 33
  • Please post a sample literal string and state whether it is receiving a highlight, and if so, what face is it defaulting to. – lawlist Sep 10 '13 at 19:32
  • OK, I have edited the question to include an example. – Jon Claus Sep 10 '13 at 19:57
  • Have you thought about revising your `regexp` to consider `'` as a potential ending and a potential beginning to your regexp set forth in `add-custom-keyw`, and excluding anything within the single quotes -- e.g., exclude something like this: `"\\('\\)\\(\\(.\\|\n\\)+?\\)\\('\\)"` The face used for string literals is: `font-lock-string-face` – lawlist Sep 10 '13 at 21:52

1 Answers1

2

Try this in place of the sexp you have:

 '("<\\?[^\\?]*\\?>" 0 font-lock-special-macro-face t)
                                                    ^

The last part, t means that this highlighting should override any existing highlighting for the same text.

Drew
  • 29,895
  • 7
  • 74
  • 104
  • I'm not sure why, but `font-lock-keyword-face` ends up being used to highlight `= $className ?>` if we use `'("<\\?[^\\?]*\\?>" 0 font-lock-special-macro-face t)`. I'm used a blank .emacs file to run the test in c++.mode with only the code proposed in the question as modified by this draft answer. – lawlist Sep 11 '13 at 04:02
  • I didn't really try to change the regexp --- I was assuming that it was correct and the problem was that two font-lock rules applied to the same text and @JonClaus needed to have this rule override the other. But without looking closer, one thing you can do is to remove the backslashes inside the `[...]`: The `?` char is not special when inside `[...]`, and there is no escaping inside `[...]` anyway. If you have a backslash there then you intend not to match a backslash either. Dunno whether that is what is wanted here. – Drew Sep 11 '13 at 05:39
  • So `font-lock-keyword-face` must also be matching `= $className ?>`. The override indicator should take care of that, if two rules are matching, *PROVIDED* this new rule appears after the other rule it is intended to override, in the list of rules. IOW, it must be appended: use `t` as the third arg to `font-lock-add-keywords`. – Drew Sep 11 '13 at 05:46
  • The code in the question has problems: The following code with Drew's answer does work as Drew describes: `(defvar font-lock-special-macro-face (make-face 'font-lock-special-macro-face)) (set-face-background 'font-lock-special-macro-face "pink") (font-lock-add-keywords 'c++-mode '(("<\\?[^\\?]*\\?>" 0 font-lock-special-macro-face t)) 'prepend)` However, @JonClaus was actually hoping for the best of both worlds -- i.e., preserve the string-literal highlighting with `font-lock-string-face` and also have his own pink highlighting elsewhere. – lawlist Sep 11 '13 at 06:10
  • The code in the question is missing `(defvar font-lock-special-macro-face . . .)` and also missing `'prepend)`. The other reason why my first test failed was because the single quote in the answer would need to be outside another pair of opening/closing parenthesis -- e.g., `'((. . .))`. – lawlist Sep 11 '13 at 06:40