2

It was hard to phrase this as a question, but here is what I want to do:

I want vim to execute a process and to write to its stdin and read from its stdout file descriptors repeatedly. In other words, I want a back-and-forth dialogue between vim and another program.

I'll use cat as a simple example. If you run cat with no command-line arguments, then whatever you type on stdin is output to stdout after each newline character.

What I would like is to have a vim window which displays the most recent output of some program and to be able to write to its stdin upon certain events. So, unlike the following:

:read !cat

which waits for you to finish typing and press Ctrl-D to close cat's stdin, I want to display the output immediately after I press enter and to keep the process running so that I can type more.

Ultimately, I don't intend to be typing the input to the process; I want events (e.g. moving the cursor) to trigger vim to write specific commands to this process and display the output.

The reason I want the program to continue running instead of invoking the process once for each event is that the output to the program will be commands that generate state. If the program had to be invoked for each command, it would have to save the state to a file and read it in each time.

An alternative I am considering: writing the program to listen on a port. Then, vim invokes a command that simply opens the socket and passes the vim command to the program and returns the message from the program. This would require me writing two programs, though, which I hope is unnecessary.

What I am trying to do here is write a tool that analyses your code and provides an interactive command-line interface (e.g commands like that do things like "output a list of all the lines which set this variable). However, rather than running this program in a separate terminal or screen session, I would like vim to be able to integrate the output of this program in a window, if that is possible.

master_latch
  • 434
  • 5
  • 12
  • 1
    I'm not that sure about this, but I think this may be near impossible in vim due to certain underlying implementation limitations; something along the lines of not being able to properly deal will external processes? Either way, I think I would prefer your alternative port solution; other vim plugins work this way I believe. – Nate W. Feb 22 '14 at 23:14
  • I wish I could upvote this question twice! It's exactly what I want to do. – steveire Jan 11 '16 at 14:08
  • I use vim & perl code to communicate with vlc over tcpip sockets: http://vim.wikia.com/wiki/Vim_vlc_controller_and_lyric_synchronizer – mosh Mar 22 '18 at 11:55

1 Answers1

1

You should check out vimproc. You can use vimproc#popen3 to start the process. vimproc#popen3 returns an object(=dictionary) with a stdin member field that has a write method and a stdout member field that has a read method.

The problem is how to trigger the reading and writing. Vim is single thread, so you'll have to rely on autocmd events. Obviously you'll want to try reading whenever you write something(just in case), but you should also use the CursorHold event.

You can also use Python for IO. While it seems like you can use Python threading to trigger the reading, I would advise against it as Vim was never built for multithreading and from my experience, trying to hack multithreading into it with Python threads often causes race conditions and crashes Vim.

Idan Arye
  • 12,402
  • 5
  • 49
  • 68