TL;DR:
It's defined in Vim's PHP and HTML syntax files. To see how to add rules for CSS, jump to the section And how do I add to them? below, or read on for an explanation of how it works.
Where are these syntax rules getting defined?
The JavaScript heredoc is highlighted using Vim's syntax contains
1 feature, which allows syntax groups to contain other syntax groups.
To find where this is defined, first open up the syntax highlighting file for PHP:
:e $VIMRUNTIME/syntax/php.vim
Now, presumably the syntax file is finding the JavaScript heredoc based on a match of the string "javascript", so lets try searching for that:
/javascript
The third match is this comment:
" including HTML,JavaScript,SQL even if not enabled via options
Looks promising! Let's take a look at the relevant syntax line:
syn region phpHereDoc matchgroup=Delimiter
\ start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(javascript\)\c\(\i*\)\)\2$"
\ end="^\z1\(;\=$\)\@="
\ contained
\ contains=@htmlJavascript,phpIdentifierSimply,phpIdentifier,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar,@Spell
\ keepend extend
(line continuations added for easier reading)
Okay, so this syntax region finds the JavaScript heredoc with a convoluted regular expression, and allows JavaScript highlighting within the region by including the @htmlJavascript
syntax cluster
2 within the contains
argument.
But there is no corresponding definition for CSS heredocs! Lets add one. So the first thing to change is the start
regular expression. Simply change the javascript
into css
:
start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(css\)\c\(\i*\)\)\2$"
This is easy!
But we don't want JavaScript highlighting in our CSS heredoc. So we also need to change the @htmlJavascript
to the CSS equivalent. But what is the CSS equivalent? (You might be able to guess, but let's go through the motions to be sure.)
Lets search for htmljavascript
3 to see where that is defined:
/htmljavascript
Hmmm. No other results. It must be defined elsewhere! Let's have a quick look at the top of the file to see if we can find any includes:
runtime! syntax/html.vim
This looks like it could be it4.
:e $VIMRUNTIME/syntax/html.vim
Run the search again in this file, and we find this line5:
syn cluster htmlJavaScript add=@htmlPreproc
So htmlJavaScript is a cluster
, defined in html.vim
. Is there a similar cluster for CSS we can use?
/htmlcss
Yup!
syn include @htmlCss syntax/css.vim
So we just need to replace @htmlJavascript
with @htmlCss
in the contains
argument:
contains=@htmlCss,phpIdentifierSimply,phpIdentifier,[...]
And how do I add to them?
Save the entire syntax command below in the file ~/after/syntax/php.vim
so that it is run after the rest of the PHP syntax processing has been carried out, and you're done!
syn region phpHereDoc matchgroup=Delimiter
\ start="\(<<<\)\@<=\(\"\=\)\z(\(\I\i*\)\=\(css\)\c\(\i*\)\)\2$"
\ end="^\z1\(;\=$\)\@="
\ contained
\ contains=@htmlCss,phpIdentifierSimply,phpIdentifier,phpIdentifierComplex,phpBackslashSequences,phpMethodsVar,@Spell
\ keepend extend
1: See :help :syn-contains
for details.
2: See :help :syn-cluster
.
3: I've got 'ignorecase'
switched on. Without it, you'll need to search for htmlJavascript
or \chtmljavascript
4: In fact, based on the naming scheme used in Vim syntax files, we probably could have figured this out based on the htmlJavascript
name alone.
5: With "JavaScript" capitalised differently, this time. Lucky we've got 'ignorecase'
switched on, eh?
// This should be syntax-highlighted
is not a valid CSS comment, and so should be syntax highlighted as something other than a comment. CSS only supports/* */
multi-line comments.//
single-line comments are only supported if you use preprocessor languages such as Sass or Stylus.