0

If I close all buffers, I'm left with the terminal window, which automatically opens whenever I open Vim.

I would like it close automatically when I exit Vim.

I see that on the NERDTree repo, they included a code that will automatically close NERDTree if it is the last window:

" Exit Vim if NERDTree is the only window remaining in the only tab.
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif

I want similarly that: if the terminal window is the last window, Vim close it automatically.

Edit: If the terminal window and NERDTree are the last windows, I want them both to close automatically.

Because I do not want to quit them manually every time I finish editing. In addition, I have the following code for NERDTree in my vimrc:

" Exit Vim if NERDTree is the only window remaining in the only tab.
autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif

" Close the tab if NERDTree is the only window remaining in it.
autocmd BufEnter * if winnr('$') == 1 && exists('b:NERDTree') && b:NERDTree.isTabTree() | quit | endif
8
  • Welcome to Vi and Vim! Have you tried adapting the code you posted and run into some issue? Or are you not sure how to adapt it?
    – D. Ben Knoble
    Feb 7, 2023 at 13:02
  • Could you tell us what is your Operating System (Windows, Linux)? On Windows to close Vim I believe we have to exit the terminal and not only close the corresponding buffer. Feb 7, 2023 at 13:13
  • I use vim on MacOS, Vivian De Smedt.
    – Jimmy Zeng
    Feb 8, 2023 at 8:22
  • Is the solution proposed solving your problem? How can we help you more? Feb 12, 2023 at 17:40
  • 1
    I have NERDTree as well, so by default NERDTree and the terminal open. Because I have NERDTree as well, I want them to close automatically when there are no more editors.
    – Jimmy Zeng
    Feb 14, 2023 at 12:05

2 Answers 2

2

Here is a more sophisticated solution.

It try to close Vim if the only visible windows are 'side bars' (buffer that don't contains 'real' document) like:

  • Terminal
  • QuickFix window
  • LocationList window
  • Help window
  • NERDTree side bar
  • UndoTree side bar
  • Read Only buffers
function! IsSideBar(buf_nr)
  " Returns 1 if the buffer is actual a side bar
  " - A terminal
  " - The NERDTree side bar
  " - The QuickFix window
  " - The Help window
  " - The UndoTree side bar
  " - ...
  let buf_name = bufname(a:buf_nr)
  let buf_type = getbufvar(a:buf_nr, '&filetype')
  let readonly = getbufvar(a:buf_nr, '&readonly')

  let term_buffers = term_list()

  if readonly
    return 1

  elseif buf_type ==# 'qf'
    " QuickFix, LocationList:
    " Not Read Only
    return 1

  elseif buf_type ==# 'help'
    " Read Only
    " Help Window:
    return 1

  elseif buf_type ==# 'undotree'
    " Not Read Only
    return 1

  elseif buf_type ==# 'nerdtree'
    " Read Only
    return 1

  elseif index(term_buffers, a:buf_nr) >= 0
    return 1

  else
    return 0

  endif
endfunction

function! GetNumWindows()
  " Returns the number of window that are not side bars
  let num_windows = 0
  for win_nr in range(1, winnr('$'))
    let buf_nr = winbufnr(win_nr)

    if IsSideBar(buf_nr)
      continue
    endif

    let num_windows = num_windows + 1
  endfor

  return num_windows
endfunction

function! KillSideBars()
  let num_windows = GetNumWindows()
  if num_windows > 0
    " If there are some non side bar windows do nothing:
    return
  endif

  " Delete the terminal buffers that don't correspond to a window
  let term_buffers = term_list()
  for buf_nr in term_buffers
    if len(win_findbuf(buf_nr)) == 0
      " Exit terminal not associated to a window
      execute 'bd! ' . buf_nr
    endif
  endfor

  let term_buffers = term_list()
  let buf_nr = bufnr('%')
  if index(term_buffers, buf_nr) >= 0
    " Kill the terminal buffer and quit
    call feedkeys("\<C-w>:bd!\<CR>:quit\<CR>:\<BS>")
  else
    " Kill the side bar window
    call feedkeys(":quit\<CR>:\<BS>")
  endif
endfunction

autocmd BufEnter * call KillSideBars()

8
  • Thanks! It does my thing, but sometimes it delays my exit with an error Error detected while processing BufEnter Autocommands for "*":.
    – Jimmy Zeng
    Feb 21, 2023 at 1:42
  • Does it prompt you? Can you reproduce the problem with a minimal .vimrc file. Feb 21, 2023 at 4:58
  • It automatically tells me this and then disappears about half a second later
    – Jimmy Zeng
    Feb 22, 2023 at 10:01
  • Here is my .vimrc, at least the significant parts to it:
    – Jimmy Zeng
    Feb 22, 2023 at 10:03
  • Thanks @Jimmy, I'm willing to help you but I need to reproduce the problem. If you could give a minimal Vim configuration and instruction to reproduce the problem I could have a look. But with just the description of the symptom I can't reproduce it and it is difficult for me to solve it. Feb 22, 2023 at 10:04
2

I would do:

autocmd BufEnter * if tabpagenr('$') == 1 && winnr('$') == 1 && &buftype ==# 'terminal' | bd! | q | endif

Compare to the NerdTree solution we do:

  • Check that the last buffer is a terminal buffer (&buftype ==# 'terminal')
  • Force to delete that buffer even it has been modified (bd!)

Your Answer

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

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