user271528
user271528

Reputation:

How to prevent quitting vim accidentally?

Is there a way to rebind :q in vim to a more complex command to prevent accidentally exiting vim?

Upvotes: 24

Views: 5341

Answers (7)

raacer
raacer

Reputation: 5462

My problem was that I find it difficult to hit the w key with my pinky finger, and I often missed, typing q or wq instead. At the same time, I also actively use commands that I occasionally type by mistake. This requires working on finger placement, but currently, I was losing all my open buffers, which was painful because I had to reopen all the files scattered across directories.

I simply want Vim to prompt for confirmation when I type q or wq. All the solutions mentioned here either didn't work as I needed by disabling these commands, or they worked poorly by not functioning correctly when background buffers were present or when the typed text was not the target command, but simply contained the letters of the target command. So I combined them into my own solution that does exactly what I need.

Here is my solution:

" Prompt for confirmation before exit."
function! ConfirmQuit()
    " Verify the entire command line."
    let l:quit = index(['q', 'wq'], getcmdline()) >= 0
    " Check that the current window is neither a help nor a command-line window."
    let l:my_window =  (&buftype != 'help' && &buftype != 'nofile')
    if l:quit && l:my_window  &&
    \ confirm("Do you really want to quit?", "&Yes\n&No", 2) == 2
        return "\<C-U>"  " Clear the command line."
    endif
    return ''  " Leave the command line unchanged."
endfunction
" Remap the newline character."
cnoremap <expr> <CR> ConfirmQuit() . '<CR>'

" Enable confirmation prompts for unsaved changes before quitting."
set confirm
  • cnoremap - Maps a key sequence (map) in the command mode (c) and avoids recursion (nore).
  • <expr> - Indicates that the second argument should be an expression returning a key sequence rather than plain text.
  • . '<CR>' - Appends the newline character to execute the resulting command, which will either be the original command or an empty command.

Upvotes: 0

Andrew Keeton
Andrew Keeton

Reputation: 23301

Using the coot/cmdalias_vim plugin, I effectively disabled the short, impulsive quit commands :q, :q!, and :wq. Hopefully this will slow me down and make me think about whether I really want to use :quit or, say, :bdelete. Here's a condensed version of the "autocmd section" of my .vimrc file:

if has("autocmd")
    augroup VIMRC_aliases
        au!
        au VimEnter * CmdAlias wqu\%[it] write|quit
        au VimEnter * CmdAlias q         echo\ "Use\ :qu[it]\ instead\ of\ :q"
        au VimEnter * CmdAlias q!        echo\ "Use\ :qu[it]!\ instead\ of\ :q!"
        au VimEnter * CmdAlias wq        echo\ "Use\ :wqu[it]\ instead\ of\ :wq"
    augroup END
endif

Upvotes: 0

vialrogo
vialrogo

Reputation: 121

I know, I know, it is a very old question, but I had the same question today and I found this post first. I developed a short script to put in .vimrc

function! ConfirmQuit(writeFile)
    if (a:writeFile)
        if (expand('%:t')=="")
            echo "Can't save a file with no name."
            return
        endif
        :write
    endif

    if (winnr('$')==1 && tabpagenr('$')==1)
        if (confirm("Do you really want to quit?", "&Yes\n&No", 2)==1)
            :quit
        endif
    else
        :quit
    endif
endfu

cnoremap <silent> q<CR>  :call ConfirmQuit(0)<CR>
cnoremap <silent> x<CR>  :call ConfirmQuit(1)<CR>

I hope this helps someone.

Upvotes: 12

zzapper
zzapper

Reputation: 5043

ConfirmQuit.vim : Provides a confirm dialog when you try to quit vim

http://www.vim.org/scripts/script.php?script_id=1072

I adapted this by using

autocmd bufenter c:/intranet/notes.txt cnoremap <silent> wq<cr> call ConfirmQuit(1)<cr>

As I only wanted this on this for a particular file

Upvotes: 3

Fabrizio Regini
Fabrizio Regini

Reputation: 1500

What you want is :close. It acts like :q but won't let you close the last window:

http://vimdoc.sourceforge.net/htmldoc/windows.html#:close

You can set an alias for the q command to map to close:

cabbrev q <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'close' : 'q')<CR>

Thanks @Paradoxial for this :cabbrev trick.

Upvotes: 15

user1655874
user1655874

Reputation:

You can use something like this to remove the :q command:

:cabbrev q <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'echo' : 'q')<CR>

This abbreviates q to echo in command mode, but doesn't allow the abbreviation to trigger if the q isn't in the first column. This way, edit q won't abbreviate to edit echo.

Upvotes: 6

Ingo Karkat
Ingo Karkat

Reputation: 172510

What are you afraid of? Vim won't let you quit (without a ! command modifier, anyway) when you still have unsaved changes, so the only thing you'll potentially lose is the window position, size, and maybe taskbar position of GVIM.

Anyway, to override built-in commands like :q, you can use the cmdalias plugin, like this:

:Alias q if\ winnr('$')>1||tabpagenr('$')>1||confirm('Really\ quit?',\ "&OK\\n&Cancel")==1|quit|endif

This checks for the last window (:q does not necessarily exit Vim), and inserts a confirmation.

Upvotes: 5

Related Questions