Search code examples
vim

Vim -- Contextually changing behavior of a command based on syntax


I tend to have comment lines like this:

// This is a comment. 
// This is the second line of a comment paragraph.

// This is a second paragraph...

I have my cursor in the middle of these lines and I want to start adding something. Often it is adding a sentence at the beginning of a paragraph. Hitting I will take me to before //. This is something I want to do often enough that it slightly bugs me that there isn't a quick way to get there without a bunch of movement commands or awkward reaches like ^wi.

I want to adjust the I command to be "smart", so that only if my cursor is in a comment syntax area do I want vim to execute ^wi.

Can I do this? I am pretty sure I can do this because I have a little command somewhere that is capable of telling me the syntax type that the cursor is inside of.


Solution

  • You could do it as a one-liner, but when conditionals are involved, I prefer to use a function:

    :nnoremap I :call SmartInsert()<CR>
    

    In the function, you can use synIDattr() to get the name of the active syntax item; see the example under :help synID(). Then you can take different actions depending on whether the name contains "Comment". Move the cursor as desired, then end the function with :startinsert.

    :help synIDattr()
    :help =~?
    :help :if
    :help :startinsert
    :help user-functions
    

    Edit by OP: Thanks for this great starting point. I got around to writing the function, here it is. It's real handy.

    function! SmartInsert()
        if synIDattr(synID(line("."), col("."), 1), "name") =~ "LineComment$"
            normal! ^w    " Can enhance this with something more general (no need tho)
            startinsert
        else
            call feedkeys('I', 'n')
        endif
    endfun
    
    nnoremap I :call SmartInsert()<CR>