4

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?

n8henrie
  • 406
  • 1
  • 5
  • 9
  • 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 04 '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 04 '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 04 '21 at 17:35
  • @BLayer Got it, see below. – n8henrie Nov 04 '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 04 '21 at 17:47
  • Out of curiosity I tried that in both Cygwin and Linux. The former is basically unusable and the latter is kind of janky...typing fast sometimes loses characters, for one thing. If it works well for you on MacOS, though, more power to you! – B Layer Nov 04 '21 at 17:56
  • Huh, it's working great for me on Linux, including typing a few sentences at ~100 WPM -- no missed letters. When testing with read I agree it's odd that it overwrites the current command line (even with clear; first), but it works great with fzf. – n8henrie Nov 04 '21 at 18:22
  • Interesting. I was testing with fzf, too. Could be a matter of us using a different Linux flavor or terminal emulator or who knows what. Regardless, have fun! – B Layer Nov 04 '21 at 18:25
  • If you configure ag for vim you have the command :Ag that might be what you want. – mattb Nov 04 '21 at 18:27

2 Answers2

1

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
n8henrie
  • 406
  • 1
  • 5
  • 9
0

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"
D. Ben Knoble
  • 26,070
  • 3
  • 29
  • 65