neovim icon indicating copy to clipboard operation
neovim copied to clipboard

Exiting :terminal kills split

Open thewatts opened this issue 7 years ago • 28 comments

  • nvim --version: 0.1.4
  • Vim (version: ) behaves differently?
  • Operating system/version: OSX 10.11.6
  • Terminal name/version: iTerm 2 Build 3.0.5
  • $TERM: xterm-256color

Actual behaviour

Start: Run Neovim in a vertical split, with a file on each side. Next: Start a terminal session in the left split. Next: End that terminal session. Result: The left split gets closed along with the terminal session.

terminal-split

Expected behaviour

Start: Run Neovim in a vertical split, with a file on each side. Next: Start a terminal session in the left split. Next: End that terminal session. Result: The left split stays in-tact, with the previous file back in focus.

This is something that happens normally when closing out of a terminal session in a single window environment, ex:

terminal-single-window

Steps to reproduce using nvim -u NORC

nvim -u NORC

Same as above (happens without plugins enabled)

thewatts avatar Aug 06 '16 05:08 thewatts

I think it's because a special buffer is used for the terminal and it's the best way to make sure it's gone after the terminal session is over.

Here's what I wrote to keep the window after the terminal closes:

function! s:termclose() abort
  let buf = expand('#')
  if !empty(buf) && buflisted(buf) && bufnr(buf) != bufnr('%')
    execute 'autocmd BufWinLeave <buffer> split' buf
  endif
endfunction

autocmd TermClose *:$SHELL,*:\$SHELL call s:termclose()

When you run :terminal without arguments or with $SHELL, it'll switch to the alternate buffer right before it closes. You may want to look at the full script because I also capture the last two screens of text in a register in case I lose the buffer prematurely: term.vim

tweekmonster avatar Aug 06 '16 05:08 tweekmonster

@tweekmonster thanks for that!

The fact that the terminal buffer is special could definitely be an indicator. However, there doesn't seem to be an issue bringing the previous buffer back into play when only running a single window. I wonder why that would be?

As for the code you provided, the buffer return seems to work like a charm :)! Many Thanks! Although - on your end, does the original file come back without any syntax highlighting?

thewatts avatar Aug 06 '16 05:08 thewatts

Although - on your end, does the original file come back without any syntax highlighting?

Does the highlighting change for you? I'm not seeing that. I'm using 0.1.5.

tweekmonster avatar Aug 06 '16 15:08 tweekmonster

@tweekmonster Yeah, it's odd. If I run :e on the file after it's loaded back in - the color comes back.

Currently running 0.1.4

color-loss

thewatts avatar Aug 06 '16 16:08 thewatts

Maybe try adding this after the split?

execute 'doautocmd FileType' buf

tweekmonster avatar Aug 06 '16 17:08 tweekmonster

Hey @tweekmonster! I really appreciate your willingness to help me with this!

When putting the line executre 'doautocmd FileType' buf into the function, I get this error:

E474: Invalid argument: syntax=config/routes.rb I checked the syntax= function for vim. It looks like it basically is just taking in a syntax specification.

config/routes.rb is the path to the file that is being re-opened in the split.

After the error, the file is still without color (which I assume is because the error itself is blocking it).

My vim-fu isn't very strong - so I apologize if I'm missing something here!

Here's the code I have with your suggested addition:

function! s:termclose() abort
  let first = max([1, line('w0') - winheight(0)])
  call setreg('t', getline(first, line('$')), 'V')
  let buf = expand('#')
  if !empty(buf) && buflisted(buf) && bufnr(buf) != bufnr('%')
    execute 'autocmd BufWinLeave <buffer> split' buf
    execute 'doautocmd FileType' buf
  endif
endfunction

thewatts avatar Aug 07 '16 00:08 thewatts

Oh, that was wrong. Try it with:

execute 'doautocmd FileType' getbufvar(buf, '&filetype')

tweekmonster avatar Aug 07 '16 00:08 tweekmonster

@tweekmonster really appreciate the help! That wasn't the ticket, unfortunately.

The file still comes up without any color. I tried to automate the process of calling :edit on the file (essentially reloading it - fixing the colors) once the buffer had been loaded - but that didn't work either.

thewatts avatar Aug 07 '16 02:08 thewatts

I may have to wait until 0.1.5 ships to see if that's the fix.

thewatts avatar Aug 07 '16 03:08 thewatts

0.1.5 is already released.

Shougo avatar Sep 17 '16 05:09 Shougo

This is still occurring in 0.1.5 for me.

dubiousdavid avatar Nov 04 '16 02:11 dubiousdavid

This is just how :bdelete works, it's not unique to terminal buffers. When you press a key to close the terminal buffer, it essentially :bdeletes the buffer, which takes the window with it.

When the [Process exited ..] message appears, press <C-\><C-N> to get to normal mode, then do whatever you would do to visit another buffer in the same window.

However, I added this to https://github.com/neovim/neovim/issues/5431.

justinmk avatar Nov 04 '16 10:11 justinmk

I'm wondering about the ratio of times I'd have needed the :term output later on (like :cl for :make), versus how many times it's really just a fire-and-forget.

Would it make sense to keep the buffer around a bit, and/or perhaps recycle it for the same command (a similar one/another one with some identical ID?) instead of allocating fresh buffers all the time?

I've already ended up with buffer numbers ~600, and even if only a few of them are still alive it would be easier to navigate if the buffer numbers were kept as small as possible.

phmarek avatar Nov 09 '16 12:11 phmarek

@phmarek Check out neoterm.

