The following elisp snippet should do. The important details are:
- Strings are handled by syntax highlighting and not by pattern matching (i.e., keyword highlighting). This has very high priority. So one needs to override it explicitly by the value
t
for the MATCHER flag OVERRIDE (see doc of font-lock-keywords
).
- One cannot use a regexp as keyword MATCHER since one has to check only SQL keywords within strings. The code below provides
php-sql-keyword-matcher
for that purpose. The test for strings is done via syntax-ppss
(see the doc for this function).
Note that I only have a display of class color
. So I could not test the other classes. I assume that you have an other display class since strings are displayed in italic face in your example. If you do not get the expected result please customize the face php-sql-keyword-face
.
(require 'sql) ;; for sql-keywords
(require 'php-mode) ;; for php-mode-hook
(defvar php-sql-keywords (concat "\\<" (mapconcat 'car sql-mode-ansi-font-lock-keywords "\\|") "\\>")
"SQL keywords for php-mode stolen from `sql-mode-ansi-font-lock-keywords'.")
(defun php-sql-keyword-matcher (end)
"Search for SQl keywords within PHP strings."
(let (pos (case-fold-search t))
(while (and (setq pos (re-search-forward php-sql-keywords end t))
(null (nth 3 (syntax-ppss pos)))))
(when pos (message "Found keyword at %s" pos))
pos))
(defface php-sql-keyword-face
'((((class grayscale)) :slant nil :inherit font-lock-string-face)
(((class color)) :slant italic :inherit font-lock-string-face)
(t :slant nil :inherit font-lock-string-face))
"Face to highlight SQL keywords within PHP strings."
:group 'php-sql)
(defcustom php-sql-keyword-face 'php-sql-keyword-face
"Face to highlight SQL keywords within PHP strings."
:type 'face
:group 'php-sql)
(defun php-add-sql-keyword-matcher ()
"Hook to add fontification of sql-keywords in strings."
(font-lock-add-keywords
nil
'((php-sql-keyword-matcher 0 php-sql-keyword-face t))
'append))
(add-hook 'php-mode-hook 'php-add-sql-keyword-matcher)
Note: Please do not only insert images of texts that are needed for the reconstruction of the problem. The ascii text can ease potential helpers the reconstruction of the problem.
For the case that someone other has a better solution I insert the ASCII-version of the text here:
$sSql = 'SELECT T05.foo
T07.bar
FROM db_pgm_intranet.inttbl_keyuser_proces_keyuser T05
INNER JOIN db_pgm_intranet.inttbl_keyuser_keyuser T07
ON T07.nKkuID = T01.nKpkKeyuserID
LEFT JOIN db_pgm_intranet.inttbl_keyuser_applicate T07
ON T06.nKpaProcesID = T07.nKapID';
And here a picture of the text as it looks like when I load it into emacs with PHP mode:

With display class color
strings are not italic but have a different color. Therefore, I have chosen italic font face for SQL keywords within strings.
The comments indicate some difficulties with this answer. It has been indicated that the solution would not work with the default font set to Consolas
. I've just tested it and on my system it also works with Consola font as default:

In the help for font-lock-add-keywords
I found the following text:
For example:
(font-lock-add-keywords 'c-mode
'(("\\<\\(FIXME\\):" 1 'font-lock-warning-face prepend)
("\\<\\(and\\|or\\|not\\)\\>" . 'font-lock-keyword-face)))
adds two fontification patterns for C mode, to fontify 'FIXME:' words, even in
comments, and to fontify and
, or
and not
words as keywords.
The first case "FIXME
" is the interesting one. Here they use prepend
as override flag.