One of the great things about Vim is how nicely it integrates with the Unix shell. I love the fact that all the cool unix commands are only a few keystrokes away. For example, when writing README or HOWTO files I often like to generate nice looking headings via:
:r!figlet Readme Title
Sometimes I use vim as a hex-viewer by doing:
Unfortunately, none of that works on windows. Whenever I work on my home desktop, I find myself missing the ability to escape to bash and do some quick unix thing. It is doubly frustrating, seeing how I already to have a functional Unix shell on that platform. It is called Cygwin and I have been using it for years. It even ships with Vim, albeit most mirrors have outdated versions. I prefer to use the native 64 bit Windows vim build from vim.org rather than whatever is bundled with Cygwin. Not to mention that
So the problem is that these two products do not talk to each other. By default Vim escapes to the windows cmd.exe shell, and Cygwin bash does not know how to call the Windows version from the command line. So I started searching for a way to marry the two.
The official Vim wiki has some suggestions on how to accomplish this but I found their solution to be inadequate. When I ran a bash command from inside of Vim, it would always execute in my home directory rather than from the path where the file was located. So my figlet example would work, but xxd one would not.
What finally got me on the right track was this post. Unfortunately, it is not the most straightforward advice, but it is sound. The bottom line is that the problem is twofold:
- The vimrun.exe on Windows Vim build was not really meant to be used with anything else other than cmd.exe. You can try to force it to use something else, but it won’t always work.
- The default Cygwin shell blows, since it is essentially cmd.exe but paths, line endings and other little details are different
So what’s the solution? Well, we hack the vimrun executable, and use a different shell to execute commands. Fortunately the first part was already accomplished by a little project known as VimShell which provides you with a modified version of vimrun.exe. Here is what you need to do:
Grab this file, then drop it into your Vim directory (usually something like C:\Program Files (x86)\Vim\vim73\).
Next, in that same directory create a file named shell.txt with the following contents:
"putty.exe" -cygterm "bash -i '#F;read;#'" "putty.exe" -cygterm "bash '#F#'" "putty.exe" -cygterm -
Yep, that says putty. That’s the second part of our equation. But not this one. You want to grab PuttyCyg which is essentially a modified version that can be used as a Cygwin terminal proxy. You just drop it somewhere in your %PATH% and you should be all set.
Finally, you need to add the following few lines to your .vimrc in order to make the Cygwin shell escape and quote things properly:
if has('win32') set shellxquote= set shellpipe=2>&1\|tee set shellredir=>%s\ 2>&1 set shellslash endif
Once you are done that, you should be good to go. If your Cygwin installation complains about paths, you may need to add the following environment variable to your windows config:
Note that you set the Windows environment variables via the Advanced Settings dialog ine the System applet of Control Panel. When you’re done it should look like this:
Once you are done with all that setup, you should be able to “bang-escape” out of Vim into Cygwin and execute the commands I have shown you at the beginning of this post a and more. One more remaining thing to do is to enable Cygwin to call the Windows version of Vim directly. Or rather gVim since that’s what I usually use.
Under Cygwin, go to your .bash_profile and the following line:
alias gvim='HOME=`cygpath -d $HOME` /cygdrive/c/vim/gvim.exe'
You may need to change the cygdrive letter if your version of Vim is installed somewhere else.
This is by no means a perfect solution, but it has been working for me so far and allowed me to have a semi-reliable access to unix commands from within Vim.