Help managing terminal buffers

I really like neovim terminal implementation. Previously I used tmux when coding and managing my systems some windows would be neovim and some tmux.

But after I started using the builtin terminal I felt It was a way better experience for me, because I can copy and paste things around using the registers, search and highlight the output of a command, organize the windows around. Hide it and bring it back since It’s just a buffer.

But I’m also looking for ways to improve the workflow, I currenlty have some mapping I’m happy with.

But I do have one thing I would like to improve. I sometimes have over 5 terminal buffers open because I’m sshing into other machines and I’m not looking at them so they are hidden and that’s great. The problem I have is finding them. Since all therminal buffers are named like: term://~//51266:/usr/bin/zsh I understand this is to make it easy to restore sessions since the buffer name contains the command being run.

But at the same time this makes it very hard to distinguish between terminal buffers (pretty much all are going to be named /usr/bin/zsh/ for me). I believe the buffer names cannot be changed. But I’m looking for alternatives.

I’ve tried previewing them with teslescope.nvim which does not work for me. Also tried with fzf.vim and also not possible.

I’ve found this issue in which someone also wants something different, like when you have a terminal window in linux and it changes the window title to the command you’re running. Would be really useful.

1 Like

If you’re ok with giving up using the command :term one option would be:

  1. create the command :Term which wraps :terminal and add the buffer/window ID to a global table and stores it with a more informative name (you can get creative with vim.fn.regex and vim.split()
  2. Add autocompletion to :Term to show only the buffers listed in that global table. You can do this by adding the flag -complete=custom,v:lua.my_terminal_tables. See :help command-complete for more details on this.
  3. Write a telescope extension to search that global table, which would let you select/filter only those buffers. I think there is a way to inject those results into the telescope buffer search.
3 Likes

It might be easier to use NeoTerm or Iron.nvim, which both do some terminal buffer bookkeeping for you.

However I’m not sure if either of them specifically lets you e.g. load all terminal buffers into the quickfix list, or assign friendlier names to terminal buffers.

2 Likes

Check out Floaterm, and you can set up to use FZF to quickly find your floaterm terminals.
I map Capslock to a kind of hyperkey, so among many other neat things:
Capslock - I → Home → Toggle Floaterm
Capslock - I -Command → Shift-Home → New Floaterm
Capslock - O → End → Next Floaterm
Capslock - O - Command → Shift-End → Next Floaterm reversed
Capslock - U → PageUp → Exit terminal mode or Scroll up in normal mode (So Capslock -U twice will get me scrolling up my terminal buffer, super neat)
Capslock - P → PageDown → Scroll down

4 Likes

not sure if you want to go this route but if you do a “buffers as tabs” approach you can very quickly cycle through your terminals to quickly visually find your terminal.

Setup:

Plug 'akinsho/nvim-bufferline.lua'

" NOTE: Must go after plug#end()
" see :help bufferline for other options
:lua << EOF
  require'bufferline'.setup{
    -- override some options from their defaults
    options = {
        tab_size = 10,
        show_buffer_close_icons = false,
    }
  }
EOF

" MAPPINGS
" NOTE: a is alt, s is shift
" These commands will cycle through your buffer tabs and honor the custom ordering if you change the order of buffers.
" The vim commands :bnext and :bprevious will not respect the custom ordering.
nnoremap <silent><a-l> :BufferLineCycleNext<CR>
nnoremap <silent><a-h> :BufferLineCyclePrev<CR>

" These commands will move the current buffer tab backwards or forwards in the list of buffer tabs.
nnoremap <silent><a-s-l> :BufferLineMoveNext<CR>
nnoremap <silent><a-s-h> :BufferLineMovePrev<CR>

" kill buffer tab
nnoremap <silent> <a-q> :silent! up! <bar> silent! bd! <bar> call BufferLineCycleNext() <cr>

Cycle through buffers, re-organize buffers, kill buffers
all

for others reading, if you dont want terminal buffers polluting your tabs add:

" Add the terminal to unlisted buffers so that buffer line doesnt show it
" NOTE: Tried all the Buf* stuff but only this one seemed to work
" and so it only gets removed from buffer tabs when you leave the terminal
autocmd BufLeave bash* setlocal nobuflisted
2 Likes

Pretty cool answer all of them thank you all! Will look into each one and let everyone know what I ended up doing!

Neovim has the b:term_title buffer variable on terminal buffers, this updates as terminal programs change the terminal title (echoing an escape sequence). This is the same method that terminal programs can use to set the title of terminal windows in any other terminal emulator.

Assuming that your ssh client or host changes the terminal title to something that is useful to you, then looking at b:term_title for all your terminal buffers should give you what you want. If they don’t then you could script something to do it and this would work in Neovim or in other terminals.

This is a one-liner that lists all terminal buffer ids with their term_title. That might help as a starting point.

echo join(map(filter(nvim_list_bufs(), {i,v -> getbufvar(v,"&buftype") == 'terminal'}), {i,v -> [v,getbufvar(v,"term_title")]}), "\n")

5 Likes

That’s great. I had not red the “Status Variable” section on the help manual. That’s just what I need, I can use the titles to better distinguish them with simple function, can also use Telespoce for it. Thanks!

Do you mind sharing your current configs and mapping? I’m looking for a more lightweight, to replace or in addition to floaterm for regular non-floating terminals.