Skip to content

Instantly share code, notes, and snippets.

@bokwoon95
Last active April 14, 2019 13:15
Show Gist options
  • Save bokwoon95/2db266a35bd20f27ebbfefe1a355a603 to your computer and use it in GitHub Desktop.
Save bokwoon95/2db266a35bd20f27ebbfefe1a355a603 to your computer and use it in GitHub Desktop.
Vim/Nvim reusable terminal buffers(s)
fun! Term(...) abort
let l:currmax=0
let l:currwinnr=win_getid()
for l:bn in range(1,bufnr('$'))
let l:currbufname = bufname(l:bn)
let l:currshellnr = str2nr(bufname(l:bn)[10:-1])
if bufloaded(l:bn) && l:currbufname =~# "term:shell.*" && l:currshellnr != 0
if l:currshellnr > l:currmax
let l:currmax = l:currshellnr
endif
endif
endfor
" decide the terminal buffer's l:name
" if user provided an argument and it is not an empty string, use it
" if there was a terminal opened/closed before this, use its name
" else default to term:shell
let l:name =
\(a:0 > 0 && a:1 != "") ? "term:" . a:1 :
\exists("w:lasttermname") ? w:lasttermname :
\"term:shell".(l:currmax+1)
if bufwinnr(l:name) > 0
" if the terminal is open in a window, close it
execute bufwinnr(l:name) . "wincmd c"
elseif bufname('%') =~# "term:.*"
execute bufwinnr(bufname('%')) . "wincmd c"
else
" else open a new split
execute float2nr((winheight(0)*0.37)) . "split"
if bufexists(l:name)
" if the terminal buffer already exists, switch to it
execute "buffer " . l:name
else
" else open a new terminal buffer and rename it to l:name
execute has('nvim') ? "terminal" : "terminal ++curwin"
execute "file " . l:name
endif
" set this terminal buffer's name as the last interacted terminal buffer
call setwinvar(l:currwinnr, 'lasttermname', l:name)
endif
endfun
fun! s:termnames(ArgLead, CmdLine, CursorPos) abort
"obtain the list of available terminal buffers for autocompletion"
let l:termnames = []
for l:bn in range(1,bufnr('$'))
if bufname(l:bn) =~# "term:.*" && bufloaded(l:bn)
call add(l:termnames, bufname(l:bn)[5:-1])
endif
endfor
return filter(l:termnames, 'v:val =~ "^'. a:ArgLead .'"')
endfun
command! -nargs=? -complete=customlist,s:termnames Term silent call Term(<f-args>)
nnoremap <C-w><C-t> :call Term()<CR>
tnoremap <C-w><C-t> <C-\><C-n>:call Term()<CR>
" Usage
" Calling :Term will toggle open/close a terminal buffer. By default, the terminal buffer's name is 'shell'
" Specify a name for the terminal by calling :Term <name>.
" If no <name> is provided, :Term defaults to the name of the last terminal buffer opened or closed.
" You can open multiple terminal buffers by using different names
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment