0

I have written a vimscript function to toggle comments on/off on lines selected in visual mode. The function successfully adds comments but freezes when I try to uncomment selected lines.

The function is

" Function to automatically toggle comments (on visual selection)
function! ToggleComments()
    let cFamilyTypes = ['c', 'cpp', 'cc', 'cxx', 'cs', 'java']
    let commentString = ""
    let commentChar = ''
    let counter = 0 " Indicates if the line was commented, so don't comment again
    if index(cFamilyTypes, &filetype) != -1
        let commentString = "//"
        let commentChar = '/'
    endif
    if &filetype == 'vim'
        let commentString = "\""
        let commentChar = '"'
    endif

    " Check if comments exist at the beginning of the current line and
    " delete them
    call feedkeys("0")
    while getline(".")[col(".")-1] == commentChar || getline(".")[col(".")-1] == ' '  || getline(".")[col(".")-1] == '\t'     
        if getline(".")[col(".")-1] == commentChar
            call feedkeys("x")
            let counter += 1
            continue
        endif
        call feedkeys("l")
    endwhile
    " Code to check and delete existing comments ends here

    " If counter was not incremented, the line is uncommented. So add
    " comments
    if counter == 0
        call feedkeys("0")
        execute "normal! i" . commentString . "\<ESC>"
        let counter = 0
    endif
    " Code to add comments ends here

endfunction
" Function to automatically toggle comments ends here

I call the function by :'<,'>call ToggleComments()

I am a beginner to vimscript so can someone tell me what I am doing wrong?

7
  • 3
    Have a look at tpope/commentary’s source code if you’re really interested in toggling comments – D. Ben Knoble Feb 9 '20 at 13:13
  • 4
    yes; but no shame in having inspiration from other sources. – D. Ben Knoble Feb 9 '20 at 13:17
  • 1
    You probably shouldn't be using feedkeys() here, instead, just use normal! to run normal mode commands, e.g. normal! 0 or normal! x etc. Not sure if that will fix all the bugs you have here, just wanted to point this out as a "best practices" kind of thing... – filbranden Feb 9 '20 at 22:39
  • 1
    @filbranden Thank you! It worked. I replaced every feedkeys() call by a execute "normal! <something>" and it works as intended. Can you post this as an answer, so i can accept it? – aks Feb 10 '20 at 18:09
  • 1
    @aks Will do. A bit later though, I'll dig up the reference that feedkeys() actually happens after your function call. (Anyways, get the exact details straight.) Will post an answer though. – filbranden Feb 10 '20 at 18:14
2

The issue is that you're calling feedkeys() and that function adds the keypresses to the end of the typeahead buffer, which means they don't execute right away.

From :help feedkeys():

By default the string is added to the end of the typeahead buffer, thus if a mapping is still being executed the characters come after them.

There are flags you can pass to feedkeys() to change this behavior... But in any case, the actual intent of your commands here is to run Normal mode commands and using :normal! is a much better way to accomplish that.

So I suggest you change your code to use normal! 0, normal! x and normal! l instead of the feedkeys() calls, that should solve the issue for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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