7

I'd like to mimic the behaviour of i.e. TextMate and VScode and friends, in a GUI-vim: "closing" the last actual-content-window simply leaves me with an empty Vim window, and then "closing" that is what finally quits the actual editor.

In particular, I'd like to ensure that, when the last window is closed,

  1. If that window was attached to content or saved to disk: a new, empty buffer is created instead, so that Vim doesn't exit;
  2. If the current, last-closed buffer was empty and not saved to disk: Vim actually exits.

What's the most idiomatic way to achieve this?

(Bonus points: the above, but :Startify or some other plugin invocation, instead of an empty buffer)

4
  • 1
    QuitPre and ExitPre autocommand events may helps you.
    – Alex Kroll
    Jan 29, 2020 at 4:47
  • Also VimLeavePre, but not sure how you'd cancel quitting at that point... Also, how do you really quit if you have a hook like that?
    – filbranden
    Jan 29, 2020 at 4:55
  • 1
    There's this: stackoverflow.com/q/12556267/9447571 but all the solutions involve using cabbrev or cmap to catch :q and friends...
    – filbranden
    Jan 29, 2020 at 10:31
  • I'm actually not particularly interested in intercepting :q or friends; I'm happy to map, and learn, a new command for this. For reference, there's the vim-sayonara plugin; but that's almost precisely the opposite of what I want — I almost never delete buffers, I much prefer to keep then around, with their undo-histories and for :bufdo. Feb 5, 2020 at 18:06

2 Answers 2

8

This is something I wanted when I first started using Vim, but I no longer do. From looking at your account, I can see you've been using Vim for several years, but for the benefit of other readers who are new users, I thought I'd explain why I no longer feel the need for this.

Vim offers several different methods for closing windows and buffers, and these have slightly different behaviours. In my use, I know what my goal is, and so I run whichever command that will achieve it.

  • :q This will close a window, and, if it is the last window, it will quit Vim. So if I don't want to quit Vim, I don't run this command!

  • :bd This will delete a buffer, and in doing so, it will close any window that is currently displaying that buffer. But if you run it when you only have one window open, then Vim will not quit, and instead, one of your hidden buffers will be displayed. If you don't have any other buffers open, then a new, empty buffer will be displayed.

  • :%bd If you don't want to switch to another existing buffer, but instead want to close all visible and hidden buffers and start editing a new empty buffer, then you can pass a % range into the :bd command, to tell it to delete all your buffers.

  • :enew If I only have one window open and I have some other hidden buffers that I don't want closed, then I will instead use this command to switch from my current buffer to a new empty one.

  • :close or Ctrl-Wc Close a window, but if there is only one window remaining, don't close it. For some reason I sometimes use Ctrl-Wc to close a window instead of :q. It's not because of the difference in behaviour (if I only have one window open I don't ever use this command because I know it won't do anything!); it seems to be just what I feel like typing at the time.

So to address the actual question, when I only have one window open, I know in advance of running a command whether I want to:

  1. Start editing a new empty buffer, or
  2. Quit Vim.

For 2, I use :q. For 1, I use :enew, :bd, or occasionally :%bd.

2
  • I came by to snark "excuse me, I've been using Vim for decades", and then was very nonplussed and pleased to see that you'd already deduced that for yourself. Now I can only offer love. 😍 Feb 5, 2020 at 18:00
  • 1
    @ELLIOTCABLE Yep! I wrote the above presuming that you were already aware of and unsatisfied by it. But other people might not be, so I thought it was worth an answer. :)
    – Rich
    Feb 5, 2020 at 19:04
0

How about the following command? It doesn't implement your specifications precisely, but I think it should achieve your goals. (If not, let me know in what situations it doesn't work for you and I'll tweak it.)

function! Quit() abort
  if winnr('$') > 1 || getline(1, '$') == [''] && bufname('%') == ''
    quit
  else
    enew
  endif
endfunction

command Quit call Quit()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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