1

I have this function and mapping:

fun! TwiceToQuit()
    sil! q

    if v:errmsg == 'E37: No write since last change (add ! to override)'
        echohl ErrorMsg
        echo 'No write since last change, really quit?'
        echohl None
        if !exists('w:countofq')
            let w:countofq = 0
        endif
        let w:countofq += 1
        if w:countofq == 2
            q!
        endif
    endif
endfun

noremap <F2> <Esc>:call TwiceToQuit()<CR>

So when I press F2 at a modified file it asks me if I really want to quit, if so I press F2 again.

It works, but I have a few problems:

  1. When I have 2 windows, one with some regular file and the second one with help and I press F2 when the first window is active, it closes the whole vim. I have found some autocommand event related to this - QuitPre, but there aren't any autocommands associated with it so I don't know why is this happening.

  2. If I accidentally hold F2, it just spams the command so everything gets closed. I don't want that.

  3. I want to reset the variable w:countofq if I press some other key than F2. Is that possible?

  • 2
    Are you aware of the 'confirm' option?I think that does pretty much what your funtion does? – Martin Tournoij Jul 1 '15 at 23:16
  • @Carpetsmoker♦ I am aware of it, still I want to do it like this, because pressing F2 again is much simpler than pressing anything else. Using vimscript is about simplifying your life, isn't it? :-) – MichalH Jul 2 '15 at 9:14
2

Here's how I would do it:

fun! TwiceToQuit()
    " Buffer is not modified. We can quit
    if !&modified
        quit
        return
    endif

    echohl ErrorMsg
    echo 'No write since last change; press again to force quit.'
    echohl None

    " Get a single character
    let l:char = getchar()

    " If this is <F2>, quit
    if char2nr(l:char) == 128 && l:char[1:] ==# 'k2'
        quit!
    else
        " This clears the red error message in the " commandline
        execute "normal! \<C-l>" 

        " Try and execute the character
        if !empty(nr2char(l:char))
            execute 'normal! ' . nr2char(l:char)
        endif
    endif
endfun 

noremap <F2> <Esc>:call TwiceToQuit()<CR>

We don't need to call :quit to see if the buffer is modified, we can use the "special" 'modified' setting for that.

After that we use the getchar() function to get the next character; which is an easier way of doing things than keeping some state variable.

If I accidentally hold F2, it just spams the command so everything gets closed. I don't want that.

There is no obvious way to prevent this. As far as I know, Vim can't see if you've pressed <F2> twice, or held the key for 5 seconds.

2
  1. That is the way, Vims :q command works. Until recently there was not really a way around it. Vim doesn't consider a help window to be important, so whenever only a help buffer is open, it will silently quit. You could try either to use :helpclose explictly to close all help windows or use :.q to explicitly close only the current window. Both are relative recent additions and won't work in older Vims. Put this in your function to check for the number on windows currently open (:h winnr()) and you should be able to get it working.

  2. Not possible.

  3. not really possible,except you really want to map every other character away and reset the variable.

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.