19

Recently there was an add-on to NeoVim which allows opening terminal in a vim buffer. This has appealing possibilities to send text from one vim window to another replicating, for example, a REPL like behavior.

In the past I was using tmux for this kind of configuration. However now I would like to try it out using only NeoVim.

My question is - how can I send a block of text from one vim split to another? Or maybe rather - how can I automate the sequence of selecting text, yanking it, changing splits and then pasting?

4 Answers 4

17

Basically when you have text selected, you want to remap a key sequence to copy, switch to terminal, paste, and then possibly switch windows back and reselect the text. If you have two splits open, this would look something like:

vnoremap <F5> y<c-w>wp<c-w>pgv
"explanation:
xnoremap <F5>                   Remap F5 in visual/select mode (could be any key combo)
              y                 copy selected text
               <c-w>w           switch to next window
                     p          paste (for terminals this sends the text to the terminal)
                      <c-w>p    switch to previous window
                            gv  reselect

If there are more than two splits and the terminal is not the one after where your text is selected, you'd want to either use a different mapping that works for your layout (i.e. <c-w>t moves to the top left window) or you'd want to write a function that loops through all windows and finds the right one.

2
  • From what I can see, using p in a terminal buffer does not enter Terminal mode, so the following <C-\><C-N> should not be necessary. (That said, it's also totally harmless.)
    – tommcdo
    Mar 28, 2015 at 0:27
  • @tommcdo good call, hadn't tried the feature myself yet so was just taking a shot. I'll remove that part.
    – Matt Boehm
    Mar 28, 2015 at 4:32
18

Neovim terminal buffers always have an associated job id, so one way is to use the job control API to send the text. Add this to your vimrc:

augroup Terminal
  au!
  au TermOpen * let g:last_terminal_job_id = b:terminal_job_id
augroup END

Which will save the the job id of the last created terminal into the g:last_terminal_job_id variable. Then you can create some functions/commands/mappings that will send the data using the jobsend function, here's an example:

function! REPLSend(lines)
  call jobsend(g:last_terminal_job_id, add(a:lines, ''))
endfunction

command! REPLSendLine call REPLSend([getline('.')])

nnoremap <silent> <f6> :REPLSendLine<cr>

The above would send the current line, but you can extend it to send visual selection.

2

Neoterm is a plugin for neovim that is developed for this purpose. It implements a new command :TREPLSend which will take the current line and send it to a terminal window. Works fine for basic bash and any language that has a REPL mode.

2

In addition to the answers here I have implemented a plugin for this purpose: vim-sendtowindow.

It provides a send-to-window operator that can be combined with any vim motion in order to select text for sending to the adjacent window. In addition it conveniently positions the cursor after the sent text and is dot repeatable.

A small example below:

example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.