Vim, context-sensitive comment/uncomment behavior

PHPvim

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.

Best Answer

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 -->
        else
            normal I//
        endif
    endfor
endfunction
vmap <silent> . :call <SID>MyComment()<CR>
Related Question