Vim – How to Invoke Vim Editor and Pipe Output to Bash

pipestdoutvim

Sometimes I need to write text and then pipe that text into another command. My usual workflow goes something like this:

vim
# I edit and save my file as file.txt
cat file.txt | pandoc -o file.pdf # pandoc is an example 
rm file.txt

I find this cumbersome and seeking to learn bash scripting I'd like to make the process much simpler by writing a command which fires open an editor and when the editor closes pipe the output of the editor to stdout.
Then I'd be able to run the command as quickedit | pandoc -o file.pdf.

I'm not sure how this would work. I already wrote a function to automate this by following the exact workflow above plus some additions. It generates a random string to act as a filename and passes that to vim when the function is invoked. When the user exits vim by saving the file, the function prints the file to the console and then deletes the file.

function quickedit {
    filename="$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32)"
    vim $filename
    cat $filename
    rm $filename
}
# The problem:
# => Vim: Warning: Output is not to a terminal

The problem I soon encountered is that when I do something like quickedit | command vim itself can't be used as an editor because all output is constrained to the pipe.

I'm wondering if there are any workarounds to this, so that I could pipe the output of my quickedit function. The suboptimal alternative is to fire up a separate editor, say sublime text, but I really want to stay in the terminal.

Best Answer

vipe is a program for editing pipelines:

command1 | vipe | command2

You get an editor with the complete output of command1, and when you exit, the contents are passed on to command2 via the pipe.

In this case, there's no command1. So, you could do:

: | vipe | pandoc -o foo.pdf

Or:

vipe <&- | pandoc -o foo.pdf

vipe picks up on the EDITOR and VISUAL variables, so you can use those to get it to open Vim.

If you've not got it installed, vipe is available in the moreutils package; sudo apt-get install moreutils, or whatever your flavour's equivalent is.

Related Question