Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send buffer to a running terminal window in vim 8

Tags:

terminal

vim

Is it possible to send the contents of a buffer to a running terminal window. That window can be running e.g a REPL for python code.

I mean the new terminal feature of VIM rather than external plugins or previous versions.

like image 248
Stagrovin Avatar asked Mar 16 '18 10:03

Stagrovin


People also ask

How do I open a terminal window in Vim?

Opening instance of Terminal within Vim. The terminal can be opened in various ways the most preferred way is by typing in :term from Vim. This will create a horizontal split from the current editor and split it into half. You can change the size of the split using the mouse according to your preference.

How do I switch between NVIM and terminal?

Use ctrl-w N to switch to "terminal-normal mode", which will let you navigate around. It could be useful to then copy content to the clipboard. Then return to regular terminal mode, simply type i just like how you'd enter insert mode from a regular window. ctrl-w : will open command mode like in regular Vim.

How do I close a terminal buffer in Vim?

You can just press Ctrl + D in terminal to close it. But if you don't want to close it, just want to switch windows you can do Ctrl-W w (if you have multiple panes you can specify to which you switch with the seccond letter (h,j,k,l), W just switches vim windows.

Can Vim be used as a terminal?

Vim is used on a terminal, and to use the terminal, you'll have some command line interpreter which executes commands to do things like changing your current directory, listing all files in the current directory, copying a file, removing files, etc.


1 Answers

You can use term_sendkeys() to send data to a terminal buffer. However there are some considerations:

  • Need to capture data to use term_sendkeys() often this is via yanking text
  • Need to know which terminal buffer to send to

Here is some code simplify and automate the send to terminal buffer workflow. Put inside vimrc file or make a small plugin.

augroup send_to_term
  autocmd!
  autocmd TerminalOpen * if &buftype ==# 'terminal' |
        \   let t:send_to_term = +expand('<abuf>') |
        \ endif
augroup END


function! s: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:send_to_term(keys)
  let bufnr = get(t:, 'send_to_term', 0)
  if bufnr > 0 && bufexists(bufnr) && getbufvar(bufnr, '&buftype') ==# 'terminal'
    let keys = substitute(a:keys, '\n$', '', '')
    call term_sendkeys(bufnr, keys . "\<cr>")
    echo "Sent " . len(keys) . " chars -> " . bufname(bufnr)
  else
    echom "Error: No terminal"
  endif
endfunction

command! -range -bar SendToTerm call s:send_to_term(join(getline(<line1>, <line2>), "\n"))
nmap <script> <Plug>(send-to-term-line) :<c-u>SendToTerm<cr>
nmap <script> <Plug>(send-to-term) :<c-u>set opfunc=<SID>op<cr>g@
xmap <script> <Plug>(send-to-term) :<c-u>call <SID>op(visualmode(), 1)<cr>

You can make setup your own mappings. Example:

nmap yrr <Plug>(send-to-term-line)
nmap yr <Plug>(send-to-term)
xmap R <Plug>(send-to-term)

You can now use :[range]SendToTerm to send a [range] of lines to the last used terminal buffer in a tab-page. You can also use yrr to send a line, yr{motion} to send a {motion} text, or use R to send visually selected text to the terminal buffer. Note: You must have a terminal buffer opened beforehand in the current tab-page.

like image 120
Peter Rincker Avatar answered Sep 22 '22 07:09

Peter Rincker