cover image for post '"Can't open file" when Running External Commands from VIM on Windows'

"Can't open file" when Running External Commands from VIM on Windows

One of the many features that make VIM great is the power to run an external command and add its output to the text. Let’s say you often like to count the number of 5s in a string and you have a Python script that does that for you:

import sys

nr_of_fives = sys.argv[1].count("5")
sys.stdout.write(str(nr_of_fives))

You can then map a sequence of characters in VIM to run this script on a named buffer:

imap <leader>e <c-r>=system('cmd /c count_fives.py ' . shellescape(@0))<cr>

Then you only need to yank the desired text to buffer e and run the script from insert mode with e and the number of fives should be inserted at the cursor position. Unfortunately, on Windows you might run into the following error message if you copy more than one line, i.e, if your buffer contains line feeds \n: [responsive]

problem.png

The problem lies with the way multi line arguments are handled on Windows. I’m sure there is a way to tweak VIM to get the format that Windows needs, but didn’t manage to find it yet. But for the most part my external scripts don’t need the newline information anyway, so I don’t mind replacing the newlines with something else (e.g., tabs) before passing the result as argument:

imap <leader>e <c-r>=system('cmd /c count_fives.py ' . shellescape(substitute(@0,'\n','\t','g')))<cr>

As long as expandtab is set there should be any tabs in VIM and the script can safely substitute tabs back to newlines if needed.