Is there a way to use a read filter that calls an interactive command?

My use case is a grep command that returns a long list of tags that I might want to include in a blog post; I was hoping to be able to filter it with fzf, something like:

:r ! grep foo bar.txt | fzf -m

Unfortunately this doesn't show the interactive fzf prompt, seems to freeze, and when killed with Ctrl-c reads a bunch of gibberish into the buffer.

Trying a more simple example, this reads foo into the buffer:

:r ! { myvar=foo; echo "${myvar}"; }

This doesn't work:

:r ! { read myvar; echo "${myvar}"; }

I thought perhaps it was an issue with stdin so I also tried (without success):

:r ! { read -u 3 myvar 3<&0; echo "${myvar}"; }

Am I going about this wrong?

  • Well, for one thing the output of the commands following :r ! are written to a temporary file (whose contents are inserted into the buffer when execution completes). Using an interactive command when you can't see any output isn't very useful. :)
    – B Layer
    Nov 4 '21 at 16:24
  • (cont.) Even if you could interact with something like fzf anything and everything it writes to stdout or stderr (e.g. a copy of its listing for each time the list changes/refreshes) is going to be captured and inserted into the buffer.
    – B Layer
    Nov 4 '21 at 16:48
  • @BLayer thanks for your input! Yes, I saw the notes about the tempfile in :help filter. I wonder if there's a way to redirect the fzf output into the same temporary file.
    – n8henrie
    Nov 4 '21 at 17:35
  • @BLayer Got it, see below.
    – n8henrie
    Nov 4 '21 at 17:37
  • Cool. That's why I wrote a comment and not an answer...I couldn't rule out a fix/workaround that would meet your needs. :)
    – B Layer
    Nov 4 '21 at 17:47

On MacOS and Linux, this seems to work in vim (but not neovim):

:set noshelltemp

Afterwards this works as hoped.

:r ! echo -e 'foo\nbar\nbaz' | fzf -m

It’s probably easier to run your commands with :terminal (which is fully interactive) and then paste things you need out of the new window.

FWIW, on macOS with vim, the following works (though the UX is odd):

:read !read && echo "$REPLY"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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