tweekmonster avatar Nov 09 '16 13:11 tweekmonster

Personally I think this would be great, I don't know why the terms are treated so differently to other buffers.

Thanks guys

Cypher1 avatar Nov 09 '16 13:11 Cypher1

As @justinmk explained above the terminal buffers are behaving normally. I never realized before that :bdelete also closes the buffer window because usually I just :quit. Maybe #8975 is The Right Thing to Do? My rationale is that in that way there's no need to handle :bdelete in a special way when the buffer is a terminal

tssm avatar Sep 10 '18 14:09 tssm

Is there any plan to fix this? Really annoying difference from vim's :shell command which returned to the previous buffer. I need to make sure to open a new split first before using :terminal or I lose my position.

mlindner avatar Oct 26 '18 00:10 mlindner

@mlindner The plan is to work on this when someone finds time or a patch magically appears. It's currently marked for the 0.4 milestone.

justinmk avatar Oct 26 '18 01:10 justinmk

I implemented a patch for this here: https://github.com/neovim/neovim/pull/15442 But there were concerns about backward compatibility with plugins. If somebody else wants to pick up that PR where I left off and address those concerns we should be able to find a solution to this.

gpanders avatar Sep 01 '22 19:09 gpanders

This issue has been mentioned on Neovim Discourse. There might be relevant details there:

https://neovim.discourse.group/t/stop-terminal-buffer-from-auto-closing-window/3849/1

neovim-discourse avatar Mar 30 '23 08:03 neovim-discourse

Oops, I just realized that I encountered this same requirement days ago to upgrade one of my plugins. In short, the workaround is to call split or vsplit inside the WinClosed buffer-local autocmd.

I did feel that things could be a lot easier if upstream could provide this functionality be default.

nyngwang avatar Mar 30 '23 08:03 nyngwang

@nyngwang 🤔 Simply adding this block doesn't change things for me. Would be nice if you could provide a full code sample?

mar-muel avatar Mar 30 '23 14:03 mar-muel

@mar-muel Hi, sorry for causing any confusion. You're right that it doesn't work in other cases.

UPDATE: I found a new general way after some trying: (to try it simply delete/comment-out the two group=) The only problem now is that it doesn't record the buffer on enter before you call :term.

Click to expand
vim.api.nvim_create_autocmd({ 'TermOpen' }, {
  group = curfile_augroup,
  callback = function ()
    local cur_buf = vim.api.nvim_get_current_buf()
    vim.api.nvim_create_autocmd({ 'WinClosed' }, {
      buffer = cur_buf,
      group = curfile_augroup,
      once = true,
      callback = function ()
        vim.api.nvim_set_current_buf(vim.api.nvim_create_buf(true, false))
        vim.cmd('split')
      end,
    })
  end,
})

https://user-images.githubusercontent.com/24765272/228893605-c048f3ab-4007-4c31-a951-4501c3885261.mov

nyngwang avatar Mar 30 '23 15:03 nyngwang

Cool - yes, it does work! Unfortunately, I get issues with Telescope afterwards. Maybe something that is specific to my setup...

E5108: Error executing lua ...are/nvim/plugged/plenary.nvim/lua/plenary/popup/init.lua:408: Vim(let):E716: Key not present in Dictionary: "rhs"
stack traceback:
        [C]: in function 'nvim_set_current_win'
        ...are/nvim/plugged/plenary.nvim/lua/plenary/popup/init.lua:408: in function 'create'
        ...re/nvim/plugged/telescope.nvim/lua/telescope/pickers.lua:327: in function '_create_window'
        ...re/nvim/plugged/telescope.nvim/lua/telescope/pickers.lua:397: in function 'find'
        ...m/plugged/telescope.nvim/lua/telescope/builtin/__git.lua:54: in function 'v'
        ...m/plugged/telescope.nvim/lua/telescope/builtin/__git.lua:412: in function 'v'
        ...im/plugged/telescope.nvim/lua/telescope/builtin/init.lua:514: in function 'git_files'
        /Users/martin/.config/nvim/lua/usr/telescope.lua:6: in function 'project_files'
        [string ":lua"]:1: in main chunk

mar-muel avatar Mar 30 '23 15:03 mar-muel

@mar-muel Yup, it also breaks my fzf-lua, which is a similar alternative to Telescope, on closing its floating terminal buffer so I believe more hotfixes/conditions/etc need to be added to it.

UPDATE: This solves it: (but again, we still need to find a way to restore the non-terminal buffer where we call :term)

      callback = function ()
+       if vim.bo.filetype == 'fzf' then return end -- in my case fzf-lua terminal buffer has filetype `fzf`.
        vim.api.nvim_set_current_buf(vim.api.nvim_create_buf(true, false))
        vim.cmd('split')
      end,

nyngwang avatar Mar 30 '23 15:03 nyngwang

Yeah, overall, I foresee too many of these types of issues. Would be very nice if there was an upstream fix in neovim for this.

Although if someone finds a fix for telescope, that would be very much appreciated.

mar-muel avatar Mar 30 '23 16:03 mar-muel

Although if someone finds a fix for telescope, that would be very much appreciated.

@mar-muel You could try this: if vim.bo.filetype == 'TelescopePrompt' then return end as a temporary workaround. Or maybe if vim.bo.filetype ~= '' then return end so any plugin that follows the good principle to set a custom filetype for its own things will be skipped by the autocmd.

nyngwang avatar Mar 30 '23 16:03 nyngwang

If one only needs to mimic Vim's :shell, then :tabe +term kind of works

iam28th avatar Apr 26 '24 06:04 iam28th