I'd like to use Vim in the middle of a pipe. This existing post looks like what I'd like to do, except I was hoping to do it without Python's help -- only with bash. [It it helps, the environment is the bash shell in the Terminal IDE app on Android.]
Please, I know how to pipe a buffer through a command from inside Vim. That's great, but not what I want here. I want to exit Vim and pass the active buffer to stdout.
FWIW, I also know how to pass another command into Vim as input. Again, that's not what I'm trying to get here.
Take a look at vipe
which is part of moreutils
. It allows you to use any editor as part of a pipe.
ls -al | vipe | less
To use it with vim
just make sure to set it as your default editor in your bashrc
or cshrc
or whatever shell you use.
EDITOR=vim
UPDATE: If you want a bash
only solution you could use a script like this
#!/bin/bash
# create temporary file
TMPFILE=`mktemp /tmp/vipe.bashXXXXXXXX`
cat > ${TMPFILE}
vim ${TMPFILE} < /dev/tty > /dev/tty
cat ${TMPFILE}
rm ${TMPFILE}
For a more portable version please replace
vim ${TMPFILE}
with
${EDITOR} ${TMPFILE}
To print buffer to shell standard output, vim
needs to start in Ex mode, otherwise it'll open "normal" way with its own window and clear any output buffers on quit.
Here is the simplest working example:
$ echo foo | vim +%p -escq /dev/stdin
foo
which is equivalent to:
$ echo foo | vim -es '+%print' '+:q!' /dev/stdin
foo
Special file descriptor to standard input needs to be specified (/dev/stdin
) in order to prevent extra annoying messages.
And here are some examples with parsing strings:
$ echo This is example. | vim '+s/example/test/g' '+%p' -escq! /dev/stdin
This is test.
$ echo This is example. | vim - '+s/example/test/g' '+%p' -escq!
Vim: Reading from stdin...
This is test.
Related:
You cannot simply put vim inside a pipe, because then Vim cannot display its UI.
ls | vim - | more # Does not work
One way to solve this is to use gvim -f -
inside the pipe, as it opens in a separate window. You need to write the file via :w >> /dev/stdout
and then :quit!
.
Alternatively (and the only way in a console-only non-graphical environment), you could write your own script / function vimAndMore
that takes the command that should be following vim in the pipe as an argument, and goes like this:
vimAndMore()
{
TMPFILE=/tmp/pipecontents
# Slurp stdin into the temp file.
cat - > "$TMPFILE" || exit $?
# Reconnect stdin to the terminal, so that Vim doesn't complain with "Warning:
# Input is not from a terminal", and the terminal is kept intact.
exec 0</dev/tty
# Launch the editor.
"${EDITOR:-vim}" "$TMPFILE" || exit $?
# Carry on with the pipe.
cat "$TMPFILE" | exec "$@"
rm "$TMPFILE"
}
And change the pipe to this:
ls | vimAndMore | more
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With