vimfzfvim-fzf

Can't run a script with fzf from vim


I have a bash script that assembles some data, then pipes it through fzf for the user to choose, then manipulates the choice, then prints it to stdout.

This simulates the script:

#!/bin/sh
echo hello | fzf | sed 's/h/j/g'

This works great from the command line, but when running it from vim to include in the current buffer, the fzf TUI never displays, and I get ANSI escape sequences included in the result:

enter image description here

It doesn't matter how I run the command from vim. I've tried :read !{cmd}, :.!{cmd}, and even :let a=system('{cmd}').

For example, I would expect this to work:

:read !echo hello | fzf | sed 's/h/j/g'

fzf seems to be confusing stdout for a tty.

I know this isn't a limitation of vim, since if I substitute fzf for another interactive chooser with a tty, it works.

Is there an fzf or vim option to make this work?


Solution

  • Vim doesn't deal with interactive commands that easily. As you've seen, fzf outputs a lot of code to manipulate the display, and read is expecting a raw result.

    You can do this with execute instead of using read directly. Building off another answer ( Capture the output of an interactive script in vim ) but changing things up to work with fzf, I've modified @joshtch's solution to work with an arbitrary script, and checked that it works with fzf:

    my-fzf-script.sh:

    #!/bin/sh
    ls | fzf
    

    and the vim side of things:

    function! <SID>InteractiveFZFCommand()
        let tempfile=tempname()
        execute '!./my-fzf-script.sh >' . shellescape(tempfile)
        try
            silent execute 'read' tempfile
        finally
            call delete(tempfile)
        endtry
    endfunction
    
    command! -nargs=0 InteractiveFZFCommand call <SID>InteractiveFZFCommand()