Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I edit a lot of PHP code with Vim, and I've run into a snag with some macros in my .vimrc.

I currently use these two macros to comment/uncomment in C-style

"c-style (//) comment (press the [.] key)
au FileType php vnoremap . :s/^\(\s*\)\(.\+\)$/\1\/\/\2/<CR>:noh<CR>gv
"c-style (//) uncomment (press the [,] key)
au FileType php vnoremap , :s/^\(\s*\)\/\//\1/<CR>:noh<CR>gv

And these two to comment/uncomment in HTML-style

"html-style (<!-- -->) comment (press the [.] key)
au FileType html vnoremap . :s/^\(\s*\)\(.\+\)$/\1<!-- \2 -->/g<CR>:noh<CR>gv
"html-style (<!-- -->) uncomment (press the [,] key)
au FileType html vnoremap , :s/^\(\s*\)<!-- \(.*\) -->/\1\2/g<CR>:noh<CR>gv

These macros work fine when applied to their intended file-type, but since there is often HTML embedded inside a PHP file, the PHP commenting style is useless.

Is there a way for Vim to detect if it's working on a chunk of HTML code inside a PHP file, and then apply the correct commenting behaviour?

Edit: I know that I can manually set the filetype, and that there are plugins available for this, I was looking to learn more about writing better macros.

share|improve this question
So you're sort of looking for a Vim analog to Emacs's MMM mode, which leads to vim.wikia.com/wiki/… – Gilles Jul 6 '11 at 21:32

To do what you want there is really no way to get around writing a function and mapping it your preferred keys.

To get started :echo synIDattr(synID(line("."), col("."), 1), "name") will print the name of the highlight group for the current word under the cursor.

You can use that information to determine which comment style to use.

A rough example to get you started:

function! s:MyComment () range
    for i in range(a:firstline, a:lastline)
        exe "normal " . i . "gg"
        normal ^
        let stuff = synIDattr(synID(line("."), col("."), 1), "name")
        if strpart(stuff, 0, 4) == "html"
            normal I<!-- 
            normal A -->
            normal I//
vmap <silent> . :call <SID>MyComment()<CR>
share|improve this answer

In case you can accept to choose manually which type of comment you want to use, I would recommend this tip.

You would have 4 combinations to remember:

,* comment  
,c uncomment

HTML style: 
,< comment 
,d uncomment
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.