1

So, to begin, this is similar to Pipe shell command into buffer in real-time.

The difference is that the top answer there pipes the output to a new buffer. How do I pipe the output to the editor itself in real time?

For example, I have this open in my vim (with line numbers on for illustration):

1 for num in "a" "b" "c"; do echo "${num}"; sleep 1; done
2
3
4

What I want is to be able to run a command that execute that line (something like yyp!!bash), and get these in the editor in the interval of 1 second:

1 for num in "a" "b" "c"; do echo "${num}"; sleep 1; done
2 a
3
4

then

1 for num in "a" "b" "c"; do echo "${num}"; sleep 1; done
2 a
3 b
4

then

1 for num in "a" "b" "c"; do echo "${num}"; sleep 1; done
2 a
3 b
4 c

Is this possible to do in vim?

Currently yyp!!bash will print the output only after the whole command is finished (i.e., only gets the output after three seconds).

Update

If that's not possible (as hinted in the comments), alternatively I would be interested in an editable terminal, essentially being able to edit the output (and the input) of :term.

5
  • For vim 8 we have :terminal command. Also :read !bash should works. :help read for explanations. I'm not sure is asynchronous input possible in vim.
    – Alex Kroll
    Commented Mar 20, 2019 at 12:13
  • You should read the entire file :help channel.txt. Perhaps it is doable.
    – Ralf
    Commented Mar 20, 2019 at 12:57
  • You are just trying to mimic an interactive shell behavior. But assuming you have recent enough neo/vim, you can just use another split for :h :terminal. Otherwise, r !cmd would write the output of cmd after the command is finished.
    – 3N4N
    Commented Mar 20, 2019 at 14:47
  • Yeah, essentially it's mimicking interactive shell behavior, but with editable command prompt and output buffer. I saw my friend doing this in emacs, so I also would like to do the same in vim (too costly to change to emacs now...), as I find it useful to run short commands and make sure the outputs are logged. At the very least, then, how to go to insert mode while in terminal opened by :term?
    – justhalf
    Commented Mar 20, 2019 at 15:23
  • maybe you can do it in python line by line(using subprocess) and use the vim lib for running commands (like insert) that will output it at real time.
    – eyal karni
    Commented Mar 20, 2019 at 16:52

3 Answers 3

1

You've clarified in the comments that your need would be satisfied if you could edit the output buffer and current command prompt when in a :terminal buffer.

You can achieve the latter by using your shell's "edit in an editor" function. In bash, this is called edit-and-execute-command and is usually bound to Ctrl-XCtrl-E (make sure your EDITOR variable is set). Other shells have similar features, although I haven't tested these.

Amazingly, this even works inside a :terminal buffer, spawning a new instance of Vim inside Vim.

Unfortunately, unless I'm misreading :help terminal.txt, it's not possible to edit the contents of a Vim terminal window.

Before looking into rolling your own solution, you might like to look into the Conque plugin. Whilst development on it has ceased, it's always worked well for me. To use it to run a bash shell you run the command:

:ConqueTerm bash

The new shell starts in insert mode. You can escape to normal mode by pressing Esc as usual, after which you can edit any output using regular Vim commands.

Entering insert mode while on the command line will return you to typing into the prompt, but you can still use edit-and-execute-command to edit the current command as I described above. The one proviso is that when you are in the Vim-inside-a-Vim in Conque, pressing Esc will exit insert mode of the outer instance of Vim. The easiest way to exit insert mode in the inner Vim is to press Ctrl-C instead, but setting up a mapping would also work.

All the above applies to Vim. I don't know what the situation is like in Neovim, which has it's own similar-but-different implementation of a terminal window.

1
  • 1
    when you need neovim inside a neovim :terminal buffer, it works really well if EDITOR is set to 'nvr' (neovim remote); then you reuse the same nvim instance and it just opens a new buffer Commented May 10, 2021 at 8:11
1

Well looking at your comments... Try to reuse built in :terminal either by manually copy-pasting to it or using plugin https://github.com/habamax/vim-sendtoterm

It might look like:

enter image description here

5
  • When you say "manually copy-pasting to it", are you referring to the OS copy? Or vim copy? How do you do that?
    – justhalf
    Commented Mar 22, 2019 at 15:43
  • I don't do it, I use plugin. But if I did I would use barebone vim copy paste like yy<C-w>w<C-r>", this is not tested though ;)
    – Maxim Kim
    Commented Mar 22, 2019 at 16:52
  • so, vim help tells me that it should be yy<C-w>w<C-w>"". Where yy copy current line to anonymous register, <C-w>w switch to next window (terminal in our case) then <C-w>"" insert contents of anonymous " register.
    – Maxim Kim
    Commented Mar 22, 2019 at 17:00
  • :h t_CTRL-W_quote
    – Maxim Kim
    Commented Mar 22, 2019 at 17:01
  • neovim is easier -- it is just p to paste
    – Maxim Kim
    Commented Mar 22, 2019 at 17:03
0

Nor in realtime, but you could do::

:0r !<c-r><c-l><cr>

The :0r means read into vim line 0. The exclamation mark says execute the following in the shell. Assuming your cursor is on the command to be executed <c-r><c-l> means fetches the current line into the command I am typing, then the final <cr> just means hits enter.

The result won't be read until all the sleeps/outputs have been completed.

Your Answer

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

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