Make a buffer active by its number
You can combine win_gotoid()
& win_findbuf()
to accomplish this:
:call win_gotoid(get(win_findbuf(g:tn), 0))
But we can do better for terminal like things by improving a few things:
- Automatically set our variable on
TerminalOpen
autocmd
- Provide methods to send text to the terminal
- Provide a command to jump to the term or open it
Add the following to your vimrc
or better yet ~/.vim/packages/bundle/start/send-to-term/plugin/send-to-term.vim
:
augroup sent_to_term
autocmd!
autocmd BufWinEnter,TerminalOpen * if &buftype ==# 'terminal' |
\ let t:sent_to_term_bufnr = +expand('<abuf>') |
\ endif
augroup END
function! s:term_op(type, ...)
let [sel, rv, rt] = [&selection, @@, getregtype('"')]
let &selection = "inclusive"
if a:0
silent exe "normal! `<" . a:type . "`>y"
elseif a:type == 'line'
silent exe "normal! '[V']y"
elseif a:type == 'block'
silent exe "normal! `[\<C-V>`]y"
else
silent exe "normal! `[v`]y"
endif
call s:send_to_term(@@)
let &selection = sel
call setreg('"', rv, rt)
endfunction
function! s:get_current_term(...)
if a:0
let bufnr = bufnr(a:1)
else
let bufnr = get(t:, 'sent_to_term_bufnr', 0)
endif
if bufnr > 0 && bufexists(bufnr) && getbufvar(bufnr, '&buftype') ==# 'terminal'
return bufnr
else
let v:errmsg = 'No Terminal'
throw "SendToTerm: " . v:errmsg
endif
endfunction
function! s:send_to_term(keys, ...)
let restore = bufnr('%')
try
let bufnr = call(function('s:get_current_term'), a:000)
silent execute 'b ' . bufnr
let lnum = line('$')
normal! G$mp
let keys = substitute(a:keys, '\n$', '', '')
call term_sendkeys(bufnr, keys . "\<cr>")
echo "Terminal: Sent " . len(keys) . " chars -> " . bufname(bufnr)
call setpos("'[", [bufnr, count(keys, "\n") + 1 + lnum, 1, 1])
catch /^SendToTerm:/
echohl ErrorMsg
echo "Error: " . v:errmsg
echohl None
finally
silent execute 'b ' . restore
endtry
endfunction
function! s:goto_term(...)
try
let bufnr = call(function('s:get_current_term'), a:000)
let winid = get(win_findbuf(bufnr), 0)
if winid > 0
call win_gotoid(winid)
else
execute 'sb ' . bufnr
endif
catch /^SendToTerm:/
echohl ErrorMsg
echo "Error: " . v:errmsg
echohl None
endtry
endfunction
command! -range -bar -nargs=? -complete=buffer SendToTerm call s:send_to_term(join(getline(<line1>, <line2>), "\n"), <f-args>)
command! -bar GotoTerm call s:goto_term()
nmap <script> <Plug>(send-to-term-line) :<c-u>SendToTerm<cr>
nmap <script> <Plug>(send-to-term) :<c-u>set opfunc=<SID>term_op<cr>g@
xmap <script> <Plug>(send-to-term) :<c-u>call <SID>term_op(visualmode(), 1)<cr>
With this you can use :GotoTerm
to jump to the last opened terminal buffer and use :SendToTerm
with a range to send a range of lines to the terminal buffer. I also provided <Plug>
mappings to send motions and visually selected text to the terminal.
nmap yrr <Plug>(send-to-term-line)
nmap yr <Plug>(send-to-term)
xmap R <Plug>(send-to-term)